();
/**
* Creates a new instance with no {@link ChannelFactory} set.
* {@link #setFactory(ChannelFactory)} must be called at once before any
* I/O operation is requested.
*/
protected Bootstrap() {
}
/**
* Creates a new instance with the specified initial {@link ChannelFactory}.
*/
protected Bootstrap(ChannelFactory channelFactory) {
setFactory(channelFactory);
}
/**
* Returns the {@link ChannelFactory} that will be used to perform an
* I/O operation.
*
* @throws IllegalStateException
* if the factory is not set for this bootstrap yet.
* The factory can be set in the constructor or
* {@link #setFactory(ChannelFactory)}.
*/
public ChannelFactory getFactory() {
ChannelFactory factory = this.factory;
if (factory == null) {
throw new IllegalStateException(
"factory is not set yet.");
}
return factory;
}
/**
* Sets the {@link ChannelFactory} that will be used to perform an I/O
* operation. This method can be called only once and can't be called at
* all if the factory was specified in the constructor.
*
* @throws IllegalStateException
* if the factory is already set
*/
public void setFactory(ChannelFactory factory) {
if (factory == null) {
throw new NullPointerException("factory");
}
if (this.factory != null) {
throw new IllegalStateException(
"factory can't change once set.");
}
this.factory = factory;
}
/**
* Returns the default {@link ChannelPipeline} which is cloned when a new
* {@link Channel} is created. {@link Bootstrap} creates a new pipeline
* which has the same entries with the returned pipeline for a new
* {@link Channel}.
*
* Please note that this method is a convenience method that works only
* when 1) you create only one channel from this bootstrap (e.g.
* one-time client-side or connectionless channel) or 2) all handlers
* in the pipeline is stateless. You have to use
* {@link #setPipelineFactory(ChannelPipelineFactory)} if 1) your
* pipeline contains a stateful {@link ChannelHandler} and 2) one or
* more channels are going to be created by this bootstrap (e.g. server-side
* channels).
*
* @return the default {@link ChannelPipeline}
*
* @throws IllegalStateException
* if {@link #setPipelineFactory(ChannelPipelineFactory)} was
* called by a user last time.
*/
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = this.pipeline;
if (pipeline == null) {
throw new IllegalStateException(
"getPipeline() cannot be called " +
"if setPipelineFactory() was called.");
}
return pipeline;
}
/**
* Sets the default {@link ChannelPipeline} which is cloned when a new
* {@link Channel} is created. {@link Bootstrap} creates a new pipeline
* which has the same entries with the specified pipeline for a new channel.
*
* Calling this method also sets the {@code pipelineFactory} property to an
* internal {@link ChannelPipelineFactory} implementation which returns
* a shallow copy of the specified pipeline.
*
* Please note that this method is a convenience method that works only
* when 1) you create only one channel from this bootstrap (e.g.
* one-time client-side or connectionless channel) or 2) all handlers
* in the pipeline is stateless. You have to use
* {@link #setPipelineFactory(ChannelPipelineFactory)} if 1) your
* pipeline contains a stateful {@link ChannelHandler} and 2) one or
* more channels are going to be created by this bootstrap (e.g. server-side
* channels).
*/
public void setPipeline(ChannelPipeline pipeline) {
if (pipeline == null) {
throw new NullPointerException("pipeline");
}
this.pipeline = pipeline;
pipelineFactory = pipelineFactory(pipeline);
}
/**
* Dependency injection friendly convenience method for
* {@link #getPipeline()} which returns the default pipeline of this
* bootstrap as an ordered map.
*
* Please note that this method is a convenience method that works only
* when 1) you create only one channel from this bootstrap (e.g.
* one-time client-side or connectionless channel) or 2) all handlers
* in the pipeline is stateless. You have to use
* {@link #setPipelineFactory(ChannelPipelineFactory)} if 1) your
* pipeline contains a stateful {@link ChannelHandler} and 2) one or
* more channels are going to be created by this bootstrap (e.g. server-side
* channels).
*
* @throws IllegalStateException
* if {@link #setPipelineFactory(ChannelPipelineFactory)} was
* called by a user last time.
*/
public Map getPipelineAsMap() {
ChannelPipeline pipeline = this.pipeline;
if (pipeline == null) {
throw new IllegalStateException("pipelineFactory in use");
}
return pipeline.toMap();
}
/**
* Dependency injection friendly convenience method for
* {@link #setPipeline(ChannelPipeline)} which sets the default pipeline of
* this bootstrap from an ordered map.
*
* Please note that this method is a convenience method that works only
* when 1) you create only one channel from this bootstrap (e.g.
* one-time client-side or connectionless channel) or 2) all handlers
* in the pipeline is stateless. You have to use
* {@link #setPipelineFactory(ChannelPipelineFactory)} if 1) your
* pipeline contains a stateful {@link ChannelHandler} and 2) one or
* more channels are going to be created by this bootstrap (e.g. server-side
* channels).
*
* @throws IllegalArgumentException
* if the specified map is not an ordered map
*/
public void setPipelineAsMap(Map pipelineMap) {
if (pipelineMap == null) {
throw new NullPointerException("pipelineMap");
}
if (!isOrderedMap(pipelineMap)) {
throw new IllegalArgumentException(
"pipelineMap is not an ordered map. " +
"Please use " +
LinkedHashMap.class.getName() + '.');
}
ChannelPipeline pipeline = pipeline();
for (Map.Entry e: pipelineMap.entrySet()) {
pipeline.addLast(e.getKey(), e.getValue());
}
setPipeline(pipeline);
}
/**
* Returns the {@link ChannelPipelineFactory} which creates a new
* {@link ChannelPipeline} for each new {@link Channel}.
*
* @see #getPipeline()
*/
public ChannelPipelineFactory getPipelineFactory() {
return pipelineFactory;
}
/**
* Sets the {@link ChannelPipelineFactory} which creates a new
* {@link ChannelPipeline} for each new {@link Channel}. Calling this
* method invalidates the current {@code pipeline} property of this
* bootstrap. Subsequent {@link #getPipeline()} and {@link #getPipelineAsMap()}
* calls will raise {@link IllegalStateException}.
*
* @see #setPipeline(ChannelPipeline)
* @see #setPipelineAsMap(Map)
*/
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
if (pipelineFactory == null) {
throw new NullPointerException("pipelineFactory");
}
pipeline = null;
this.pipelineFactory = pipelineFactory;
}
/**
* Returns the options which configures a new {@link Channel} and its
* child {@link Channel}s. The names of the child {@link Channel} options
* are prepended with {@code "child."} (e.g. {@code "child.keepAlive"}).
*/
public Map getOptions() {
return new TreeMap(options);
}
/**
* Sets the options which configures a new {@link Channel} and its child
* {@link Channel}s. To set the options of a child {@link Channel}, prepend
* {@code "child."} to the option name (e.g. {@code "child.keepAlive"}).
*/
public void setOptions(Map options) {
if (options == null) {
throw new NullPointerException("options");
}
this.options = new HashMap(options);
}
/**
* Returns the value of the option with the specified key. To retrieve
* the option value of a child {@link Channel}, prepend {@code "child."}
* to the option name (e.g. {@code "child.keepAlive"}).
*
* @param key the option name
*
* @return the option value if the option is found.
* {@code null} otherwise.
*/
public Object getOption(String key) {
if (key == null) {
throw new NullPointerException("key");
}
return options.get(key);
}
/**
* Sets an option with the specified key and value. If there's already
* an option with the same key, it is replaced with the new value. If the
* specified value is {@code null}, an existing option with the specified
* key is removed. To set the option value of a child {@link Channel},
* prepend {@code "child."} to the option name (e.g. {@code "child.keepAlive"}).
*
* @param key the option name
* @param value the option value
*/
public void setOption(String key, Object value) {
if (key == null) {
throw new NullPointerException("key");
}
if (value == null) {
options.remove(key);
} else {
options.put(key, value);
}
}
/**
* This method simply delegates the call to
* {@link ChannelFactory#releaseExternalResources()}.
*/
public void releaseExternalResources() {
ChannelFactory factory = this.factory;
if (factory != null) {
factory.releaseExternalResources();
}
}
/**
* This method simply delegates the call to
* {@link ChannelFactory#shutdown()}.
*/
public void shutdown() {
ChannelFactory factory = this.factory;
if (factory != null) {
factory.shutdown();
}
}
/**
* Returns {@code true} if and only if the specified {@code map} is an
* ordered map, like {@link LinkedHashMap} is.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
static boolean isOrderedMap(Map, ?> map) {
Class> mapType = map.getClass();
if (LinkedHashMap.class.isAssignableFrom(mapType)) {
// LinkedHashMap is an ordered map.
return true;
}
// Not a LinkedHashMap - start autodetection.
// Detect Apache Commons Collections OrderedMap implementations.
Class> type = mapType;
while (type != null) {
for (Class> i: type.getInterfaces()) {
if (i.getName().endsWith("OrderedMap")) {
// Seems like it's an ordered map - guessed from that
// it implements OrderedMap interface.
return true;
}
}
type = type.getSuperclass();
}
// Does not implement OrderedMap interface. As a last resort, try to
// create a new instance and test if the insertion order is maintained.
Map newMap;
try {
newMap = (Map) mapType.newInstance();
} catch (Exception e) {
// No default constructor - cannot proceed anymore.
return false;
}
// Run some tests.
List expectedKeys = new ArrayList();
String dummyValue = "dummyValue";
for (short element: ORDER_TEST_SAMPLES) {
String key = String.valueOf(element);
newMap.put(key, dummyValue);
expectedKeys.add(key);
Iterator it = expectedKeys.iterator();
for (Object actualKey: newMap.keySet()) {
if (!it.next().equals(actualKey)) {
// Did not pass the test.
return false;
}
}
}
// The specified map passed the insertion order test.
return true;
}
private static final short[] ORDER_TEST_SAMPLES = {
682, 807, 637, 358, 570, 828, 407, 319,
105, 41, 563, 544, 518, 298, 418, 50,
156, 769, 984, 503, 191, 578, 309, 710,
327, 720, 591, 939, 374, 707, 43, 463,
227, 174, 30, 531, 135, 930, 190, 823,
925, 835, 328, 239, 415, 500, 144, 460,
83, 774, 921, 4, 95, 468, 687, 493,
991, 436, 245, 742, 149, 821, 142, 782,
297, 918, 917, 424, 978, 992, 79, 906,
535, 515, 850, 80, 125, 378, 307, 883,
836, 160, 27, 630, 668, 226, 560, 698,
467, 829, 476, 163, 977, 367, 325, 184,
204, 312, 486, 53, 179, 592, 252, 750,
893, 517, 937, 124, 148, 719, 973, 566,
405, 449, 452, 777, 349, 761, 167, 783,
220, 802, 117, 604, 216, 363, 120, 621,
219, 182, 817, 244, 438, 465, 934, 888,
628, 209, 631, 17, 870, 679, 826, 945,
680, 848, 974, 573, 626, 865, 109, 317,
91, 494, 965, 473, 725, 388, 302, 936,
660, 150, 122, 949, 295, 392, 63, 634,
772, 143, 990, 895, 538, 59, 541, 32,
669, 321, 811, 756, 82, 955, 953, 636,
390, 162, 688, 444, 70, 590, 183, 745,
543, 666, 951, 642, 747, 765, 98, 469,
884, 929, 178, 721, 994, 840, 353, 726,
940, 759, 624, 919, 667, 629, 272, 979,
326, 608, 453, 11, 322, 347, 647, 354,
381, 746, 472, 890, 249, 536, 733, 404,
170, 959, 34, 899, 195, 651, 140, 856,
201, 237, 51, 933, 268, 849, 294, 115,
157, 14, 854, 373, 186, 872, 71, 523,
931, 952, 655, 561, 607, 862, 554, 661,
313, 909, 511, 752, 986, 311, 287, 775,
505, 878, 422, 103, 299, 119, 107, 344,
487, 776, 445, 218, 549, 697, 454, 6,
462, 455, 52, 481, 594, 126, 112, 66,
877, 172, 153, 912, 834, 741, 610, 915,
964, 831, 575, 714, 250, 461, 814, 913,
369, 542, 882, 851, 427, 838, 867, 507,
434, 569, 20, 950, 792, 605, 798, 962,
923, 258, 972, 762, 809, 843, 674, 448,
280, 495, 285, 822, 283, 147, 451, 993,
794, 982, 748, 189, 274, 96, 73, 810,
401, 261, 277, 346, 527, 645, 601, 868,
248, 879, 371, 428, 559, 278, 265, 62,
225, 853, 483, 771, 9, 8, 339, 653,
263, 28, 477, 995, 208, 880, 292, 480,
516, 457, 286, 897, 21, 852, 971, 658,
623, 528, 316, 471, 860, 306, 638, 711,
875, 671, 108, 158, 646, 24, 257, 724,
193, 341, 902, 599, 565, 334, 506, 684,
960, 780, 429, 801, 910, 308, 383, 901,
489, 81, 512, 164, 755, 514, 723, 141,
296, 958, 686, 15, 799, 579, 598, 558,
414, 64, 420, 730, 256, 131, 45, 129,
259, 338, 999, 175, 740, 790, 324, 985,
896, 482, 841, 606, 377, 111, 372, 699,
988, 233, 243, 203, 781, 969, 903, 662,
632, 301, 44, 981, 36, 412, 946, 816,
284, 447, 214, 672, 758, 954, 804, 2,
928, 886, 421, 596, 574, 16, 892, 68,
546, 522, 490, 873, 656, 696, 864, 130,
40, 393, 926, 394, 932, 876, 664, 293,
154, 916, 55, 196, 842, 498, 177, 948,
540, 127, 271, 113, 844, 576, 132, 943,
12, 123, 291, 31, 212, 529, 547, 171,
582, 609, 793, 830, 221, 440, 568, 118,
406, 194, 827, 360, 622, 389, 800, 571,
213, 262, 403, 408, 881, 289, 635, 967,
432, 376, 649, 832, 857, 717, 145, 510,
159, 980, 683, 580, 484, 379, 246, 88,
567, 320, 643, 7, 924, 397, 10, 787,
845, 779, 670, 716, 19, 600, 382, 0,
210, 665, 228, 97, 266, 90, 304, 456,
180, 152, 425, 310, 768, 223, 702, 997,
577, 663, 290, 537, 416, 426, 914, 691,
23, 281, 497, 508, 48, 681, 581, 728,
99, 795, 530, 871, 957, 889, 206, 813,
839, 709, 805, 253, 151, 613, 65, 654,
93, 639, 784, 891, 352, 67, 430, 754,
76, 187, 443, 676, 362, 961, 874, 330,
331, 384, 85, 217, 855, 818, 738, 361,
314, 3, 615, 520, 355, 920, 689, 22,
188, 49, 904, 935, 136, 475, 693, 749,
519, 812, 100, 207, 963, 364, 464, 572,
731, 230, 833, 385, 499, 545, 273, 232,
398, 478, 975, 564, 399, 504, 35, 562,
938, 211, 26, 337, 54, 614, 586, 433,
450, 763, 238, 305, 941, 370, 885, 837,
234, 110, 137, 395, 368, 695, 342, 907,
396, 474, 176, 737, 796, 446, 37, 894,
727, 648, 431, 1, 366, 525, 553, 704,
329, 627, 479, 33, 492, 260, 241, 86,
185, 491, 966, 247, 13, 587, 602, 409,
335, 650, 235, 611, 470, 442, 597, 254,
343, 539, 146, 585, 593, 641, 770, 94,
976, 705, 181, 255, 315, 718, 526, 987,
692, 983, 595, 898, 282, 133, 439, 633,
534, 861, 269, 619, 677, 502, 375, 224,
806, 869, 417, 584, 612, 803, 58, 84,
788, 797, 38, 700, 751, 603, 652, 57,
240, 947, 350, 270, 333, 116, 736, 69,
74, 104, 767, 318, 735, 859, 357, 555,
411, 267, 712, 675, 532, 825, 496, 927,
942, 102, 46, 192, 114, 744, 138, 998,
72, 617, 134, 846, 166, 77, 900, 5,
303, 387, 400, 47, 729, 922, 222, 197,
351, 509, 524, 165, 485, 300, 944, 380,
625, 778, 685, 29, 589, 766, 161, 391,
423, 42, 734, 552, 215, 824, 908, 229,
89, 251, 199, 616, 78, 644, 242, 722,
25, 437, 732, 956, 275, 200, 970, 753,
791, 336, 556, 847, 703, 236, 715, 75,
863, 713, 785, 911, 786, 620, 551, 413,
39, 739, 820, 808, 764, 701, 819, 173,
989, 345, 690, 459, 60, 106, 887, 996,
365, 673, 968, 513, 18, 419, 550, 588,
435, 264, 789, 340, 659, 466, 356, 288,
56, 708, 557, 488, 760, 332, 402, 168,
202, 521, 757, 205, 706, 441, 773, 231,
583, 386, 678, 618, 815, 279, 87, 533,
61, 548, 92, 169, 694, 905, 198, 121,
410, 139, 657, 640, 743, 128, 458, 866,
501, 348, 155, 276, 101, 858, 323, 359,
};
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/bootstrap/ClientBootstrap.java 0000664 0000000 0000000 00000025314 12255541277 0030600 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.bootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineException;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
/**
* A helper class which creates a new client-side {@link Channel} and makes a
* connection attempt.
*
* Configuring a channel
*
* {@link #setOption(String, Object) Options} are used to configure a channel:
*
*
* {@link ClientBootstrap} b = ...;
*
* // Options for a new channel
* b.setOption("remoteAddress", new {@link InetSocketAddress}("example.com", 8080));
* b.setOption("tcpNoDelay", true);
* b.setOption("receiveBufferSize", 1048576);
*
*
* For the detailed list of available options, please refer to
* {@link ChannelConfig} and its sub-types.
*
* Configuring a channel pipeline
*
* Every channel has its own {@link ChannelPipeline} and you can configure it
* in two ways.
*
* The recommended approach is to specify a {@link ChannelPipelineFactory} by
* calling {@link #setPipelineFactory(ChannelPipelineFactory)}.
*
*
* {@link ClientBootstrap} b = ...;
* b.setPipelineFactory(new MyPipelineFactory());
*
* public class MyPipelineFactory implements {@link ChannelPipelineFactory} {
* public {@link ChannelPipeline} getPipeline() throws Exception {
* // Create and configure a new pipeline for a new channel.
* {@link ChannelPipeline} p = {@link Channels}.pipeline();
* p.addLast("encoder", new EncodingHandler());
* p.addLast("decoder", new DecodingHandler());
* p.addLast("logic", new LogicHandler());
* return p;
* }
* }
*
*
* The alternative approach, which works only in a certain situation, is to use
* the default pipeline and let the bootstrap to shallow-copy the default
* pipeline for each new channel:
*
*
* {@link ClientBootstrap} b = ...;
* {@link ChannelPipeline} p = b.getPipeline();
*
* // Add handlers to the default pipeline.
* p.addLast("encoder", new EncodingHandler());
* p.addLast("decoder", new DecodingHandler());
* p.addLast("logic", new LogicHandler());
*
*
* Please note 'shallow-copy' here means that the added {@link ChannelHandler}s
* are not cloned but only their references are added to the new pipeline.
* Therefore, you cannot use this approach if you are going to open more than
* one {@link Channel}s or run a server that accepts incoming connections to
* create its child channels.
*
* Applying different settings for different {@link Channel}s
*
* {@link ClientBootstrap} is just a helper class. It neither allocates nor
* manages any resources. What manages the resources is the
* {@link ChannelFactory} implementation you specified in the constructor of
* {@link ClientBootstrap}. Therefore, it is OK to create as many
* {@link ClientBootstrap} instances as you want with the same
* {@link ChannelFactory} to apply different settings for different
* {@link Channel}s.
*
* @apiviz.landmark
*/
public class ClientBootstrap extends Bootstrap {
/**
* Creates a new instance with no {@link ChannelFactory} set.
* {@link #setFactory(ChannelFactory)} must be called before any I/O
* operation is requested.
*/
public ClientBootstrap() {
}
/**
* Creates a new instance with the specified initial {@link ChannelFactory}.
*/
public ClientBootstrap(ChannelFactory channelFactory) {
super(channelFactory);
}
/**
* Attempts a new connection with the current {@code "remoteAddress"} and
* {@code "localAddress"} option. If the {@code "localAddress"} option is
* not set, the local address of a new channel is determined automatically.
* This method is similar to the following code:
*
*
* {@link ClientBootstrap} b = ...;
* b.connect(b.getOption("remoteAddress"), b.getOption("localAddress"));
*
*
* @return a future object which notifies when this connection attempt
* succeeds or fails
*
* @throws IllegalStateException
* if {@code "remoteAddress"} option was not set
* @throws ClassCastException
* if {@code "remoteAddress"} or {@code "localAddress"} option's
* value is neither a {@link SocketAddress} nor {@code null}
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture connect() {
SocketAddress remoteAddress = (SocketAddress) getOption("remoteAddress");
if (remoteAddress == null) {
throw new IllegalStateException("remoteAddress option is not set.");
}
return connect(remoteAddress);
}
/**
* Attempts a new connection with the specified {@code remoteAddress} and
* the current {@code "localAddress"} option. If the {@code "localAddress"}
* option is not set, the local address of a new channel is determined
* automatically. This method is identical with the following code:
*
*
* {@link ClientBootstrap} b = ...;
* b.connect(remoteAddress, b.getOption("localAddress"));
*
*
* @return a future object which notifies when this connection attempt
* succeeds or fails
*
* @throws ClassCastException
* if {@code "localAddress"} option's value is
* neither a {@link SocketAddress} nor {@code null}
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture connect(SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
return connect(remoteAddress, localAddress);
}
/**
* Attempts a new connection with the specified {@code remoteAddress} and
* the specified {@code localAddress}. If the specified local address is
* {@code null}, the local address of a new channel is determined
* automatically.
*
* @return a future object which notifies when this connection attempt
* succeeds or fails
*
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture connect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
ChannelPipeline pipeline;
try {
pipeline = getPipelineFactory().getPipeline();
} catch (Exception e) {
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
}
// Set the options.
Channel ch = getFactory().newChannel(pipeline);
boolean success = false;
try {
ch.getConfig().setOptions(getOptions());
success = true;
} finally {
if (!success) {
ch.close();
}
}
// Bind.
if (localAddress != null) {
ch.bind(localAddress);
}
// Connect.
return ch.connect(remoteAddress);
}
/**
* Attempts to bind a channel with the specified {@code localAddress}. later the channel can
* be connected to a remoteAddress by calling {@link Channel#connect(SocketAddress)}.This method
* is useful where bind and connect need to be done in separate steps.
*
* For an instance, a user can set an attachment to the {@link Channel} via
* {@link Channel#setAttachment(Object)} before beginning a connection attempt so that the user can access
* the attachment once the connection is established:
*
*
* ChannelFuture bindFuture = bootstrap.bind(new InetSocketAddress("192.168.0.15", 0));
* Channel channel = bindFuture.getChannel();
* channel.setAttachment(dataObj);
* channel.connect(new InetSocketAddress("192.168.0.30", 8080));
*
*
* The attachment can be accessed then in the handler like the following:
*
*
* public class YourHandler extends SimpleChannelUpstreamHandler {
* public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
* Object dataObject = ctx.getChannel().getAttachment();
* }
* }
*
*
*
* @return a future object which notifies when this bind attempt
* succeeds or fails
*
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture bind(final SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
ChannelPipeline pipeline;
try {
pipeline = getPipelineFactory().getPipeline();
} catch (Exception e) {
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
}
// Set the options.
Channel ch = getFactory().newChannel(pipeline);
boolean success = false;
try {
ch.getConfig().setOptions(getOptions());
success = true;
} finally {
if (!success) {
ch.close();
}
}
// Bind.
return ch.bind(localAddress);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/bootstrap/ConnectionlessBootstrap.java 0000664 0000000 0000000 00000026705 12255541277 0032355 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.bootstrap;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineException;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
/**
* A helper class which creates a new server-side {@link Channel} for a
* connectionless transport.
*
* Only for connectionless transports
*
* This bootstrap is for connectionless transports only such as UDP/IP.
* Use {@link ServerBootstrap} instead for connection oriented transports.
* Do not use this helper if you are using a connection oriented transport such
* as TCP/IP and local transport which accepts an incoming connection and lets
* the accepted child channels handle received messages.
*
* Configuring channels
*
* {@link #setOption(String, Object) Options} are used to configure a channel:
*
*
* {@link ConnectionlessBootstrap} b = ...;
*
* // Options for a new channel
* b.setOption("localAddress", new {@link InetSocketAddress}(8080));
* b.setOption("tcpNoDelay", true);
* b.setOption("receiveBufferSize", 1048576);
*
*
* For the detailed list of available options, please refer to
* {@link ChannelConfig} and its sub-types.
*
* Configuring a channel pipeline
*
* Every channel has its own {@link ChannelPipeline} and you can configure it
* in two ways.
*
* The recommended approach is to specify a {@link ChannelPipelineFactory} by
* calling {@link #setPipelineFactory(ChannelPipelineFactory)}.
*
*
* {@link ConnectionlessBootstrap} b = ...;
* b.setPipelineFactory(new MyPipelineFactory());
*
* public class MyPipelineFactory implements {@link ChannelPipelineFactory} {
* public {@link ChannelPipeline} getPipeline() throws Exception {
* // Create and configure a new pipeline for a new channel.
* {@link ChannelPipeline} p = {@link Channels}.pipeline();
* p.addLast("encoder", new EncodingHandler());
* p.addLast("decoder", new DecodingHandler());
* p.addLast("logic", new LogicHandler());
* return p;
* }
* }
*
*
* The alternative approach, which works only in a certain situation, is to use
* the default pipeline and let the bootstrap to shallow-copy the default
* pipeline for each new channel:
*
*
* {@link ConnectionlessBootstrap} b = ...;
* {@link ChannelPipeline} p = b.getPipeline();
*
* // Add handlers to the default pipeline.
* p.addLast("encoder", new EncodingHandler());
* p.addLast("decoder", new DecodingHandler());
* p.addLast("logic", new LogicHandler());
*
*
* Please note 'shallow-copy' here means that the added {@link ChannelHandler}s
* are not cloned but only their references are added to the new pipeline.
* Therefore, you cannot use this approach if you are going to open more than
* one {@link Channel}s or run a server that accepts incoming connections to
* create its child channels.
*
* Applying different settings for different {@link Channel}s
*
* {@link ConnectionlessBootstrap} is just a helper class. It neither
* allocates nor manages any resources. What manages the resources is the
* {@link ChannelFactory} implementation you specified in the constructor of
* {@link ConnectionlessBootstrap}. Therefore, it is OK to create as
* many {@link ConnectionlessBootstrap} instances as you want with the same
* {@link ChannelFactory} to apply different settings for different
* {@link Channel}s.
*
* @apiviz.landmark
*/
public class ConnectionlessBootstrap extends Bootstrap {
/**
* Creates a new instance with no {@link ChannelFactory} set.
* {@link #setFactory(ChannelFactory)} must be called before any I/O
* operation is requested.
*/
public ConnectionlessBootstrap() {
}
/**
* Creates a new instance with the specified initial {@link ChannelFactory}.
*/
public ConnectionlessBootstrap(ChannelFactory channelFactory) {
super(channelFactory);
}
/**
* Creates a new channel which is bound to the local address which was
* specified in the current {@code "localAddress"} option. This method is
* similar to the following code:
*
*
* {@link ConnectionlessBootstrap} b = ...;
* b.bind(b.getOption("localAddress"));
*
*
* @return a new bound channel which accepts incoming connections
*
* @throws IllegalStateException
* if {@code "localAddress"} option was not set
* @throws ClassCastException
* if {@code "localAddress"} option's value is
* neither a {@link SocketAddress} nor {@code null}
* @throws ChannelException
* if failed to create a new channel and
* bind it to the local address
*/
public Channel bind() {
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
if (localAddress == null) {
throw new IllegalStateException("localAddress option is not set.");
}
return bind(localAddress);
}
/**
* Creates a new channel which is bound to the specified local address.
*
* @return a new bound channel which accepts incoming connections
*
* @throws ChannelException
* if failed to create a new channel and
* bind it to the local address
*/
public Channel bind(final SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
ChannelPipeline pipeline;
try {
pipeline = getPipelineFactory().getPipeline();
} catch (Exception e) {
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
}
Channel ch = getFactory().newChannel(pipeline);
// Apply options.
boolean success = false;
try {
ch.getConfig().setOptions(getOptions());
success = true;
} finally {
if (!success) {
ch.close();
}
}
// Bind
ChannelFuture future = ch.bind(localAddress);
// Wait for the future.
future.awaitUninterruptibly();
if (!future.isSuccess()) {
future.getChannel().close().awaitUninterruptibly();
throw new ChannelException("Failed to bind to: " + localAddress, future.getCause());
}
return ch;
}
/**
* Creates a new connected channel with the current {@code "remoteAddress"}
* and {@code "localAddress"} option. If the {@code "localAddress"} option
* is not set, the local address of a new channel is determined
* automatically. This method is similar to the following code:
*
*
* {@link ConnectionlessBootstrap} b = ...;
* b.connect(b.getOption("remoteAddress"), b.getOption("localAddress"));
*
*
* @return a future object which notifies when the creation of the connected
* channel succeeds or fails
*
* @throws IllegalStateException
* if {@code "remoteAddress"} option was not set
* @throws ClassCastException
* if {@code "remoteAddress"} or {@code "localAddress"} option's
* value is neither a {@link SocketAddress} nor {@code null}
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture connect() {
SocketAddress remoteAddress = (SocketAddress) getOption("remoteAddress");
if (remoteAddress == null) {
throw new IllegalStateException("remoteAddress option is not set.");
}
return connect(remoteAddress);
}
/**
* Creates a new connected channel with the specified
* {@code "remoteAddress"} and the current {@code "localAddress"} option.
* If the {@code "localAddress"} option is not set, the local address of
* a new channel is determined automatically. This method is identical
* with the following code:
*
*
* {@link ConnectionlessBootstrap} b = ...;
* b.connect(remoteAddress, b.getOption("localAddress"));
*
*
* @return a future object which notifies when the creation of the connected
* channel succeeds or fails
*
* @throws ClassCastException
* if {@code "localAddress"} option's value is
* neither a {@link SocketAddress} nor {@code null}
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture connect(SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remotedAddress");
}
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
return connect(remoteAddress, localAddress);
}
/**
* Creates a new connected channel with the specified
* {@code "remoteAddress"} and the specified {@code "localAddress"}.
* If the specified local address is {@code null}, the local address of a
* new channel is determined automatically.
*
* @return a future object which notifies when the creation of the connected
* channel succeeds or fails
*
* @throws ChannelPipelineException
* if this bootstrap's {@link #setPipelineFactory(ChannelPipelineFactory) pipelineFactory}
* failed to create a new {@link ChannelPipeline}
*/
public ChannelFuture connect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
ChannelPipeline pipeline;
try {
pipeline = getPipelineFactory().getPipeline();
} catch (Exception e) {
throw new ChannelPipelineException("Failed to initialize a pipeline.", e);
}
// Set the options.
Channel ch = getFactory().newChannel(pipeline);
boolean success = false;
try {
ch.getConfig().setOptions(getOptions());
success = true;
} finally {
if (!success) {
ch.close();
}
}
// Bind.
if (localAddress != null) {
ch.bind(localAddress);
}
// Connect.
return ch.connect(remoteAddress);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/bootstrap/ServerBootstrap.java 0000664 0000000 0000000 00000036456 12255541277 0030641 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.bootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ChildChannelStateEvent;
import org.jboss.netty.channel.DefaultChannelFuture;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.ServerChannelFactory;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import static org.jboss.netty.channel.Channels.*;
/**
* A helper class which creates a new server-side {@link Channel} and accepts
* incoming connections.
*
* Only for connection oriented transports
*
* This bootstrap is for connection oriented transports only such as TCP/IP
* and local transport. Use {@link ConnectionlessBootstrap} instead for
* connectionless transports. Do not use this helper if you are using a
* connectionless transport such as UDP/IP which does not accept an incoming
* connection but receives messages by itself without creating a child channel.
*
* Parent channel and its children
*
* A parent channel is a channel which is supposed to accept incoming
* connections. It is created by this bootstrap's {@link ChannelFactory} via
* {@link #bind()} and {@link #bind(SocketAddress)}.
*
* Once successfully bound, the parent channel starts to accept incoming
* connections, and the accepted connections become the children of the
* parent channel.
*
*
Configuring channels
*
* {@link #setOption(String, Object) Options} are used to configure both a
* parent channel and its child channels. To configure the child channels,
* prepend {@code "child."} prefix to the actual option names of a child
* channel:
*
*
* {@link ServerBootstrap} b = ...;
*
* // Options for a parent channel
* b.setOption("localAddress", new {@link InetSocketAddress}(8080));
* b.setOption("reuseAddress", true);
*
* // Options for its children
* b.setOption("child.tcpNoDelay", true);
* b.setOption("child.receiveBufferSize", 1048576);
*
*
* For the detailed list of available options, please refer to
* {@link ChannelConfig} and its sub-types.
*
* Configuring a parent channel pipeline
*
* It is rare to customize the pipeline of a parent channel because what it is
* supposed to do is very typical. However, you might want to add a handler
* to deal with some special needs such as degrading the process
* UID from
* a superuser to a
* normal user and changing the current VM security manager for better
* security. To support such a case,
* the {@link #setParentHandler(ChannelHandler) parentHandler} property is
* provided.
*
* Configuring a child channel pipeline
*
* Every channel has its own {@link ChannelPipeline} and you can configure it
* in two ways.
*
* The recommended approach is to specify a {@link ChannelPipelineFactory} by
* calling {@link #setPipelineFactory(ChannelPipelineFactory)}.
*
*
* {@link ServerBootstrap} b = ...;
* b.setPipelineFactory(new MyPipelineFactory());
*
* public class MyPipelineFactory implements {@link ChannelPipelineFactory} {
* public {@link ChannelPipeline} getPipeline() throws Exception {
* // Create and configure a new pipeline for a new channel.
* {@link ChannelPipeline} p = {@link Channels}.pipeline();
* p.addLast("encoder", new EncodingHandler());
* p.addLast("decoder", new DecodingHandler());
* p.addLast("logic", new LogicHandler());
* return p;
* }
* }
*
*
* The alternative approach, which works only in a certain situation, is to use
* the default pipeline and let the bootstrap to shallow-copy the default
* pipeline for each new channel:
*
*
* {@link ServerBootstrap} b = ...;
* {@link ChannelPipeline} p = b.getPipeline();
*
* // Add handlers to the default pipeline.
* p.addLast("encoder", new EncodingHandler());
* p.addLast("decoder", new DecodingHandler());
* p.addLast("logic", new LogicHandler());
*
*
* Please note 'shallow-copy' here means that the added {@link ChannelHandler}s
* are not cloned but only their references are added to the new pipeline.
* Therefore, you cannot use this approach if you are going to open more than
* one {@link Channel}s or run a server that accepts incoming connections to
* create its child channels.
*
* Applying different settings for different {@link Channel}s
*
* {@link ServerBootstrap} is just a helper class. It neither allocates nor
* manages any resources. What manages the resources is the
* {@link ChannelFactory} implementation you specified in the constructor of
* {@link ServerBootstrap}. Therefore, it is OK to create as many
* {@link ServerBootstrap} instances as you want with the same
* {@link ChannelFactory} to apply different settings for different
* {@link Channel}s.
*
* @apiviz.landmark
*/
public class ServerBootstrap extends Bootstrap {
private volatile ChannelHandler parentHandler;
/**
* Creates a new instance with no {@link ChannelFactory} set.
* {@link #setFactory(ChannelFactory)} must be called before any I/O
* operation is requested.
*/
public ServerBootstrap() {
}
/**
* Creates a new instance with the specified initial {@link ChannelFactory}.
*/
public ServerBootstrap(ChannelFactory channelFactory) {
super(channelFactory);
}
/**
* Sets the {@link ServerChannelFactory} that will be used to perform an I/O
* operation. This method can be called only once and can't be called at
* all if the factory was specified in the constructor.
*
* @throws IllegalStateException
* if the factory is already set
* @throws IllegalArgumentException
* if the specified {@code factory} is not a
* {@link ServerChannelFactory}
*/
@Override
public void setFactory(ChannelFactory factory) {
if (factory == null) {
throw new NullPointerException("factory");
}
if (!(factory instanceof ServerChannelFactory)) {
throw new IllegalArgumentException(
"factory must be a " +
ServerChannelFactory.class.getSimpleName() + ": " +
factory.getClass());
}
super.setFactory(factory);
}
/**
* Returns an optional {@link ChannelHandler} which intercepts an event
* of a newly bound server-side channel which accepts incoming connections.
*
* @return the parent channel handler.
* {@code null} if no parent channel handler is set.
*/
public ChannelHandler getParentHandler() {
return parentHandler;
}
/**
* Sets an optional {@link ChannelHandler} which intercepts an event of
* a newly bound server-side channel which accepts incoming connections.
*
* @param parentHandler
* the parent channel handler.
* {@code null} to unset the current parent channel handler.
*/
public void setParentHandler(ChannelHandler parentHandler) {
this.parentHandler = parentHandler;
}
/**
* Creates a new channel which is bound to the local address which was
* specified in the current {@code "localAddress"} option. This method is
* similar to the following code:
*
*
* {@link ServerBootstrap} b = ...;
* b.bind(b.getOption("localAddress"));
*
*
* This operation will block until the channel is bound.
*
* @return a new bound channel which accepts incoming connections
*
* @throws IllegalStateException
* if {@code "localAddress"} option was not set
* @throws ClassCastException
* if {@code "localAddress"} option's value is
* neither a {@link SocketAddress} nor {@code null}
* @throws ChannelException
* if failed to create a new channel and
* bind it to the local address
*/
public Channel bind() {
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
if (localAddress == null) {
throw new IllegalStateException("localAddress option is not set.");
}
return bind(localAddress);
}
/**
* Creates a new channel which is bound to the specified local address. This operation will block until
* the channel is bound.
*
* @return a new bound channel which accepts incoming connections
*
* @throws ChannelException
* if failed to create a new channel and
* bind it to the local address
*/
public Channel bind(final SocketAddress localAddress) {
ChannelFuture future = bindAsync(localAddress);
// Wait for the future.
future.awaitUninterruptibly();
if (!future.isSuccess()) {
future.getChannel().close().awaitUninterruptibly();
throw new ChannelException("Failed to bind to: " + localAddress, future.getCause());
}
return future.getChannel();
}
/**
* Bind a channel asynchronous to the local address
* specified in the current {@code "localAddress"} option. This method is
* similar to the following code:
*
*
* {@link ServerBootstrap} b = ...;
* b.bindAsync(b.getOption("localAddress"));
*
*
*
* @return a new {@link ChannelFuture} which will be notified once the Channel is
* bound and accepts incoming connections
*
* @throws IllegalStateException
* if {@code "localAddress"} option was not set
* @throws ClassCastException
* if {@code "localAddress"} option's value is
* neither a {@link SocketAddress} nor {@code null}
* @throws ChannelException
* if failed to create a new channel and
* bind it to the local address
*/
public ChannelFuture bindAsync() {
SocketAddress localAddress = (SocketAddress) getOption("localAddress");
if (localAddress == null) {
throw new IllegalStateException("localAddress option is not set.");
}
return bindAsync(localAddress);
}
/**
* Bind a channel asynchronous to the specified local address.
*
* @return a new {@link ChannelFuture} which will be notified once the Channel is
* bound and accepts incoming connections
*
*/
public ChannelFuture bindAsync(final SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
Binder binder = new Binder(localAddress);
ChannelHandler parentHandler = getParentHandler();
ChannelPipeline bossPipeline = pipeline();
bossPipeline.addLast("binder", binder);
if (parentHandler != null) {
bossPipeline.addLast("userHandler", parentHandler);
}
Channel channel = getFactory().newChannel(bossPipeline);
final ChannelFuture bfuture = new DefaultChannelFuture(channel, false);
binder.bindFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
bfuture.setSuccess();
} else {
// Call close on bind failure
bfuture.getChannel().close();
bfuture.setFailure(future.getCause());
}
}
});
return bfuture;
}
private final class Binder extends SimpleChannelUpstreamHandler {
private final SocketAddress localAddress;
private final Map childOptions =
new HashMap();
private final DefaultChannelFuture bindFuture = new DefaultChannelFuture(null, false);
Binder(SocketAddress localAddress) {
this.localAddress = localAddress;
}
@Override
public void channelOpen(
ChannelHandlerContext ctx,
ChannelStateEvent evt) {
try {
evt.getChannel().getConfig().setPipelineFactory(getPipelineFactory());
// Split options into two categories: parent and child.
Map allOptions = getOptions();
Map parentOptions = new HashMap();
for (Entry e: allOptions.entrySet()) {
if (e.getKey().startsWith("child.")) {
childOptions.put(
e.getKey().substring(6),
e.getValue());
} else if (!"pipelineFactory".equals(e.getKey())) {
parentOptions.put(e.getKey(), e.getValue());
}
}
// Apply parent options.
evt.getChannel().getConfig().setOptions(parentOptions);
} finally {
ctx.sendUpstream(evt);
}
evt.getChannel().bind(localAddress).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
bindFuture.setSuccess();
} else {
bindFuture.setFailure(future.getCause());
}
}
});
}
@Override
public void childChannelOpen(
ChannelHandlerContext ctx,
ChildChannelStateEvent e) throws Exception {
// Apply child options.
try {
e.getChildChannel().getConfig().setOptions(childOptions);
} catch (Throwable t) {
fireExceptionCaught(e.getChildChannel(), t);
}
ctx.sendUpstream(e);
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
bindFuture.setFailure(e.getCause());
ctx.sendUpstream(e);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/bootstrap/package-info.java 0000664 0000000 0000000 00000001564 12255541277 0030011 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* IoC/DI friendly helper classes which enable an easy implementation of
* typical client side and server side channel initialization.
*
* @apiviz.landmark
* @apiviz.exclude ^org\.jboss\.netty\.util\.
*/
package org.jboss.netty.bootstrap;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ 0000775 0000000 0000000 00000000000 12255541277 0024050 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/AbstractChannelBuffer.java 0000664 0000000 0000000 00000046434 12255541277 0031114 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
import java.util.NoSuchElementException;
/**
* A skeletal implementation of a buffer.
*/
public abstract class AbstractChannelBuffer implements ChannelBuffer {
private int readerIndex;
private int writerIndex;
private int markedReaderIndex;
private int markedWriterIndex;
public int readerIndex() {
return readerIndex;
}
public void readerIndex(int readerIndex) {
if (readerIndex < 0 || readerIndex > writerIndex) {
throw new IndexOutOfBoundsException();
}
this.readerIndex = readerIndex;
}
public int writerIndex() {
return writerIndex;
}
public void writerIndex(int writerIndex) {
if (writerIndex < readerIndex || writerIndex > capacity()) {
throw new IndexOutOfBoundsException("Invalid readerIndex: "
+ readerIndex + " - Maximum is " + writerIndex);
}
this.writerIndex = writerIndex;
}
public void setIndex(int readerIndex, int writerIndex) {
if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
throw new IndexOutOfBoundsException("Invalid writerIndex: "
+ writerIndex + " - Maximum is " + readerIndex + " or " + capacity());
}
this.readerIndex = readerIndex;
this.writerIndex = writerIndex;
}
public void clear() {
readerIndex = writerIndex = 0;
}
public boolean readable() {
return readableBytes() > 0;
}
public boolean writable() {
return writableBytes() > 0;
}
public int readableBytes() {
return writerIndex - readerIndex;
}
public int writableBytes() {
return capacity() - writerIndex;
}
public void markReaderIndex() {
markedReaderIndex = readerIndex;
}
public void resetReaderIndex() {
readerIndex(markedReaderIndex);
}
public void markWriterIndex() {
markedWriterIndex = writerIndex;
}
public void resetWriterIndex() {
writerIndex = markedWriterIndex;
}
public void discardReadBytes() {
if (readerIndex == 0) {
return;
}
setBytes(0, this, readerIndex, writerIndex - readerIndex);
writerIndex -= readerIndex;
markedReaderIndex = Math.max(markedReaderIndex - readerIndex, 0);
markedWriterIndex = Math.max(markedWriterIndex - readerIndex, 0);
readerIndex = 0;
}
public void ensureWritableBytes(int writableBytes) {
if (writableBytes > writableBytes()) {
throw new IndexOutOfBoundsException("Writable bytes exceeded: Got "
+ writableBytes + ", maximum is " + writableBytes());
}
}
public short getUnsignedByte(int index) {
return (short) (getByte(index) & 0xFF);
}
public int getUnsignedShort(int index) {
return getShort(index) & 0xFFFF;
}
public int getMedium(int index) {
int value = getUnsignedMedium(index);
if ((value & 0x800000) != 0) {
value |= 0xff000000;
}
return value;
}
public long getUnsignedInt(int index) {
return getInt(index) & 0xFFFFFFFFL;
}
public char getChar(int index) {
return (char) getShort(index);
}
public float getFloat(int index) {
return Float.intBitsToFloat(getInt(index));
}
public double getDouble(int index) {
return Double.longBitsToDouble(getLong(index));
}
public void getBytes(int index, byte[] dst) {
getBytes(index, dst, 0, dst.length);
}
public void getBytes(int index, ChannelBuffer dst) {
getBytes(index, dst, dst.writableBytes());
}
public void getBytes(int index, ChannelBuffer dst, int length) {
if (length > dst.writableBytes()) {
throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
+ length + ", maximum is " + dst.writableBytes());
}
getBytes(index, dst, dst.writerIndex(), length);
dst.writerIndex(dst.writerIndex() + length);
}
public void setChar(int index, int value) {
setShort(index, value);
}
public void setFloat(int index, float value) {
setInt(index, Float.floatToRawIntBits(value));
}
public void setDouble(int index, double value) {
setLong(index, Double.doubleToRawLongBits(value));
}
public void setBytes(int index, byte[] src) {
setBytes(index, src, 0, src.length);
}
public void setBytes(int index, ChannelBuffer src) {
setBytes(index, src, src.readableBytes());
}
public void setBytes(int index, ChannelBuffer src, int length) {
if (length > src.readableBytes()) {
throw new IndexOutOfBoundsException("Too many bytes to write: Need "
+ length + ", maximum is " + src.readableBytes());
}
setBytes(index, src, src.readerIndex(), length);
src.readerIndex(src.readerIndex() + length);
}
public void setZero(int index, int length) {
if (length == 0) {
return;
}
if (length < 0) {
throw new IllegalArgumentException(
"length must be 0 or greater than 0.");
}
int nLong = length >>> 3;
int nBytes = length & 7;
for (int i = nLong; i > 0; i --) {
setLong(index, 0);
index += 8;
}
if (nBytes == 4) {
setInt(index, 0);
} else if (nBytes < 4) {
for (int i = nBytes; i > 0; i --) {
setByte(index, (byte) 0);
index ++;
}
} else {
setInt(index, 0);
index += 4;
for (int i = nBytes - 4; i > 0; i --) {
setByte(index, (byte) 0);
index ++;
}
}
}
public byte readByte() {
if (readerIndex == writerIndex) {
throw new IndexOutOfBoundsException("Readable byte limit exceeded: "
+ readerIndex);
}
return getByte(readerIndex ++);
}
public short readUnsignedByte() {
return (short) (readByte() & 0xFF);
}
public short readShort() {
checkReadableBytes(2);
short v = getShort(readerIndex);
readerIndex += 2;
return v;
}
public int readUnsignedShort() {
return readShort() & 0xFFFF;
}
public int readMedium() {
int value = readUnsignedMedium();
if ((value & 0x800000) != 0) {
value |= 0xff000000;
}
return value;
}
public int readUnsignedMedium() {
checkReadableBytes(3);
int v = getUnsignedMedium(readerIndex);
readerIndex += 3;
return v;
}
public int readInt() {
checkReadableBytes(4);
int v = getInt(readerIndex);
readerIndex += 4;
return v;
}
public long readUnsignedInt() {
return readInt() & 0xFFFFFFFFL;
}
public long readLong() {
checkReadableBytes(8);
long v = getLong(readerIndex);
readerIndex += 8;
return v;
}
public char readChar() {
return (char) readShort();
}
public float readFloat() {
return Float.intBitsToFloat(readInt());
}
public double readDouble() {
return Double.longBitsToDouble(readLong());
}
public ChannelBuffer readBytes(int length) {
checkReadableBytes(length);
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
ChannelBuffer buf = factory().getBuffer(order(), length);
buf.writeBytes(this, readerIndex, length);
readerIndex += length;
return buf;
}
@Deprecated
public ChannelBuffer readBytes(ChannelBufferIndexFinder endIndexFinder) {
int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
if (endIndex < 0) {
throw new NoSuchElementException();
}
return readBytes(endIndex - readerIndex);
}
public ChannelBuffer readSlice(int length) {
ChannelBuffer slice = slice(readerIndex, length);
readerIndex += length;
return slice;
}
@Deprecated
public ChannelBuffer readSlice(ChannelBufferIndexFinder endIndexFinder) {
int endIndex = indexOf(readerIndex, writerIndex, endIndexFinder);
if (endIndex < 0) {
throw new NoSuchElementException();
}
return readSlice(endIndex - readerIndex);
}
public void readBytes(byte[] dst, int dstIndex, int length) {
checkReadableBytes(length);
getBytes(readerIndex, dst, dstIndex, length);
readerIndex += length;
}
public void readBytes(byte[] dst) {
readBytes(dst, 0, dst.length);
}
public void readBytes(ChannelBuffer dst) {
readBytes(dst, dst.writableBytes());
}
public void readBytes(ChannelBuffer dst, int length) {
if (length > dst.writableBytes()) {
throw new IndexOutOfBoundsException("Too many bytes to be read: Need "
+ length + ", maximum is " + dst.writableBytes());
}
readBytes(dst, dst.writerIndex(), length);
dst.writerIndex(dst.writerIndex() + length);
}
public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
checkReadableBytes(length);
getBytes(readerIndex, dst, dstIndex, length);
readerIndex += length;
}
public void readBytes(ByteBuffer dst) {
int length = dst.remaining();
checkReadableBytes(length);
getBytes(readerIndex, dst);
readerIndex += length;
}
public int readBytes(GatheringByteChannel out, int length)
throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, length);
readerIndex += readBytes;
return readBytes;
}
public void readBytes(OutputStream out, int length) throws IOException {
checkReadableBytes(length);
getBytes(readerIndex, out, length);
readerIndex += length;
}
public void skipBytes(int length) {
int newReaderIndex = readerIndex + length;
if (newReaderIndex > writerIndex) {
throw new IndexOutOfBoundsException("Readable bytes exceeded - Need "
+ newReaderIndex + ", maximum is " + writerIndex);
}
readerIndex = newReaderIndex;
}
@Deprecated
public int skipBytes(ChannelBufferIndexFinder firstIndexFinder) {
int oldReaderIndex = readerIndex;
int newReaderIndex = indexOf(oldReaderIndex, writerIndex, firstIndexFinder);
if (newReaderIndex < 0) {
throw new NoSuchElementException();
}
readerIndex(newReaderIndex);
return newReaderIndex - oldReaderIndex;
}
public void writeByte(int value) {
setByte(writerIndex, value);
writerIndex++;
}
public void writeShort(int value) {
setShort(writerIndex, value);
writerIndex += 2;
}
public void writeMedium(int value) {
setMedium(writerIndex, value);
writerIndex += 3;
}
public void writeInt(int value) {
setInt(writerIndex, value);
writerIndex += 4;
}
public void writeLong(long value) {
setLong(writerIndex, value);
writerIndex += 8;
}
public void writeChar(int value) {
writeShort(value);
}
public void writeFloat(float value) {
writeInt(Float.floatToRawIntBits(value));
}
public void writeDouble(double value) {
writeLong(Double.doubleToRawLongBits(value));
}
public void writeBytes(byte[] src, int srcIndex, int length) {
setBytes(writerIndex, src, srcIndex, length);
writerIndex += length;
}
public void writeBytes(byte[] src) {
writeBytes(src, 0, src.length);
}
public void writeBytes(ChannelBuffer src) {
writeBytes(src, src.readableBytes());
}
public void writeBytes(ChannelBuffer src, int length) {
if (length > src.readableBytes()) {
throw new IndexOutOfBoundsException("Too many bytes to write - Need "
+ length + ", maximum is " + src.readableBytes());
}
writeBytes(src, src.readerIndex(), length);
src.readerIndex(src.readerIndex() + length);
}
public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
setBytes(writerIndex, src, srcIndex, length);
writerIndex += length;
}
public void writeBytes(ByteBuffer src) {
int length = src.remaining();
setBytes(writerIndex, src);
writerIndex += length;
}
public int writeBytes(InputStream in, int length)
throws IOException {
int writtenBytes = setBytes(writerIndex, in, length);
if (writtenBytes > 0) {
writerIndex += writtenBytes;
}
return writtenBytes;
}
public int writeBytes(ScatteringByteChannel in, int length)
throws IOException {
int writtenBytes = setBytes(writerIndex, in, length);
if (writtenBytes > 0) {
writerIndex += writtenBytes;
}
return writtenBytes;
}
public void writeZero(int length) {
if (length == 0) {
return;
}
if (length < 0) {
throw new IllegalArgumentException(
"length must be 0 or greater than 0.");
}
int nLong = length >>> 3;
int nBytes = length & 7;
for (int i = nLong; i > 0; i --) {
writeLong(0);
}
if (nBytes == 4) {
writeInt(0);
} else if (nBytes < 4) {
for (int i = nBytes; i > 0; i --) {
writeByte((byte) 0);
}
} else {
writeInt(0);
for (int i = nBytes - 4; i > 0; i --) {
writeByte((byte) 0);
}
}
}
public ChannelBuffer copy() {
return copy(readerIndex, readableBytes());
}
public ChannelBuffer slice() {
return slice(readerIndex, readableBytes());
}
public ByteBuffer toByteBuffer() {
return toByteBuffer(readerIndex, readableBytes());
}
public ByteBuffer[] toByteBuffers() {
return toByteBuffers(readerIndex, readableBytes());
}
public ByteBuffer[] toByteBuffers(int index, int length) {
return new ByteBuffer[] { toByteBuffer(index, length) };
}
public String toString(Charset charset) {
return toString(readerIndex, readableBytes(), charset);
}
public String toString(int index, int length, Charset charset) {
if (length == 0) {
return "";
}
return ChannelBuffers.decodeString(
toByteBuffer(index, length), charset);
}
@Deprecated
public String toString(int index, int length, String charsetName,
ChannelBufferIndexFinder terminatorFinder) {
if (terminatorFinder == null) {
return toString(index, length, charsetName);
}
int terminatorIndex = indexOf(index, index + length, terminatorFinder);
if (terminatorIndex < 0) {
return toString(index, length, charsetName);
}
return toString(index, terminatorIndex - index, charsetName);
}
@Deprecated
public String toString(int index, int length, String charsetName) {
return toString(index, length, Charset.forName(charsetName));
}
@Deprecated
public String toString(String charsetName,
ChannelBufferIndexFinder terminatorFinder) {
return toString(readerIndex, readableBytes(), charsetName, terminatorFinder);
}
@Deprecated
public String toString(String charsetName) {
return toString(Charset.forName(charsetName));
}
public int indexOf(int fromIndex, int toIndex, byte value) {
return ChannelBuffers.indexOf(this, fromIndex, toIndex, value);
}
public int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
return ChannelBuffers.indexOf(this, fromIndex, toIndex, indexFinder);
}
public int bytesBefore(byte value) {
return bytesBefore(readerIndex(), readableBytes(), value);
}
public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
return bytesBefore(readerIndex(), readableBytes(), indexFinder);
}
public int bytesBefore(int length, byte value) {
checkReadableBytes(length);
return bytesBefore(readerIndex(), length, value);
}
public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
checkReadableBytes(length);
return bytesBefore(readerIndex(), length, indexFinder);
}
public int bytesBefore(int index, int length, byte value) {
if (index < 0 || length < 0 || index + length > capacity()) {
throw new IndexOutOfBoundsException();
}
int endIndex = indexOf(index, index + length, value);
if (endIndex < 0) {
return -1;
}
return endIndex - index;
}
public int bytesBefore(int index, int length,
ChannelBufferIndexFinder indexFinder) {
if (index < 0 || length < 0 || index + length > capacity()) {
throw new IndexOutOfBoundsException();
}
int endIndex = indexOf(index, index + length, indexFinder);
if (endIndex < 0) {
return -1;
}
return endIndex - index;
}
@Override
public int hashCode() {
return ChannelBuffers.hashCode(this);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ChannelBuffer)) {
return false;
}
return ChannelBuffers.equals(this, (ChannelBuffer) o);
}
public int compareTo(ChannelBuffer that) {
return ChannelBuffers.compare(this, that);
}
@Override
public String toString() {
return getClass().getSimpleName() + '(' +
"ridx=" + readerIndex + ", " +
"widx=" + writerIndex + ", " +
"cap=" + capacity() +
')';
}
/**
* Throws an {@link IndexOutOfBoundsException} if the current
* {@linkplain #readableBytes() readable bytes} of this buffer is less
* than the specified value.
*/
protected void checkReadableBytes(int minimumReadableBytes) {
if (readableBytes() < minimumReadableBytes) {
throw new IndexOutOfBoundsException("Not enough readable bytes - Need "
+ minimumReadableBytes + ", maximum is " + readableBytes());
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/AbstractChannelBufferFactory.java 0000664 0000000 0000000 00000003456 12255541277 0032441 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.nio.ByteOrder;
/**
* A skeletal implementation of {@link ChannelBufferFactory}.
*/
public abstract class AbstractChannelBufferFactory implements ChannelBufferFactory {
private final ByteOrder defaultOrder;
/**
* Creates a new factory whose default {@link ByteOrder} is
* {@link ByteOrder#BIG_ENDIAN}.
*/
protected AbstractChannelBufferFactory() {
this(ByteOrder.BIG_ENDIAN);
}
/**
* Creates a new factory with the specified default {@link ByteOrder}.
*
* @param defaultOrder the default {@link ByteOrder} of this factory
*/
protected AbstractChannelBufferFactory(ByteOrder defaultOrder) {
if (defaultOrder == null) {
throw new NullPointerException("defaultOrder");
}
this.defaultOrder = defaultOrder;
}
public ChannelBuffer getBuffer(int capacity) {
return getBuffer(getDefaultOrder(), capacity);
}
public ChannelBuffer getBuffer(byte[] array, int offset, int length) {
return getBuffer(getDefaultOrder(), array, offset, length);
}
public ByteOrder getDefaultOrder() {
return defaultOrder;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/BigEndianHeapChannelBuffer.java 0000664 0000000 0000000 00000010536 12255541277 0031761 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.nio.ByteOrder;
/**
* A big-endian Java heap buffer. It is recommended to use {@link ChannelBuffers#buffer(int)}
* and {@link ChannelBuffers#wrappedBuffer(byte[])} instead of calling the
* constructor explicitly.
*/
public class BigEndianHeapChannelBuffer extends HeapChannelBuffer {
/**
* Creates a new big-endian heap buffer with a newly allocated byte array.
*
* @param length the length of the new byte array
*/
public BigEndianHeapChannelBuffer(int length) {
super(length);
}
/**
* Creates a new big-endian heap buffer with an existing byte array.
*
* @param array the byte array to wrap
*/
public BigEndianHeapChannelBuffer(byte[] array) {
super(array);
}
private BigEndianHeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
super(array, readerIndex, writerIndex);
}
public ChannelBufferFactory factory() {
return HeapChannelBufferFactory.getInstance(ByteOrder.BIG_ENDIAN);
}
public ByteOrder order() {
return ByteOrder.BIG_ENDIAN;
}
public short getShort(int index) {
return (short) (array[index] << 8 | array[index + 1] & 0xFF);
}
public int getUnsignedMedium(int index) {
return (array[index] & 0xff) << 16 |
(array[index + 1] & 0xff) << 8 |
array[index + 2] & 0xff;
}
public int getInt(int index) {
return (array[index] & 0xff) << 24 |
(array[index + 1] & 0xff) << 16 |
(array[index + 2] & 0xff) << 8 |
array[index + 3] & 0xff;
}
public long getLong(int index) {
return ((long) array[index] & 0xff) << 56 |
((long) array[index + 1] & 0xff) << 48 |
((long) array[index + 2] & 0xff) << 40 |
((long) array[index + 3] & 0xff) << 32 |
((long) array[index + 4] & 0xff) << 24 |
((long) array[index + 5] & 0xff) << 16 |
((long) array[index + 6] & 0xff) << 8 |
(long) array[index + 7] & 0xff;
}
public void setShort(int index, int value) {
array[index] = (byte) (value >>> 8);
array[index + 1] = (byte) value;
}
public void setMedium(int index, int value) {
array[index] = (byte) (value >>> 16);
array[index + 1] = (byte) (value >>> 8);
array[index + 2] = (byte) value;
}
public void setInt(int index, int value) {
array[index] = (byte) (value >>> 24);
array[index + 1] = (byte) (value >>> 16);
array[index + 2] = (byte) (value >>> 8);
array[index + 3] = (byte) value;
}
public void setLong(int index, long value) {
array[index] = (byte) (value >>> 56);
array[index + 1] = (byte) (value >>> 48);
array[index + 2] = (byte) (value >>> 40);
array[index + 3] = (byte) (value >>> 32);
array[index + 4] = (byte) (value >>> 24);
array[index + 5] = (byte) (value >>> 16);
array[index + 6] = (byte) (value >>> 8);
array[index + 7] = (byte) value;
}
public ChannelBuffer duplicate() {
return new BigEndianHeapChannelBuffer(array, readerIndex(), writerIndex());
}
public ChannelBuffer copy(int index, int length) {
if (index < 0 || length < 0 || index + length > array.length) {
throw new IndexOutOfBoundsException("Too many bytes to copy - Need "
+ (index + length) + ", maximum is " + array.length);
}
byte[] copiedArray = new byte[length];
System.arraycopy(array, index, copiedArray, 0, length);
return new BigEndianHeapChannelBuffer(copiedArray);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ByteBufferBackedChannelBuffer.java 0000664 0000000 0000000 00000025112 12255541277 0032466 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link ChannelBuffers#directBuffer(int)}
* and {@link ChannelBuffers#wrappedBuffer(ByteBuffer)} instead of calling the
* constructor explicitly.
*/
public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer {
private final ByteBuffer buffer;
private final ByteOrder order;
private final int capacity;
/**
* Creates a new buffer which wraps the specified buffer's slice.
*/
public ByteBufferBackedChannelBuffer(ByteBuffer buffer) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
order = buffer.order();
this.buffer = buffer.slice().order(order);
capacity = buffer.remaining();
writerIndex(capacity);
}
private ByteBufferBackedChannelBuffer(ByteBufferBackedChannelBuffer buffer) {
this.buffer = buffer.buffer;
order = buffer.order;
capacity = buffer.capacity;
setIndex(buffer.readerIndex(), buffer.writerIndex());
}
public ChannelBufferFactory factory() {
if (buffer.isDirect()) {
return DirectChannelBufferFactory.getInstance(order());
} else {
return HeapChannelBufferFactory.getInstance(order());
}
}
public boolean isDirect() {
return buffer.isDirect();
}
public ByteOrder order() {
return order;
}
public int capacity() {
return capacity;
}
public boolean hasArray() {
return buffer.hasArray();
}
public byte[] array() {
return buffer.array();
}
public int arrayOffset() {
return buffer.arrayOffset();
}
public byte getByte(int index) {
return buffer.get(index);
}
public short getShort(int index) {
return buffer.getShort(index);
}
public int getUnsignedMedium(int index) {
return (getByte(index) & 0xff) << 16 |
(getByte(index + 1) & 0xff) << 8 |
getByte(index + 2) & 0xff;
}
public int getInt(int index) {
return buffer.getInt(index);
}
public long getLong(int index) {
return buffer.getLong(index);
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
if (dst instanceof ByteBufferBackedChannelBuffer) {
ByteBufferBackedChannelBuffer bbdst = (ByteBufferBackedChannelBuffer) dst;
ByteBuffer data = bbdst.buffer.duplicate();
data.limit(dstIndex + length).position(dstIndex);
getBytes(index, data);
} else if (buffer.hasArray()) {
dst.setBytes(dstIndex, buffer.array(), index + buffer.arrayOffset(), length);
} else {
dst.setBytes(dstIndex, this, index, length);
}
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
ByteBuffer data = buffer.duplicate();
try {
data.limit(index + length).position(index);
} catch (IllegalArgumentException e) {
throw new IndexOutOfBoundsException("Too many bytes to read - Need "
+ (index + length) + ", maximum is " + data.limit());
}
data.get(dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
ByteBuffer data = buffer.duplicate();
int bytesToCopy = Math.min(capacity() - index, dst.remaining());
try {
data.limit(index + bytesToCopy).position(index);
} catch (IllegalArgumentException e) {
throw new IndexOutOfBoundsException("Too many bytes to read - Need "
+ (index + bytesToCopy) + ", maximum is " + data.limit());
}
dst.put(data);
}
public void setByte(int index, int value) {
buffer.put(index, (byte) value);
}
public void setShort(int index, int value) {
buffer.putShort(index, (short) value);
}
public void setMedium(int index, int value) {
setByte(index, (byte) (value >>> 16));
setByte(index + 1, (byte) (value >>> 8));
setByte(index + 2, (byte) value);
}
public void setInt(int index, int value) {
buffer.putInt(index, value);
}
public void setLong(int index, long value) {
buffer.putLong(index, value);
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
if (src instanceof ByteBufferBackedChannelBuffer) {
ByteBufferBackedChannelBuffer bbsrc = (ByteBufferBackedChannelBuffer) src;
ByteBuffer data = bbsrc.buffer.duplicate();
data.limit(srcIndex + length).position(srcIndex);
setBytes(index, data);
} else if (buffer.hasArray()) {
src.getBytes(srcIndex, buffer.array(), index + buffer.arrayOffset(), length);
} else {
src.getBytes(srcIndex, this, index, length);
}
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
ByteBuffer data = buffer.duplicate();
data.limit(index + length).position(index);
data.put(src, srcIndex, length);
}
public void setBytes(int index, ByteBuffer src) {
ByteBuffer data = buffer.duplicate();
data.limit(index + src.remaining()).position(index);
data.put(src);
}
public void getBytes(int index, OutputStream out, int length) throws IOException {
if (length == 0) {
return;
}
if (buffer.hasArray()) {
out.write(
buffer.array(),
index + buffer.arrayOffset(),
length);
} else {
byte[] tmp = new byte[length];
((ByteBuffer) buffer.duplicate().position(index)).get(tmp);
out.write(tmp);
}
}
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
if (length == 0) {
return 0;
}
return out.write((ByteBuffer) buffer.duplicate().position(index).limit(index + length));
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
int readBytes = 0;
if (buffer.hasArray()) {
index += buffer.arrayOffset();
do {
int localReadBytes = in.read(buffer.array(), index, length);
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
readBytes += localReadBytes;
index += localReadBytes;
length -= localReadBytes;
} while (length > 0);
} else {
byte[] tmp = new byte[length];
int i = 0;
do {
int localReadBytes = in.read(tmp, i, tmp.length - i);
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
readBytes += localReadBytes;
i += readBytes;
} while (i < tmp.length);
((ByteBuffer) buffer.duplicate().position(index)).put(tmp);
}
return readBytes;
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
ByteBuffer slice = (ByteBuffer) buffer.duplicate().limit(index + length).position(index);
int readBytes = 0;
while (readBytes < length) {
int localReadBytes;
try {
localReadBytes = in.read(slice);
} catch (ClosedChannelException e) {
localReadBytes = -1;
}
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
return readBytes;
}
}
if (localReadBytes == 0) {
break;
}
readBytes += localReadBytes;
}
return readBytes;
}
public ByteBuffer toByteBuffer(int index, int length) {
if (index == 0 && length == capacity()) {
return buffer.duplicate().order(order());
} else {
return ((ByteBuffer) buffer.duplicate().position(
index).limit(index + length)).slice().order(order());
}
}
public ChannelBuffer slice(int index, int length) {
if (index == 0 && length == capacity()) {
ChannelBuffer slice = duplicate();
slice.setIndex(0, length);
return slice;
} else {
if (index >= 0 && length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
return new ByteBufferBackedChannelBuffer(
((ByteBuffer) buffer.duplicate().position(
index).limit(index + length)).order(order()));
}
}
public ChannelBuffer duplicate() {
return new ByteBufferBackedChannelBuffer(this);
}
public ChannelBuffer copy(int index, int length) {
ByteBuffer src;
try {
src = (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
} catch (IllegalArgumentException e) {
throw new IndexOutOfBoundsException("Too many bytes to read - Need "
+ (index + length));
}
ByteBuffer dst = buffer.isDirect() ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length);
dst.put(src);
dst.order(order());
dst.clear();
return new ByteBufferBackedChannelBuffer(dst);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ChannelBuffer.java 0000664 0000000 0000000 00000213422 12255541277 0027421 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
/**
* A random and sequential accessible sequence of zero or more bytes (octets).
* This interface provides an abstract view for one or more primitive byte
* arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}.
*
* Creation of a buffer
*
* It is recommended to create a new buffer using the helper methods in
* {@link ChannelBuffers} rather than calling an individual implementation's
* constructor.
*
* Random Access Indexing
*
* Just like an ordinary primitive byte array, {@link ChannelBuffer} uses
* zero-based indexing .
* It means the index of the first byte is always {@code 0} and the index of the last byte is
* always {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you
* can do the following, regardless of its internal implementation:
*
*
* {@link ChannelBuffer} buffer = ...;
* for (int i = 0; i < buffer.capacity(); i ++) {
* byte b = buffer.getByte(i);
* System.out.println((char) b);
* }
*
*
* Sequential Access Indexing
*
* {@link ChannelBuffer} provides two pointer variables to support sequential
* read and write operations - {@link #readerIndex() readerIndex} for a read
* operation and {@link #writerIndex() writerIndex} for a write operation
* respectively. The following diagram shows how a buffer is segmented into
* three areas by the two pointers:
*
*
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* | | (CONTENT) | |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* Readable bytes (the actual content)
*
* This segment is where the actual data is stored. Any operation whose name
* starts with {@code read} or {@code skip} will get or skip the data at the
* current {@link #readerIndex() readerIndex} and increase it by the number of
* read bytes. If the argument of the read operation is also a
* {@link ChannelBuffer} and no destination index is specified, the specified
* buffer's {@link #readerIndex() readerIndex} is increased together.
*
* If there's not enough content left, {@link IndexOutOfBoundsException} is
* raised. The default value of newly allocated, wrapped or copied buffer's
* {@link #readerIndex() readerIndex} is {@code 0}.
*
*
* // Iterates the readable bytes of a buffer.
* {@link ChannelBuffer} buffer = ...;
* while (buffer.readable()) {
* System.out.println(buffer.readByte());
* }
*
*
* Writable bytes
*
* This segment is a undefined space which needs to be filled. Any operation
* whose name ends with {@code write} will write the data at the current
* {@link #writerIndex() writerIndex} and increase it by the number of written
* bytes. If the argument of the write operation is also a {@link ChannelBuffer},
* and no source index is specified, the specified buffer's
* {@link #readerIndex() readerIndex} is increased together.
*
* If there's not enough writable bytes left, {@link IndexOutOfBoundsException}
* is raised. The default value of newly allocated buffer's
* {@link #writerIndex() writerIndex} is {@code 0}. The default value of
* wrapped or copied buffer's {@link #writerIndex() writerIndex} is the
* {@link #capacity() capacity} of the buffer.
*
*
* // Fills the writable bytes of a buffer with random integers.
* {@link ChannelBuffer} buffer = ...;
* while (buffer.writableBytes() >= 4) {
* buffer.writeInt(random.nextInt());
* }
*
*
* Discardable bytes
*
* This segment contains the bytes which were read already by a read operation.
* Initially, the size of this segment is {@code 0}, but its size increases up
* to the {@link #writerIndex() writerIndex} as read operations are executed.
* The read bytes can be discarded by calling {@link #discardReadBytes()} to
* reclaim unused area as depicted by the following diagram:
*
*
* BEFORE discardReadBytes()
*
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* AFTER discardReadBytes()
*
* +------------------+--------------------------------------+
* | readable bytes | writable bytes (got more space) |
* +------------------+--------------------------------------+
* | | |
* readerIndex (0) <= writerIndex (decreased) <= capacity
*
*
* Please note that there is no guarantee about the content of writable bytes
* after calling {@link #discardReadBytes()}. The writable bytes will not be
* moved in most cases and could even be filled with completely different data
* depending on the underlying buffer implementation.
*
* Clearing the buffer indexes
*
* You can set both {@link #readerIndex() readerIndex} and
* {@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}.
* It does not clear the buffer content (e.g. filling with {@code 0}) but just
* clears the two pointers. Please also note that the semantic of this
* operation is different from {@link ByteBuffer#clear()}.
*
*
* BEFORE clear()
*
* +-------------------+------------------+------------------+
* | discardable bytes | readable bytes | writable bytes |
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* AFTER clear()
*
* +---------------------------------------------------------+
* | writable bytes (got more space) |
* +---------------------------------------------------------+
* | |
* 0 = readerIndex = writerIndex <= capacity
*
*
* Search operations
*
* Various {@link #indexOf(int, int, byte)} methods help you locate an index of
* a value which meets a certain criteria. Complicated dynamic sequential
* search can be done with {@link ChannelBufferIndexFinder} as well as simple
* static single byte search.
*
* If you are decoding variable length data such as NUL-terminated string, you
* will find {@link #bytesBefore(byte)} also useful.
*
*
Mark and reset
*
* There are two marker indexes in every buffer. One is for storing
* {@link #readerIndex() readerIndex} and the other is for storing
* {@link #writerIndex() writerIndex}. You can always reposition one of the
* two indexes by calling a reset method. It works in a similar fashion to
* the mark and reset methods in {@link InputStream} except that there's no
* {@code readlimit}.
*
* Derived buffers
*
* You can create a view of an existing buffer by calling either
* {@link #duplicate()}, {@link #slice()} or {@link #slice(int, int)}.
* A derived buffer will have an independent {@link #readerIndex() readerIndex},
* {@link #writerIndex() writerIndex} and marker indexes, while it shares
* other internal data representation, just like a NIO buffer does.
*
* In case a completely fresh copy of an existing buffer is required, please
* call {@link #copy()} method instead.
*
*
Conversion to existing JDK types
*
* Byte array
*
* If a {@link ChannelBuffer} is backed by a byte array (i.e. {@code byte[]}),
* you can access it directly via the {@link #array()} method. To determine
* if a buffer is backed by a byte array, {@link #hasArray()} should be used.
*
* NIO Buffers
*
* Various {@link #toByteBuffer()} and {@link #toByteBuffers()} methods convert
* a {@link ChannelBuffer} into one or more NIO buffers. These methods avoid
* buffer allocation and memory copy whenever possible, but there's no
* guarantee that memory copy will not be involved.
*
* Strings
*
* Various {@link #toString(String)} methods convert a {@link ChannelBuffer}
* into a {@link String}. Please note that {@link #toString()} is not a
* conversion method.
*
* I/O Streams
*
* Please refer to {@link ChannelBufferInputStream} and
* {@link ChannelBufferOutputStream}.
*
* @apiviz.landmark
*/
public interface ChannelBuffer extends Comparable {
/**
* Returns the factory which creates a {@link ChannelBuffer} whose
* type and default {@link ByteOrder} are same with this buffer.
*/
ChannelBufferFactory factory();
/**
* Returns the number of bytes (octets) this buffer can contain.
*/
int capacity();
/**
* Returns the endianness
* of this buffer.
*/
ByteOrder order();
/**
* Returns {@code true} if and only if this buffer is backed by an
* NIO direct buffer.
*/
boolean isDirect();
/**
* Returns the {@code readerIndex} of this buffer.
*/
int readerIndex();
/**
* Sets the {@code readerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code readerIndex} is
* less than {@code 0} or
* greater than {@code this.writerIndex}
*/
void readerIndex(int readerIndex);
/**
* Returns the {@code writerIndex} of this buffer.
*/
int writerIndex();
/**
* Sets the {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code writerIndex} is
* less than {@code this.readerIndex} or
* greater than {@code this.capacity}
*/
void writerIndex(int writerIndex);
/**
* Sets the {@code readerIndex} and {@code writerIndex} of this buffer
* in one shot. This method is useful when you have to worry about the
* invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)}
* methods. For example, the following code will fail:
*
*
* // Create a buffer whose readerIndex, writerIndex and capacity are
* // 0, 0 and 8 respectively.
* {@link ChannelBuffer} buf = {@link ChannelBuffers}.buffer(8);
*
* // IndexOutOfBoundsException is thrown because the specified
* // readerIndex (2) cannot be greater than the current writerIndex (0).
* buf.readerIndex(2);
* buf.writerIndex(4);
*
*
* The following code will also fail:
*
*
* // Create a buffer whose readerIndex, writerIndex and capacity are
* // 0, 8 and 8 respectively.
* {@link ChannelBuffer} buf = {@link ChannelBuffers}.wrappedBuffer(new byte[8]);
*
* // readerIndex becomes 8.
* buf.readLong();
*
* // IndexOutOfBoundsException is thrown because the specified
* // writerIndex (4) cannot be less than the current readerIndex (8).
* buf.writerIndex(4);
* buf.readerIndex(2);
*
*
* By contrast, this method guarantees that it never
* throws an {@link IndexOutOfBoundsException} as long as the specified
* indexes meet basic constraints, regardless what the current index
* values of the buffer are:
*
*
* // No matter what the current state of the buffer is, the following
* // call always succeeds as long as the capacity of the buffer is not
* // less than 4.
* buf.setIndex(2, 4);
*
*
* @throws IndexOutOfBoundsException
* if the specified {@code readerIndex} is less than 0,
* if the specified {@code writerIndex} is less than the specified
* {@code readerIndex} or if the specified {@code writerIndex} is
* greater than {@code this.capacity}
*/
void setIndex(int readerIndex, int writerIndex);
/**
* Returns the number of readable bytes which is equal to
* {@code (this.writerIndex - this.readerIndex)}.
*/
int readableBytes();
/**
* Returns the number of writable bytes which is equal to
* {@code (this.capacity - this.writerIndex)}.
*/
int writableBytes();
/**
* Returns {@code true}
* if and only if {@code (this.writerIndex - this.readerIndex)} is greater
* than {@code 0}.
*/
boolean readable();
/**
* Returns {@code true}
* if and only if {@code (this.capacity - this.writerIndex)} is greater
* than {@code 0}.
*/
boolean writable();
/**
* Sets the {@code readerIndex} and {@code writerIndex} of this buffer to
* {@code 0}.
* This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}.
*
* Please note that the behavior of this method is different
* from that of NIO buffer, which sets the {@code limit} to
* the {@code capacity} of the buffer.
*/
void clear();
/**
* Marks the current {@code readerIndex} in this buffer. You can
* reposition the current {@code readerIndex} to the marked
* {@code readerIndex} by calling {@link #resetReaderIndex()}.
* The initial value of the marked {@code readerIndex} is {@code 0}.
*/
void markReaderIndex();
/**
* Repositions the current {@code readerIndex} to the marked
* {@code readerIndex} in this buffer.
*
* @throws IndexOutOfBoundsException
* if the current {@code writerIndex} is less than the marked
* {@code readerIndex}
*/
void resetReaderIndex();
/**
* Marks the current {@code writerIndex} in this buffer. You can
* reposition the current {@code writerIndex} to the marked
* {@code writerIndex} by calling {@link #resetWriterIndex()}.
* The initial value of the marked {@code writerIndex} is {@code 0}.
*/
void markWriterIndex();
/**
* Repositions the current {@code writerIndex} to the marked
* {@code writerIndex} in this buffer.
*
* @throws IndexOutOfBoundsException
* if the current {@code readerIndex} is greater than the marked
* {@code writerIndex}
*/
void resetWriterIndex();
/**
* Discards the bytes between the 0th index and {@code readerIndex}.
* It moves the bytes between {@code readerIndex} and {@code writerIndex}
* to the 0th index, and sets {@code readerIndex} and {@code writerIndex}
* to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively.
*
* Please refer to the class documentation for more detailed explanation.
*/
void discardReadBytes();
/**
* Makes sure the number of {@linkplain #writableBytes() the writable bytes}
* is equal to or greater than the specified value. If there is enough
* writable bytes in this buffer, this method returns with no side effect.
* Otherwise:
*
* a non-dynamic buffer will throw an {@link IndexOutOfBoundsException}.
* a dynamic buffer will expand its capacity so that the number of the
* {@link #writableBytes() writable bytes} becomes equal to or greater
* than the specified value. The expansion involves the reallocation of
* the internal buffer and consequently memory copy.
*
*
* @param writableBytes
* the expected minimum number of writable bytes
* @throws IndexOutOfBoundsException
* if {@linkplain #writableBytes() the writable bytes} of this
* buffer is less than the specified value and if this buffer is
* not a dynamic buffer
*/
void ensureWritableBytes(int writableBytes);
/**
* Gets a byte at the specified absolute {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 1} is greater than {@code this.capacity}
*/
byte getByte(int index);
/**
* Gets an unsigned byte at the specified absolute {@code index} in this
* buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 1} is greater than {@code this.capacity}
*/
short getUnsignedByte(int index);
/**
* Gets a 16-bit short integer at the specified absolute {@code index} in
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
short getShort(int index);
/**
* Gets an unsigned 16-bit short integer at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
int getUnsignedShort(int index);
/**
* Gets a 24-bit medium integer at the specified absolute {@code index} in
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 3} is greater than {@code this.capacity}
*/
int getMedium(int index);
/**
* Gets an unsigned 24-bit medium integer at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 3} is greater than {@code this.capacity}
*/
int getUnsignedMedium(int index);
/**
* Gets a 32-bit integer at the specified absolute {@code index} in
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
int getInt(int index);
/**
* Gets an unsigned 32-bit integer at the specified absolute {@code index}
* in this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
long getUnsignedInt(int index);
/**
* Gets a 64-bit long integer at the specified absolute {@code index} in
* this buffer. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
long getLong(int index);
/**
* Gets a 2-byte UTF-16 character at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
char getChar(int index);
/**
* Gets a 32-bit floating point number at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
float getFloat(int index);
/**
* Gets a 64-bit floating point number at the specified absolute
* {@code index} in this buffer. This method does not modify
* {@code readerIndex} or {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
double getDouble(int index);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index} until the destination becomes
* non-writable. This method is basically same with
* {@link #getBytes(int, ChannelBuffer, int, int)}, except that this
* method increases the {@code writerIndex} of the destination by the
* number of the transferred bytes while
* {@link #getBytes(int, ChannelBuffer, int, int)} does not.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* the source buffer (i.e. {@code this}).
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + dst.writableBytes} is greater than
* {@code this.capacity}
*/
void getBytes(int index, ChannelBuffer dst);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}. This method is basically same
* with {@link #getBytes(int, ChannelBuffer, int, int)}, except that this
* method increases the {@code writerIndex} of the destination by the
* number of the transferred bytes while
* {@link #getBytes(int, ChannelBuffer, int, int)} does not.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* the source buffer (i.e. {@code this}).
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code length} is greater than {@code dst.writableBytes}
*/
void getBytes(int index, ChannelBuffer dst, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex}
* of both the source (i.e. {@code this}) and the destination.
*
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code dstIndex} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code dstIndex + length} is greater than
* {@code dst.capacity}
*/
void getBytes(int index, ChannelBuffer dst, int dstIndex, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + dst.length} is greater than
* {@code this.capacity}
*/
void getBytes(int index, byte[] dst);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex}
* of this buffer.
*
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code dstIndex} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code dstIndex + length} is greater than
* {@code dst.length}
*/
void getBytes(int index, byte[] dst, int dstIndex, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index} until the destination's position
* reaches its limit.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer while the destination's {@code position} will be increased.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + dst.remaining()} is greater than
* {@code this.capacity}
*/
void getBytes(int index, ByteBuffer dst);
/**
* Transfers this buffer's data to the specified stream starting at the
* specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than
* {@code this.capacity}
* @throws IOException
* if the specified stream threw an exception during I/O
*/
void getBytes(int index, OutputStream out, int length) throws IOException;
/**
* Transfers this buffer's data to the specified channel starting at the
* specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than
* {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
int getBytes(int index, GatheringByteChannel out, int length) throws IOException;
/**
* Sets the specified byte at the specified absolute {@code index} in this
* buffer. The 24 high-order bits of the specified value are ignored.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 1} is greater than {@code this.capacity}
*/
void setByte(int index, int value);
/**
* Sets the specified 16-bit short integer at the specified absolute
* {@code index} in this buffer. The 16 high-order bits of the specified
* value are ignored.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
void setShort(int index, int value);
/**
* Sets the specified 24-bit medium integer at the specified absolute
* {@code index} in this buffer. Please note that the most significant
* byte is ignored in the specified value.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 3} is greater than {@code this.capacity}
*/
void setMedium(int index, int value);
/**
* Sets the specified 32-bit integer at the specified absolute
* {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
void setInt(int index, int value);
/**
* Sets the specified 64-bit long integer at the specified absolute
* {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
void setLong(int index, long value);
/**
* Sets the specified 2-byte UTF-16 character at the specified absolute
* {@code index} in this buffer.
* The 16 high-order bits of the specified value are ignored.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 2} is greater than {@code this.capacity}
*/
void setChar(int index, int value);
/**
* Sets the specified 32-bit floating-point number at the specified
* absolute {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
void setFloat(int index, float value);
/**
* Sets the specified 64-bit floating-point number at the specified
* absolute {@code index} in this buffer.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
void setDouble(int index, double value);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index} until the source buffer becomes
* unreadable. This method is basically same with
* {@link #setBytes(int, ChannelBuffer, int, int)}, except that this
* method increases the {@code readerIndex} of the source buffer by
* the number of the transferred bytes while
* {@link #setBytes(int, ChannelBuffer, int, int)} does not.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* the source buffer (i.e. {@code this}).
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + src.readableBytes} is greater than
* {@code this.capacity}
*/
void setBytes(int index, ChannelBuffer src);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index}. This method is basically same
* with {@link #setBytes(int, ChannelBuffer, int, int)}, except that this
* method increases the {@code readerIndex} of the source buffer by
* the number of the transferred bytes while
* {@link #setBytes(int, ChannelBuffer, int, int)} does not.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* the source buffer (i.e. {@code this}).
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code length} is greater than {@code src.readableBytes}
*/
void setBytes(int index, ChannelBuffer src, int length);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex}
* of both the source (i.e. {@code this}) and the destination.
*
* @param srcIndex the first index of the source
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code srcIndex} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code srcIndex + length} is greater than
* {@code src.capacity}
*/
void setBytes(int index, ChannelBuffer src, int srcIndex, int length);
/**
* Transfers the specified source array's data to this buffer starting at
* the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + src.length} is greater than
* {@code this.capacity}
*/
void setBytes(int index, byte[] src);
/**
* Transfers the specified source array's data to this buffer starting at
* the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0},
* if the specified {@code srcIndex} is less than {@code 0},
* if {@code index + length} is greater than
* {@code this.capacity}, or
* if {@code srcIndex + length} is greater than {@code src.length}
*/
void setBytes(int index, byte[] src, int srcIndex, int length);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index} until the source buffer's position
* reaches its limit.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + src.remaining()} is greater than
* {@code this.capacity}
*/
void setBytes(int index, ByteBuffer src);
/**
* Transfers the content of the specified source stream to this buffer
* starting at the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @param length the number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel.
* {@code -1} if the specified channel is closed.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than {@code this.capacity}
* @throws IOException
* if the specified stream threw an exception during I/O
*/
int setBytes(int index, InputStream in, int length) throws IOException;
/**
* Transfers the content of the specified source channel to this buffer
* starting at the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel.
* {@code -1} if the specified channel is closed.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
int setBytes(int index, ScatteringByteChannel in, int length) throws IOException;
/**
* Fills this buffer with NUL (0x00) starting at the specified
* absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @param length the number of NUL s to write to the buffer
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than {@code this.capacity}
*/
void setZero(int index, int length);
/**
* Gets a byte at the current {@code readerIndex} and increases
* the {@code readerIndex} by {@code 1} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 1}
*/
byte readByte();
/**
* Gets an unsigned byte at the current {@code readerIndex} and increases
* the {@code readerIndex} by {@code 1} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 1}
*/
short readUnsignedByte();
/**
* Gets a 16-bit short integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
*/
short readShort();
/**
* Gets an unsigned 16-bit short integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
*/
int readUnsignedShort();
/**
* Gets a 24-bit medium integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 3} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 3}
*/
int readMedium();
/**
* Gets an unsigned 24-bit medium integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 3} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 3}
*/
int readUnsignedMedium();
/**
* Gets a 32-bit integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
int readInt();
/**
* Gets an unsigned 32-bit integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
long readUnsignedInt();
/**
* Gets a 64-bit integer at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
*/
long readLong();
/**
* Gets a 2-byte UTF-16 character at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 2} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 2}
*/
char readChar();
/**
* Gets a 32-bit floating point number at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
float readFloat();
/**
* Gets a 64-bit floating point number at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
*/
double readDouble();
/**
* Transfers this buffer's data to a newly created buffer starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}).
* The returned buffer's {@code readerIndex} and {@code writerIndex} are
* {@code 0} and {@code length} respectively.
*
* @param length the number of bytes to transfer
*
* @return the newly created buffer which contains the transferred bytes
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
ChannelBuffer readBytes(int length);
/**
* @deprecated Use {@link #bytesBefore(ChannelBufferIndexFinder)} and {@link #readBytes(int)} instead.
*/
@Deprecated
ChannelBuffer readBytes(ChannelBufferIndexFinder indexFinder);
/**
* Returns a new slice of this buffer's sub-region starting at the current
* {@code readerIndex} and increases the {@code readerIndex} by the size
* of the new slice (= {@code length}).
*
* @param length the size of the new slice
*
* @return the newly created slice
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
ChannelBuffer readSlice(int length);
/**
* @deprecated Use {@link #bytesBefore(ChannelBufferIndexFinder)} and {@link #readSlice(int)} instead.
*/
@Deprecated
ChannelBuffer readSlice(ChannelBufferIndexFinder indexFinder);
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} until the destination becomes
* non-writable, and increases the {@code readerIndex} by the number of the
* transferred bytes. This method is basically same with
* {@link #readBytes(ChannelBuffer, int, int)}, except that this method
* increases the {@code writerIndex} of the destination by the number of
* the transferred bytes while {@link #readBytes(ChannelBuffer, int, int)}
* does not.
*
* @throws IndexOutOfBoundsException
* if {@code dst.writableBytes} is greater than
* {@code this.readableBytes}
*/
void readBytes(ChannelBuffer dst);
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}). This method
* is basically same with {@link #readBytes(ChannelBuffer, int, int)},
* except that this method increases the {@code writerIndex} of the
* destination by the number of the transferred bytes (= {@code length})
* while {@link #readBytes(ChannelBuffer, int, int)} does not.
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes} or
* if {@code length} is greater than {@code dst.writableBytes}
*/
void readBytes(ChannelBuffer dst, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}).
*
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code dstIndex} is less than {@code 0},
* if {@code length} is greater than {@code this.readableBytes}, or
* if {@code dstIndex + length} is greater than
* {@code dst.capacity}
*/
void readBytes(ChannelBuffer dst, int dstIndex, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code dst.length}).
*
* @throws IndexOutOfBoundsException
* if {@code dst.length} is greater than {@code this.readableBytes}
*/
void readBytes(byte[] dst);
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
* by the number of the transferred bytes (= {@code length}).
*
* @param dstIndex the first index of the destination
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code dstIndex} is less than {@code 0},
* if {@code length} is greater than {@code this.readableBytes}, or
* if {@code dstIndex + length} is greater than {@code dst.length}
*/
void readBytes(byte[] dst, int dstIndex, int length);
/**
* Transfers this buffer's data to the specified destination starting at
* the current {@code readerIndex} until the destination's position
* reaches its limit, and increases the {@code readerIndex} by the
* number of the transferred bytes.
*
* @throws IndexOutOfBoundsException
* if {@code dst.remaining()} is greater than
* {@code this.readableBytes}
*/
void readBytes(ByteBuffer dst);
/**
* Transfers this buffer's data to the specified stream starting at the
* current {@code readerIndex}.
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
* @throws IOException
* if the specified stream threw an exception during I/O
*/
void readBytes(OutputStream out, int length) throws IOException;
/**
* Transfers this buffer's data to the specified stream starting at the
* current {@code readerIndex}.
*
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
int readBytes(GatheringByteChannel out, int length) throws IOException;
/**
* Increases the current {@code readerIndex} by the specified
* {@code length} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
void skipBytes(int length);
/**
* @deprecated Use {@link #bytesBefore(ChannelBufferIndexFinder)} and {@link #skipBytes(int)} instead.
*/
@Deprecated
int skipBytes(ChannelBufferIndexFinder indexFinder);
/**
* Sets the specified byte at the current {@code writerIndex}
* and increases the {@code writerIndex} by {@code 1} in this buffer.
* The 24 high-order bits of the specified value are ignored.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 1}
*/
void writeByte(int value);
/**
* Sets the specified 16-bit short integer at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 2}
* in this buffer. The 16 high-order bits of the specified value are ignored.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 2}
*/
void writeShort(int value);
/**
* Sets the specified 24-bit medium integer at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 3}
* in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 3}
*/
void writeMedium(int value);
/**
* Sets the specified 32-bit integer at the current {@code writerIndex}
* and increases the {@code writerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 4}
*/
void writeInt(int value);
/**
* Sets the specified 64-bit long integer at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
* in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 8}
*/
void writeLong(long value);
/**
* Sets the specified 2-byte UTF-16 character at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 2}
* in this buffer. The 16 high-order bits of the specified value are ignored.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 2}
*/
void writeChar(int value);
/**
* Sets the specified 32-bit floating point number at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 4}
* in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 4}
*/
void writeFloat(float value);
/**
* Sets the specified 64-bit floating point number at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
* in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 8}
*/
void writeDouble(double value);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} until the source buffer becomes
* unreadable, and increases the {@code writerIndex} by the number of
* the transferred bytes. This method is basically same with
* {@link #writeBytes(ChannelBuffer, int, int)}, except that this method
* increases the {@code readerIndex} of the source buffer by the number of
* the transferred bytes while {@link #writeBytes(ChannelBuffer, int, int)}
* does not.
*
* @throws IndexOutOfBoundsException
* if {@code src.readableBytes} is greater than
* {@code this.writableBytes}
*/
void writeBytes(ChannelBuffer src);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code length}). This method
* is basically same with {@link #writeBytes(ChannelBuffer, int, int)},
* except that this method increases the {@code readerIndex} of the source
* buffer by the number of the transferred bytes (= {@code length}) while
* {@link #writeBytes(ChannelBuffer, int, int)} does not.
*
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.writableBytes} or
* if {@code length} is greater then {@code src.readableBytes}
*/
void writeBytes(ChannelBuffer src, int length);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code length}).
*
* @param srcIndex the first index of the source
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code srcIndex} is less than {@code 0},
* if {@code srcIndex + length} is greater than
* {@code src.capacity}, or
* if {@code length} is greater than {@code this.writableBytes}
*/
void writeBytes(ChannelBuffer src, int srcIndex, int length);
/**
* Transfers the specified source array's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code src.length}).
*
* @throws IndexOutOfBoundsException
* if {@code src.length} is greater than {@code this.writableBytes}
*/
void writeBytes(byte[] src);
/**
* Transfers the specified source array's data to this buffer starting at
* the current {@code writerIndex} and increases the {@code writerIndex}
* by the number of the transferred bytes (= {@code length}).
*
* @param srcIndex the first index of the source
* @param length the number of bytes to transfer
*
* @throws IndexOutOfBoundsException
* if the specified {@code srcIndex} is less than {@code 0},
* if {@code srcIndex + length} is greater than
* {@code src.length}, or
* if {@code length} is greater than {@code this.writableBytes}
*/
void writeBytes(byte[] src, int srcIndex, int length);
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} until the source buffer's position
* reaches its limit, and increases the {@code writerIndex} by the
* number of the transferred bytes.
*
* @throws IndexOutOfBoundsException
* if {@code src.remaining()} is greater than
* {@code this.writableBytes}
*/
void writeBytes(ByteBuffer src);
/**
* Transfers the content of the specified stream to this buffer
* starting at the current {@code writerIndex} and increases the
* {@code writerIndex} by the number of the transferred bytes.
*
* @param length the number of bytes to transfer
*
* @return the actual number of bytes read in from the specified stream
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.writableBytes}
* @throws IOException
* if the specified stream threw an exception during I/O
*/
int writeBytes(InputStream in, int length) throws IOException;
/**
* Transfers the content of the specified channel to this buffer
* starting at the current {@code writerIndex} and increases the
* {@code writerIndex} by the number of the transferred bytes.
*
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.writableBytes}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
int writeBytes(ScatteringByteChannel in, int length) throws IOException;
/**
* Fills this buffer with NUL (0x00) starting at the current
* {@code writerIndex} and increases the {@code writerIndex} by the
* specified {@code length}.
*
* @param length the number of NUL s to write to the buffer
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.writableBytes}
*/
void writeZero(int length);
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search takes place from the specified {@code fromIndex}
* (inclusive) to the specified {@code toIndex} (exclusive).
*
* If {@code fromIndex} is greater than {@code toIndex}, the search is
* performed in a reversed order.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the absolute index of the first occurrence if found.
* {@code -1} otherwise.
*/
int indexOf(int fromIndex, int toIndex, byte value);
/**
* Locates the first place where the specified {@code indexFinder}
* returns {@code true}. The search takes place from the specified
* {@code fromIndex} (inclusive) to the specified {@code toIndex}
* (exclusive).
*
* If {@code fromIndex} is greater than {@code toIndex}, the search is
* performed in a reversed order.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the absolute index where the specified {@code indexFinder}
* returned {@code true}. {@code -1} if the {@code indexFinder}
* did not return {@code true} at all.
*/
int indexOf(int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder);
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search takes place from the current {@code readerIndex}
* (inclusive) to the current {@code writerIndex} (exclusive).
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the current {@code readerIndex}
* and the first occurrence if found. {@code -1} otherwise.
*/
int bytesBefore(byte value);
/**
* Locates the first place where the specified {@code indexFinder} returns
* {@code true}. The search takes place from the current {@code readerIndex}
* (inclusive) to the current {@code writerIndex}.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the current {@code readerIndex}
* and the first place where the {@code indexFinder} returned
* {@code true}. {@code -1} if the {@code indexFinder} did not
* return {@code true} at all.
*/
int bytesBefore(ChannelBufferIndexFinder indexFinder);
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search starts from the current {@code readerIndex}
* (inclusive) and lasts for the specified {@code length}.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the current {@code readerIndex}
* and the first occurrence if found. {@code -1} otherwise.
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
int bytesBefore(int length, byte value);
/**
* Locates the first place where the specified {@code indexFinder} returns
* {@code true}. The search starts the current {@code readerIndex}
* (inclusive) and lasts for the specified {@code length}.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the current {@code readerIndex}
* and the first place where the {@code indexFinder} returned
* {@code true}. {@code -1} if the {@code indexFinder} did not
* return {@code true} at all.
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
*/
int bytesBefore(int length, ChannelBufferIndexFinder indexFinder);
/**
* Locates the first occurrence of the specified {@code value} in this
* buffer. The search starts from the specified {@code index} (inclusive)
* and lasts for the specified {@code length}.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the specified {@code index}
* and the first occurrence if found. {@code -1} otherwise.
*
* @throws IndexOutOfBoundsException
* if {@code index + length} is greater than {@code this.capacity}
*/
int bytesBefore(int index, int length, byte value);
/**
* Locates the first place where the specified {@code indexFinder} returns
* {@code true}. The search starts the specified {@code index} (inclusive)
* and lasts for the specified {@code length}.
*
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @return the number of bytes between the specified {@code index}
* and the first place where the {@code indexFinder} returned
* {@code true}. {@code -1} if the {@code indexFinder} did not
* return {@code true} at all.
*
* @throws IndexOutOfBoundsException
* if {@code index + length} is greater than {@code this.capacity}
*/
int bytesBefore(int index, int length, ChannelBufferIndexFinder indexFinder);
/**
* Returns a copy of this buffer's readable bytes. Modifying the content
* of the returned buffer or this buffer does not affect each other at all.
* This method is identical to {@code buf.copy(buf.readerIndex(), buf.readableBytes())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ChannelBuffer copy();
/**
* Returns a copy of this buffer's sub-region. Modifying the content of
* the returned buffer or this buffer does not affect each other at all.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ChannelBuffer copy(int index, int length);
/**
* Returns a slice of this buffer's readable bytes. Modifying the content
* of the returned buffer or this buffer affects each other's content
* while they maintain separate indexes and marks. This method is
* identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ChannelBuffer slice();
/**
* Returns a slice of this buffer's sub-region. Modifying the content of
* the returned buffer or this buffer affects each other's content while
* they maintain separate indexes and marks.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ChannelBuffer slice(int index, int length);
/**
* Returns a buffer which shares the whole region of this buffer.
* Modifying the content of the returned buffer or this buffer affects
* each other's content while they maintain separate indexes and marks.
* This method is identical to {@code buf.slice(0, buf.capacity())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ChannelBuffer duplicate();
/**
* Converts this buffer's readable bytes into a NIO buffer. The returned
* buffer might or might not share the content with this buffer, while
* they have separate indexes and marks. This method is identical to
* {@code buf.toByteBuffer(buf.readerIndex(), buf.readableBytes())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ByteBuffer toByteBuffer();
/**
* Converts this buffer's sub-region into a NIO buffer. The returned
* buffer might or might not share the content with this buffer, while
* they have separate indexes and marks.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ByteBuffer toByteBuffer(int index, int length);
/**
* Converts this buffer's readable bytes into an array of NIO buffers.
* The returned buffers might or might not share the content with this
* buffer, while they have separate indexes and marks. This method is
* identical to {@code buf.toByteBuffers(buf.readerIndex(), buf.readableBytes())}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ByteBuffer[] toByteBuffers();
/**
* Converts this buffer's sub-region into an array of NIO buffers.
* The returned buffers might or might not share the content with this
* buffer, while they have separate indexes and marks.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*/
ByteBuffer[] toByteBuffers(int index, int length);
/**
* Returns {@code true} if and only if this buffer has a backing byte array.
* If this method returns true, you can safely call {@link #array()} and
* {@link #arrayOffset()}.
*/
boolean hasArray();
/**
* Returns the backing byte array of this buffer.
*
* @throws UnsupportedOperationException
* if there no accessible backing byte array
*/
byte[] array();
/**
* Returns the offset of the first byte within the backing byte array of
* this buffer.
*
* @throws UnsupportedOperationException
* if there no accessible backing byte array
*/
int arrayOffset();
/**
* Decodes this buffer's readable bytes into a string with the specified
* character set name. This method is identical to
* {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws UnsupportedCharsetException
* if the specified character set name is not supported by the
* current VM
*/
String toString(Charset charset);
/**
* Decodes this buffer's sub-region into a string with the specified
* character set. This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*/
String toString(int index, int length, Charset charset);
/**
* @deprecated Use {@link #toString(Charset)} instead.
*/
@Deprecated
String toString(String charsetName);
/**
* @deprecated Use {@link #bytesBefore(ChannelBufferIndexFinder)} and {@link #toString(int, int, Charset)} instead.
*/
@Deprecated
String toString(
String charsetName, ChannelBufferIndexFinder terminatorFinder);
/**
* @deprecated Use {@link #bytesBefore(int, int, ChannelBufferIndexFinder)} and
* {@link #toString(int, int, Charset)} instead.
*/
@Deprecated
String toString(int index, int length, String charsetName);
/**
* @deprecated Use {@link #bytesBefore(int, int, ChannelBufferIndexFinder)} and
* {@link #toString(int, int, Charset)} instead.
*/
@Deprecated
String toString(
int index, int length, String charsetName,
ChannelBufferIndexFinder terminatorFinder);
/**
* Returns a hash code which was calculated from the content of this
* buffer. If there's a byte array which is
* {@linkplain #equals(Object) equal to} this array, both arrays should
* return the same value.
*/
int hashCode();
/**
* Determines if the content of the specified buffer is identical to the
* content of this array. 'Identical' here means:
*
* the size of the contents of the two buffers are same and
* every single byte of the content of the two buffers are same.
*
* Please note that it does not compare {@link #readerIndex()} nor
* {@link #writerIndex()}. This method also returns {@code false} for
* {@code null} and an object which is not an instance of
* {@link ChannelBuffer} type.
*/
boolean equals(Object obj);
/**
* Compares the content of the specified buffer to the content of this
* buffer. Comparison is performed in the same manner with the string
* comparison functions of various languages such as {@code strcmp},
* {@code memcmp} and {@link String#compareTo(String)}.
*/
int compareTo(ChannelBuffer buffer);
/**
* Returns the string representation of this buffer. This method does not
* necessarily return the whole content of the buffer but returns
* the values of the key properties such as {@link #readerIndex()},
* {@link #writerIndex()} and {@link #capacity()}.
*/
String toString();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ChannelBufferFactory.java 0000664 0000000 0000000 00000010406 12255541277 0030746 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* A factory that creates or pools {@link ChannelBuffer}s.
*/
public interface ChannelBufferFactory {
/**
* Returns a {@link ChannelBuffer} with the specified {@code capacity}.
* This method is identical to {@code getBuffer(getDefaultOrder(), capacity)}.
*
* @param capacity the capacity of the returned {@link ChannelBuffer}
* @return a {@link ChannelBuffer} with the specified {@code capacity},
* whose {@code readerIndex} and {@code writerIndex} are {@code 0}
*/
ChannelBuffer getBuffer(int capacity);
/**
* Returns a {@link ChannelBuffer} with the specified {@code endianness}
* and {@code capacity}.
*
* @param endianness the endianness of the returned {@link ChannelBuffer}
* @param capacity the capacity of the returned {@link ChannelBuffer}
* @return a {@link ChannelBuffer} with the specified {@code endianness} and
* {@code capacity}, whose {@code readerIndex} and {@code writerIndex}
* are {@code 0}
*/
ChannelBuffer getBuffer(ByteOrder endianness, int capacity);
/**
* Returns a {@link ChannelBuffer} whose content is equal to the sub-region
* of the specified {@code array}. Depending on the factory implementation,
* the returned buffer could wrap the {@code array} or create a new copy of
* the {@code array}.
* This method is identical to {@code getBuffer(getDefaultOrder(), array, offset, length)}.
*
* @param array the byte array
* @param offset the offset of the byte array
* @param length the length of the byte array
*
* @return a {@link ChannelBuffer} with the specified content,
* whose {@code readerIndex} and {@code writerIndex}
* are {@code 0} and {@code (length - offset)} respectively
*/
ChannelBuffer getBuffer(byte[] array, int offset, int length);
/**
* Returns a {@link ChannelBuffer} whose content is equal to the sub-region
* of the specified {@code array}. Depending on the factory implementation,
* the returned buffer could wrap the {@code array} or create a new copy of
* the {@code array}.
*
* @param endianness the endianness of the returned {@link ChannelBuffer}
* @param array the byte array
* @param offset the offset of the byte array
* @param length the length of the byte array
*
* @return a {@link ChannelBuffer} with the specified content,
* whose {@code readerIndex} and {@code writerIndex}
* are {@code 0} and {@code (length - offset)} respectively
*/
ChannelBuffer getBuffer(ByteOrder endianness, byte[] array, int offset, int length);
/**
* Returns a {@link ChannelBuffer} whose content is equal to the sub-region
* of the specified {@code nioBuffer}. Depending on the factory
* implementation, the returned buffer could wrap the {@code nioBuffer} or
* create a new copy of the {@code nioBuffer}.
*
* @param nioBuffer the NIO {@link ByteBuffer}
*
* @return a {@link ChannelBuffer} with the specified content,
* whose {@code readerIndex} and {@code writerIndex}
* are {@code 0} and {@code nioBuffer.remaining()} respectively
*/
ChannelBuffer getBuffer(ByteBuffer nioBuffer);
/**
* Returns the default endianness of the {@link ChannelBuffer} which is
* returned by {@link #getBuffer(int)}.
*
* @return the default endianness of the {@link ChannelBuffer} which is
* returned by {@link #getBuffer(int)}
*/
ByteOrder getDefaultOrder();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ChannelBufferIndexFinder.java 0000664 0000000 0000000 00000011372 12255541277 0031541 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
/**
* Locates an index of data in a {@link ChannelBuffer}.
*
* This interface enables the sequential search for the data which meets more
* complex and dynamic condition than just a simple value matching. Please
* refer to {@link ChannelBuffer#indexOf(int, int, ChannelBufferIndexFinder)} and
* {@link ChannelBuffer#bytesBefore(int, int, ChannelBufferIndexFinder)}
* for more explanation.
*
* @apiviz.uses org.jboss.netty.buffer.ChannelBuffer
*/
public interface ChannelBufferIndexFinder {
/**
* Returns {@code true} if and only if the data is found at the specified
* {@code guessedIndex} of the specified {@code buffer}.
*
* The implementation should not perform an operation which raises an
* exception such as {@link IndexOutOfBoundsException} nor perform
* an operation which modifies the content of the buffer.
*/
boolean find(ChannelBuffer buffer, int guessedIndex);
/**
* Index finder which locates a {@code NUL (0x00)} byte.
*/
ChannelBufferIndexFinder NUL = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
return buffer.getByte(guessedIndex) == 0;
}
};
/**
* Index finder which locates a non-{@code NUL (0x00)} byte.
*/
ChannelBufferIndexFinder NOT_NUL = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
return buffer.getByte(guessedIndex) != 0;
}
};
/**
* Index finder which locates a {@code CR ('\r')} byte.
*/
ChannelBufferIndexFinder CR = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
return buffer.getByte(guessedIndex) == '\r';
}
};
/**
* Index finder which locates a non-{@code CR ('\r')} byte.
*/
ChannelBufferIndexFinder NOT_CR = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
return buffer.getByte(guessedIndex) != '\r';
}
};
/**
* Index finder which locates a {@code LF ('\n')} byte.
*/
ChannelBufferIndexFinder LF = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
return buffer.getByte(guessedIndex) == '\n';
}
};
/**
* Index finder which locates a non-{@code LF ('\n')} byte.
*/
ChannelBufferIndexFinder NOT_LF = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
return buffer.getByte(guessedIndex) != '\n';
}
};
/**
* Index finder which locates a {@code CR ('\r')} or {@code LF ('\n')}.
*/
ChannelBufferIndexFinder CRLF = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
byte b = buffer.getByte(guessedIndex);
return b == '\r' || b == '\n';
}
};
/**
* Index finder which locates a byte which is neither a {@code CR ('\r')}
* nor a {@code LF ('\n')}.
*/
ChannelBufferIndexFinder NOT_CRLF = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
byte b = buffer.getByte(guessedIndex);
return b != '\r' && b != '\n';
}
};
/**
* Index finder which locates a linear whitespace
* ({@code ' '} and {@code '\t'}).
*/
ChannelBufferIndexFinder LINEAR_WHITESPACE = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
byte b = buffer.getByte(guessedIndex);
return b == ' ' || b == '\t';
}
};
/**
* Index finder which locates a byte which is not a linear whitespace
* (neither {@code ' '} nor {@code '\t'}).
*/
ChannelBufferIndexFinder NOT_LINEAR_WHITESPACE = new ChannelBufferIndexFinder() {
public boolean find(ChannelBuffer buffer, int guessedIndex) {
byte b = buffer.getByte(guessedIndex);
return b != ' ' && b != '\t';
}
};
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ChannelBufferInputStream.java 0000664 0000000 0000000 00000015025 12255541277 0031614 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
/**
* An {@link InputStream} which reads data from a {@link ChannelBuffer}.
*
* A read operation against this stream will occur at the {@code readerIndex}
* of its underlying buffer and the {@code readerIndex} will increase during
* the read operation.
*
* This stream implements {@link DataInput} for your convenience.
* The endianness of the stream is not always big endian but depends on
* the endianness of the underlying buffer.
*
* @see ChannelBufferOutputStream
* @apiviz.uses org.jboss.netty.buffer.ChannelBuffer
*/
public class ChannelBufferInputStream extends InputStream implements DataInput {
private final ChannelBuffer buffer;
private final int startIndex;
private final int endIndex;
/**
* Creates a new stream which reads data from the specified {@code buffer}
* starting at the current {@code readerIndex} and ending at the current
* {@code writerIndex}.
*/
public ChannelBufferInputStream(ChannelBuffer buffer) {
this(buffer, buffer.readableBytes());
}
/**
* Creates a new stream which reads data from the specified {@code buffer}
* starting at the current {@code readerIndex} and ending at
* {@code readerIndex + length}.
*
* @throws IndexOutOfBoundsException
* if {@code readerIndex + length} is greater than
* {@code writerIndex}
*/
public ChannelBufferInputStream(ChannelBuffer buffer, int length) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
if (length < 0) {
throw new IllegalArgumentException("length: " + length);
}
if (length > buffer.readableBytes()) {
throw new IndexOutOfBoundsException("Too many bytes to be read - Needs "
+ length + ", maximum is " + buffer.readableBytes());
}
this.buffer = buffer;
startIndex = buffer.readerIndex();
endIndex = startIndex + length;
buffer.markReaderIndex();
}
/**
* Returns the number of read bytes by this stream so far.
*/
public int readBytes() {
return buffer.readerIndex() - startIndex;
}
@Override
public int available() throws IOException {
return endIndex - buffer.readerIndex();
}
@Override
public void mark(int readlimit) {
buffer.markReaderIndex();
}
@Override
public boolean markSupported() {
return true;
}
@Override
public int read() throws IOException {
if (!buffer.readable()) {
return -1;
}
return buffer.readByte() & 0xff;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int available = available();
if (available == 0) {
return -1;
}
len = Math.min(available, len);
buffer.readBytes(b, off, len);
return len;
}
@Override
public void reset() throws IOException {
buffer.resetReaderIndex();
}
@Override
public long skip(long n) throws IOException {
if (n > Integer.MAX_VALUE) {
return skipBytes(Integer.MAX_VALUE);
} else {
return skipBytes((int) n);
}
}
public boolean readBoolean() throws IOException {
checkAvailable(1);
return read() != 0;
}
public byte readByte() throws IOException {
if (!buffer.readable()) {
throw new EOFException();
}
return buffer.readByte();
}
public char readChar() throws IOException {
return (char) readShort();
}
public double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
public float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
public void readFully(byte[] b) throws IOException {
readFully(b, 0, b.length);
}
public void readFully(byte[] b, int off, int len) throws IOException {
checkAvailable(len);
buffer.readBytes(b, off, len);
}
public int readInt() throws IOException {
checkAvailable(4);
return buffer.readInt();
}
private final StringBuilder lineBuf = new StringBuilder();
public String readLine() throws IOException {
lineBuf.setLength(0);
for (;;) {
int b = read();
if (b < 0 || b == '\n') {
break;
}
lineBuf.append((char) b);
}
if (lineBuf.length() > 0) {
while (lineBuf.charAt(lineBuf.length() - 1) == '\r') {
lineBuf.setLength(lineBuf.length() - 1);
}
}
return lineBuf.toString();
}
public long readLong() throws IOException {
checkAvailable(8);
return buffer.readLong();
}
public short readShort() throws IOException {
checkAvailable(2);
return buffer.readShort();
}
public String readUTF() throws IOException {
return DataInputStream.readUTF(this);
}
public int readUnsignedByte() throws IOException {
return readByte() & 0xff;
}
public int readUnsignedShort() throws IOException {
return readShort() & 0xffff;
}
public int skipBytes(int n) throws IOException {
int nBytes = Math.min(available(), n);
buffer.skipBytes(nBytes);
return nBytes;
}
private void checkAvailable(int fieldSize) throws IOException {
if (fieldSize < 0) {
throw new IndexOutOfBoundsException("fieldSize cannot be a negative number");
}
if (fieldSize > available()) {
throw new EOFException("fieldSize is too long! Length is " + fieldSize
+ ", but maximum is " + available());
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ChannelBufferOutputStream.java 0000664 0000000 0000000 00000007407 12255541277 0032022 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* An {@link OutputStream} which writes data to a {@link ChannelBuffer}.
*
* A write operation against this stream will occur at the {@code writerIndex}
* of its underlying buffer and the {@code writerIndex} will increase during
* the write operation.
*
* This stream implements {@link DataOutput} for your convenience.
* The endianness of the stream is not always big endian but depends on
* the endianness of the underlying buffer.
*
* @see ChannelBufferInputStream
* @apiviz.uses org.jboss.netty.buffer.ChannelBuffer
*/
public class ChannelBufferOutputStream extends OutputStream implements DataOutput {
private final ChannelBuffer buffer;
private final int startIndex;
private final DataOutputStream utf8out = new DataOutputStream(this);
/**
* Creates a new stream which writes data to the specified {@code buffer}.
*/
public ChannelBufferOutputStream(ChannelBuffer buffer) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
this.buffer = buffer;
startIndex = buffer.writerIndex();
}
/**
* Returns the number of written bytes by this stream so far.
*/
public int writtenBytes() {
return buffer.writerIndex() - startIndex;
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (len == 0) {
return;
}
buffer.writeBytes(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
buffer.writeBytes(b);
}
@Override
public void write(int b) throws IOException {
buffer.writeByte((byte) b);
}
public void writeBoolean(boolean v) throws IOException {
write(v? (byte) 1 : (byte) 0);
}
public void writeByte(int v) throws IOException {
write(v);
}
public void writeBytes(String s) throws IOException {
int len = s.length();
for (int i = 0; i < len; i ++) {
write((byte) s.charAt(i));
}
}
public void writeChar(int v) throws IOException {
writeShort((short) v);
}
public void writeChars(String s) throws IOException {
int len = s.length();
for (int i = 0 ; i < len ; i ++) {
writeChar(s.charAt(i));
}
}
public void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}
public void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
public void writeInt(int v) throws IOException {
buffer.writeInt(v);
}
public void writeLong(long v) throws IOException {
buffer.writeLong(v);
}
public void writeShort(int v) throws IOException {
buffer.writeShort((short) v);
}
public void writeUTF(String s) throws IOException {
utf8out.writeUTF(s);
}
/**
* Returns the buffer where this stream is writing data.
*/
public ChannelBuffer buffer() {
return buffer;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ChannelBuffers.java 0000664 0000000 0000000 00000125470 12255541277 0027611 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import org.jboss.netty.util.CharsetUtil;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.ArrayList;
import java.util.List;
/**
* Creates a new {@link ChannelBuffer} by allocating new space or by wrapping
* or copying existing byte arrays, byte buffers and a string.
*
*
Use static import
* This classes is intended to be used with Java 5 static import statement:
*
*
* import static org.jboss.netty.buffer.{@link ChannelBuffers}.*;
*
* {@link ChannelBuffer} heapBuffer = buffer(128);
* {@link ChannelBuffer} directBuffer = directBuffer(256);
* {@link ChannelBuffer} dynamicBuffer = dynamicBuffer(512);
* {@link ChannelBuffer} wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
* {@link ChannelBuffer} copiedBuffe r = copiedBuffer({@link ByteBuffer}.allocate(128));
*
*
* Allocating a new buffer
*
* Three buffer types are provided out of the box.
*
*
* {@link #buffer(int)} allocates a new fixed-capacity heap buffer.
* {@link #directBuffer(int)} allocates a new fixed-capacity direct buffer.
* {@link #dynamicBuffer(int)} allocates a new dynamic-capacity heap
* buffer, whose capacity increases automatically as needed by a write
* operation.
*
*
* Creating a wrapped buffer
*
* Wrapped buffer is a buffer which is a view of one or more existing
* byte arrays and byte buffers. Any changes in the content of the original
* array or buffer will be visible in the wrapped buffer. Various wrapper
* methods are provided and their name is all {@code wrappedBuffer()}.
* You might want to take a look at the methods that accept varargs closely if
* you want to create a buffer which is composed of more than one array to
* reduce the number of memory copy.
*
* Creating a copied buffer
*
* Copied buffer is a deep copy of one or more existing byte arrays, byte
* buffers or a string. Unlike a wrapped buffer, there's no shared data
* between the original data and the copied buffer. Various copy methods are
* provided and their name is all {@code copiedBuffer()}. It is also convenient
* to use this operation to merge multiple buffers into one buffer.
*
* Miscellaneous utility methods
*
* This class also provides various utility methods to help implementation
* of a new buffer type, generation of hex dump and swapping an integer's
* byte order.
*
* @apiviz.landmark
* @apiviz.has org.jboss.netty.buffer.ChannelBuffer oneway - - creates
*/
public final class ChannelBuffers {
/**
* Big endian byte order.
*/
public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
/**
* Little endian byte order.
*/
public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
/**
* A buffer whose capacity is {@code 0}.
*/
public static final ChannelBuffer EMPTY_BUFFER = new EmptyChannelBuffer();
private static final char[] HEXDUMP_TABLE = new char[256 * 4];
static {
final char[] DIGITS = "0123456789abcdef".toCharArray();
for (int i = 0; i < 256; i ++) {
HEXDUMP_TABLE[i << 1] = DIGITS[i >>> 4 & 0x0F];
HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F];
}
}
/**
* Creates a new big-endian Java heap buffer with the specified
* {@code capacity}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer buffer(int capacity) {
return buffer(BIG_ENDIAN, capacity);
}
/**
* Creates a new Java heap buffer with the specified {@code endianness}
* and {@code capacity}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer buffer(ByteOrder endianness, int capacity) {
if (endianness == BIG_ENDIAN) {
if (capacity == 0) {
return EMPTY_BUFFER;
}
return new BigEndianHeapChannelBuffer(capacity);
} else if (endianness == LITTLE_ENDIAN) {
if (capacity == 0) {
return EMPTY_BUFFER;
}
return new LittleEndianHeapChannelBuffer(capacity);
} else {
throw new NullPointerException("endianness");
}
}
/**
* Creates a new big-endian direct buffer with the specified
* {@code capacity}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer directBuffer(int capacity) {
return directBuffer(BIG_ENDIAN, capacity);
}
/**
* Creates a new direct buffer with the specified {@code endianness} and
* {@code capacity}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer directBuffer(ByteOrder endianness, int capacity) {
if (endianness == null) {
throw new NullPointerException("endianness");
}
if (capacity == 0) {
return EMPTY_BUFFER;
}
ChannelBuffer buffer = new ByteBufferBackedChannelBuffer(
ByteBuffer.allocateDirect(capacity).order(endianness));
buffer.clear();
return buffer;
}
/**
* Creates a new big-endian dynamic buffer whose estimated data length is
* {@code 256} bytes. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer dynamicBuffer() {
return dynamicBuffer(BIG_ENDIAN, 256);
}
public static ChannelBuffer dynamicBuffer(ChannelBufferFactory factory) {
if (factory == null) {
throw new NullPointerException("factory");
}
return new DynamicChannelBuffer(factory.getDefaultOrder(), 256, factory);
}
/**
* Creates a new big-endian dynamic buffer with the specified estimated
* data length. More accurate estimation yields less unexpected
* reallocation overhead. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer dynamicBuffer(int estimatedLength) {
return dynamicBuffer(BIG_ENDIAN, estimatedLength);
}
/**
* Creates a new dynamic buffer with the specified endianness and
* the specified estimated data length. More accurate estimation yields
* less unexpected reallocation overhead. The new buffer's
* {@code readerIndex} and {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer dynamicBuffer(ByteOrder endianness, int estimatedLength) {
return new DynamicChannelBuffer(endianness, estimatedLength);
}
/**
* Creates a new big-endian dynamic buffer with the specified estimated
* data length using the specified factory. More accurate estimation yields
* less unexpected reallocation overhead. The new buffer's {@code readerIndex}
* and {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer dynamicBuffer(int estimatedLength, ChannelBufferFactory factory) {
if (factory == null) {
throw new NullPointerException("factory");
}
return new DynamicChannelBuffer(factory.getDefaultOrder(), estimatedLength, factory);
}
/**
* Creates a new dynamic buffer with the specified endianness and
* the specified estimated data length using the specified factory.
* More accurate estimation yields less unexpected reallocation overhead.
* The new buffer's {@code readerIndex} and {@code writerIndex} are {@code 0}.
*/
public static ChannelBuffer dynamicBuffer(
ByteOrder endianness, int estimatedLength, ChannelBufferFactory factory) {
return new DynamicChannelBuffer(endianness, estimatedLength, factory);
}
/**
* Creates a new big-endian buffer which wraps the specified {@code array}.
* A modification on the specified array's content will be visible to the
* returned buffer.
*/
public static ChannelBuffer wrappedBuffer(byte[] array) {
return wrappedBuffer(BIG_ENDIAN, array);
}
/**
* Creates a new buffer which wraps the specified {@code array} with the
* specified {@code endianness}. A modification on the specified array's
* content will be visible to the returned buffer.
*/
public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[] array) {
if (endianness == BIG_ENDIAN) {
if (array.length == 0) {
return EMPTY_BUFFER;
}
return new BigEndianHeapChannelBuffer(array);
} else if (endianness == LITTLE_ENDIAN) {
if (array.length == 0) {
return EMPTY_BUFFER;
}
return new LittleEndianHeapChannelBuffer(array);
} else {
throw new NullPointerException("endianness");
}
}
/**
* Creates a new big-endian buffer which wraps the sub-region of the
* specified {@code array}. A modification on the specified array's
* content will be visible to the returned buffer.
*/
public static ChannelBuffer wrappedBuffer(byte[] array, int offset, int length) {
return wrappedBuffer(BIG_ENDIAN, array, offset, length);
}
/**
* Creates a new buffer which wraps the sub-region of the specified
* {@code array} with the specified {@code endianness}. A modification on
* the specified array's content will be visible to the returned buffer.
*/
public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
if (endianness == null) {
throw new NullPointerException("endianness");
}
if (offset == 0) {
if (length == array.length) {
return wrappedBuffer(endianness, array);
} else {
if (length == 0) {
return EMPTY_BUFFER;
} else {
return new TruncatedChannelBuffer(wrappedBuffer(endianness, array), length);
}
}
} else {
if (length == 0) {
return EMPTY_BUFFER;
} else {
return new SlicedChannelBuffer(wrappedBuffer(endianness, array), offset, length);
}
}
}
/**
* Creates a new buffer which wraps the specified NIO buffer's current
* slice. A modification on the specified buffer's content will be
* visible to the returned buffer.
*/
public static ChannelBuffer wrappedBuffer(ByteBuffer buffer) {
if (!buffer.hasRemaining()) {
return EMPTY_BUFFER;
}
if (buffer.hasArray()) {
return wrappedBuffer(
buffer.order(), buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
} else {
return new ByteBufferBackedChannelBuffer(buffer);
}
}
/**
* Creates a new buffer which wraps the specified buffer's readable bytes.
* A modification on the specified buffer's content will be visible to the
* returned buffer.
*/
public static ChannelBuffer wrappedBuffer(ChannelBuffer buffer) {
if (buffer.readable()) {
return buffer.slice();
} else {
return EMPTY_BUFFER;
}
}
/**
* Creates a new big-endian composite buffer which wraps the specified
* arrays without copying them. A modification on the specified arrays'
* content will be visible to the returned buffer.
*/
public static ChannelBuffer wrappedBuffer(byte[]... arrays) {
return wrappedBuffer(BIG_ENDIAN, arrays);
}
/**
* Creates a new composite buffer which wraps the specified arrays without
* copying them. A modification on the specified arrays' content will be
* visible to the returned buffer.
*
* @param endianness the endianness of the new buffer
*/
public static ChannelBuffer wrappedBuffer(ByteOrder endianness, byte[]... arrays) {
switch (arrays.length) {
case 0:
break;
case 1:
if (arrays[0].length != 0) {
return wrappedBuffer(endianness, arrays[0]);
}
break;
default:
// Get the list of the component, while guessing the byte order.
final List components = new ArrayList(arrays.length);
for (byte[] a: arrays) {
if (a == null) {
break;
}
if (a.length > 0) {
components.add(wrappedBuffer(endianness, a));
}
}
return compositeBuffer(endianness, components, false);
}
return EMPTY_BUFFER;
}
private static ChannelBuffer compositeBuffer(
ByteOrder endianness, List components, boolean gathering) {
switch (components.size()) {
case 0:
return EMPTY_BUFFER;
case 1:
return components.get(0);
default:
return new CompositeChannelBuffer(endianness, components, gathering);
}
}
/**
* Creates a new composite buffer which wraps the readable bytes of the
* specified buffers without copying them. A modification on the content
* of the specified buffers will be visible to the returned buffer.
*
* @throws IllegalArgumentException
* if the specified buffers' endianness are different from each
* other
*/
public static ChannelBuffer wrappedBuffer(ChannelBuffer... buffers) {
return wrappedBuffer(false, buffers);
}
/**
* Creates a new composite buffer which wraps the readable bytes of the
* specified buffers without copying them. A modification on the content
* of the specified buffers will be visible to the returned buffer.
* If gathering is {@code true} then gathering writes will be used when ever
* possible.
*
* @throws IllegalArgumentException
* if the specified buffers' endianness are different from each
* other
*/
public static ChannelBuffer wrappedBuffer(boolean gathering, ChannelBuffer... buffers) {
switch (buffers.length) {
case 0:
break;
case 1:
if (buffers[0].readable()) {
return wrappedBuffer(buffers[0]);
}
break;
default:
ByteOrder order = null;
final List components = new ArrayList(buffers.length);
for (ChannelBuffer c: buffers) {
if (c == null) {
break;
}
if (c.readable()) {
if (order != null) {
if (!order.equals(c.order())) {
throw new IllegalArgumentException(
"inconsistent byte order");
}
} else {
order = c.order();
}
if (c instanceof CompositeChannelBuffer) {
// Expand nested composition.
components.addAll(
((CompositeChannelBuffer) c).decompose(
c.readerIndex(), c.readableBytes()));
} else {
// An ordinary buffer (non-composite)
components.add(c.slice());
}
}
}
return compositeBuffer(order, components, gathering);
}
return EMPTY_BUFFER;
}
/**
* Creates a new composite buffer which wraps the slices of the specified
* NIO buffers without copying them. A modification on the content of the
* specified buffers will be visible to the returned buffer.
*
* @throws IllegalArgumentException
* if the specified buffers' endianness are different from each
* other
*/
public static ChannelBuffer wrappedBuffer(ByteBuffer... buffers) {
return wrappedBuffer(false, buffers);
}
/**
* Creates a new composite buffer which wraps the slices of the specified
* NIO buffers without copying them. A modification on the content of the
* specified buffers will be visible to the returned buffer.
* If gathering is {@code true} then gathering writes will be used when ever
* possible.
*
* @throws IllegalArgumentException
* if the specified buffers' endianness are different from each
* other
*/
public static ChannelBuffer wrappedBuffer(boolean gathering, ByteBuffer... buffers) {
switch (buffers.length) {
case 0:
break;
case 1:
if (buffers[0].hasRemaining()) {
return wrappedBuffer(buffers[0]);
}
break;
default:
ByteOrder order = null;
final List components = new ArrayList(buffers.length);
for (ByteBuffer b: buffers) {
if (b == null) {
break;
}
if (b.hasRemaining()) {
if (order != null) {
if (!order.equals(b.order())) {
throw new IllegalArgumentException(
"inconsistent byte order");
}
} else {
order = b.order();
}
components.add(wrappedBuffer(b));
}
}
return compositeBuffer(order, components, gathering);
}
return EMPTY_BUFFER;
}
/**
* Creates a new big-endian buffer whose content is a copy of the
* specified {@code array}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0} and {@code array.length} respectively.
*/
public static ChannelBuffer copiedBuffer(byte[] array) {
return copiedBuffer(BIG_ENDIAN, array);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is a copy of the specified {@code array}. The new buffer's
* {@code readerIndex} and {@code writerIndex} are {@code 0} and
* {@code array.length} respectively.
*/
public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array) {
if (endianness == BIG_ENDIAN) {
if (array.length == 0) {
return EMPTY_BUFFER;
}
return new BigEndianHeapChannelBuffer(array.clone());
} else if (endianness == LITTLE_ENDIAN) {
if (array.length == 0) {
return EMPTY_BUFFER;
}
return new LittleEndianHeapChannelBuffer(array.clone());
} else {
throw new NullPointerException("endianness");
}
}
/**
* Creates a new big-endian buffer whose content is a copy of the
* specified {@code array}'s sub-region. The new buffer's
* {@code readerIndex} and {@code writerIndex} are {@code 0} and
* the specified {@code length} respectively.
*/
public static ChannelBuffer copiedBuffer(byte[] array, int offset, int length) {
return copiedBuffer(BIG_ENDIAN, array, offset, length);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is a copy of the specified {@code array}'s sub-region. The new
* buffer's {@code readerIndex} and {@code writerIndex} are {@code 0} and
* the specified {@code length} respectively.
*/
public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[] array, int offset, int length) {
if (endianness == null) {
throw new NullPointerException("endianness");
}
if (length == 0) {
return EMPTY_BUFFER;
}
byte[] copy = new byte[length];
System.arraycopy(array, offset, copy, 0, length);
return wrappedBuffer(endianness, copy);
}
/**
* Creates a new buffer whose content is a copy of the specified
* {@code buffer}'s current slice. The new buffer's {@code readerIndex}
* and {@code writerIndex} are {@code 0} and {@code buffer.remaining}
* respectively.
*/
public static ChannelBuffer copiedBuffer(ByteBuffer buffer) {
int length = buffer.remaining();
if (length == 0) {
return EMPTY_BUFFER;
}
byte[] copy = new byte[length];
int position = buffer.position();
try {
buffer.get(copy);
} finally {
buffer.position(position);
}
return wrappedBuffer(buffer.order(), copy);
}
/**
* Creates a new buffer whose content is a copy of the specified
* {@code buffer}'s readable bytes. The new buffer's {@code readerIndex}
* and {@code writerIndex} are {@code 0} and {@code buffer.readableBytes}
* respectively.
*/
public static ChannelBuffer copiedBuffer(ChannelBuffer buffer) {
if (buffer.readable()) {
return buffer.copy();
} else {
return EMPTY_BUFFER;
}
}
/**
* Creates a new big-endian buffer whose content is a merged copy of
* the specified {@code arrays}. The new buffer's {@code readerIndex}
* and {@code writerIndex} are {@code 0} and the sum of all arrays'
* {@code length} respectively.
*/
public static ChannelBuffer copiedBuffer(byte[]... arrays) {
return copiedBuffer(BIG_ENDIAN, arrays);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is a merged copy of the specified {@code arrays}. The new
* buffer's {@code readerIndex} and {@code writerIndex} are {@code 0}
* and the sum of all arrays' {@code length} respectively.
*/
public static ChannelBuffer copiedBuffer(ByteOrder endianness, byte[]... arrays) {
switch (arrays.length) {
case 0:
return EMPTY_BUFFER;
case 1:
if (arrays[0].length == 0) {
return EMPTY_BUFFER;
} else {
return copiedBuffer(endianness, arrays[0]);
}
}
// Merge the specified arrays into one array.
int length = 0;
for (byte[] a: arrays) {
if (Integer.MAX_VALUE - length < a.length) {
throw new IllegalArgumentException(
"The total length of the specified arrays is too big.");
}
length += a.length;
}
if (length == 0) {
return EMPTY_BUFFER;
}
byte[] mergedArray = new byte[length];
for (int i = 0, j = 0; i < arrays.length; i ++) {
byte[] a = arrays[i];
System.arraycopy(a, 0, mergedArray, j, a.length);
j += a.length;
}
return wrappedBuffer(endianness, mergedArray);
}
/**
* Creates a new buffer whose content is a merged copy of the specified
* {@code buffers}' readable bytes. The new buffer's {@code readerIndex}
* and {@code writerIndex} are {@code 0} and the sum of all buffers'
* {@code readableBytes} respectively.
*
* @throws IllegalArgumentException
* if the specified buffers' endianness are different from each
* other
*/
public static ChannelBuffer copiedBuffer(ChannelBuffer... buffers) {
switch (buffers.length) {
case 0:
return EMPTY_BUFFER;
case 1:
return copiedBuffer(buffers[0]);
}
ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
for (int i = 0; i < buffers.length; i ++) {
copiedBuffers[i] = copiedBuffer(buffers[i]);
}
return wrappedBuffer(false, copiedBuffers);
}
/**
* Creates a new buffer whose content is a merged copy of the specified
* {@code buffers}' slices. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0} and the sum of all buffers'
* {@code remaining} respectively.
*
* @throws IllegalArgumentException
* if the specified buffers' endianness are different from each
* other
*/
public static ChannelBuffer copiedBuffer(ByteBuffer... buffers) {
switch (buffers.length) {
case 0:
return EMPTY_BUFFER;
case 1:
return copiedBuffer(buffers[0]);
}
ChannelBuffer[] copiedBuffers = new ChannelBuffer[buffers.length];
for (int i = 0; i < buffers.length; i ++) {
copiedBuffers[i] = copiedBuffer(buffers[i]);
}
return wrappedBuffer(false, copiedBuffers);
}
/**
* Creates a new big-endian buffer whose content is the specified
* {@code string} encoded in the specified {@code charset}.
* The new buffer's {@code readerIndex} and {@code writerIndex} are
* {@code 0} and the length of the encoded string respectively.
*/
public static ChannelBuffer copiedBuffer(CharSequence string, Charset charset) {
return copiedBuffer(BIG_ENDIAN, string, charset);
}
/**
* Creates a new big-endian buffer whose content is a subregion of
* the specified {@code string} encoded in the specified {@code charset}.
* The new buffer's {@code readerIndex} and {@code writerIndex} are
* {@code 0} and the length of the encoded string respectively.
*/
public static ChannelBuffer copiedBuffer(
CharSequence string, int offset, int length, Charset charset) {
return copiedBuffer(BIG_ENDIAN, string, offset, length, charset);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is the specified {@code string} encoded in the specified
* {@code charset}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0} and the length of the encoded string
* respectively.
*/
public static ChannelBuffer copiedBuffer(ByteOrder endianness, CharSequence string, Charset charset) {
if (string == null) {
throw new NullPointerException("string");
}
if (string instanceof CharBuffer) {
return copiedBuffer(endianness, (CharBuffer) string, charset);
}
return copiedBuffer(endianness, CharBuffer.wrap(string), charset);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is a subregion of the specified {@code string} encoded in the
* specified {@code charset}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0} and the length of the encoded string
* respectively.
*/
public static ChannelBuffer copiedBuffer(
ByteOrder endianness, CharSequence string, int offset, int length, Charset charset) {
if (string == null) {
throw new NullPointerException("string");
}
if (length == 0) {
return EMPTY_BUFFER;
}
if (string instanceof CharBuffer) {
CharBuffer buf = (CharBuffer) string;
if (buf.hasArray()) {
return copiedBuffer(
endianness,
buf.array(),
buf.arrayOffset() + buf.position() + offset,
length, charset);
}
buf = buf.slice();
buf.limit(length);
buf.position(offset);
return copiedBuffer(endianness, buf, charset);
}
return copiedBuffer(
endianness, CharBuffer.wrap(string, offset, offset + length),
charset);
}
/**
* Creates a new big-endian buffer whose content is the specified
* {@code array} encoded in the specified {@code charset}.
* The new buffer's {@code readerIndex} and {@code writerIndex} are
* {@code 0} and the length of the encoded string respectively.
*/
public static ChannelBuffer copiedBuffer(char[] array, Charset charset) {
return copiedBuffer(BIG_ENDIAN, array, 0, array.length, charset);
}
/**
* Creates a new big-endian buffer whose content is a subregion of
* the specified {@code array} encoded in the specified {@code charset}.
* The new buffer's {@code readerIndex} and {@code writerIndex} are
* {@code 0} and the length of the encoded string respectively.
*/
public static ChannelBuffer copiedBuffer(
char[] array, int offset, int length, Charset charset) {
return copiedBuffer(BIG_ENDIAN, array, offset, length, charset);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is the specified {@code array} encoded in the specified
* {@code charset}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0} and the length of the encoded string
* respectively.
*/
public static ChannelBuffer copiedBuffer(ByteOrder endianness, char[] array, Charset charset) {
return copiedBuffer(endianness, array, 0, array.length, charset);
}
/**
* Creates a new buffer with the specified {@code endianness} whose
* content is a subregion of the specified {@code array} encoded in the
* specified {@code charset}. The new buffer's {@code readerIndex} and
* {@code writerIndex} are {@code 0} and the length of the encoded string
* respectively.
*/
public static ChannelBuffer copiedBuffer(
ByteOrder endianness, char[] array, int offset, int length, Charset charset) {
if (array == null) {
throw new NullPointerException("array");
}
if (length == 0) {
return EMPTY_BUFFER;
}
return copiedBuffer(
endianness, CharBuffer.wrap(array, offset, length), charset);
}
private static ChannelBuffer copiedBuffer(ByteOrder endianness, CharBuffer buffer, Charset charset) {
CharBuffer src = buffer;
ByteBuffer dst = encodeString(src, charset);
ChannelBuffer result = wrappedBuffer(endianness, dst.array());
result.writerIndex(dst.remaining());
return result;
}
/**
* @deprecated Use {@link #copiedBuffer(CharSequence, Charset)} instead.
*/
@Deprecated
public static ChannelBuffer copiedBuffer(String string, String charsetName) {
return copiedBuffer(string, Charset.forName(charsetName));
}
/**
* @deprecated Use {@link #copiedBuffer(ByteOrder, CharSequence, Charset)} instead.
*/
@Deprecated
public static ChannelBuffer copiedBuffer(ByteOrder endianness, String string, String charsetName) {
return copiedBuffer(endianness, string, Charset.forName(charsetName));
}
/**
* Creates a read-only buffer which disallows any modification operations
* on the specified {@code buffer}. The new buffer has the same
* {@code readerIndex} and {@code writerIndex} with the specified
* {@code buffer}.
*/
public static ChannelBuffer unmodifiableBuffer(ChannelBuffer buffer) {
if (buffer instanceof ReadOnlyChannelBuffer) {
buffer = ((ReadOnlyChannelBuffer) buffer).unwrap();
}
return new ReadOnlyChannelBuffer(buffer);
}
/**
* Create a {@link ChannelBuffer} from the given hex dump
*/
public static ChannelBuffer hexDump(String hexString) {
int len = hexString.length();
byte[] hexData = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
hexData[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return wrappedBuffer(hexData);
}
/**
* Returns a hex dump
* of the specified buffer's readable bytes.
*/
public static String hexDump(ChannelBuffer buffer) {
return hexDump(buffer, buffer.readerIndex(), buffer.readableBytes());
}
/**
* Returns a hex dump
* of the specified buffer's sub-region.
*/
public static String hexDump(ChannelBuffer buffer, int fromIndex, int length) {
if (length < 0) {
throw new IllegalArgumentException("length: " + length);
}
if (length == 0) {
return "";
}
int endIndex = fromIndex + length;
char[] buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) {
System.arraycopy(
HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1,
buf, dstIdx, 2);
}
return new String(buf);
}
/**
* Calculates the hash code of the specified buffer. This method is
* useful when implementing a new buffer type.
*/
public static int hashCode(ChannelBuffer buffer) {
final int aLen = buffer.readableBytes();
final int intCount = aLen >>> 2;
final int byteCount = aLen & 3;
int hashCode = 1;
int arrayIndex = buffer.readerIndex();
if (buffer.order() == BIG_ENDIAN) {
for (int i = intCount; i > 0; i --) {
hashCode = 31 * hashCode + buffer.getInt(arrayIndex);
arrayIndex += 4;
}
} else {
for (int i = intCount; i > 0; i --) {
hashCode = 31 * hashCode + swapInt(buffer.getInt(arrayIndex));
arrayIndex += 4;
}
}
for (int i = byteCount; i > 0; i --) {
hashCode = 31 * hashCode + buffer.getByte(arrayIndex ++);
}
if (hashCode == 0) {
hashCode = 1;
}
return hashCode;
}
/**
* Returns {@code true} if and only if the two specified buffers are
* identical to each other as described in {@code ChannelBuffer#equals(Object)}.
* This method is useful when implementing a new buffer type.
*/
public static boolean equals(ChannelBuffer bufferA, ChannelBuffer bufferB) {
final int aLen = bufferA.readableBytes();
if (aLen != bufferB.readableBytes()) {
return false;
}
final int longCount = aLen >>> 3;
final int byteCount = aLen & 7;
int aIndex = bufferA.readerIndex();
int bIndex = bufferB.readerIndex();
if (bufferA.order() == bufferB.order()) {
for (int i = longCount; i > 0; i --) {
if (bufferA.getLong(aIndex) != bufferB.getLong(bIndex)) {
return false;
}
aIndex += 8;
bIndex += 8;
}
} else {
for (int i = longCount; i > 0; i --) {
if (bufferA.getLong(aIndex) != swapLong(bufferB.getLong(bIndex))) {
return false;
}
aIndex += 8;
bIndex += 8;
}
}
for (int i = byteCount; i > 0; i --) {
if (bufferA.getByte(aIndex) != bufferB.getByte(bIndex)) {
return false;
}
aIndex ++;
bIndex ++;
}
return true;
}
/**
* Compares the two specified buffers as described in {@link ChannelBuffer#compareTo(ChannelBuffer)}.
* This method is useful when implementing a new buffer type.
*/
public static int compare(ChannelBuffer bufferA, ChannelBuffer bufferB) {
final int aLen = bufferA.readableBytes();
final int bLen = bufferB.readableBytes();
final int minLength = Math.min(aLen, bLen);
final int uintCount = minLength >>> 2;
final int byteCount = minLength & 3;
int aIndex = bufferA.readerIndex();
int bIndex = bufferB.readerIndex();
if (bufferA.order() == bufferB.order()) {
for (int i = uintCount; i > 0; i --) {
long va = bufferA.getUnsignedInt(aIndex);
long vb = bufferB.getUnsignedInt(bIndex);
if (va > vb) {
return 1;
}
if (va < vb) {
return -1;
}
aIndex += 4;
bIndex += 4;
}
} else {
for (int i = uintCount; i > 0; i --) {
long va = bufferA.getUnsignedInt(aIndex);
long vb = swapInt(bufferB.getInt(bIndex)) & 0xFFFFFFFFL;
if (va > vb) {
return 1;
}
if (va < vb) {
return -1;
}
aIndex += 4;
bIndex += 4;
}
}
for (int i = byteCount; i > 0; i --) {
short va = bufferA.getUnsignedByte(aIndex);
short vb = bufferB.getUnsignedByte(bIndex);
if (va > vb) {
return 1;
}
if (va < vb) {
return -1;
}
aIndex ++;
bIndex ++;
}
return aLen - bLen;
}
/**
* The default implementation of {@link ChannelBuffer#indexOf(int, int, byte)}.
* This method is useful when implementing a new buffer type.
*/
public static int indexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
if (fromIndex <= toIndex) {
return firstIndexOf(buffer, fromIndex, toIndex, value);
} else {
return lastIndexOf(buffer, fromIndex, toIndex, value);
}
}
/**
* The default implementation of {@link ChannelBuffer#indexOf(int, int, ChannelBufferIndexFinder)}.
* This method is useful when implementing a new buffer type.
*/
public static int indexOf(
ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
if (fromIndex <= toIndex) {
return firstIndexOf(buffer, fromIndex, toIndex, indexFinder);
} else {
return lastIndexOf(buffer, fromIndex, toIndex, indexFinder);
}
}
/**
* Toggles the endianness of the specified 16-bit short integer.
*/
public static short swapShort(short value) {
return (short) (value << 8 | value >>> 8 & 0xff);
}
/**
* Toggles the endianness of the specified 24-bit medium integer.
*/
public static int swapMedium(int value) {
return value << 16 & 0xff0000 | value & 0xff00 | value >>> 16 & 0xff;
}
/**
* Toggles the endianness of the specified 32-bit integer.
*/
public static int swapInt(int value) {
return swapShort((short) value) << 16 |
swapShort((short) (value >>> 16)) & 0xffff;
}
/**
* Toggles the endianness of the specified 64-bit long integer.
*/
public static long swapLong(long value) {
return (long) swapInt((int) value) << 32 |
swapInt((int) (value >>> 32)) & 0xffffffffL;
}
private static int firstIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
fromIndex = Math.max(fromIndex, 0);
if (fromIndex >= toIndex || buffer.capacity() == 0) {
return -1;
}
for (int i = fromIndex; i < toIndex; i ++) {
if (buffer.getByte(i) == value) {
return i;
}
}
return -1;
}
private static int lastIndexOf(ChannelBuffer buffer, int fromIndex, int toIndex, byte value) {
fromIndex = Math.min(fromIndex, buffer.capacity());
if (fromIndex < 0 || buffer.capacity() == 0) {
return -1;
}
for (int i = fromIndex - 1; i >= toIndex; i --) {
if (buffer.getByte(i) == value) {
return i;
}
}
return -1;
}
private static int firstIndexOf(
ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
fromIndex = Math.max(fromIndex, 0);
if (fromIndex >= toIndex || buffer.capacity() == 0) {
return -1;
}
for (int i = fromIndex; i < toIndex; i ++) {
if (indexFinder.find(buffer, i)) {
return i;
}
}
return -1;
}
private static int lastIndexOf(
ChannelBuffer buffer, int fromIndex, int toIndex, ChannelBufferIndexFinder indexFinder) {
fromIndex = Math.min(fromIndex, buffer.capacity());
if (fromIndex < 0 || buffer.capacity() == 0) {
return -1;
}
for (int i = fromIndex - 1; i >= toIndex; i --) {
if (indexFinder.find(buffer, i)) {
return i;
}
}
return -1;
}
static ByteBuffer encodeString(CharBuffer src, Charset charset) {
final CharsetEncoder encoder = CharsetUtil.getEncoder(charset);
final ByteBuffer dst = ByteBuffer.allocate(
(int) ((double) src.remaining() * encoder.maxBytesPerChar()));
try {
CoderResult cr = encoder.encode(src, dst, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = encoder.flush(dst);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
throw new IllegalStateException(x);
}
dst.flip();
return dst;
}
static String decodeString(ByteBuffer src, Charset charset) {
final CharsetDecoder decoder = CharsetUtil.getDecoder(charset);
final CharBuffer dst = CharBuffer.allocate(
(int) ((double) src.remaining() * decoder.maxCharsPerByte()));
try {
CoderResult cr = decoder.decode(src, dst, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = decoder.flush(dst);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
throw new IllegalStateException(x);
}
return dst.flip().toString();
}
private ChannelBuffers() {
// Unused
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/CompositeChannelBuffer.java 0000664 0000000 0000000 00000066322 12255541277 0031311 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import org.jboss.netty.util.internal.DetectionUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A virtual buffer which shows multiple buffers as a single merged buffer. It
* is recommended to use {@link ChannelBuffers#wrappedBuffer(ChannelBuffer...)}
* instead of calling the constructor explicitly.
*/
public class CompositeChannelBuffer extends AbstractChannelBuffer {
private final ByteOrder order;
private ChannelBuffer[] components;
private int[] indices;
private int lastAccessedComponentId;
private final boolean gathering;
public CompositeChannelBuffer(ByteOrder endianness, List buffers, boolean gathering) {
order = endianness;
this.gathering = gathering;
setComponents(buffers);
}
/**
* Return {@code true} if gathering writes / reads should be used
* for this {@link CompositeChannelBuffer}
*/
public boolean useGathering() {
return gathering && DetectionUtil.javaVersion() >= 7;
}
/**
* Same with {@link #slice(int, int)} except that this method returns a list.
*/
public List decompose(int index, int length) {
if (length == 0) {
return Collections.emptyList();
}
if (index + length > capacity()) {
throw new IndexOutOfBoundsException("Too many bytes to decompose - Need "
+ (index + length) + ", capacity is " + capacity());
}
int componentId = componentId(index);
List slice = new ArrayList(components.length);
// The first component
ChannelBuffer first = components[componentId].duplicate();
first.readerIndex(index - indices[componentId]);
ChannelBuffer buf = first;
int bytesToSlice = length;
do {
int readableBytes = buf.readableBytes();
if (bytesToSlice <= readableBytes) {
// Last component
buf.writerIndex(buf.readerIndex() + bytesToSlice);
slice.add(buf);
break;
} else {
// Not the last component
slice.add(buf);
bytesToSlice -= readableBytes;
componentId ++;
// Fetch the next component.
buf = components[componentId].duplicate();
}
} while (bytesToSlice > 0);
// Slice all components because only readable bytes are interesting.
for (int i = 0; i < slice.size(); i ++) {
slice.set(i, slice.get(i).slice());
}
return slice;
}
/**
* Setup this ChannelBuffer from the list
*/
private void setComponents(List newComponents) {
assert !newComponents.isEmpty();
// Clear the cache.
lastAccessedComponentId = 0;
// Build the component array.
components = new ChannelBuffer[newComponents.size()];
for (int i = 0; i < components.length; i ++) {
ChannelBuffer c = newComponents.get(i);
if (c.order() != order()) {
throw new IllegalArgumentException(
"All buffers must have the same endianness.");
}
assert c.readerIndex() == 0;
assert c.writerIndex() == c.capacity();
components[i] = c;
}
// Build the component lookup table.
indices = new int[components.length + 1];
indices[0] = 0;
for (int i = 1; i <= components.length; i ++) {
indices[i] = indices[i - 1] + components[i - 1].capacity();
}
// Reset the indexes.
setIndex(0, capacity());
}
private CompositeChannelBuffer(CompositeChannelBuffer buffer) {
order = buffer.order;
gathering = buffer.gathering;
components = buffer.components.clone();
indices = buffer.indices.clone();
setIndex(buffer.readerIndex(), buffer.writerIndex());
}
public ChannelBufferFactory factory() {
return HeapChannelBufferFactory.getInstance(order());
}
public ByteOrder order() {
return order;
}
public boolean isDirect() {
return false;
}
public boolean hasArray() {
return false;
}
public byte[] array() {
throw new UnsupportedOperationException();
}
public int arrayOffset() {
throw new UnsupportedOperationException();
}
public int capacity() {
return indices[components.length];
}
public int numComponents() {
return components.length;
}
public byte getByte(int index) {
int componentId = componentId(index);
return components[componentId].getByte(index - indices[componentId]);
}
public short getShort(int index) {
int componentId = componentId(index);
if (index + 2 <= indices[componentId + 1]) {
return components[componentId].getShort(index - indices[componentId]);
} else if (order() == ByteOrder.BIG_ENDIAN) {
return (short) ((getByte(index) & 0xff) << 8 | getByte(index + 1) & 0xff);
} else {
return (short) (getByte(index) & 0xff | (getByte(index + 1) & 0xff) << 8);
}
}
public int getUnsignedMedium(int index) {
int componentId = componentId(index);
if (index + 3 <= indices[componentId + 1]) {
return components[componentId].getUnsignedMedium(index - indices[componentId]);
} else if (order() == ByteOrder.BIG_ENDIAN) {
return (getShort(index) & 0xffff) << 8 | getByte(index + 2) & 0xff;
} else {
return getShort(index) & 0xFFFF | (getByte(index + 2) & 0xFF) << 16;
}
}
public int getInt(int index) {
int componentId = componentId(index);
if (index + 4 <= indices[componentId + 1]) {
return components[componentId].getInt(index - indices[componentId]);
} else if (order() == ByteOrder.BIG_ENDIAN) {
return (getShort(index) & 0xffff) << 16 | getShort(index + 2) & 0xffff;
} else {
return getShort(index) & 0xFFFF | (getShort(index + 2) & 0xFFFF) << 16;
}
}
public long getLong(int index) {
int componentId = componentId(index);
if (index + 8 <= indices[componentId + 1]) {
return components[componentId].getLong(index - indices[componentId]);
} else if (order() == ByteOrder.BIG_ENDIAN) {
return (getInt(index) & 0xffffffffL) << 32 | getInt(index + 4) & 0xffffffffL;
} else {
return getInt(index) & 0xFFFFFFFFL | (getInt(index + 4) & 0xFFFFFFFFL) << 32;
}
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
if (index > capacity() - length || dstIndex > dst.length - length) {
throw new IndexOutOfBoundsException("Too many bytes to read - Needs "
+ (index + length) + ", maximum is " + capacity() + " or "
+ dst.length);
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index must be >= 0");
}
if (length == 0) {
return;
}
int componentId = componentId(index);
int i = componentId;
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
s.getBytes(index - adjustment, dst, dstIndex, localLength);
index += localLength;
dstIndex += localLength;
length -= localLength;
i ++;
}
}
public void getBytes(int index, ByteBuffer dst) {
int componentId = componentId(index);
int limit = dst.limit();
int length = dst.remaining();
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be read - Needs "
+ (index + length) + ", maximum is " + capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index must be >= 0");
}
int i = componentId;
try {
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
dst.limit(dst.position() + localLength);
s.getBytes(index - adjustment, dst);
index += localLength;
length -= localLength;
i ++;
}
} finally {
dst.limit(limit);
}
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
if (index > capacity() - length || dstIndex > dst.capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be read - Needs "
+ (index + length) + " or " + (dstIndex + length) + ", maximum is "
+ capacity() + " or " + dst.capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index must be >= 0");
}
if (length == 0) {
return;
}
int i = componentId(index);
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
s.getBytes(index - adjustment, dst, dstIndex, localLength);
index += localLength;
dstIndex += localLength;
length -= localLength;
i ++;
}
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
if (useGathering()) {
return (int) out.write(toByteBuffers(index, length));
}
// XXX Gathering write is not supported because of a known issue.
// See http://bugs.sun.com/view_bug.do?bug_id=6210541
// This issue appeared in 2004 and is still unresolved!?
return out.write(toByteBuffer(index, length));
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be read - needs "
+ (index + length) + ", maximum of " + capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index must be >= 0");
}
if (length == 0) {
return;
}
int i = componentId(index);
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
s.getBytes(index - adjustment, out, localLength);
index += localLength;
length -= localLength;
i ++;
}
}
public void setByte(int index, int value) {
int componentId = componentId(index);
components[componentId].setByte(index - indices[componentId], value);
}
public void setShort(int index, int value) {
int componentId = componentId(index);
if (index + 2 <= indices[componentId + 1]) {
components[componentId].setShort(index - indices[componentId], value);
} else if (order() == ByteOrder.BIG_ENDIAN) {
setByte(index, (byte) (value >>> 8));
setByte(index + 1, (byte) value);
} else {
setByte(index , (byte) value);
setByte(index + 1, (byte) (value >>> 8));
}
}
public void setMedium(int index, int value) {
int componentId = componentId(index);
if (index + 3 <= indices[componentId + 1]) {
components[componentId].setMedium(index - indices[componentId], value);
} else if (order() == ByteOrder.BIG_ENDIAN) {
setShort(index, (short) (value >> 8));
setByte(index + 2, (byte) value);
} else {
setShort(index , (short) value);
setByte(index + 2, (byte) (value >>> 16));
}
}
public void setInt(int index, int value) {
int componentId = componentId(index);
if (index + 4 <= indices[componentId + 1]) {
components[componentId].setInt(index - indices[componentId], value);
} else if (order() == ByteOrder.BIG_ENDIAN) {
setShort(index, (short) (value >>> 16));
setShort(index + 2, (short) value);
} else {
setShort(index , (short) value);
setShort(index + 2, (short) (value >>> 16));
}
}
public void setLong(int index, long value) {
int componentId = componentId(index);
if (index + 8 <= indices[componentId + 1]) {
components[componentId].setLong(index - indices[componentId], value);
} else if (order() == ByteOrder.BIG_ENDIAN) {
setInt(index, (int) (value >>> 32));
setInt(index + 4, (int) value);
} else {
setInt(index , (int) value);
setInt(index + 4, (int) (value >>> 32));
}
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
int componentId = componentId(index);
if (index > capacity() - length || srcIndex > src.length - length) {
throw new IndexOutOfBoundsException("Too many bytes to read - needs "
+ (index + length) + " or " + (srcIndex + length) + ", maximum is "
+ capacity() + " or " + src.length);
}
int i = componentId;
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
s.setBytes(index - adjustment, src, srcIndex, localLength);
index += localLength;
srcIndex += localLength;
length -= localLength;
i ++;
}
}
public void setBytes(int index, ByteBuffer src) {
int componentId = componentId(index);
int limit = src.limit();
int length = src.remaining();
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be written - Needs "
+ (index + length) + ", maximum is " + capacity());
}
int i = componentId;
try {
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
src.limit(src.position() + localLength);
s.setBytes(index - adjustment, src);
index += localLength;
length -= localLength;
i ++;
}
} finally {
src.limit(limit);
}
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
int componentId = componentId(index);
if (index > capacity() - length || srcIndex > src.capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to be written - Needs "
+ (index + length) + " or " + (srcIndex + length) + ", maximum is "
+ capacity() + " or " + src.capacity());
}
int i = componentId;
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
s.setBytes(index - adjustment, src, srcIndex, localLength);
index += localLength;
srcIndex += localLength;
length -= localLength;
i ++;
}
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
int componentId = componentId(index);
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to write - Needs "
+ (index + length) + ", maximum is " + capacity());
}
int i = componentId;
int readBytes = 0;
do {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
int localReadBytes = s.setBytes(index - adjustment, in, localLength);
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
if (localReadBytes == localLength) {
index += localLength;
length -= localLength;
readBytes += localLength;
i ++;
} else {
index += localReadBytes;
length -= localReadBytes;
readBytes += localReadBytes;
}
} while (length > 0);
return readBytes;
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
int componentId = componentId(index);
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to write - Needs "
+ (index + length) + ", maximum is " + capacity());
}
int i = componentId;
int readBytes = 0;
do {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
int localReadBytes = s.setBytes(index - adjustment, in, localLength);
if (localReadBytes == 0) {
break;
}
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
if (localReadBytes == localLength) {
index += localLength;
length -= localLength;
readBytes += localLength;
i ++;
} else {
index += localReadBytes;
length -= localReadBytes;
readBytes += localReadBytes;
}
} while (length > 0);
return readBytes;
}
public ChannelBuffer duplicate() {
ChannelBuffer duplicate = new CompositeChannelBuffer(this);
duplicate.setIndex(readerIndex(), writerIndex());
return duplicate;
}
public ChannelBuffer copy(int index, int length) {
int componentId = componentId(index);
if (index > capacity() - length) {
throw new IndexOutOfBoundsException("Too many bytes to copy - Needs "
+ (index + length) + ", maximum is " + capacity());
}
ChannelBuffer dst = factory().getBuffer(order(), length);
copyTo(index, length, componentId, dst);
return dst;
}
private void copyTo(int index, int length, int componentId, ChannelBuffer dst) {
int dstIndex = 0;
int i = componentId;
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
s.getBytes(index - adjustment, dst, dstIndex, localLength);
index += localLength;
dstIndex += localLength;
length -= localLength;
i ++;
}
dst.writerIndex(dst.capacity());
}
/**
* Returns the {@link ChannelBuffer} portion of this {@link CompositeChannelBuffer} that
* contains the specified {@code index}. This is an expert method!
*
*
* Please note that since a {@link CompositeChannelBuffer} is made up of
* multiple {@link ChannelBuffer}s, this does not return the full buffer.
* Instead, it only returns a portion of the composite buffer where the
* index is located
*
*
*
* @param index The {@code index} to search for and include in the returned {@link ChannelBuffer}
* @return The {@link ChannelBuffer} that contains the specified {@code index}
* @throws IndexOutOfBoundsException when the specified {@code index} is
* less than zero, or larger than {@code capacity()}
*/
public ChannelBuffer getBuffer(int index) {
if (index < 0 || index >= capacity()) {
throw new IndexOutOfBoundsException("Invalid index: " + index
+ " - Bytes needed: " + index + ", maximum is "
+ capacity());
}
//Return the component byte buffer
return components[componentId(index)];
}
public ChannelBuffer slice(int index, int length) {
if (index == 0) {
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
} else if (index < 0 || index > capacity() - length) {
throw new IndexOutOfBoundsException("Invalid index: " + index
+ " - Bytes needed: " + (index + length) + ", maximum is "
+ capacity());
} else if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
List components = decompose(index, length);
switch (components.size()) {
case 0:
return ChannelBuffers.EMPTY_BUFFER;
case 1:
return components.get(0);
default:
return new CompositeChannelBuffer(order(), components, gathering);
}
}
public ByteBuffer toByteBuffer(int index, int length) {
if (components.length == 1) {
return components[0].toByteBuffer(index, length);
}
ByteBuffer[] buffers = toByteBuffers(index, length);
ByteBuffer merged = ByteBuffer.allocate(length).order(order());
for (ByteBuffer b: buffers) {
merged.put(b);
}
merged.flip();
return merged;
}
@Override
public ByteBuffer[] toByteBuffers(int index, int length) {
if (index + length > capacity()) {
throw new IndexOutOfBoundsException("Too many bytes to convert - Needs"
+ (index + length) + ", maximum is " + capacity());
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index must be >= 0");
}
if (length == 0) {
return new ByteBuffer[0];
}
List buffers = new ArrayList(components.length);
int i = componentId(index);
while (length > 0) {
ChannelBuffer s = components[i];
int adjustment = indices[i];
int localLength = Math.min(length, s.capacity() - (index - adjustment));
buffers.add(s.toByteBuffer(index - adjustment, localLength));
index += localLength;
length -= localLength;
i ++;
}
return buffers.toArray(new ByteBuffer[buffers.size()]);
}
private int componentId(int index) {
int lastComponentId = lastAccessedComponentId;
if (index >= indices[lastComponentId]) {
if (index < indices[lastComponentId + 1]) {
return lastComponentId;
}
// Search right
for (int i = lastComponentId + 1; i < components.length; i ++) {
if (index < indices[i + 1]) {
lastAccessedComponentId = i;
return i;
}
}
} else {
// Search left
for (int i = lastComponentId - 1; i >= 0; i --) {
if (index >= indices[i]) {
lastAccessedComponentId = i;
return i;
}
}
}
throw new IndexOutOfBoundsException("Invalid index: " + index + ", maximum: " + indices.length);
}
@Override
public void discardReadBytes() {
// Only the bytes between readerIndex and writerIndex will be kept.
// New readerIndex and writerIndex will become 0 and
// (previous writerIndex - previous readerIndex) respectively.
final int localReaderIndex = readerIndex();
if (localReaderIndex == 0) {
return;
}
int localWriterIndex = writerIndex();
final int bytesToMove = capacity() - localReaderIndex;
List list = decompose(localReaderIndex, bytesToMove);
// If the list is empty we need to assign a new one because
// we get a List that is immutable.
//
// See https://github.com/netty/netty/issues/325
if (list.isEmpty()) {
list = new ArrayList(1);
}
// Add a new buffer so that the capacity of this composite buffer does
// not decrease due to the discarded components.
// XXX Might create too many components if discarded by small amount.
final ChannelBuffer padding = ChannelBuffers.buffer(order(), localReaderIndex);
padding.writerIndex(localReaderIndex);
list.add(padding);
// Reset the index markers to get the index marker values.
int localMarkedReaderIndex = localReaderIndex;
try {
resetReaderIndex();
localMarkedReaderIndex = readerIndex();
} catch (IndexOutOfBoundsException e) {
// ignore
}
int localMarkedWriterIndex = localWriterIndex;
try {
resetWriterIndex();
localMarkedWriterIndex = writerIndex();
} catch (IndexOutOfBoundsException e) {
// ignore
}
setComponents(list);
// reset marked Indexes
localMarkedReaderIndex = Math.max(localMarkedReaderIndex - localReaderIndex, 0);
localMarkedWriterIndex = Math.max(localMarkedWriterIndex - localReaderIndex, 0);
setIndex(localMarkedReaderIndex, localMarkedWriterIndex);
markReaderIndex();
markWriterIndex();
// reset real indexes
localWriterIndex = Math.max(localWriterIndex - localReaderIndex, 0);
setIndex(0, localWriterIndex);
}
@Override
public String toString() {
String result = super.toString();
result = result.substring(0, result.length() - 1);
return result + ", components=" + components.length + ')';
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/DirectChannelBufferFactory.java 0000664 0000000 0000000 00000016770 12255541277 0032113 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* A {@link ChannelBufferFactory} which pre-allocates a large chunk of direct
* buffer and returns its slice on demand. Direct buffers are reclaimed via
* {@link ReferenceQueue} in most JDK implementations, and therefore they are
* deallocated less efficiently than an ordinary heap buffer. Consequently,
* a user will get {@link OutOfMemoryError} when one tries to allocate small
* direct buffers more often than the GC throughput of direct buffers, which
* is much lower than the GC throughput of heap buffers. This factory avoids
* this problem by allocating a large chunk of pre-allocated direct buffer and
* reducing the number of the garbage collected internal direct buffer objects.
*/
public class DirectChannelBufferFactory extends AbstractChannelBufferFactory {
private static final DirectChannelBufferFactory INSTANCE_BE =
new DirectChannelBufferFactory(ByteOrder.BIG_ENDIAN);
private static final DirectChannelBufferFactory INSTANCE_LE =
new DirectChannelBufferFactory(ByteOrder.LITTLE_ENDIAN);
public static ChannelBufferFactory getInstance() {
return INSTANCE_BE;
}
public static ChannelBufferFactory getInstance(ByteOrder defaultEndianness) {
if (defaultEndianness == ByteOrder.BIG_ENDIAN) {
return INSTANCE_BE;
} else if (defaultEndianness == ByteOrder.LITTLE_ENDIAN) {
return INSTANCE_LE;
} else if (defaultEndianness == null) {
throw new NullPointerException("defaultEndianness");
} else {
throw new IllegalStateException("Should not reach here");
}
}
private final Object bigEndianLock = new Object();
private final Object littleEndianLock = new Object();
private final int preallocatedBufCapacity;
private ChannelBuffer preallocatedBEBuf;
private int preallocatedBEBufPos;
private ChannelBuffer preallocatedLEBuf;
private int preallocatedLEBufPos;
/**
* Creates a new factory whose default {@link ByteOrder} is
* {@link ByteOrder#BIG_ENDIAN}.
*/
public DirectChannelBufferFactory() {
this(ByteOrder.BIG_ENDIAN);
}
/**
* Creates a new factory whose default {@link ByteOrder} is
* {@link ByteOrder#BIG_ENDIAN}.
*/
public DirectChannelBufferFactory(int preallocatedBufferCapacity) {
this(ByteOrder.BIG_ENDIAN, preallocatedBufferCapacity);
}
/**
* Creates a new factory with the specified default {@link ByteOrder}.
*
* @param defaultOrder the default {@link ByteOrder} of this factory
*/
public DirectChannelBufferFactory(ByteOrder defaultOrder) {
this(defaultOrder, 1048576);
}
/**
* Creates a new factory with the specified default {@link ByteOrder}.
*
* @param defaultOrder the default {@link ByteOrder} of this factory
*/
public DirectChannelBufferFactory(ByteOrder defaultOrder, int preallocatedBufferCapacity) {
super(defaultOrder);
if (preallocatedBufferCapacity <= 0) {
throw new IllegalArgumentException(
"preallocatedBufCapacity must be greater than 0: " + preallocatedBufferCapacity);
}
preallocatedBufCapacity = preallocatedBufferCapacity;
}
public ChannelBuffer getBuffer(ByteOrder order, int capacity) {
if (order == null) {
throw new NullPointerException("order");
}
if (capacity < 0) {
throw new IllegalArgumentException("capacity: " + capacity);
}
if (capacity == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
if (capacity >= preallocatedBufCapacity) {
return ChannelBuffers.directBuffer(order, capacity);
}
ChannelBuffer slice;
if (order == ByteOrder.BIG_ENDIAN) {
slice = allocateBigEndianBuffer(capacity);
} else {
slice = allocateLittleEndianBuffer(capacity);
}
slice.clear();
return slice;
}
public ChannelBuffer getBuffer(ByteOrder order, byte[] array, int offset, int length) {
if (array == null) {
throw new NullPointerException("array");
}
if (offset < 0) {
throw new IndexOutOfBoundsException("offset: " + offset);
}
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
if (offset + length > array.length) {
throw new IndexOutOfBoundsException("length: " + length);
}
ChannelBuffer buf = getBuffer(order, length);
buf.writeBytes(array, offset, length);
return buf;
}
public ChannelBuffer getBuffer(ByteBuffer nioBuffer) {
if (!nioBuffer.isReadOnly() && nioBuffer.isDirect()) {
return ChannelBuffers.wrappedBuffer(nioBuffer);
}
ChannelBuffer buf = getBuffer(nioBuffer.order(), nioBuffer.remaining());
int pos = nioBuffer.position();
buf.writeBytes(nioBuffer);
nioBuffer.position(pos);
return buf;
}
private ChannelBuffer allocateBigEndianBuffer(int capacity) {
ChannelBuffer slice;
synchronized (bigEndianLock) {
if (preallocatedBEBuf == null) {
preallocatedBEBuf = ChannelBuffers.directBuffer(ByteOrder.BIG_ENDIAN, preallocatedBufCapacity);
slice = preallocatedBEBuf.slice(0, capacity);
preallocatedBEBufPos = capacity;
} else if (preallocatedBEBuf.capacity() - preallocatedBEBufPos >= capacity) {
slice = preallocatedBEBuf.slice(preallocatedBEBufPos, capacity);
preallocatedBEBufPos += capacity;
} else {
preallocatedBEBuf = ChannelBuffers.directBuffer(ByteOrder.BIG_ENDIAN, preallocatedBufCapacity);
slice = preallocatedBEBuf.slice(0, capacity);
preallocatedBEBufPos = capacity;
}
}
return slice;
}
private ChannelBuffer allocateLittleEndianBuffer(int capacity) {
ChannelBuffer slice;
synchronized (littleEndianLock) {
if (preallocatedLEBuf == null) {
preallocatedLEBuf = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, preallocatedBufCapacity);
slice = preallocatedLEBuf.slice(0, capacity);
preallocatedLEBufPos = capacity;
} else if (preallocatedLEBuf.capacity() - preallocatedLEBufPos >= capacity) {
slice = preallocatedLEBuf.slice(preallocatedLEBufPos, capacity);
preallocatedLEBufPos += capacity;
} else {
preallocatedLEBuf = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, preallocatedBufCapacity);
slice = preallocatedLEBuf.slice(0, capacity);
preallocatedLEBufPos = capacity;
}
}
return slice;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/DuplicatedChannelBuffer.java 0000664 0000000 0000000 00000011560 12255541277 0031417 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A derived buffer which simply forwards all data access requests to its
* parent. It is recommended to use {@link ChannelBuffer#duplicate()} instead
* of calling the constructor explicitly.
*/
public class DuplicatedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
private final ChannelBuffer buffer;
public DuplicatedChannelBuffer(ChannelBuffer buffer) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
this.buffer = buffer;
setIndex(buffer.readerIndex(), buffer.writerIndex());
}
private DuplicatedChannelBuffer(DuplicatedChannelBuffer buffer) {
this.buffer = buffer.buffer;
setIndex(buffer.readerIndex(), buffer.writerIndex());
}
public ChannelBuffer unwrap() {
return buffer;
}
public ChannelBufferFactory factory() {
return buffer.factory();
}
public ByteOrder order() {
return buffer.order();
}
public boolean isDirect() {
return buffer.isDirect();
}
public int capacity() {
return buffer.capacity();
}
public boolean hasArray() {
return buffer.hasArray();
}
public byte[] array() {
return buffer.array();
}
public int arrayOffset() {
return buffer.arrayOffset();
}
public byte getByte(int index) {
return buffer.getByte(index);
}
public short getShort(int index) {
return buffer.getShort(index);
}
public int getUnsignedMedium(int index) {
return buffer.getUnsignedMedium(index);
}
public int getInt(int index) {
return buffer.getInt(index);
}
public long getLong(int index) {
return buffer.getLong(index);
}
public ChannelBuffer duplicate() {
return new DuplicatedChannelBuffer(this);
}
public ChannelBuffer copy(int index, int length) {
return buffer.copy(index, length);
}
public ChannelBuffer slice(int index, int length) {
return buffer.slice(index, length);
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
buffer.getBytes(index, dst);
}
public void setByte(int index, int value) {
buffer.setByte(index, value);
}
public void setShort(int index, int value) {
buffer.setShort(index, value);
}
public void setMedium(int index, int value) {
buffer.setMedium(index, value);
}
public void setInt(int index, int value) {
buffer.setInt(index, value);
}
public void setLong(int index, long value) {
buffer.setLong(index, value);
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
buffer.setBytes(index, src, srcIndex, length);
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
buffer.setBytes(index, src, srcIndex, length);
}
public void setBytes(int index, ByteBuffer src) {
buffer.setBytes(index, src);
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
buffer.getBytes(index, out, length);
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
return buffer.getBytes(index, out, length);
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
return buffer.setBytes(index, in, length);
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
return buffer.setBytes(index, in, length);
}
public ByteBuffer toByteBuffer(int index, int length) {
return buffer.toByteBuffer(index, length);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/DynamicChannelBuffer.java 0000664 0000000 0000000 00000020445 12255541277 0030727 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A dynamic capacity buffer which increases its capacity as needed. It is
* recommended to use {@link ChannelBuffers#dynamicBuffer(int)} instead of
* calling the constructor explicitly.
*/
public class DynamicChannelBuffer extends AbstractChannelBuffer {
private final ChannelBufferFactory factory;
private final ByteOrder endianness;
private ChannelBuffer buffer;
public DynamicChannelBuffer(int estimatedLength) {
this(ByteOrder.BIG_ENDIAN, estimatedLength);
}
public DynamicChannelBuffer(ByteOrder endianness, int estimatedLength) {
this(endianness, estimatedLength, HeapChannelBufferFactory.getInstance(endianness));
}
public DynamicChannelBuffer(ByteOrder endianness, int estimatedLength, ChannelBufferFactory factory) {
if (estimatedLength < 0) {
throw new IllegalArgumentException("estimatedLength: " + estimatedLength);
}
if (endianness == null) {
throw new NullPointerException("endianness");
}
if (factory == null) {
throw new NullPointerException("factory");
}
this.factory = factory;
this.endianness = endianness;
buffer = factory.getBuffer(order(), estimatedLength);
}
@Override
public void ensureWritableBytes(int minWritableBytes) {
if (minWritableBytes <= writableBytes()) {
return;
}
int newCapacity;
if (capacity() == 0) {
newCapacity = 1;
} else {
newCapacity = capacity();
}
int minNewCapacity = writerIndex() + minWritableBytes;
while (newCapacity < minNewCapacity) {
newCapacity <<= 1;
// Check if we exceeded the maximum size of 2gb if this is the case then
// newCapacity == 0
//
// https://github.com/netty/netty/issues/258
if (newCapacity == 0) {
throw new IllegalStateException("Maximum size of 2gb exceeded");
}
}
ChannelBuffer newBuffer = factory().getBuffer(order(), newCapacity);
newBuffer.writeBytes(buffer, 0, writerIndex());
buffer = newBuffer;
}
public ChannelBufferFactory factory() {
return factory;
}
public ByteOrder order() {
return endianness;
}
public boolean isDirect() {
return buffer.isDirect();
}
public int capacity() {
return buffer.capacity();
}
public boolean hasArray() {
return buffer.hasArray();
}
public byte[] array() {
return buffer.array();
}
public int arrayOffset() {
return buffer.arrayOffset();
}
public byte getByte(int index) {
return buffer.getByte(index);
}
public short getShort(int index) {
return buffer.getShort(index);
}
public int getUnsignedMedium(int index) {
return buffer.getUnsignedMedium(index);
}
public int getInt(int index) {
return buffer.getInt(index);
}
public long getLong(int index) {
return buffer.getLong(index);
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
buffer.getBytes(index, dst);
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
return buffer.getBytes(index, out, length);
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
buffer.getBytes(index, out, length);
}
public void setByte(int index, int value) {
buffer.setByte(index, value);
}
public void setShort(int index, int value) {
buffer.setShort(index, value);
}
public void setMedium(int index, int value) {
buffer.setMedium(index, value);
}
public void setInt(int index, int value) {
buffer.setInt(index, value);
}
public void setLong(int index, long value) {
buffer.setLong(index, value);
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
buffer.setBytes(index, src, srcIndex, length);
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
buffer.setBytes(index, src, srcIndex, length);
}
public void setBytes(int index, ByteBuffer src) {
buffer.setBytes(index, src);
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
return buffer.setBytes(index, in, length);
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
return buffer.setBytes(index, in, length);
}
@Override
public void writeByte(int value) {
ensureWritableBytes(1);
super.writeByte(value);
}
@Override
public void writeShort(int value) {
ensureWritableBytes(2);
super.writeShort(value);
}
@Override
public void writeMedium(int value) {
ensureWritableBytes(3);
super.writeMedium(value);
}
@Override
public void writeInt(int value) {
ensureWritableBytes(4);
super.writeInt(value);
}
@Override
public void writeLong(long value) {
ensureWritableBytes(8);
super.writeLong(value);
}
@Override
public void writeBytes(byte[] src, int srcIndex, int length) {
ensureWritableBytes(length);
super.writeBytes(src, srcIndex, length);
}
@Override
public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
ensureWritableBytes(length);
super.writeBytes(src, srcIndex, length);
}
@Override
public void writeBytes(ByteBuffer src) {
ensureWritableBytes(src.remaining());
super.writeBytes(src);
}
@Override
public int writeBytes(InputStream in, int length) throws IOException {
ensureWritableBytes(length);
return super.writeBytes(in, length);
}
@Override
public int writeBytes(ScatteringByteChannel in, int length)
throws IOException {
ensureWritableBytes(length);
return super.writeBytes(in, length);
}
@Override
public void writeZero(int length) {
ensureWritableBytes(length);
super.writeZero(length);
}
public ChannelBuffer duplicate() {
return new DuplicatedChannelBuffer(this);
}
public ChannelBuffer copy(int index, int length) {
DynamicChannelBuffer copiedBuffer = new DynamicChannelBuffer(order(), Math.max(length, 64), factory());
copiedBuffer.buffer = buffer.copy(index, length);
copiedBuffer.setIndex(0, length);
return copiedBuffer;
}
public ChannelBuffer slice(int index, int length) {
if (index == 0) {
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
return new TruncatedChannelBuffer(this, length);
} else {
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
return new SlicedChannelBuffer(this, index, length);
}
}
public ByteBuffer toByteBuffer(int index, int length) {
return buffer.toByteBuffer(index, length);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/EmptyChannelBuffer.java 0000664 0000000 0000000 00000013264 12255541277 0030442 0 ustar 00root root 0000000 0000000 /*
* Copyright 2013 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* An immutable empty buffer implementation. Typically used as a singleton via
* {@link ChannelBuffers#EMPTY_BUFFER} and returned by {@link ChannelBuffers#buffer(int)} etc when
* an empty buffer is requested.
*
* Note: For backwards compatibility, this class extends {@link BigEndianHeapChannelBuffer}.
* However, it never makes any writes to the reader and writer indices, which avoids contention
* when the singleton instance is used concurrently.
*/
public class EmptyChannelBuffer extends BigEndianHeapChannelBuffer {
private static final byte[] BUFFER = {};
EmptyChannelBuffer() {
super(BUFFER);
}
@Override
public void clear() {
}
@Override
public void readerIndex(int readerIndex) {
if (readerIndex != 0) {
throw new IndexOutOfBoundsException("Invalid readerIndex: "
+ readerIndex + " - Maximum is 0");
}
}
@Override
public void writerIndex(int writerIndex) {
if (writerIndex != 0) {
throw new IndexOutOfBoundsException("Invalid writerIndex: "
+ writerIndex + " - Maximum is 0");
}
}
@Override
public void setIndex(int readerIndex, int writerIndex) {
if (writerIndex != 0 || readerIndex != 0) {
throw new IndexOutOfBoundsException("Invalid writerIndex: "
+ writerIndex + " - Maximum is " + readerIndex + " or "
+ capacity());
}
}
@Override
public void markReaderIndex() {
}
@Override
public void resetReaderIndex() {
}
@Override
public void markWriterIndex() {
}
@Override
public void resetWriterIndex() {
}
@Override
public void discardReadBytes() {
}
@Override
public ChannelBuffer readBytes(int length) {
checkReadableBytes(length);
return this;
}
@Override
public ChannelBuffer readSlice(int length) {
checkReadableBytes(length);
return this;
}
@Override
public void readBytes(byte[] dst, int dstIndex, int length) {
checkReadableBytes(length);
}
@Override
public void readBytes(byte[] dst) {
checkReadableBytes(dst.length);
}
@Override
public void readBytes(ChannelBuffer dst) {
checkReadableBytes(dst.writableBytes());
}
@Override
public void readBytes(ChannelBuffer dst, int length) {
checkReadableBytes(length);
}
@Override
public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
checkReadableBytes(length);
}
@Override
public void readBytes(ByteBuffer dst) {
checkReadableBytes(dst.remaining());
}
@Override
public int readBytes(GatheringByteChannel out, int length) throws IOException {
checkReadableBytes(length);
return 0;
}
@Override
public void readBytes(OutputStream out, int length) throws IOException {
checkReadableBytes(length);
}
@Override
public void skipBytes(int length) {
checkReadableBytes(length);
}
@Override
public void writeBytes(byte[] src, int srcIndex, int length) {
checkWritableBytes(length);
}
@Override
public void writeBytes(ChannelBuffer src, int length) {
checkWritableBytes(length);
}
@Override
public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
checkWritableBytes(length);
}
@Override
public void writeBytes(ByteBuffer src) {
checkWritableBytes(src.remaining());
}
@Override
public int writeBytes(InputStream in, int length) throws IOException {
checkWritableBytes(length);
return 0;
}
@Override
public int writeBytes(ScatteringByteChannel in, int length) throws IOException {
checkWritableBytes(length);
return 0;
}
@Override
public void writeZero(int length) {
checkWritableBytes(length);
}
/**
* Throws an {@link IndexOutOfBoundsException} the length is not 0.
*/
private void checkWritableBytes(int length) {
if (length == 0) {
return;
}
if (length > 0) {
throw new IndexOutOfBoundsException("Writable bytes exceeded - Need "
+ length + ", maximum is " + 0);
} else {
throw new IndexOutOfBoundsException("length < 0");
}
}
/**
* Throws an {@link IndexOutOfBoundsException} the length is not 0.
*/
protected void checkReadableBytes(int length) {
if (length == 0) {
return;
}
if (length > 0) {
throw new IndexOutOfBoundsException("Not enough readable bytes - Need "
+ length + ", maximum is " + readableBytes());
} else {
throw new IndexOutOfBoundsException("length < 0");
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/HeapChannelBuffer.java 0000664 0000000 0000000 00000014074 12255541277 0030221 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A skeletal implementation for Java heap buffers.
*/
public abstract class HeapChannelBuffer extends AbstractChannelBuffer {
/**
* The underlying heap byte array that this buffer is wrapping.
*/
protected final byte[] array;
/**
* Creates a new heap buffer with a newly allocated byte array.
*
* @param length the length of the new byte array
*/
protected HeapChannelBuffer(int length) {
this(new byte[length], 0, 0);
}
/**
* Creates a new heap buffer with an existing byte array.
*
* @param array the byte array to wrap
*/
protected HeapChannelBuffer(byte[] array) {
this(array, 0, array.length);
}
/**
* Creates a new heap buffer with an existing byte array.
*
* @param array the byte array to wrap
* @param readerIndex the initial reader index of this buffer
* @param writerIndex the initial writer index of this buffer
*/
protected HeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
if (array == null) {
throw new NullPointerException("array");
}
this.array = array;
setIndex(readerIndex, writerIndex);
}
public boolean isDirect() {
return false;
}
public int capacity() {
return array.length;
}
public boolean hasArray() {
return true;
}
public byte[] array() {
return array;
}
public int arrayOffset() {
return 0;
}
public byte getByte(int index) {
return array[index];
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
if (dst instanceof HeapChannelBuffer) {
getBytes(index, ((HeapChannelBuffer) dst).array, dstIndex, length);
} else {
dst.setBytes(dstIndex, array, index, length);
}
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
System.arraycopy(array, index, dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
out.write(array, index, length);
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
return out.write(ByteBuffer.wrap(array, index, length));
}
public void setByte(int index, int value) {
array[index] = (byte) value;
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
if (src instanceof HeapChannelBuffer) {
setBytes(index, ((HeapChannelBuffer) src).array, srcIndex, length);
} else {
src.getBytes(srcIndex, array, index, length);
}
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
System.arraycopy(src, srcIndex, array, index, length);
}
public void setBytes(int index, ByteBuffer src) {
src.get(array, index, src.remaining());
}
public int setBytes(int index, InputStream in, int length) throws IOException {
int readBytes = 0;
do {
int localReadBytes = in.read(array, index, length);
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
readBytes += localReadBytes;
index += localReadBytes;
length -= localReadBytes;
} while (length > 0);
return readBytes;
}
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
ByteBuffer buf = ByteBuffer.wrap(array, index, length);
int readBytes = 0;
do {
int localReadBytes;
try {
localReadBytes = in.read(buf);
} catch (ClosedChannelException e) {
localReadBytes = -1;
}
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
if (localReadBytes == 0) {
break;
}
readBytes += localReadBytes;
} while (readBytes < length);
return readBytes;
}
public ChannelBuffer slice(int index, int length) {
if (index == 0) {
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
if (length == array.length) {
ChannelBuffer slice = duplicate();
slice.setIndex(0, length);
return slice;
} else {
return new TruncatedChannelBuffer(this, length);
}
} else {
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
return new SlicedChannelBuffer(this, index, length);
}
}
public ByteBuffer toByteBuffer(int index, int length) {
return ByteBuffer.wrap(array, index, length).order(order());
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/HeapChannelBufferFactory.java 0000664 0000000 0000000 00000005677 12255541277 0031562 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* A {@link ChannelBufferFactory} which merely allocates a heap buffer with
* the specified capacity. {@link HeapChannelBufferFactory} should perform
* very well in most situations because it relies on the JVM garbage collector,
* which is highly optimized for heap allocation.
*/
public class HeapChannelBufferFactory extends AbstractChannelBufferFactory {
private static final HeapChannelBufferFactory INSTANCE_BE =
new HeapChannelBufferFactory(ByteOrder.BIG_ENDIAN);
private static final HeapChannelBufferFactory INSTANCE_LE =
new HeapChannelBufferFactory(ByteOrder.LITTLE_ENDIAN);
public static ChannelBufferFactory getInstance() {
return INSTANCE_BE;
}
public static ChannelBufferFactory getInstance(ByteOrder endianness) {
if (endianness == ByteOrder.BIG_ENDIAN) {
return INSTANCE_BE;
} else if (endianness == ByteOrder.LITTLE_ENDIAN) {
return INSTANCE_LE;
} else if (endianness == null) {
throw new NullPointerException("endianness");
} else {
throw new IllegalStateException("Should not reach here");
}
}
/**
* Creates a new factory whose default {@link ByteOrder} is
* {@link ByteOrder#BIG_ENDIAN}.
*/
public HeapChannelBufferFactory() {
}
/**
* Creates a new factory with the specified default {@link ByteOrder}.
*
* @param defaultOrder the default {@link ByteOrder} of this factory
*/
public HeapChannelBufferFactory(ByteOrder defaultOrder) {
super(defaultOrder);
}
public ChannelBuffer getBuffer(ByteOrder order, int capacity) {
return ChannelBuffers.buffer(order, capacity);
}
public ChannelBuffer getBuffer(ByteOrder order, byte[] array, int offset, int length) {
return ChannelBuffers.wrappedBuffer(order, array, offset, length);
}
public ChannelBuffer getBuffer(ByteBuffer nioBuffer) {
if (nioBuffer.hasArray()) {
return ChannelBuffers.wrappedBuffer(nioBuffer);
}
ChannelBuffer buf = getBuffer(nioBuffer.order(), nioBuffer.remaining());
int pos = nioBuffer.position();
buf.writeBytes(nioBuffer);
nioBuffer.position(pos);
return buf;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/LittleEndianHeapChannelBuffer.java 0000664 0000000 0000000 00000010576 12255541277 0032521 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.nio.ByteOrder;
/**
* A little-endian Java heap buffer. It is recommended to use {@link ChannelBuffers#buffer(ByteOrder, int)}
* and {@link ChannelBuffers#wrappedBuffer(ByteOrder, byte[])} instead of
* calling the constructor explicitly.
*/
public class LittleEndianHeapChannelBuffer extends HeapChannelBuffer {
/**
* Creates a new little-endian heap buffer with a newly allocated byte array.
*
* @param length the length of the new byte array
*/
public LittleEndianHeapChannelBuffer(int length) {
super(length);
}
/**
* Creates a new little-endian heap buffer with an existing byte array.
*
* @param array the byte array to wrap
*/
public LittleEndianHeapChannelBuffer(byte[] array) {
super(array);
}
private LittleEndianHeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
super(array, readerIndex, writerIndex);
}
public ChannelBufferFactory factory() {
return HeapChannelBufferFactory.getInstance(ByteOrder.LITTLE_ENDIAN);
}
public ByteOrder order() {
return ByteOrder.LITTLE_ENDIAN;
}
public short getShort(int index) {
return (short) (array[index] & 0xFF | array[index + 1] << 8);
}
public int getUnsignedMedium(int index) {
return array[index] & 0xff |
(array[index + 1] & 0xff) << 8 |
(array[index + 2] & 0xff) << 16;
}
public int getInt(int index) {
return array[index] & 0xff |
(array[index + 1] & 0xff) << 8 |
(array[index + 2] & 0xff) << 16 |
(array[index + 3] & 0xff) << 24;
}
public long getLong(int index) {
return (long) array[index] & 0xff |
((long) array[index + 1] & 0xff) << 8 |
((long) array[index + 2] & 0xff) << 16 |
((long) array[index + 3] & 0xff) << 24 |
((long) array[index + 4] & 0xff) << 32 |
((long) array[index + 5] & 0xff) << 40 |
((long) array[index + 6] & 0xff) << 48 |
((long) array[index + 7] & 0xff) << 56;
}
public void setShort(int index, int value) {
array[index] = (byte) value;
array[index + 1] = (byte) (value >>> 8);
}
public void setMedium(int index, int value) {
array[index] = (byte) value;
array[index + 1] = (byte) (value >>> 8);
array[index + 2] = (byte) (value >>> 16);
}
public void setInt(int index, int value) {
array[index] = (byte) value;
array[index + 1] = (byte) (value >>> 8);
array[index + 2] = (byte) (value >>> 16);
array[index + 3] = (byte) (value >>> 24);
}
public void setLong(int index, long value) {
array[index] = (byte) value;
array[index + 1] = (byte) (value >>> 8);
array[index + 2] = (byte) (value >>> 16);
array[index + 3] = (byte) (value >>> 24);
array[index + 4] = (byte) (value >>> 32);
array[index + 5] = (byte) (value >>> 40);
array[index + 6] = (byte) (value >>> 48);
array[index + 7] = (byte) (value >>> 56);
}
public ChannelBuffer duplicate() {
return new LittleEndianHeapChannelBuffer(array, readerIndex(), writerIndex());
}
public ChannelBuffer copy(int index, int length) {
if (index < 0 || length < 0 || index + length > array.length) {
throw new IndexOutOfBoundsException("Too many bytes to copy - Need "
+ (index + length) + ", maximum is " + array.length);
}
byte[] copiedArray = new byte[length];
System.arraycopy(array, index, copiedArray, 0, length);
return new LittleEndianHeapChannelBuffer(copiedArray);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/ReadOnlyChannelBuffer.java 0000664 0000000 0000000 00000012526 12255541277 0031061 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A derived buffer which forbids any write requests to its parent. It is
* recommended to use {@link ChannelBuffers#unmodifiableBuffer(ChannelBuffer)}
* instead of calling the constructor explicitly.
*/
public class ReadOnlyChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
private final ChannelBuffer buffer;
public ReadOnlyChannelBuffer(ChannelBuffer buffer) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
this.buffer = buffer;
setIndex(buffer.readerIndex(), buffer.writerIndex());
}
private ReadOnlyChannelBuffer(ReadOnlyChannelBuffer buffer) {
this.buffer = buffer.buffer;
setIndex(buffer.readerIndex(), buffer.writerIndex());
}
public ChannelBuffer unwrap() {
return buffer;
}
public ChannelBufferFactory factory() {
return buffer.factory();
}
public ByteOrder order() {
return buffer.order();
}
public boolean isDirect() {
return buffer.isDirect();
}
public boolean hasArray() {
return false;
}
public byte[] array() {
throw new ReadOnlyBufferException();
}
public int arrayOffset() {
throw new ReadOnlyBufferException();
}
@Override
public void discardReadBytes() {
throw new ReadOnlyBufferException();
}
public void setByte(int index, int value) {
throw new ReadOnlyBufferException();
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
throw new ReadOnlyBufferException();
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
throw new ReadOnlyBufferException();
}
public void setBytes(int index, ByteBuffer src) {
throw new ReadOnlyBufferException();
}
public void setShort(int index, int value) {
throw new ReadOnlyBufferException();
}
public void setMedium(int index, int value) {
throw new ReadOnlyBufferException();
}
public void setInt(int index, int value) {
throw new ReadOnlyBufferException();
}
public void setLong(int index, long value) {
throw new ReadOnlyBufferException();
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
throw new ReadOnlyBufferException();
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
throw new ReadOnlyBufferException();
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
return buffer.getBytes(index, out, length);
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
buffer.getBytes(index, out, length);
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
buffer.getBytes(index, dst);
}
public ChannelBuffer duplicate() {
return new ReadOnlyChannelBuffer(this);
}
public ChannelBuffer copy(int index, int length) {
return buffer.copy(index, length);
}
public ChannelBuffer slice(int index, int length) {
return new ReadOnlyChannelBuffer(buffer.slice(index, length));
}
public byte getByte(int index) {
return buffer.getByte(index);
}
public short getShort(int index) {
return buffer.getShort(index);
}
public int getUnsignedMedium(int index) {
return buffer.getUnsignedMedium(index);
}
public int getInt(int index) {
return buffer.getInt(index);
}
public long getLong(int index) {
return buffer.getLong(index);
}
public ByteBuffer toByteBuffer(int index, int length) {
return buffer.toByteBuffer(index, length).asReadOnlyBuffer();
}
@Override
public ByteBuffer[] toByteBuffers(int index, int length) {
ByteBuffer[] bufs = buffer.toByteBuffers(index, length);
for (int i = 0; i < bufs.length; i ++) {
bufs[i] = bufs[i].asReadOnlyBuffer();
}
return bufs;
}
public int capacity() {
return buffer.capacity();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/SlicedChannelBuffer.java 0000664 0000000 0000000 00000016226 12255541277 0030550 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A derived buffer which exposes its parent's sub-region only. It is
* recommended to use {@link ChannelBuffer#slice()} and
* {@link ChannelBuffer#slice(int, int)} instead of calling the constructor
* explicitly.
*/
public class SlicedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
private final ChannelBuffer buffer;
private final int adjustment;
private final int length;
public SlicedChannelBuffer(ChannelBuffer buffer, int index, int length) {
if (index < 0 || index > buffer.capacity()) {
throw new IndexOutOfBoundsException("Invalid index of " + index
+ ", maximum is " + buffer.capacity());
}
if (index + length > buffer.capacity()) {
throw new IndexOutOfBoundsException("Invalid combined index of "
+ (index + length) + ", maximum is " + buffer.capacity());
}
this.buffer = buffer;
adjustment = index;
this.length = length;
writerIndex(length);
}
public ChannelBuffer unwrap() {
return buffer;
}
public ChannelBufferFactory factory() {
return buffer.factory();
}
public ByteOrder order() {
return buffer.order();
}
public boolean isDirect() {
return buffer.isDirect();
}
public int capacity() {
return length;
}
public boolean hasArray() {
return buffer.hasArray();
}
public byte[] array() {
return buffer.array();
}
public int arrayOffset() {
return buffer.arrayOffset() + adjustment;
}
public byte getByte(int index) {
checkIndex(index);
return buffer.getByte(index + adjustment);
}
public short getShort(int index) {
checkIndex(index, 2);
return buffer.getShort(index + adjustment);
}
public int getUnsignedMedium(int index) {
checkIndex(index, 3);
return buffer.getUnsignedMedium(index + adjustment);
}
public int getInt(int index) {
checkIndex(index, 4);
return buffer.getInt(index + adjustment);
}
public long getLong(int index) {
checkIndex(index, 8);
return buffer.getLong(index + adjustment);
}
public ChannelBuffer duplicate() {
ChannelBuffer duplicate = new SlicedChannelBuffer(buffer, adjustment, length);
duplicate.setIndex(readerIndex(), writerIndex());
return duplicate;
}
public ChannelBuffer copy(int index, int length) {
checkIndex(index, length);
return buffer.copy(index + adjustment, length);
}
public ChannelBuffer slice(int index, int length) {
checkIndex(index, length);
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
return new SlicedChannelBuffer(buffer, index + adjustment, length);
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
checkIndex(index, length);
buffer.getBytes(index + adjustment, dst, dstIndex, length);
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length);
buffer.getBytes(index + adjustment, dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
checkIndex(index, dst.remaining());
buffer.getBytes(index + adjustment, dst);
}
public void setByte(int index, int value) {
checkIndex(index);
buffer.setByte(index + adjustment, value);
}
public void setShort(int index, int value) {
checkIndex(index, 2);
buffer.setShort(index + adjustment, value);
}
public void setMedium(int index, int value) {
checkIndex(index, 3);
buffer.setMedium(index + adjustment, value);
}
public void setInt(int index, int value) {
checkIndex(index, 4);
buffer.setInt(index + adjustment, value);
}
public void setLong(int index, long value) {
checkIndex(index, 8);
buffer.setLong(index + adjustment, value);
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length);
buffer.setBytes(index + adjustment, src, srcIndex, length);
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
checkIndex(index, length);
buffer.setBytes(index + adjustment, src, srcIndex, length);
}
public void setBytes(int index, ByteBuffer src) {
checkIndex(index, src.remaining());
buffer.setBytes(index + adjustment, src);
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
checkIndex(index, length);
buffer.getBytes(index + adjustment, out, length);
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
checkIndex(index, length);
return buffer.getBytes(index + adjustment, out, length);
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
checkIndex(index, length);
return buffer.setBytes(index + adjustment, in, length);
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
checkIndex(index, length);
return buffer.setBytes(index + adjustment, in, length);
}
public ByteBuffer toByteBuffer(int index, int length) {
checkIndex(index, length);
return buffer.toByteBuffer(index + adjustment, length);
}
private void checkIndex(int index) {
if (index < 0 || index >= capacity()) {
throw new IndexOutOfBoundsException("Invalid index: " + index
+ ", maximum is " + capacity());
}
}
private void checkIndex(int startIndex, int length) {
if (length < 0) {
throw new IllegalArgumentException(
"length is negative: " + length);
}
if (startIndex < 0) {
throw new IndexOutOfBoundsException("startIndex cannot be negative");
}
if (startIndex + length > capacity()) {
throw new IndexOutOfBoundsException("Index too big - Bytes needed: "
+ (startIndex + length) + ", maximum is " + capacity());
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/TruncatedChannelBuffer.java 0000664 0000000 0000000 00000014652 12255541277 0031277 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
/**
* A derived buffer which hides its parent's tail data beyond a certain index.
* It is recommended to use {@link ChannelBuffer#slice()} and
* {@link ChannelBuffer#slice(int, int)} instead of calling the constructor
* explicitly.
*/
public class TruncatedChannelBuffer extends AbstractChannelBuffer implements WrappedChannelBuffer {
private final ChannelBuffer buffer;
private final int length;
public TruncatedChannelBuffer(ChannelBuffer buffer, int length) {
if (length > buffer.capacity()) {
throw new IndexOutOfBoundsException("Length is too large, got "
+ length + " but can't go higher than " + buffer.capacity());
}
this.buffer = buffer;
this.length = length;
writerIndex(length);
}
public ChannelBuffer unwrap() {
return buffer;
}
public ChannelBufferFactory factory() {
return buffer.factory();
}
public ByteOrder order() {
return buffer.order();
}
public boolean isDirect() {
return buffer.isDirect();
}
public int capacity() {
return length;
}
public boolean hasArray() {
return buffer.hasArray();
}
public byte[] array() {
return buffer.array();
}
public int arrayOffset() {
return buffer.arrayOffset();
}
public byte getByte(int index) {
checkIndex(index);
return buffer.getByte(index);
}
public short getShort(int index) {
checkIndex(index, 2);
return buffer.getShort(index);
}
public int getUnsignedMedium(int index) {
checkIndex(index, 3);
return buffer.getUnsignedMedium(index);
}
public int getInt(int index) {
checkIndex(index, 4);
return buffer.getInt(index);
}
public long getLong(int index) {
checkIndex(index, 8);
return buffer.getLong(index);
}
public ChannelBuffer duplicate() {
ChannelBuffer duplicate = new TruncatedChannelBuffer(buffer, length);
duplicate.setIndex(readerIndex(), writerIndex());
return duplicate;
}
public ChannelBuffer copy(int index, int length) {
checkIndex(index, length);
return buffer.copy(index, length);
}
public ChannelBuffer slice(int index, int length) {
checkIndex(index, length);
if (length == 0) {
return ChannelBuffers.EMPTY_BUFFER;
}
return buffer.slice(index, length);
}
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
checkIndex(index, length);
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length);
buffer.getBytes(index, dst, dstIndex, length);
}
public void getBytes(int index, ByteBuffer dst) {
checkIndex(index, dst.remaining());
buffer.getBytes(index, dst);
}
public void setByte(int index, int value) {
checkIndex(index);
buffer.setByte(index, value);
}
public void setShort(int index, int value) {
checkIndex(index, 2);
buffer.setShort(index, value);
}
public void setMedium(int index, int value) {
checkIndex(index, 3);
buffer.setMedium(index, value);
}
public void setInt(int index, int value) {
checkIndex(index, 4);
buffer.setInt(index, value);
}
public void setLong(int index, long value) {
checkIndex(index, 8);
buffer.setLong(index, value);
}
public void setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length);
buffer.setBytes(index, src, srcIndex, length);
}
public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
checkIndex(index, length);
buffer.setBytes(index, src, srcIndex, length);
}
public void setBytes(int index, ByteBuffer src) {
checkIndex(index, src.remaining());
buffer.setBytes(index, src);
}
public void getBytes(int index, OutputStream out, int length)
throws IOException {
checkIndex(index, length);
buffer.getBytes(index, out, length);
}
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
checkIndex(index, length);
return buffer.getBytes(index, out, length);
}
public int setBytes(int index, InputStream in, int length)
throws IOException {
checkIndex(index, length);
return buffer.setBytes(index, in, length);
}
public int setBytes(int index, ScatteringByteChannel in, int length)
throws IOException {
checkIndex(index, length);
return buffer.setBytes(index, in, length);
}
public ByteBuffer toByteBuffer(int index, int length) {
checkIndex(index, length);
return buffer.toByteBuffer(index, length);
}
private void checkIndex(int index) {
if (index < 0 || index >= capacity()) {
throw new IndexOutOfBoundsException("Invalid index of " + index
+ ", maximum is " + capacity());
}
}
private void checkIndex(int index, int length) {
if (length < 0) {
throw new IllegalArgumentException(
"length is negative: " + length);
}
if (index + length > capacity()) {
throw new IndexOutOfBoundsException("Invalid index of "
+ (index + length) + ", maximum is " + capacity());
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/WrappedChannelBuffer.java 0000664 0000000 0000000 00000001752 12255541277 0030745 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.buffer;
/**
* The common interface for buffer wrappers and derived buffers. Most users won't
* need to use this interface. It is used internally in most cases.
*/
public interface WrappedChannelBuffer extends ChannelBuffer {
/**
* Returns this buffer's parent that this buffer is wrapping.
*/
ChannelBuffer unwrap();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/buffer/package-info.java 0000664 0000000 0000000 00000014445 12255541277 0027247 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Abstraction of a byte buffer - the fundamental data structure
* to represent a low-level binary and text message.
*
* Netty uses its own buffer API instead of NIO {@link java.nio.ByteBuffer} to
* represent a sequence of bytes. This approach has significant advantage over
* using {@link java.nio.ByteBuffer}. Netty's new buffer type,
* {@link org.jboss.netty.buffer.ChannelBuffer}, has been designed from ground
* up to address the problems of {@link java.nio.ByteBuffer} and to meet the
* daily needs of network application developers. To list a few cool features:
*
* You can define your buffer type if necessary.
* Transparent zero copy is achieved by built-in composite buffer type.
* A dynamic buffer type is provided out-of-the-box, whose capacity is
* expanded on demand, just like {@link java.lang.StringBuffer}.
* There's no need to call the {@code flip()} method anymore.
* It is often faster than {@link java.nio.ByteBuffer}.
*
*
* Extensibility
*
* {@link org.jboss.netty.buffer.ChannelBuffer} has rich set of operations
* optimized for rapid protocol implementation. For example,
* {@link org.jboss.netty.buffer.ChannelBuffer} provides various operations
* for accessing unsigned values and strings and searching for certain byte
* sequence in a buffer. You can also extend or wrap existing buffer type
* to add convenient accessors. The custom buffer type still implements
* {@link org.jboss.netty.buffer.ChannelBuffer} interface rather than
* introducing an incompatible type.
*
* Transparent Zero Copy
*
* To lift up the performance of a network application to the extreme, you need
* to reduce the number of memory copy operation. You might have a set of
* buffers that could be sliced and combined to compose a whole message. Netty
* provides a composite buffer which allows you to create a new buffer from the
* arbitrary number of existing buffers with no memory copy. For example, a
* message could be composed of two parts; header and body. In a modularized
* application, the two parts could be produced by different modules and
* assembled later when the message is sent out.
*
* +--------+----------+
* | header | body |
* +--------+----------+
*
* If {@link java.nio.ByteBuffer} were used, you would have to create a new big
* buffer and copy the two parts into the new buffer. Alternatively, you can
* perform a gathering write operation in NIO, but it restricts you to represent
* the composite of buffers as an array of {@link java.nio.ByteBuffer}s rather
* than a single buffer, breaking the abstraction and introducing complicated
* state management. Moreover, it's of no use if you are not going to read or
* write from an NIO channel.
*
* // The composite type is incompatible with the component type.
* ByteBuffer[] message = new ByteBuffer[] { header, body };
*
* By contrast, {@link org.jboss.netty.buffer.ChannelBuffer} does not have such
* caveats because it is fully extensible and has a built-in composite buffer
* type.
*
* // The composite type is compatible with the component type.
* ChannelBuffer message = ChannelBuffers.wrappedBuffer(header, body);
*
* // Therefore, you can even create a composite by mixing a composite and an
* // ordinary buffer.
* ChannelBuffer messageWithFooter = ChannelBuffers.wrappedBuffer(message, footer);
*
* // Because the composite is still a ChannelBuffer, you can access its content
* // easily, and the accessor method will behave just like it's a single buffer
* // even if the region you want to access spans over multiple components. The
* // unsigned integer being read here is located across body and footer.
* messageWithFooter.getUnsignedInt(
* messageWithFooter.readableBytes() - footer.readableBytes() - 1);
*
*
* Automatic Capacity Extension
*
* Many protocols define variable length messages, which means there's no way to
* determine the length of a message until you construct the message or it is
* difficult and inconvenient to calculate the length precisely. It is just
* like when you build a {@link java.lang.String}. You often estimate the length
* of the resulting string and let {@link java.lang.StringBuffer} expand itself
* on demand. Netty allows you to do the same via a dynamic buffer
* which is created by the
* {@link org.jboss.netty.buffer.ChannelBuffers#dynamicBuffer()} method.
*
* // A new dynamic buffer is created. Internally, the actual buffer is created
* // lazily to avoid potentially wasted memory space.
* ChannelBuffer b = ChannelBuffers.dynamicBuffer(4);
*
* // When the first write attempt is made, the internal buffer is created with
* // the specified initial capacity (4).
* b.writeByte('1');
*
* b.writeByte('2');
* b.writeByte('3');
* b.writeByte('4');
*
* // When the number of written bytes exceeds the initial capacity (4), the
* // internal buffer is reallocated automatically with a larger capacity.
* b.writeByte('5');
*
*
* Better Performance
*
* Most frequently used buffer implementation of
* {@link org.jboss.netty.buffer.ChannelBuffer} is a very thin wrapper of a
* byte array (i.e. {@code byte[]}). Unlike {@link java.nio.ByteBuffer}, it has
* no complicated boundary check and index compensation, and therefore it is
* easier for a JVM to optimize the buffer access. More complicated buffer
* implementation is used only for sliced or composite buffers, and it performs
* as well as {@link java.nio.ByteBuffer}.
*
* @apiviz.landmark
* @apiviz.exclude ^java\.lang\.
* @apiviz.exclude ^java\.io\.[^\.]+Stream$
*/
package org.jboss.netty.buffer;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ 0000775 0000000 0000000 00000000000 12255541277 0024207 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/AbstractChannel.java 0000664 0000000 0000000 00000024445 12255541277 0030117 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.util.internal.ConcurrentHashMap;
import java.net.SocketAddress;
import java.util.Random;
import java.util.concurrent.ConcurrentMap;
/**
* A skeletal {@link Channel} implementation.
*/
public abstract class AbstractChannel implements Channel {
static final ConcurrentMap allChannels = new ConcurrentHashMap();
private static final Random random = new Random();
private static Integer allocateId(Channel channel) {
Integer id = random.nextInt();
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 = id.intValue() + 1;
}
}
}
private final Integer id;
private final Channel parent;
private final ChannelFactory factory;
private final ChannelPipeline pipeline;
private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
private final ChannelCloseFuture closeFuture = new ChannelCloseFuture();
private volatile int interestOps = OP_READ;
/** Cache for the string representation of this channel */
private boolean strValConnected;
private String strVal;
private volatile Object attachment;
/**
* 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
*/
protected AbstractChannel(
Channel parent, ChannelFactory factory,
ChannelPipeline pipeline, ChannelSink sink) {
this.parent = parent;
this.factory = factory;
this.pipeline = pipeline;
id = allocateId(this);
pipeline.attach(this, sink);
}
/**
* (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.
* @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
*/
protected AbstractChannel(
Integer id,
Channel parent, ChannelFactory factory,
ChannelPipeline pipeline, ChannelSink sink) {
this.id = id;
this.parent = parent;
this.factory = factory;
this.pipeline = pipeline;
pipeline.attach(this, sink);
}
public final Integer getId() {
return id;
}
public Channel getParent() {
return parent;
}
public ChannelFactory getFactory() {
return factory;
}
public ChannelPipeline getPipeline() {
return pipeline;
}
/**
* Returns the cached {@link SucceededChannelFuture} instance.
*/
protected ChannelFuture getSucceededFuture() {
return succeededFuture;
}
/**
* Returns the {@link FailedChannelFuture} whose cause is an
* {@link UnsupportedOperationException}.
*/
protected ChannelFuture getUnsupportedOperationFuture() {
return new FailedChannelFuture(this, new UnsupportedOperationException());
}
/**
* Returns the ID of this channel.
*/
@Override
public final int hashCode() {
return id;
}
/**
* Returns {@code true} if and only if the specified object is identical
* with this channel (i.e: {@code this == o}).
*/
@Override
public final boolean equals(Object o) {
return this == o;
}
/**
* Compares the {@linkplain #getId() ID} of the two channels.
*/
public final int compareTo(Channel o) {
return getId().compareTo(o.getId());
}
public boolean isOpen() {
return !closeFuture.isDone();
}
/**
* 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
*/
protected boolean setClosed() {
// Deallocate the current channel's ID from allChannels so that other
// new channels can use it.
allChannels.remove(id);
return closeFuture.setClosed();
}
public ChannelFuture bind(SocketAddress localAddress) {
return Channels.bind(this, localAddress);
}
public ChannelFuture unbind() {
return Channels.unbind(this);
}
public ChannelFuture close() {
ChannelFuture returnedCloseFuture = Channels.close(this);
assert closeFuture == returnedCloseFuture;
return closeFuture;
}
public ChannelFuture getCloseFuture() {
return closeFuture;
}
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);
}
/**
* 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.
*/
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);
}
public Object getAttachment() {
return attachment;
}
public void setAttachment(Object attachment) {
this.attachment = attachment;
}
/**
* 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.
*/
@Override
public String toString() {
boolean connected = isConnected();
if (strValConnected == connected && strVal != null) {
return strVal;
}
StringBuilder buf = new StringBuilder(128);
buf.append("[id: 0x");
buf.append(getIdString());
SocketAddress localAddress = getLocalAddress();
SocketAddress remoteAddress = getRemoteAddress();
if (remoteAddress != null) {
buf.append(", ");
if (getParent() == null) {
buf.append(localAddress);
buf.append(connected? " => " : " :> ");
buf.append(remoteAddress);
} else {
buf.append(remoteAddress);
buf.append(connected? " => " : " :> ");
buf.append(localAddress);
}
} else if (localAddress != null) {
buf.append(", ");
buf.append(localAddress);
}
buf.append(']');
String strVal = buf.toString();
this.strVal = strVal;
strValConnected = connected;
return strVal;
}
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;
}
private final class ChannelCloseFuture extends DefaultChannelFuture {
public ChannelCloseFuture() {
super(AbstractChannel.this, false);
}
@Override
public boolean setSuccess() {
// User is not supposed to call this method - ignore silently.
return false;
}
@Override
public boolean setFailure(Throwable cause) {
// User is not supposed to call this method - ignore silently.
return false;
}
boolean setClosed() {
return super.setSuccess();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/AbstractChannelSink.java 0000664 0000000 0000000 00000005141 12255541277 0030734 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import static org.jboss.netty.channel.Channels.*;
/**
* A skeletal {@link ChannelSink} implementation.
*/
public abstract class AbstractChannelSink implements ChannelSink {
/**
* Creates a new instance.
*/
protected AbstractChannelSink() {
}
/**
* Sends an {@link ExceptionEvent} upstream with the specified
* {@code cause}.
*
* @param event the {@link ChannelEvent} which caused a
* {@link ChannelHandler} to raise an exception
* @param cause the exception raised by a {@link ChannelHandler}
*/
public void exceptionCaught(ChannelPipeline pipeline,
ChannelEvent event, ChannelPipelineException cause) throws Exception {
Throwable actualCause = cause.getCause();
if (actualCause == null) {
actualCause = cause;
}
if (isFireExceptionCaughtLater(event, actualCause)) {
fireExceptionCaughtLater(event.getChannel(), actualCause);
} else {
fireExceptionCaught(event.getChannel(), actualCause);
}
}
/**
* Returns {@code true} if and only if the specified {@code actualCause}, which was raised while
* handling the specified {@code event}, must trigger an {@code exceptionCaught()} event in
* an I/O thread.
*
* @param event the event which raised exception
* @param actualCause the raised exception
*/
protected boolean isFireExceptionCaughtLater(ChannelEvent event, Throwable actualCause) {
return false;
}
/**
* This implementation just directly call {@link Runnable#run()}.
* Sub-classes should override this if they can handle it in a better way
*/
public ChannelFuture execute(ChannelPipeline pipeline, Runnable task) {
try {
task.run();
return succeededFuture(pipeline.getChannel());
} catch (Throwable t) {
return failedFuture(pipeline.getChannel(), t);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/AbstractServerChannel.java 0000664 0000000 0000000 00000005235 12255541277 0031302 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
/**
* A skeletal server-side {@link Channel} implementation. A server-side
* {@link Channel} does not allow the following operations:
*
* {@link #connect(SocketAddress)}
* {@link #disconnect()}
* {@link #getInterestOps()}
* {@link #setInterestOps(int)}
* {@link #write(Object)}
* {@link #write(Object, SocketAddress)}
* and the shortcut methods which calls the methods mentioned above
*
*/
public abstract class AbstractServerChannel extends AbstractChannel implements ServerChannel {
/**
* Creates a new instance.
*
* @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
*/
protected AbstractServerChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink) {
super(null, factory, pipeline, sink);
}
@Override
public ChannelFuture connect(SocketAddress remoteAddress) {
return getUnsupportedOperationFuture();
}
@Override
public ChannelFuture disconnect() {
return getUnsupportedOperationFuture();
}
@Override
public int getInterestOps() {
return OP_NONE;
}
@Override
public ChannelFuture setInterestOps(int interestOps) {
return getUnsupportedOperationFuture();
}
@Override
protected void setInterestOpsNow(int interestOps) {
// Ignore.
}
@Override
public ChannelFuture write(Object message) {
return getUnsupportedOperationFuture();
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
return getUnsupportedOperationFuture();
}
public boolean isConnected() {
return false;
}
}
AdaptiveReceiveBufferSizePredictor.java 0000664 0000000 0000000 00000012550 12255541277 0033677 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.util.ArrayList;
import java.util.List;
/**
* The {@link ReceiveBufferSizePredictor} that automatically increases and
* decreases the predicted buffer size on feed back.
*
* It gradually increases the expected number of readable bytes if the previous
* read fully filled the allocated buffer. It gradually decreases the expected
* number of readable bytes if the read operation was not able to fill a certain
* amount of the allocated buffer two times consecutively. Otherwise, it keeps
* returning the same prediction.
*/
public class AdaptiveReceiveBufferSizePredictor implements
ReceiveBufferSizePredictor {
static final int DEFAULT_MINIMUM = 64;
static final int DEFAULT_INITIAL = 1024;
static final int DEFAULT_MAXIMUM = 65536;
private static final int INDEX_INCREMENT = 4;
private static final int INDEX_DECREMENT = 1;
private static final int[] SIZE_TABLE;
static {
List sizeTable = new ArrayList();
for (int i = 1; i <= 8; i ++) {
sizeTable.add(i);
}
for (int i = 4; i < 32; i ++) {
long v = 1L << i;
long inc = v >>> 4;
v -= inc << 3;
for (int j = 0; j < 8; j ++) {
v += inc;
if (v > Integer.MAX_VALUE) {
sizeTable.add(Integer.MAX_VALUE);
} else {
sizeTable.add((int) v);
}
}
}
SIZE_TABLE = new int[sizeTable.size()];
for (int i = 0; i < SIZE_TABLE.length; i ++) {
SIZE_TABLE[i] = sizeTable.get(i);
}
}
private static int getSizeTableIndex(final int size) {
if (size <= 16) {
return size - 1;
}
int bits = 0;
int v = size;
do {
v >>>= 1;
bits ++;
} while (v != 0);
final int baseIdx = bits << 3;
final int startIdx = baseIdx - 18;
final int endIdx = baseIdx - 25;
for (int i = startIdx; i >= endIdx; i --) {
if (size >= SIZE_TABLE[i]) {
return i;
}
}
throw new Error("shouldn't reach here; please file a bug report.");
}
private final int minIndex;
private final int maxIndex;
private int index;
private int nextReceiveBufferSize;
private boolean decreaseNow;
/**
* Creates a new predictor with the default parameters. With the default
* parameters, the expected buffer size starts from {@code 1024}, does not
* go down below {@code 64}, and does not go up above {@code 65536}.
*/
public AdaptiveReceiveBufferSizePredictor() {
this(DEFAULT_MINIMUM, DEFAULT_INITIAL, DEFAULT_MAXIMUM);
}
/**
* Creates a new predictor with the specified parameters.
*
* @param minimum the inclusive lower bound of the expected buffer size
* @param initial the initial buffer size when no feed back was received
* @param maximum the inclusive upper bound of the expected buffer size
*/
public AdaptiveReceiveBufferSizePredictor(int minimum, int initial, int maximum) {
if (minimum <= 0) {
throw new IllegalArgumentException("minimum: " + minimum);
}
if (initial < minimum) {
throw new IllegalArgumentException("initial: " + initial);
}
if (maximum < initial) {
throw new IllegalArgumentException("maximum: " + maximum);
}
int minIndex = getSizeTableIndex(minimum);
if (SIZE_TABLE[minIndex] < minimum) {
this.minIndex = minIndex + 1;
} else {
this.minIndex = minIndex;
}
int maxIndex = getSizeTableIndex(maximum);
if (SIZE_TABLE[maxIndex] > maximum) {
this.maxIndex = maxIndex - 1;
} else {
this.maxIndex = maxIndex;
}
index = getSizeTableIndex(initial);
nextReceiveBufferSize = SIZE_TABLE[index];
}
public int nextReceiveBufferSize() {
return nextReceiveBufferSize;
}
public void previousReceiveBufferSize(int previousReceiveBufferSize) {
if (previousReceiveBufferSize <= SIZE_TABLE[Math.max(0, index - INDEX_DECREMENT - 1)]) {
if (decreaseNow) {
index = Math.max(index - INDEX_DECREMENT, minIndex);
nextReceiveBufferSize = SIZE_TABLE[index];
decreaseNow = false;
} else {
decreaseNow = true;
}
} else if (previousReceiveBufferSize >= nextReceiveBufferSize) {
index = Math.min(index + INDEX_INCREMENT, maxIndex);
nextReceiveBufferSize = SIZE_TABLE[index];
decreaseNow = false;
}
}
}
AdaptiveReceiveBufferSizePredictorFactory.java 0000664 0000000 0000000 00000004730 12255541277 0035230 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* The {@link ReceiveBufferSizePredictorFactory} that creates a new
* {@link AdaptiveReceiveBufferSizePredictor}.
*/
public class AdaptiveReceiveBufferSizePredictorFactory implements
ReceiveBufferSizePredictorFactory {
private final int minimum;
private final int initial;
private final int maximum;
/**
* Creates a new factory with the default parameters. With the default
* parameters, the expected buffer size starts from {@code 1024}, does not
* go down below {@code 64}, and does not go up above {@code 65536}.
*/
public AdaptiveReceiveBufferSizePredictorFactory() {
this(AdaptiveReceiveBufferSizePredictor.DEFAULT_MINIMUM,
AdaptiveReceiveBufferSizePredictor.DEFAULT_INITIAL,
AdaptiveReceiveBufferSizePredictor.DEFAULT_MAXIMUM);
}
/**
* Creates a new factory with the specified parameters.
*
* @param minimum the inclusive lower bound of the expected buffer size
* @param initial the initial buffer size when no feed back was received
* @param maximum the inclusive upper bound of the expected buffer size
*/
public AdaptiveReceiveBufferSizePredictorFactory(int minimum, int initial, int maximum) {
if (minimum <= 0) {
throw new IllegalArgumentException("minimum: " + minimum);
}
if (initial < minimum) {
throw new IllegalArgumentException("initial: " + initial);
}
if (maximum < initial) {
throw new IllegalArgumentException("maximum: " + maximum);
}
this.minimum = minimum;
this.initial = initial;
this.maximum = maximum;
}
public ReceiveBufferSizePredictor getPredictor() throws Exception {
return new AdaptiveReceiveBufferSizePredictor(minimum, initial, maximum);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/Channel.java 0000664 0000000 0000000 00000034516 12255541277 0026433 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.SelectionKey;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.ServerSocketChannel;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.channel.socket.nio.NioSocketChannelConfig;
/**
* A nexus to a network socket or a component which is capable of I/O
* operations such as read, write, connect, and bind.
*
* A channel provides a user:
*
* the current state of the channel (e.g. is it open? is it connected?),
* the {@linkplain ChannelConfig configuration parameters} of the channel (e.g. receive buffer size),
* the I/O operations that the channel supports (e.g. read, write, connect, and bind), and
* the {@link ChannelPipeline} which handles all {@linkplain ChannelEvent I/O events and requests}
* associated with the channel.
*
*
* All I/O operations are asynchronous.
*
* All I/O operations in Netty are asynchronous. It means any I/O calls will
* return immediately with no guarantee that the requested I/O operation has
* been completed at the end of the call. Instead, you will be returned with
* a {@link ChannelFuture} instance which will notify you when the requested I/O
* operation has succeeded, failed, or canceled.
*
*
Channels are hierarchical
*
* A {@link Channel} can have a {@linkplain #getParent() parent} depending on
* how it was created. For instance, a {@link SocketChannel}, that was accepted
* by {@link ServerSocketChannel}, will return the {@link ServerSocketChannel}
* as its parent on {@link #getParent()}.
*
* The semantics of the hierarchical structure depends on the transport
* implementation where the {@link Channel} belongs to. For example, you could
* write a new {@link Channel} implementation that creates the sub-channels that
* share one socket connection, as BEEP and
* SSH do.
*
*
Downcast to access transport-specific operations
*
* Some transports exposes additional operations that is specific to the
* transport. Down-cast the {@link Channel} to sub-type to invoke such
* operations. For example, with the old I/O datagram transport, multicast
* join / leave operations are provided by {@link DatagramChannel}.
*
*
InterestOps
*
* A {@link Channel} has a property called {@link #getInterestOps() interestOps}
* which is similar to that of {@link SelectionKey#interestOps() NIO SelectionKey}.
* It is represented as a bit
* field which is composed of the two flags.
*
* {@link #OP_READ} - If set, a message sent by a remote peer will be read
* immediately. If unset, the message from the remote peer will not be read
* until the {@link #OP_READ} flag is set again (i.e. read suspension).
* {@link #OP_WRITE} - If set, a write request will not be sent to a remote
* peer until the {@link #OP_WRITE} flag is cleared and the write request
* will be pending in a queue. If unset, the write request will be flushed
* out as soon as possible from the queue.
* {@link #OP_READ_WRITE} - This is a combination of {@link #OP_READ} and
* {@link #OP_WRITE}, which means only write requests are suspended.
* {@link #OP_NONE} - This is a combination of (NOT {@link #OP_READ}) and
* (NOT {@link #OP_WRITE}), which means only read operation is suspended.
*
*
* You can set or clear the {@link #OP_READ} flag to suspend and resume read
* operation via {@link #setReadable(boolean)}.
*
* Please note that you cannot suspend or resume write operation just like you
* can set or clear {@link #OP_READ}. The {@link #OP_WRITE} flag is read only
* and provided simply as a mean to tell you if the size of pending write
* requests exceeded a certain threshold or not so that you don't issue too many
* pending writes that lead to an {@link OutOfMemoryError}. For example, the
* NIO socket transport uses the {@code writeBufferLowWaterMark} and
* {@code writeBufferHighWaterMark} properties in {@link NioSocketChannelConfig}
* to determine when to set or clear the {@link #OP_WRITE} flag.
*
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.ChannelConfig
* @apiviz.composedOf org.jboss.netty.channel.ChannelPipeline
*
* @apiviz.exclude ^org\.jboss\.netty\.channel\.([a-z]+\.)+[^\.]+Channel$
*/
public interface Channel extends Comparable {
/**
* The {@link #getInterestOps() interestOps} value which tells that only
* read operation has been suspended.
*/
int OP_NONE = 0;
/**
* The {@link #getInterestOps() interestOps} value which tells that neither
* read nor write operation has been suspended.
*/
int OP_READ = 1;
/**
* The {@link #getInterestOps() interestOps} value which tells that both
* read and write operation has been suspended.
*/
int OP_WRITE = 4;
/**
* The {@link #getInterestOps() interestOps} value which tells that only
* write operation has been suspended.
*/
int OP_READ_WRITE = OP_READ | OP_WRITE;
/**
* Returns the unique integer ID of this channel.
*/
Integer getId();
/**
* Returns the {@link ChannelFactory} which created this channel.
*/
ChannelFactory getFactory();
/**
* Returns the parent of this channel.
*
* @return the parent channel.
* {@code null} if this channel does not have a parent channel.
*/
Channel getParent();
/**
* Returns the configuration of this channel.
*/
ChannelConfig getConfig();
/**
* Returns the {@link ChannelPipeline} which handles {@link ChannelEvent}s
* associated with this channel.
*/
ChannelPipeline getPipeline();
/**
* Returns {@code true} if and only if this channel is open.
*/
boolean isOpen();
/**
* Returns {@code true} if and only if this channel is bound to a
* {@linkplain #getLocalAddress() local address}.
*/
boolean isBound();
/**
* Returns {@code true} if and only if this channel is connected to a
* {@linkplain #getRemoteAddress() remote address}.
*/
boolean isConnected();
/**
* Returns the local address where this channel is bound to. The returned
* {@link SocketAddress} is supposed to be down-cast into more concrete
* type such as {@link InetSocketAddress} to retrieve the detailed
* information.
*
* @return the local address of this channel.
* {@code null} if this channel is not bound.
*/
SocketAddress getLocalAddress();
/**
* Returns the remote address where this channel is connected to. The
* returned {@link SocketAddress} is supposed to be down-cast into more
* concrete type such as {@link InetSocketAddress} to retrieve the detailed
* information.
*
* @return the remote address of this channel.
* {@code null} if this channel is not connected.
* If this channel is not connected but it can receive messages
* from arbitrary remote addresses (e.g. {@link DatagramChannel},
* use {@link MessageEvent#getRemoteAddress()} to determine
* the origination of the received message as this method will
* return {@code null}.
*/
SocketAddress getRemoteAddress();
/**
* Sends a message to this channel asynchronously. If this channel was
* created by a connectionless transport (e.g. {@link DatagramChannel})
* and is not connected yet, you have to call {@link #write(Object, SocketAddress)}
* instead. Otherwise, the write request will fail with
* {@link NotYetConnectedException} and an {@code 'exceptionCaught'} event
* will be triggered.
*
* @param message the message to write
*
* @return the {@link ChannelFuture} which will be notified when the
* write request succeeds or fails
*
* @throws NullPointerException if the specified message is {@code null}
*/
ChannelFuture write(Object message);
/**
* Sends a message to this channel asynchronously. It has an additional
* parameter that allows a user to specify where to send the specified
* message instead of this channel's current remote address. If this
* channel was created by a connectionless transport (e.g. {@link DatagramChannel})
* and is not connected yet, you must specify non-null address. Otherwise,
* the write request will fail with {@link NotYetConnectedException} and
* an {@code 'exceptionCaught'} event will be triggered.
*
* @param message the message to write
* @param remoteAddress where to send the specified message.
* This method is identical to {@link #write(Object)}
* if {@code null} is specified here.
*
* @return the {@link ChannelFuture} which will be notified when the
* write request succeeds or fails
*
* @throws NullPointerException if the specified message is {@code null}
*/
ChannelFuture write(Object message, SocketAddress remoteAddress);
/**
* Binds this channel to the specified local address asynchronously.
*
* @param localAddress where to bind
*
* @return the {@link ChannelFuture} which will be notified when the
* bind request succeeds or fails
*
* @throws NullPointerException if the specified address is {@code null}
*/
ChannelFuture bind(SocketAddress localAddress);
/**
* Connects this channel to the specified remote address asynchronously.
*
* @param remoteAddress where to connect
*
* @return the {@link ChannelFuture} which will be notified when the
* connection request succeeds or fails
*
* @throws NullPointerException if the specified address is {@code null}
*/
ChannelFuture connect(SocketAddress remoteAddress);
/**
* Disconnects this channel from the current remote address asynchronously.
*
* @return the {@link ChannelFuture} which will be notified when the
* disconnection request succeeds or fails
*/
ChannelFuture disconnect();
/**
* Unbinds this channel from the current local address asynchronously.
*
* @return the {@link ChannelFuture} which will be notified when the
* unbind request succeeds or fails
*/
ChannelFuture unbind();
/**
* Closes this channel asynchronously. If this channel is bound or
* connected, it will be disconnected and unbound first. Once a channel
* is closed, it can not be open again. Calling this method on a closed
* channel has no effect. Please note that this method always returns the
* same future instance.
*
* @return the {@link ChannelFuture} which will be notified when the
* close request succeeds or fails
*/
ChannelFuture close();
/**
* Returns the {@link ChannelFuture} which will be notified when this
* channel is closed. This method always returns the same future instance.
*/
ChannelFuture getCloseFuture();
/**
* Returns the current {@code interestOps} of this channel.
*
* @return {@link #OP_NONE}, {@link #OP_READ}, {@link #OP_WRITE}, or
* {@link #OP_READ_WRITE}
*/
int getInterestOps();
/**
* Returns {@code true} if and only if the I/O thread will read a message
* from this channel. This method is a shortcut to the following code:
*
* return (getInterestOps() & OP_READ) != 0;
*
*/
boolean isReadable();
/**
* Returns {@code true} if and only if the I/O thread will perform the
* requested write operation immediately. Any write requests made when
* this method returns {@code false} are queued until the I/O thread is
* ready to process the queued write requests. This method is a shortcut
* to the following code:
*
* return (getInterestOps() & OP_WRITE) == 0;
*
*/
boolean isWritable();
/**
* Changes the {@code interestOps} of this channel asynchronously.
*
* @param interestOps the new {@code interestOps}
*
* @return the {@link ChannelFuture} which will be notified when the
* {@code interestOps} change request succeeds or fails
*/
ChannelFuture setInterestOps(int interestOps);
/**
* Suspends or resumes the read operation of the I/O thread asynchronously.
* This method is a shortcut to the following code:
*
* int interestOps = getInterestOps();
* if (readable) {
* setInterestOps(interestOps | OP_READ);
* } else {
* setInterestOps(interestOps & ~OP_READ);
* }
*
*
* @param readable {@code true} to resume the read operation and
* {@code false} to suspend the read operation
*
* @return the {@link ChannelFuture} which will be notified when the
* {@code interestOps} change request succeeds or fails
*/
ChannelFuture setReadable(boolean readable);
/**
* Retrieves an object which is {@link #setAttachment(Object) attached} to
* this {@link Channel}.
*
* @return {@code null} if no object was attached or {@code null} was
* attached
*/
Object getAttachment();
/**
* Attaches an object to this {@link Channel} to store a stateful
* information
*/
void setAttachment(Object attachment);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelConfig.java 0000664 0000000 0000000 00000012545 12255541277 0027557 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.nio.ByteOrder;
import java.util.Map;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.buffer.HeapChannelBufferFactory;
import org.jboss.netty.channel.socket.SocketChannelConfig;
import org.jboss.netty.channel.socket.nio.NioSocketChannelConfig;
/**
* A set of configuration properties of a {@link Channel}.
*
* Please down-cast to more specific configuration type such as
* {@link SocketChannelConfig} or use {@link #setOptions(Map)} to set the
* transport-specific properties:
*
* {@link Channel} ch = ...;
* {@link SocketChannelConfig} cfg = ({@link SocketChannelConfig}) ch.getConfig();
* cfg.setTcpNoDelay(false);
*
*
* Option map
*
* An option map property is a dynamic write-only property which allows
* the configuration of a {@link Channel} without down-casting its associated
* {@link ChannelConfig}. To update an option map, please call {@link #setOptions(Map)}.
*
* All {@link ChannelConfig} has the following options:
*
*
*
* Name Associated setter method
*
* {@code "bufferFactory"} {@link #setBufferFactory(ChannelBufferFactory)}
*
* {@code "connectTimeoutMillis"} {@link #setConnectTimeoutMillis(int)}
*
* {@code "pipelineFactory"} {@link #setPipelineFactory(ChannelPipelineFactory)}
*
*
*
* More options are available in the sub-types of {@link ChannelConfig}. For
* example, you can configure the parameters which are specific to a TCP/IP
* socket as explained in {@link SocketChannelConfig} or {@link NioSocketChannelConfig}.
*
* @apiviz.has org.jboss.netty.channel.ChannelPipelineFactory
* @apiviz.composedOf org.jboss.netty.channel.ReceiveBufferSizePredictor
*
* @apiviz.excludeSubtypes
*/
public interface ChannelConfig {
/**
* Sets the configuration properties from the specified {@link Map}.
*/
void setOptions(Map options);
/**
* Sets a configuration property with the specified name and value.
* To override this method properly, you must call the super class:
*
* public boolean setOption(String name, Object value) {
* if (super.setOption(name, value)) {
* return true;
* }
*
* if (name.equals("additionalOption")) {
* ....
* return true;
* }
*
* return false;
* }
*
*
* @return {@code true} if and only if the property has been set
*/
boolean setOption(String name, Object value);
/**
* Returns the default {@link ChannelBufferFactory} used to create a new
* {@link ChannelBuffer}. The default is {@link HeapChannelBufferFactory}.
* You can specify a different factory to change the default
* {@link ByteOrder} for example.
*/
ChannelBufferFactory getBufferFactory();
/**
* Sets the default {@link ChannelBufferFactory} used to create a new
* {@link ChannelBuffer}. The default is {@link HeapChannelBufferFactory}.
* You can specify a different factory to change the default
* {@link ByteOrder} for example.
*/
void setBufferFactory(ChannelBufferFactory bufferFactory);
/**
* Returns the {@link ChannelPipelineFactory} which will be used when
* a child channel is created. If the {@link Channel} does not create
* a child channel, this property is not used at all, and therefore will
* be ignored.
*/
ChannelPipelineFactory getPipelineFactory();
/**
* Sets the {@link ChannelPipelineFactory} which will be used when
* a child channel is created. If the {@link Channel} does not create
* a child channel, this property is not used at all, and therefore will
* be ignored.
*/
void setPipelineFactory(ChannelPipelineFactory pipelineFactory);
/**
* Returns the connect timeout of the channel in milliseconds. If the
* {@link Channel} does not support connect operation, this property is not
* used at all, and therefore will be ignored.
*
* @return the connect timeout in milliseconds. {@code 0} if disabled.
*/
int getConnectTimeoutMillis();
/**
* Sets the connect timeout of the channel in milliseconds. If the
* {@link Channel} does not support connect operation, this property is not
* used at all, and therefore will be ignored.
*
* @param connectTimeoutMillis the connect timeout in milliseconds.
* {@code 0} to disable.
*/
void setConnectTimeoutMillis(int connectTimeoutMillis);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelDownstreamHandler.java 0000664 0000000 0000000 00000006432 12255541277 0031771 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* Handles or intercepts a downstream {@link ChannelEvent}, and sends a
* {@link ChannelEvent} to the next handler in a {@link ChannelPipeline}.
*
* The most common use case of this interface is to intercept an I/O request
* such as {@link Channel#write(Object)} and {@link Channel#close()}.
*
*
{@link SimpleChannelDownstreamHandler}
*
* In most cases, you will get to use a {@link SimpleChannelDownstreamHandler}
* to implement a downstream handler because it provides an individual handler
* method for each event type. You might want to implement this interface
* directly though if you want to handle various types of events in more
* generic way.
*
*
Firing an event to the next handler
*
* You can forward the received event downstream or upstream. In most cases,
* {@link ChannelDownstreamHandler} will send the event downstream
* (i.e. outbound) although it is legal to send the event upstream (i.e. inbound):
*
*
* // Sending the event downstream (outbound)
* void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
* ...
* ctx.sendDownstream(e);
* ...
* }
*
* // Sending the event upstream (inbound)
* void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
* ...
* ctx.sendUpstream(new {@link UpstreamChannelStateEvent}(...));
* ...
* }
*
*
* Using the helper class to send an event
*
* You will also find various helper methods in {@link Channels} to be useful
* to generate and send an artificial or manipulated event.
*
* Caution:
*
* Use the *Later(..) methods of the {@link Channels} class if you want to send an upstream event
* from a {@link ChannelDownstreamHandler} otherwise you may run into threading issues.
*
*
State management
*
* Please refer to {@link ChannelHandler}.
*
* Thread safety
*
* {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream}
* may be invoked by more than one thread simultaneously. If the handler
* accesses a shared resource or stores stateful information, you might need
* proper synchronization in the handler implementation.
*
* @apiviz.exclude ^org\.jboss\.netty\.handler\..*$
*/
public interface ChannelDownstreamHandler extends ChannelHandler {
/**
* Handles the specified downstream event.
*
* @param ctx the context object for this handler
* @param e the downstream event to process or intercept
*/
void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelEvent.java 0000664 0000000 0000000 00000021366 12255541277 0027434 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketAddress;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.socket.ServerSocketChannel;
/**
* An I/O event or I/O request associated with a {@link Channel}.
*
* A {@link ChannelEvent} is handled by a series of {@link ChannelHandler}s in
* a {@link ChannelPipeline}.
*
*
Upstream events and downstream events, and their interpretation
*
* Every event is either an upstream event or a downstream event.
* If an event flows forward from the first handler to the last handler in a
* {@link ChannelPipeline}, we call it an upstream event and say "an
* event goes upstream." If an event flows backward from the last
* handler to the first handler in a {@link ChannelPipeline}, we call it a
* downstream event and say "an event goes downstream."
* (Please refer to the diagram in {@link ChannelPipeline} for more explanation.)
*
* When your server receives a message from a client, the event associated with
* the received message is an upstream event. When your server sends a message
* or reply to the client, the event associated with the write request is a
* downstream event. The same rule applies for the client side. If your client
* sent a request to the server, it means your client triggered a downstream
* event. If your client received a response from the server, it means
* your client will be notified with an upstream event. Upstream events are
* often the result of inbound operations such as {@link InputStream#read(byte[])},
* and downstream events are the request for outbound operations such as
* {@link OutputStream#write(byte[])}, {@link Socket#connect(SocketAddress)},
* and {@link Socket#close()}.
*
*
Upstream events
*
*
*
* Event name Event type and condition Meaning
*
*
* {@code "messageReceived"}
* {@link MessageEvent}
* a message object (e.g. {@link ChannelBuffer}) was received from a remote peer
*
*
* {@code "exceptionCaught"}
* {@link ExceptionEvent}
* an exception was raised by an I/O thread or a {@link ChannelHandler}
*
*
* {@code "channelOpen"}
* {@link ChannelStateEvent} (state = {@link ChannelState#OPEN OPEN}, value = {@code true})
* a {@link Channel} is open, but not bound nor connected
* Be aware that this event is fired from within the Boss-Thread so you should not
* execute any heavy operation in there as it will block the dispatching to other workers!
*
*
* {@code "channelClosed"}
* {@link ChannelStateEvent} (state = {@link ChannelState#OPEN OPEN}, value = {@code false})
* a {@link Channel} was closed and all its related resources were released
*
*
* {@code "channelBound"}
* {@link ChannelStateEvent} (state = {@link ChannelState#BOUND BOUND}, value = {@link SocketAddress})
* a {@link Channel} is open and bound to a local address, but not connected.
* Be aware that this event is fired from within the Boss-Thread so you should not
* execute any heavy operation in there as it will block the dispatching to other workers!
*
*
* {@code "channelUnbound"}
* {@link ChannelStateEvent} (state = {@link ChannelState#BOUND BOUND}, value = {@code null})
* a {@link Channel} was unbound from the current local address
*
*
* {@code "channelConnected"}
* {@link ChannelStateEvent} (state = {@link ChannelState#CONNECTED CONNECTED}, value =
* {@link SocketAddress})
* a {@link Channel} is open, bound to a local address, and connected to a remote address
* Be aware that this event is fired from within the Boss-Thread so you should not
* execute any heavy operation in there as it will block the dispatching to other workers!
*
*
* {@code "writeComplete"}
* {@link WriteCompletionEvent}
* something has been written to a remote peer
*
*
* {@code "channelDisconnected"}
* {@link ChannelStateEvent} (state = {@link ChannelState#CONNECTED CONNECTED}, value = {@code null})
* a {@link Channel} was disconnected from its remote peer
*
*
* {@code "channelInterestChanged"}
* {@link ChannelStateEvent} (state = {@link ChannelState#INTEREST_OPS INTEREST_OPS}, no value)
* a {@link Channel}'s {@link Channel#getInterestOps() interestOps} was changed
*
*
*
* These two additional event types are used only for a parent channel which
* can have a child channel (e.g. {@link ServerSocketChannel}).
*
*
*
* Event name Event type and condition Meaning
*
*
* {@code "childChannelOpen"}
* {@link ChildChannelStateEvent} ({@code childChannel.isOpen() = true})
* a child {@link Channel} was open (e.g. a server channel accepted a connection.)
*
*
* {@code "childChannelClosed"}
* {@link ChildChannelStateEvent} ({@code childChannel.isOpen() = false})
* a child {@link Channel} was closed (e.g. the accepted connection was closed.)
*
*
*
* Downstream events
*
*
*
* Event name Event type and condition Meaning
*
*
* {@code "write"}
* {@link MessageEvent} Send a message to the {@link Channel}.
*
*
* {@code "bind"}
* {@link ChannelStateEvent} (state = {@link ChannelState#BOUND BOUND}, value = {@link SocketAddress})
* Bind the {@link Channel} to the specified local address.
*
*
* {@code "unbind"}
* {@link ChannelStateEvent} (state = {@link ChannelState#BOUND BOUND}, value = {@code null})
* Unbind the {@link Channel} from the current local address.
*
*
* {@code "connect"}
* {@link ChannelStateEvent} (state = {@link ChannelState#CONNECTED CONNECTED}, value =
* {@link SocketAddress})
* Connect the {@link Channel} to the specified remote address.
*
*
* {@code "disconnect"}
* {@link ChannelStateEvent} (state = {@link ChannelState#CONNECTED CONNECTED}, value = {@code null})
* Disconnect the {@link Channel} from the current remote address.
*
*
* {@code "close"}
* {@link ChannelStateEvent} (state = {@link ChannelState#OPEN OPEN}, value = {@code false})
* Close the {@link Channel}.
*
*
*
* Other event types and conditions which were not addressed here will be
* ignored and discarded. Please note that there's no {@code "open"} in the
* table. It is because a {@link Channel} is always open when it is created
* by a {@link ChannelFactory}.
*
*
Additional resources worth reading
*
* Please refer to the {@link ChannelHandler} and {@link ChannelPipeline}
* documentation to find out how an event flows in a pipeline and how to handle
* the event in your application.
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.ChannelFuture
*/
public interface ChannelEvent {
/**
* Returns the {@link Channel} which is associated with this event.
*/
Channel getChannel();
/**
* Returns the {@link ChannelFuture} which is associated with this event.
* If this event is an upstream event, this method will always return a
* {@link SucceededChannelFuture} because the event has occurred already.
* If this event is a downstream event (i.e. I/O request), the returned
* future will be notified when the I/O request succeeds or fails.
*/
ChannelFuture getFuture();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelException.java 0000664 0000000 0000000 00000002556 12255541277 0030311 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link RuntimeException} which is thrown when an I/O operation fails.
*
* @apiviz.exclude
*/
public class ChannelException extends RuntimeException {
private static final long serialVersionUID = 2908618315971075004L;
/**
* Creates a new exception.
*/
public ChannelException() {
}
/**
* Creates a new exception.
*/
public ChannelException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new exception.
*/
public ChannelException(String message) {
super(message);
}
/**
* Creates a new exception.
*/
public ChannelException(Throwable cause) {
super(cause);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelFactory.java 0000664 0000000 0000000 00000007005 12255541277 0027754 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.util.concurrent.Executor;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.util.ExternalResourceReleasable;
/**
* The main interface to a transport that creates a {@link Channel} associated
* with a certain communication entity such as a network socket. For example,
* the {@link NioServerSocketChannelFactory} creates a channel which has a
* NIO-based server socket as its underlying communication entity.
*
* Once a new {@link Channel} is created, the {@link ChannelPipeline} which
* was specified as a parameter in the {@link #newChannel(ChannelPipeline)}
* is attached to the new {@link Channel}, and starts to handle all associated
* {@link ChannelEvent}s.
*
*
Graceful shutdown
*
* To shut down a network application service which is managed by a factory.
* you should follow the following steps:
*
* close all channels created by the factory and their child channels
* usually using {@link ChannelGroup#close()}, and
* call {@link #releaseExternalResources()}.
*
*
* For detailed transport-specific information on shutting down a factory,
* please refer to the Javadoc of {@link ChannelFactory}'s subtypes, such as
* {@link NioServerSocketChannelFactory}.
*
* @apiviz.landmark
* @apiviz.has org.jboss.netty.channel.Channel oneway - - creates
*
* @apiviz.exclude ^org\.jboss\.netty\.channel\.([a-z]+\.)+.*ChannelFactory$
*/
public interface ChannelFactory extends ExternalResourceReleasable {
/**
* Creates and opens a new {@link Channel} and attaches the specified
* {@link ChannelPipeline} to the new {@link Channel}.
*
* @param pipeline the {@link ChannelPipeline} which is going to be
* attached to the new {@link Channel}
*
* @return the newly open channel
*
* @throws ChannelException if failed to create and open a new channel
*/
Channel newChannel(ChannelPipeline pipeline);
/**
* Shudown the ChannelFactory and all the resource it created internal.
*/
void shutdown();
/**
* Releases the external resources that this factory depends on to function.
* An external resource is a resource that this factory didn't create by
* itself. For example, {@link Executor}s that you specified in the factory
* constructor are external resources. You can call this method to release
* all external resources conveniently when the resources are not used by
* this factory or any other part of your application. An unexpected
* behavior will be resulted in if the resources are released when there's
* an open channel which is managed by this factory.
*
* This will also call {@link #shutdown()} before do any action
*/
void releaseExternalResources();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelFuture.java 0000664 0000000 0000000 00000032623 12255541277 0027623 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.handler.execution.ExecutionHandler;
/**
* The result of an asynchronous {@link Channel} I/O operation.
*
* All I/O operations in Netty are asynchronous. It means any I/O calls will
* return immediately with no guarantee that the requested I/O operation has
* been completed at the end of the call. Instead, you will be returned with
* a {@link ChannelFuture} instance which gives you the information about the
* result or status of the I/O operation.
*
* A {@link ChannelFuture} is either uncompleted or completed .
* When an I/O operation begins, a new future object is created. The new future
* is uncompleted initially - it is neither succeeded, failed, nor cancelled
* because the I/O operation is not finished yet. If the I/O operation is
* finished either successfully, with failure, or by cancellation, the future is
* marked as completed with more specific information, such as the cause of the
* failure. Please note that even failure and cancellation belong to the
* completed state.
*
* +---------------------------+
* | Completed successfully |
* +---------------------------+
* +----> isDone() = true |
* +--------------------------+ | | isSuccess() = true |
* | Uncompleted | | +===========================+
* +--------------------------+ | | Completed with failure |
* | isDone() = false | | +---------------------------+
* | isSuccess() = false |----+----> isDone() = true |
* | isCancelled() = false | | | getCause() = non-null |
* | getCause() = null | | +===========================+
* +--------------------------+ | | Completed by cancellation |
* | +---------------------------+
* +----> isDone() = true |
* | isCancelled() = true |
* +---------------------------+
*
*
* Various methods are provided to let you check if the I/O operation has been
* completed, wait for the completion, and retrieve the result of the I/O
* operation. It also allows you to add {@link ChannelFutureListener}s so you
* can get notified when the I/O operation is completed.
*
* Prefer {@link #addListener(ChannelFutureListener)} to {@link #await()}
*
* It is recommended to prefer {@link #addListener(ChannelFutureListener)} to
* {@link #await()} wherever possible to get notified when an I/O operation is
* done and to do any follow-up tasks.
*
* {@link #addListener(ChannelFutureListener)} is non-blocking. It simply adds
* the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and
* I/O thread will notify the listeners when the I/O operation associated with
* the future is done. {@link ChannelFutureListener} yields the best
* performance and resource utilization because it does not block at all, but
* it could be tricky to implement a sequential logic if you are not used to
* event-driven programming.
*
* By contrast, {@link #await()} is a blocking operation. Once called, the
* caller thread blocks until the operation is done. It is easier to implement
* a sequential logic with {@link #await()}, but the caller thread blocks
* unnecessarily until the I/O operation is done and there's relatively
* expensive cost of inter-thread notification. Moreover, there's a chance of
* dead lock in a particular circumstance, which is described below.
*
*
Do not call {@link #await()} inside {@link ChannelHandler}
*
* The event handler methods in {@link ChannelHandler} is often called by
* an I/O thread unless an {@link ExecutionHandler} is in the
* {@link ChannelPipeline}. If {@link #await()} is called by an event handler
* method, which is called by the I/O thread, the I/O operation it is waiting
* for might never be complete because {@link #await()} can block the I/O
* operation it is waiting for, which is a dead lock.
*
* // BAD - NEVER DO THIS
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* if (e.getMessage() instanceof GoodByeMessage) {
* {@link ChannelFuture} future = e.getChannel().close();
* future.awaitUninterruptibly();
* // Perform post-closure operation
* // ...
* }
* }
*
* // GOOD
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* if (e.getMessage() instanceof GoodByeMessage) {
* {@link ChannelFuture} future = e.getChannel().close();
* future.addListener(new {@link ChannelFutureListener}() {
* public void operationComplete({@link ChannelFuture} future) {
* // Perform post-closure operation
* // ...
* }
* });
* }
* }
*
*
* In spite of the disadvantages mentioned above, there are certainly the cases
* where it is more convenient to call {@link #await()}. In such a case, please
* make sure you do not call {@link #await()} in an I/O thread. Otherwise,
* {@link IllegalStateException} will be raised to prevent a dead lock.
*
*
Do not confuse I/O timeout and await timeout
*
* The timeout value you specify with {@link #await(long)},
* {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or
* {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O
* timeout at all. If an I/O operation times out, the future will be marked as
* 'completed with failure,' as depicted in the diagram above. For example,
* connect timeout should be configured via a transport-specific option:
*
* // BAD - NEVER DO THIS
* {@link ClientBootstrap} b = ...;
* {@link ChannelFuture} f = b.connect(...);
* f.awaitUninterruptibly(10, TimeUnit.SECONDS);
* if (f.isCancelled()) {
* // Connection attempt cancelled by user
* } else if (!f.isSuccess()) {
* // You might get a NullPointerException here because the future
* // might not be completed yet.
* f.getCause().printStackTrace();
* } else {
* // Connection established successfully
* }
*
* // GOOD
* {@link ClientBootstrap} b = ...;
* // Configure the connect timeout option.
* b.setOption("connectTimeoutMillis", 10000);
* {@link ChannelFuture} f = b.connect(...);
* f.awaitUninterruptibly();
*
* // Now we are sure the future is completed.
* assert f.isDone();
*
* if (f.isCancelled()) {
* // Connection attempt cancelled by user
* } else if (!f.isSuccess()) {
* f.getCause().printStackTrace();
* } else {
* // Connection established successfully
* }
*
*
* @apiviz.landmark
* @apiviz.owns org.jboss.netty.channel.ChannelFutureListener - - notifies
*/
public interface ChannelFuture {
/**
* Returns a channel where the I/O operation associated with this
* future takes place.
*/
Channel getChannel();
/**
* Returns {@code true} if and only if this future is
* complete, regardless of whether the operation was successful, failed,
* or cancelled.
*/
boolean isDone();
/**
* Returns {@code true} if and only if this future was
* cancelled by a {@link #cancel()} method.
*/
boolean isCancelled();
/**
* Returns {@code true} if and only if the I/O operation was completed
* successfully.
*/
boolean isSuccess();
/**
* Returns the cause of the failed I/O operation if the I/O operation has
* failed.
*
* @return the cause of the failure.
* {@code null} if succeeded or this future is not
* completed yet.
*/
Throwable getCause();
/**
* Cancels the I/O operation associated with this future
* and notifies all listeners if canceled successfully.
*
* @return {@code true} if and only if the operation has been canceled.
* {@code false} if the operation can't be canceled or is already
* completed.
*/
boolean cancel();
/**
* Marks this future as a success and notifies all
* listeners.
*
* @return {@code true} if and only if successfully marked this future as
* a success. Otherwise {@code false} because this future is
* already marked as either a success or a failure.
*/
boolean setSuccess();
/**
* Marks this future as a failure and notifies all
* listeners.
*
* @return {@code true} if and only if successfully marked this future as
* a failure. Otherwise {@code false} because this future is
* already marked as either a success or a failure.
*/
boolean setFailure(Throwable cause);
/**
* Notifies the progress of the operation to the listeners that implements
* {@link ChannelFutureProgressListener}. Please note that this method will
* not do anything and return {@code false} if this future is complete
* already.
*
* @return {@code true} if and only if notification was made.
*/
boolean setProgress(long amount, long current, long total);
/**
* Adds the specified listener to this future. The
* specified listener is notified when this future is
* {@linkplain #isDone() done}. If this future is already
* completed, the specified listener is notified immediately.
*/
void addListener(ChannelFutureListener listener);
/**
* Removes the specified listener from this future.
* The specified listener is no longer notified when this
* future is {@linkplain #isDone() done}. If the specified
* listener is not associated with this future, this method
* does nothing and returns silently.
*/
void removeListener(ChannelFutureListener listener);
/**
* @deprecated Use {@link #sync()} or {@link #syncUninterruptibly()} instead.
*/
@Deprecated
ChannelFuture rethrowIfFailed() throws Exception;
/**
* Waits for this future until it is done, and rethrows the cause of the failure if this future
* failed. If the cause of the failure is a checked exception, it is wrapped with a new
* {@link ChannelException} before being thrown.
*/
ChannelFuture sync() throws InterruptedException;
/**
* Waits for this future until it is done, and rethrows the cause of the failure if this future
* failed. If the cause of the failure is a checked exception, it is wrapped with a new
* {@link ChannelException} before being thrown.
*/
ChannelFuture syncUninterruptibly();
/**
* Waits for this future to be completed.
*
* @throws InterruptedException
* if the current thread was interrupted
*/
ChannelFuture await() throws InterruptedException;
/**
* Waits for this future to be completed without
* interruption. This method catches an {@link InterruptedException} and
* discards it silently.
*/
ChannelFuture awaitUninterruptibly();
/**
* Waits for this future to be completed within the
* specified time limit.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*
* @throws InterruptedException
* if the current thread was interrupted
*/
boolean await(long timeout, TimeUnit unit) throws InterruptedException;
/**
* Waits for this future to be completed within the
* specified time limit.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*
* @throws InterruptedException
* if the current thread was interrupted
*/
boolean await(long timeoutMillis) throws InterruptedException;
/**
* Waits for this future to be completed within the
* specified time limit without interruption. This method catches an
* {@link InterruptedException} and discards it silently.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*/
boolean awaitUninterruptibly(long timeout, TimeUnit unit);
/**
* Waits for this future to be completed within the
* specified time limit without interruption. This method catches an
* {@link InterruptedException} and discards it silently.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*/
boolean awaitUninterruptibly(long timeoutMillis);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelFutureListener.java 0000664 0000000 0000000 00000004703 12255541277 0031327 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.util.EventListener;
/**
* Listens to the result of a {@link ChannelFuture}. The result of the
* asynchronous {@link Channel} I/O operation is notified once this listener
* is added by calling {@link ChannelFuture#addListener(ChannelFutureListener)}.
*
* Return the control to the caller quickly
*
* {@link #operationComplete(ChannelFuture)} is directly called by an I/O
* thread. Therefore, performing a time consuming task or a blocking operation
* in the handler method can cause an unexpected pause during I/O. If you need
* to perform a blocking operation on I/O completion, try to execute the
* operation in a different thread using a thread pool.
*/
public interface ChannelFutureListener extends EventListener {
/**
* A {@link ChannelFutureListener} that closes the {@link Channel} which is
* associated with the specified {@link ChannelFuture}.
*/
ChannelFutureListener CLOSE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
future.getChannel().close();
}
};
/**
* A {@link ChannelFutureListener} that closes the {@link Channel} when the
* operation ended up with a failure or cancellation rather than a success.
*/
ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
future.getChannel().close();
}
}
};
/**
* Invoked when the I/O operation associated with the {@link ChannelFuture}
* has been completed.
*
* @param future the source {@link ChannelFuture} which called this
* callback
*/
void operationComplete(ChannelFuture future) throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelFutureNotifier.java 0000664 0000000 0000000 00000002332 12255541277 0031315 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* ChannelFutureListener implementation which takes another ChannelFuture and notifies it
* once the operationComplete method was called.
*/
public final class ChannelFutureNotifier implements ChannelFutureListener {
private final ChannelFuture future;
public ChannelFutureNotifier(ChannelFuture future) {
this.future = future;
}
public void operationComplete(ChannelFuture cf) throws Exception {
if (cf.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(cf.getCause());
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelFutureProgressListener.java 0000664 0000000 0000000 00000004315 12255541277 0033053 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* Listens to the progress of a time-consuming I/O operation such as a large
* file transfer. If this listener is added to a {@link ChannelFuture} of an
* I/O operation that supports progress notification, the listener's
* {@link #operationProgressed(ChannelFuture, long, long, long)} method will be
* called back by an I/O thread. If the operation does not support progress
* notification, {@link #operationProgressed(ChannelFuture, long, long, long)}
* will not be invoked. Like a usual {@link ChannelFutureListener} that this
* interface extends, {@link #operationComplete(ChannelFuture)} will be called
* when the future is marked as complete.
*
* Return the control to the caller quickly
*
* {@link #operationProgressed(ChannelFuture, long, long, long)} and
* {@link #operationComplete(ChannelFuture)} is directly called by an I/O
* thread. Therefore, performing a time consuming task or a blocking operation
* in the handler method can cause an unexpected pause during I/O. If you need
* to perform a blocking operation on I/O completion, try to execute the
* operation in a different thread using a thread pool.
*/
public interface ChannelFutureProgressListener extends ChannelFutureListener {
/**
* Invoked when the I/O operation associated with the {@link ChannelFuture}
* has been progressed.
*
* @param future the source {@link ChannelFuture} which called this
* callback
*/
void operationProgressed(ChannelFuture future, long amount, long current, long total) throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelHandler.java 0000664 0000000 0000000 00000021170 12255541277 0027721 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.bootstrap.Bootstrap;
import org.jboss.netty.channel.group.ChannelGroup;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Handles or intercepts a {@link ChannelEvent}, and sends a
* {@link ChannelEvent} to the next handler in a {@link ChannelPipeline}.
*
* Sub-types
*
* {@link ChannelHandler} itself does not provide any method. To handle a
* {@link ChannelEvent} you need to implement its sub-interfaces. There are
* two sub-interfaces which handles a received event, one for upstream events
* and the other for downstream events:
*
* {@link ChannelUpstreamHandler} handles and intercepts an upstream {@link ChannelEvent}.
* {@link ChannelDownstreamHandler} handles and intercepts a downstream {@link ChannelEvent}.
*
*
* You will also find more detailed explanation from the documentation of
* each sub-interface on how an event is interpreted when it goes upstream and
* downstream respectively.
*
* The context object
*
* A {@link ChannelHandler} is provided with a {@link ChannelHandlerContext}
* object. A {@link ChannelHandler} is supposed to interact with the
* {@link ChannelPipeline} it belongs to via a context object. Using the
* context object, the {@link ChannelHandler} can pass events upstream or
* downstream, modify the pipeline dynamically, or store the information
* (attachment) which is specific to the handler.
*
*
State management
*
* A {@link ChannelHandler} often needs to store some stateful information.
* The simplest and recommended approach is to use member variables:
*
* public class DataServerHandler extends {@link SimpleChannelHandler} {
*
* private boolean loggedIn;
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* {@link Channel} ch = e.getChannel();
* Object o = e.getMessage();
* if (o instanceof LoginMessage) {
* authenticate((LoginMessage) o);
* loggedIn = true;
* } else (o instanceof GetDataMessage) {
* if (loggedIn ) {
* ch.write(fetchSecret((GetDataMessage) o));
* } else {
* fail();
* }
* }
* }
* ...
* }
*
* Because the handler instance has a state variable which is dedicated to
* one connection, you have to create a new handler instance for each new
* channel to avoid a race condition where a unauthenticated client can get
* the confidential information:
*
* // Create a new handler instance per channel.
* // See {@link Bootstrap#setPipelineFactory(ChannelPipelineFactory)}.
* public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
* public {@link ChannelPipeline} getPipeline() {
* return {@link Channels}.pipeline(new DataServerHandler() );
* }
* }
*
*
* Using an attachment
*
* Although it's recommended to use member variables to store the state of a
* handler, for some reason you might not want to create many handler instances.
* In such a case, you can use an attachment which is provided by
* {@link ChannelHandlerContext}:
*
* {@code @Sharable}
* public class DataServerHandler extends {@link SimpleChannelHandler} {
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* {@link Channel} ch = e.getChannel();
* Object o = e.getMessage();
* if (o instanceof LoginMessage) {
* authenticate((LoginMessage) o);
* ctx.setAttachment(true) ;
* } else (o instanceof GetDataMessage) {
* if (Boolean.TRUE.equals(ctx.getAttachment()) ) {
* ch.write(fetchSecret((GetDataMessage) o));
* } else {
* fail();
* }
* }
* }
* ...
* }
*
* Now that the state of the handler is stored as an attachment, you can add the
* same handler instance to different pipelines:
*
* public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
*
* private static final DataServerHandler SHARED = new DataServerHandler();
*
* public {@link ChannelPipeline} getPipeline() {
* return {@link Channels}.pipeline(SHARED );
* }
* }
*
*
* Using a {@link ChannelLocal}
*
* If you have a state variable which needs to be accessed either from other
* handlers or outside handlers, you can use {@link ChannelLocal}:
*
* public final class DataServerState {
*
* public static final {@link ChannelLocal}<Boolean> loggedIn = new {@link ChannelLocal}<>() {
* protected Boolean initialValue(Channel channel) {
* return false;
* }
* }
* ...
* }
*
* {@code @Sharable}
* public class DataServerHandler extends {@link SimpleChannelHandler} {
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* Channel ch = e.getChannel();
* Object o = e.getMessage();
* if (o instanceof LoginMessage) {
* authenticate((LoginMessage) o);
* DataServerState.loggedIn.set(ch, true);
* } else (o instanceof GetDataMessage) {
* if (DataServerState.loggedIn.get(ch) ) {
* ctx.getChannel().write(fetchSecret((GetDataMessage) o));
* } else {
* fail();
* }
* }
* }
* ...
* }
*
* // Print the remote addresses of the authenticated clients:
* {@link ChannelGroup} allClientChannels = ...;
* for ({@link Channel} ch: allClientChannels) {
* if (DataServerState.loggedIn.get(ch) ) {
* System.out.println(ch.getRemoteAddress());
* }
* }
*
*
* The {@code @Sharable} annotation
*
* In the examples above which used an attachment or a {@link ChannelLocal},
* you might have noticed the {@code @Sharable} annotation.
*
* If a {@link ChannelHandler} is annotated with the {@code @Sharable}
* annotation, it means you can create an instance of the handler just once and
* add it to one or more {@link ChannelPipeline}s multiple times without
* a race condition.
*
* If this annotation is not specified, you have to create a new handler
* instance every time you add it to a pipeline because it has unshared state
* such as member variables.
*
* This annotation is provided for documentation purpose, just like
* the JCIP annotations .
*
*
Additional resources worth reading
*
* Please refer to the {@link ChannelEvent} and {@link ChannelPipeline} to find
* out what a upstream event and a downstream event are, what fundamental
* differences they have, and how they flow in a pipeline.
*
* @apiviz.landmark
* @apiviz.exclude ^org\.jboss\.netty\.handler\..*$
*/
public interface ChannelHandler {
/**
* Indicates that the same instance of the annotated {@link ChannelHandler}
* can be added to one or more {@link ChannelPipeline}s multiple times
* without a race condition.
*
* If this annotation is not specified, you have to create a new handler
* instance every time you add it to a pipeline because it has unshared
* state such as member variables.
*
* This annotation is provided for documentation purpose, just like
* the JCIP annotations .
*/
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Sharable {
// no value
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelHandlerContext.java 0000664 0000000 0000000 00000015664 12255541277 0031301 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
* and other handlers. A handler can send a {@link ChannelEvent} upstream or
* downstream, modify the {@link ChannelPipeline} it belongs to dynamically.
*
*
Sending an event
*
* You can send or forward a {@link ChannelEvent} to the closest handler in the
* same {@link ChannelPipeline} by calling {@link #sendUpstream(ChannelEvent)}
* or {@link #sendDownstream(ChannelEvent)}. Please refer to
* {@link ChannelPipeline} to understand how an event flows.
*
* Modifying a pipeline
*
* You can get the {@link ChannelPipeline} your handler belongs to by calling
* {@link #getPipeline()}. A non-trivial application could insert, remove, or
* replace handlers in the pipeline dynamically in runtime.
*
* Retrieving for later use
*
* You can keep the {@link ChannelHandlerContext} for later use, such as
* triggering an event outside the handler methods, even from a different thread.
*
* public class MyHandler extends {@link SimpleChannelHandler}
* implements {@link LifeCycleAwareChannelHandler} {
*
* private {@link ChannelHandlerContext} ctx;
*
* public void beforeAdd({@link ChannelHandlerContext} ctx) {
* this.ctx = ctx;
* }
*
* public void login(String username, password) {
* {@link Channels}.write(
* this.ctx ,
* {@link Channels}.succeededFuture(this.ctx.getChannel() ),
* new LoginMessage(username, password));
* }
* ...
* }
*
*
* Storing stateful information
*
* {@link #setAttachment(Object)} and {@link #getAttachment()} allow you to
* store and access stateful information that is related with a handler and its
* context. Please refer to {@link ChannelHandler} to learn various recommended
* ways to manage stateful information.
*
* A handler can have more than one context
*
* Please note that a {@link ChannelHandler} instance can be added to more than
* one {@link ChannelPipeline}. It means a single {@link ChannelHandler}
* instance can have more than one {@link ChannelHandlerContext} and therefore
* the single instance can be invoked with different
* {@link ChannelHandlerContext}s if it is added to one or more
* {@link ChannelPipeline}s more than once.
*
* For example, the following handler will have as many independent attachments
* as how many times it is added to pipelines, regardless if it is added to the
* same pipeline multiple times or added to different pipelines multiple times:
*
* public class FactorialHandler extends {@link SimpleChannelHandler} {
*
* // This handler will receive a sequence of increasing integers starting
* // from 1.
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} evt) {
* Integer a = (Integer) ctx.getAttachment();
* Integer b = (Integer) evt.getMessage();
*
* if (a == null) {
* a = 1;
* }
*
* ctx.setAttachment(Integer.valueOf(a * b));
* }
* }
*
* // Different context objects are given to "f1", "f2", "f3", and "f4" even if
* // they refer to the same handler instance. Because the FactorialHandler
* // stores its state in a context object (as an attachment), the factorial is
* // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
* FactorialHandler fh = new FactorialHandler();
*
* {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
* p1.addLast("f1", fh);
* p1.addLast("f2", fh);
*
* {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
* p2.addLast("f3", fh);
* p2.addLast("f4", fh);
*
*
* Additional resources worth reading
*
* Please refer to the {@link ChannelHandler}, {@link ChannelEvent}, and
* {@link ChannelPipeline} to find out what a upstream event and a downstream
* event are, what fundamental differences they have, how they flow in a
* pipeline, and how to handle the event in your application.
*
* @apiviz.owns org.jboss.netty.channel.ChannelHandler
*/
public interface ChannelHandlerContext {
/**
* Returns the {@link Channel} that the {@link ChannelPipeline} belongs to.
* This method is a shortcut to getPipeline().getChannel() .
*/
Channel getChannel();
/**
* Returns the {@link ChannelPipeline} that the {@link ChannelHandler}
* belongs to.
*/
ChannelPipeline getPipeline();
/**
* Returns the name of the {@link ChannelHandler} in the
* {@link ChannelPipeline}.
*/
String getName();
/**
* Returns the {@link ChannelHandler} that this context object is
* serving.
*/
ChannelHandler getHandler();
/**
* Returns {@code true} if and only if the {@link ChannelHandler} is an
* instance of {@link ChannelUpstreamHandler}.
*/
boolean canHandleUpstream();
/**
* Returns {@code true} if and only if the {@link ChannelHandler} is an
* instance of {@link ChannelDownstreamHandler}.
*/
boolean canHandleDownstream();
/**
* Sends the specified {@link ChannelEvent} to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with this context. It is recommended to use
* the shortcut methods in {@link Channels} rather than calling this method
* directly.
*/
void sendUpstream(ChannelEvent e);
/**
* Sends the specified {@link ChannelEvent} to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with this context. It is
* recommended to use the shortcut methods in {@link Channels} rather than
* calling this method directly.
*/
void sendDownstream(ChannelEvent e);
/**
* Retrieves an object which is {@link #setAttachment(Object) attached} to
* this context.
*
* @return {@code null} if no object was attached or
* {@code null} was attached
*/
Object getAttachment();
/**
* Attaches an object to this context to store a stateful information
* specific to the {@link ChannelHandler} which is associated with this
* context.
*/
void setAttachment(Object attachment);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelHandlerLifeCycleException.java 0000664 0000000 0000000 00000003007 12255541277 0033357 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link RuntimeException} which is thrown when a
* {@link LifeCycleAwareChannelHandler} throws an {@link Exception}
* in its handler methods.
*
* @apiviz.exclude
*/
public class ChannelHandlerLifeCycleException extends RuntimeException {
private static final long serialVersionUID = 8764799996088850672L;
/**
* Creates a new exception.
*/
public ChannelHandlerLifeCycleException() {
}
/**
* Creates a new exception.
*/
public ChannelHandlerLifeCycleException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new exception.
*/
public ChannelHandlerLifeCycleException(String message) {
super(message);
}
/**
* Creates a new exception.
*/
public ChannelHandlerLifeCycleException(Throwable cause) {
super(cause);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelLocal.java 0000664 0000000 0000000 00000012626 12255541277 0027404 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.util.internal.ConcurrentIdentityWeakKeyHashMap;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
/**
* A global variable that is local to a {@link Channel}. Think of this as a
* variation of {@link ThreadLocal} whose key is a {@link Channel} rather than
* a {@link Thread#currentThread()}. One difference is that you always have to
* specify the {@link Channel} to access the variable.
*
* Alternatively, you might want to use the
* {@link ChannelHandlerContext#setAttachment(Object) ChannelHandlerContext.attachment}
* property, which performs better.
* @apiviz.stereotype utility
*/
public class ChannelLocal implements Iterable> {
private final ConcurrentMap map =
new ConcurrentIdentityWeakKeyHashMap();
private final ChannelFutureListener remover = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
remove(future.getChannel());
}
};
private final boolean removeOnClose;
/**
* Creates a {@link Channel} local variable by calling {@link #ChannelLocal(boolean)} with
* {@code false} as parameter
*/
public ChannelLocal() {
this(false);
}
/**
* Creates a {@link Channel} local variable.
*
* @param removeOnClose if {@code true} the {@link ChannelLocal} will remove a
* {@link Channel} from it own once the {@link Channel} was closed.
*/
public ChannelLocal(boolean removeOnClose) {
this.removeOnClose = removeOnClose;
}
/**
* Returns the initial value of the variable. By default, it returns
* {@code null}. Override it to change the initial value.
*
* @param channel the channel where this local variable is accessed with
*/
protected T initialValue(Channel channel) {
return null;
}
/**
* Returns the value of this variable.
*/
public T get(Channel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
T value = map.get(channel);
if (value == null) {
value = initialValue(channel);
if (value != null) {
T oldValue = setIfAbsent(channel, value);
if (oldValue != null) {
value = oldValue;
}
}
}
return value;
}
/**
* Sets the value of this variable.
*
* @return the old value. {@code null} if there was no old value.
*/
public T set(Channel channel, T value) {
if (value == null) {
return remove(channel);
} else {
if (channel == null) {
throw new NullPointerException("channel");
}
T old = map.put(channel, value);
if (removeOnClose) {
channel.getCloseFuture().addListener(remover);
}
return old;
}
}
/**
* Sets the value of this variable only when no value was set.
*
* @return {@code null} if the specified value was set.
* An existing value if failed to set.
*/
public T setIfAbsent(Channel channel, T value) {
if (value == null) {
return get(channel);
} else {
if (channel == null) {
throw new NullPointerException("channel");
}
T mapping = map.putIfAbsent(channel, value);
if (removeOnClose && mapping == null) {
channel.getCloseFuture().addListener(remover);
}
return mapping;
}
}
/**
* Removes the variable and returns the removed value. If no value was set,
* this method returns the return value of {@link #initialValue(Channel)},
* which is {@code null} by default.
*
* @return the removed value.
* {@linkplain #initialValue(Channel) an initial value} (by default
* {@code null}) if no value was set.
*/
public T remove(Channel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
T removed = map.remove(channel);
if (removed == null) {
return initialValue(channel);
} else {
if (removeOnClose) {
channel.getCloseFuture().removeListener(remover);
}
return removed;
}
}
/**
* Returns a read-only {@link Iterator} that holds all {@link Entry}'s of this ChannelLocal
*/
public Iterator> iterator() {
return Collections.unmodifiableSet(map.entrySet()).iterator();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelPipeline.java 0000664 0000000 0000000 00000050225 12255541277 0030114 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
import org.jboss.netty.handler.ssl.SslHandler;
/**
* A list of {@link ChannelHandler}s which handles or intercepts
* {@link ChannelEvent}s of a {@link Channel}. {@link ChannelPipeline}
* implements an advanced form of the
* Intercepting
* Filter pattern to give a user full control over how an event is handled
* and how the {@link ChannelHandler}s in the pipeline interact with each other.
*
* Creation of a pipeline
*
* For each new channel, a new pipeline must be created and attached to the
* channel. Once attached, the coupling between the channel and the pipeline
* is permanent; the channel cannot attach another pipeline to it nor detach
* the current pipeline from it.
*
* The recommended way to create a new pipeline is to use the helper methods in
* {@link Channels} rather than calling an individual implementation's
* constructor:
*
* import static org.jboss.netty.channel.{@link Channels}.*;
* {@link ChannelPipeline} pipeline = pipeline(); // same with Channels.pipeline()
*
*
* How an event flows in a pipeline
*
* The following diagram describes how {@link ChannelEvent}s are processed by
* {@link ChannelHandler}s in a {@link ChannelPipeline} typically.
* A {@link ChannelEvent} can be handled by either a {@link ChannelUpstreamHandler}
* or a {@link ChannelDownstreamHandler} and be forwarded to the closest
* handler by calling {@link ChannelHandlerContext#sendUpstream(ChannelEvent)}
* or {@link ChannelHandlerContext#sendDownstream(ChannelEvent)}. The meaning
* of the event is interpreted somewhat differently depending on whether it is
* going upstream or going downstream. Please refer to {@link ChannelEvent} for
* more information.
*
* I/O Request
* via {@link Channel} or
* {@link ChannelHandlerContext}
* |
* +----------------------------------------+---------------+
* | ChannelPipeline | |
* | \|/ |
* | +----------------------+ +-----------+------------+ |
* | | Upstream Handler N | | Downstream Handler 1 | |
* | +----------+-----------+ +-----------+------------+ |
* | /|\ | |
* | | \|/ |
* | +----------+-----------+ +-----------+------------+ |
* | | Upstream Handler N-1 | | Downstream Handler 2 | |
* | +----------+-----------+ +-----------+------------+ |
* | /|\ . |
* | . . |
* | [ sendUpstream() ] [ sendDownstream() ] |
* | [ + INBOUND data ] [ + OUTBOUND data ] |
* | . . |
* | . \|/ |
* | +----------+-----------+ +-----------+------------+ |
* | | Upstream Handler 2 | | Downstream Handler M-1 | |
* | +----------+-----------+ +-----------+------------+ |
* | /|\ | |
* | | \|/ |
* | +----------+-----------+ +-----------+------------+ |
* | | Upstream Handler 1 | | Downstream Handler M | |
* | +----------+-----------+ +-----------+------------+ |
* | /|\ | |
* +-------------+--------------------------+---------------+
* | \|/
* +-------------+--------------------------+---------------+
* | | | |
* | [ Socket.read() ] [ Socket.write() ] |
* | |
* | Netty Internal I/O Threads (Transport Implementation) |
* +--------------------------------------------------------+
*
* An upstream event is handled by the upstream handlers in the bottom-up
* direction as shown on the left side of the diagram. An upstream handler
* usually handles the inbound data generated by the I/O thread on the bottom
* of the diagram. The inbound data is often read from a remote peer via the
* actual input operation such as {@link InputStream#read(byte[])}.
* If an upstream event goes beyond the top upstream handler, it is discarded
* silently.
*
* A downstream event is handled by the downstream handler in the top-down
* direction as shown on the right side of the diagram. A downstream handler
* usually generates or transforms the outbound traffic such as write requests.
* If a downstream event goes beyond the bottom downstream handler, it is
* handled by an I/O thread associated with the {@link Channel}. The I/O thread
* often performs the actual output operation such as {@link OutputStream#write(byte[])}.
*
* For example, let us assume that we created the following pipeline:
*
* {@link ChannelPipeline} p = {@link Channels}.pipeline();
* p.addLast("1", new UpstreamHandlerA());
* p.addLast("2", new UpstreamHandlerB());
* p.addLast("3", new DownstreamHandlerA());
* p.addLast("4", new DownstreamHandlerB());
* p.addLast("5", new UpstreamHandlerX());
*
* In the example above, the class whose name starts with {@code Upstream} means
* it is an upstream handler. The class whose name starts with
* {@code Downstream} means it is a downstream handler.
*
* In the given example configuration, the handler evaluation order is 1, 2, 3,
* 4, 5 when an event goes upstream. When an event goes downstream, the order
* is 5, 4, 3, 2, 1. On top of this principle, {@link ChannelPipeline} skips
* the evaluation of certain handlers to shorten the stack depth:
*
* 3 and 4 don't implement {@link ChannelUpstreamHandler}, and therefore the
* actual evaluation order of an upstream event will be: 1, 2, and 5.
* 1, 2, and 5 don't implement {@link ChannelDownstreamHandler}, and
* therefore the actual evaluation order of a downstream event will be:
* 4 and 3.
* If 5 extended {@link SimpleChannelHandler} which implements both
* {@link ChannelUpstreamHandler} and {@link ChannelDownstreamHandler}, the
* evaluation order of an upstream and a downstream event could be 125 and
* 543 respectively.
*
*
* Building a pipeline
*
* A user is supposed to have one or more {@link ChannelHandler}s in a
* pipeline to receive I/O events (e.g. read) and to request I/O operations
* (e.g. write and close). For example, a typical server will have the following
* handlers in each channel's pipeline, but your mileage may vary depending on
* the complexity and characteristics of the protocol and business logic:
*
*
* Protocol Decoder - translates binary data (e.g. {@link ChannelBuffer})
* into a Java object.
* Protocol Encoder - translates a Java object into binary data.
* {@link ExecutionHandler} - applies a thread model.
* Business Logic Handler - performs the actual business logic
* (e.g. database access).
*
*
* and it could be represented as shown in the following example:
*
*
* {@link ChannelPipeline} pipeline = {@link Channels#pipeline() Channels.pipeline()};
* pipeline.addLast("decoder", new MyProtocolDecoder());
* pipeline.addLast("encoder", new MyProtocolEncoder());
* pipeline.addLast("executor", new {@link ExecutionHandler}(
* new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));
* pipeline.addLast("handler", new MyBusinessLogicHandler());
*
*
* Thread safety
*
* A {@link ChannelHandler} can be added or removed at any time because a
* {@link ChannelPipeline} is thread safe. For example, you can insert a
* {@link SslHandler} when sensitive information is about to be exchanged,
* and remove it after the exchange.
*
*
Pitfall
*
* Due to the internal implementation detail of the current default
* {@link ChannelPipeline}, the following code does not work as expected if
* FirstHandler is the last handler in the pipeline:
*
* public class FirstHandler extends {@link SimpleChannelUpstreamHandler} {
*
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* // Remove this handler from the pipeline,
* ctx.getPipeline().remove(this);
* // And let SecondHandler handle the current event.
* ctx.getPipeline().addLast("2nd", new SecondHandler());
* ctx.sendUpstream(e);
* }
* }
*
* To implement the expected behavior, you have to add SecondHandler
* before the removal or make sure there is at least one more handler between
* FirstHandler and SecondHandler .
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.ChannelHandlerContext
* @apiviz.owns org.jboss.netty.channel.ChannelHandler
* @apiviz.uses org.jboss.netty.channel.ChannelSink - - sends events downstream
*/
public interface ChannelPipeline {
/**
* Inserts a {@link ChannelHandler} at the first position of this pipeline.
*
* @param name the name of the handler to insert first
* @param handler the handler to insert first
*
* @throws IllegalArgumentException
* if there's an entry with the same name already in the pipeline
* @throws NullPointerException
* if the specified name or handler is {@code null}
*/
void addFirst(String name, ChannelHandler handler);
/**
* Appends a {@link ChannelHandler} at the last position of this pipeline.
*
* @param name the name of the handler to append
* @param handler the handler to append
*
* @throws IllegalArgumentException
* if there's an entry with the same name already in the pipeline
* @throws NullPointerException
* if the specified name or handler is {@code null}
*/
void addLast(String name, ChannelHandler handler);
/**
* Inserts a {@link ChannelHandler} before an existing handler of this
* pipeline.
*
* @param baseName the name of the existing handler
* @param name the name of the handler to insert before
* @param handler the handler to insert before
*
* @throws NoSuchElementException
* if there's no such entry with the specified {@code baseName}
* @throws IllegalArgumentException
* if there's an entry with the same name already in the pipeline
* @throws NullPointerException
* if the specified baseName, name, or handler is {@code null}
*/
void addBefore(String baseName, String name, ChannelHandler handler);
/**
* Inserts a {@link ChannelHandler} after an existing handler of this
* pipeline.
*
* @param baseName the name of the existing handler
* @param name the name of the handler to insert after
* @param handler the handler to insert after
*
* @throws NoSuchElementException
* if there's no such entry with the specified {@code baseName}
* @throws IllegalArgumentException
* if there's an entry with the same name already in the pipeline
* @throws NullPointerException
* if the specified baseName, name, or handler is {@code null}
*/
void addAfter(String baseName, String name, ChannelHandler handler);
/**
* Removes the specified {@link ChannelHandler} from this pipeline.
*
* @throws NoSuchElementException
* if there's no such handler in this pipeline
* @throws NullPointerException
* if the specified handler is {@code null}
*/
void remove(ChannelHandler handler);
/**
* Removes the {@link ChannelHandler} with the specified name from this
* pipeline.
*
* @return the removed handler
*
* @throws NoSuchElementException
* if there's no such handler with the specified name in this pipeline
* @throws NullPointerException
* if the specified name is {@code null}
*/
ChannelHandler remove(String name);
/**
* Removes the {@link ChannelHandler} of the specified type from this
* pipeline
*
* @param the type of the handler
* @param handlerType the type of the handler
*
* @return the removed handler
*
* @throws NoSuchElementException
* if there's no such handler of the specified type in this pipeline
* @throws NullPointerException
* if the specified handler type is {@code null}
*/
T remove(Class handlerType);
/**
* Removes the first {@link ChannelHandler} in this pipeline.
*
* @return the removed handler
*
* @throws NoSuchElementException
* if this pipeline is empty
*/
ChannelHandler removeFirst();
/**
* Removes the last {@link ChannelHandler} in this pipeline.
*
* @return the removed handler
*
* @throws NoSuchElementException
* if this pipeline is empty
*/
ChannelHandler removeLast();
/**
* Replaces the specified {@link ChannelHandler} with a new handler in
* this pipeline.
*
* @throws NoSuchElementException
* if the specified old handler does not exist in this pipeline
* @throws IllegalArgumentException
* if a handler with the specified new name already exists in this
* pipeline, except for the handler to be replaced
* @throws NullPointerException
* if the specified old handler, new name, or new handler is
* {@code null}
*/
void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
/**
* Replaces the {@link ChannelHandler} of the specified name with a new
* handler in this pipeline.
*
* @return the removed handler
*
* @throws NoSuchElementException
* if the handler with the specified old name does not exist in this pipeline
* @throws IllegalArgumentException
* if a handler with the specified new name already exists in this
* pipeline, except for the handler to be replaced
* @throws NullPointerException
* if the specified old handler, new name, or new handler is
* {@code null}
*/
ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
/**
* Replaces the {@link ChannelHandler} of the specified type with a new
* handler in this pipeline.
*
* @return the removed handler
*
* @throws NoSuchElementException
* if the handler of the specified old handler type does not exist
* in this pipeline
* @throws IllegalArgumentException
* if a handler with the specified new name already exists in this
* pipeline, except for the handler to be replaced
* @throws NullPointerException
* if the specified old handler, new name, or new handler is
* {@code null}
*/
T replace(Class oldHandlerType, String newName, ChannelHandler newHandler);
/**
* Returns the first {@link ChannelHandler} in this pipeline.
*
* @return the first handler. {@code null} if this pipeline is empty.
*/
ChannelHandler getFirst();
/**
* Returns the last {@link ChannelHandler} in this pipeline.
*
* @return the last handler. {@code null} if this pipeline is empty.
*/
ChannelHandler getLast();
/**
* Returns the {@link ChannelHandler} with the specified name in this
* pipeline.
*
* @return the handler with the specified name.
* {@code null} if there's no such handler in this pipeline.
*/
ChannelHandler get(String name);
/**
* Returns the {@link ChannelHandler} of the specified type in this
* pipeline.
*
* @return the handler of the specified handler type.
* {@code null} if there's no such handler in this pipeline.
*/
T get(Class handlerType);
/**
* Returns the context object of the specified {@link ChannelHandler} in
* this pipeline.
*
* @return the context object of the specified handler.
* {@code null} if there's no such handler in this pipeline.
*/
ChannelHandlerContext getContext(ChannelHandler handler);
/**
* Returns the context object of the {@link ChannelHandler} with the
* specified name in this pipeline.
*
* @return the context object of the handler with the specified name.
* {@code null} if there's no such handler in this pipeline.
*/
ChannelHandlerContext getContext(String name);
/**
* Returns the context object of the {@link ChannelHandler} of the
* specified type in this pipeline.
*
* @return the context object of the handler of the specified type.
* {@code null} if there's no such handler in this pipeline.
*/
ChannelHandlerContext getContext(Class extends ChannelHandler> handlerType);
/**
* Sends the specified {@link ChannelEvent} to the first
* {@link ChannelUpstreamHandler} in this pipeline.
*
* @throws NullPointerException
* if the specified event is {@code null}
*/
void sendUpstream(ChannelEvent e);
/**
* Sends the specified {@link ChannelEvent} to the last
* {@link ChannelDownstreamHandler} in this pipeline.
*
* @throws NullPointerException
* if the specified event is {@code null}
*/
void sendDownstream(ChannelEvent e);
/**
* Schedules the specified task to be executed in the I/O thread associated
* with this pipeline's {@link Channel}.
*/
ChannelFuture execute(Runnable task);
/**
* Returns the {@link Channel} that this pipeline is attached to.
*
* @return the channel. {@code null} if this pipeline is not attached yet.
*/
Channel getChannel();
/**
* Returns the {@link ChannelSink} that this pipeline is attached to.
*
* @return the sink. {@code null} if this pipeline is not attached yet.
*/
ChannelSink getSink();
/**
* Attaches this pipeline to the specified {@link Channel} and
* {@link ChannelSink}. Once a pipeline is attached, it can't be detached
* nor attached again.
*
* @throws IllegalStateException if this pipeline is attached already
*/
void attach(Channel channel, ChannelSink sink);
/**
* Returns {@code true} if and only if this pipeline is attached to
* a {@link Channel}.
*/
boolean isAttached();
/**
* Returns the {@link List} of the handler names.
*/
List getNames();
/**
* Converts this pipeline into an ordered {@link Map} whose keys are
* handler names and whose values are handlers.
*/
Map toMap();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelPipelineCoverage.java 0000664 0000000 0000000 00000002563 12255541277 0031572 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.jboss.netty.channel.ChannelHandler.Sharable;
/**
* @deprecated Use the {@link Sharable} annotation instead.
* @apiviz.exclude
*/
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface ChannelPipelineCoverage {
/**
* {@code "all"}
*/
String ALL = "all";
/**
* {@code "one"}
*/
String ONE = "one";
/**
* The value of this annotation
*/
String value();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelPipelineException.java 0000664 0000000 0000000 00000003034 12255541277 0031767 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelException} which is thrown when a {@link ChannelPipeline}
* failed to process a {@link ChannelEvent} or when a {@link ChannelPipelineFactory}
* failed to initialize a {@link ChannelPipeline}.
*
* @apiviz.exclude
*/
public class ChannelPipelineException extends ChannelException {
private static final long serialVersionUID = 3379174210419885980L;
/**
* Creates a new instance.
*/
public ChannelPipelineException() {
}
/**
* Creates a new instance.
*/
public ChannelPipelineException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new instance.
*/
public ChannelPipelineException(String message) {
super(message);
}
/**
* Creates a new instance.
*/
public ChannelPipelineException(Throwable cause) {
super(cause);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelPipelineFactory.java 0000664 0000000 0000000 00000003400 12255541277 0031435 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.bootstrap.Bootstrap;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
/**
* Creates a new {@link ChannelPipeline} for a new {@link Channel}.
*
* When a {@linkplain ServerChannel server-side channel} accepts a new incoming
* connection, a new child channel is created for each newly accepted connection.
* A new child channel uses a new {@link ChannelPipeline}, which is created by
* the {@link ChannelPipelineFactory} specified in the server-side channel's
* {@link ChannelConfig#getPipelineFactory() "pipelineFactory"} option.
*
* Also, when a {@link ClientBootstrap} or {@link ConnectionlessBootstrap}
* creates a new channel, it uses the {@link Bootstrap#getPipelineFactory() "pipelineFactory"}
* property to create a new {@link ChannelPipeline} for each new channel.
*
* @apiviz.has org.jboss.netty.channel.ChannelPipeline oneway - - creates
*/
public interface ChannelPipelineFactory {
/**
* Returns a newly created {@link ChannelPipeline}.
*/
ChannelPipeline getPipeline() throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelSink.java 0000664 0000000 0000000 00000003402 12255541277 0027246 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* Receives and processes the terminal downstream {@link ChannelEvent}s.
*
* A {@link ChannelSink} is an internal component which is supposed to be
* implemented by a transport provider. Most users will not see this type
* in their code.
*
* @apiviz.uses org.jboss.netty.channel.ChannelPipeline - - sends events upstream
*/
public interface ChannelSink {
/**
* Invoked by {@link ChannelPipeline} when a downstream {@link ChannelEvent}
* has reached its terminal (the head of the pipeline).
*/
void eventSunk(ChannelPipeline pipeline, ChannelEvent e) throws Exception;
/**
* Invoked by {@link ChannelPipeline} when an exception was raised while
* one of its {@link ChannelHandler}s process a {@link ChannelEvent}.
*/
void exceptionCaught(ChannelPipeline pipeline, ChannelEvent e, ChannelPipelineException cause) throws Exception;
/**
* Execute the given {@link Runnable} later in the io-thread.
* Some implementation may not support this and just execute it directly.
*/
ChannelFuture execute(ChannelPipeline pipeline, Runnable task);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelState.java 0000664 0000000 0000000 00000007117 12255541277 0027431 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
/**
* The current or future state of a {@link Channel}.
*
* The state of a {@link Channel} is interpreted differently depending on the
* {@linkplain ChannelStateEvent#getValue() value} of a {@link ChannelStateEvent}
* and the direction of the event in a {@link ChannelPipeline}:
*
*
*
* Direction State Value Meaning
*
*
* Upstream {@link #OPEN}
* {@code true} The channel is open.
*
*
* Upstream {@link #OPEN}
* {@code false} The channel is closed.
*
*
* Upstream {@link #BOUND}
* {@link SocketAddress} The channel is bound to a local address.
*
*
* Upstream {@link #BOUND}
* {@code null} The channel is unbound to a local address.
*
*
* Upstream {@link #CONNECTED}
* {@link SocketAddress} The channel is connected to a remote address.
*
*
* Upstream {@link #CONNECTED}
* {@code null} The channel is disconnected from a remote address.
*
*
* Upstream {@link #INTEREST_OPS}
* an integer The channel interestOps has been changed.
*
*
* Downstream {@link #OPEN}
* {@code true} N/A
*
*
* Downstream {@link #OPEN}
* {@code false} Close the channel.
*
*
* Downstream {@link #BOUND}
* {@link SocketAddress} Bind the channel to the specified local address.
*
*
* Downstream {@link #BOUND}
* {@code null} Unbind the channel from the current local address.
*
*
* Downstream {@link #CONNECTED}
* {@link SocketAddress} Connect the channel to the specified remote address.
*
*
* Downstream {@link #CONNECTED}
* {@code null} Disconnect the channel from the current remote address.
*
*
* Downstream {@link #INTEREST_OPS}
* an integer Change the interestOps of the channel.
*
*
*
* To see how an event is interpreted further, please refer to {@link ChannelEvent}.
*/
public enum ChannelState {
/**
* Represents a {@link Channel}'s {@link Channel#isOpen() open} property
*/
OPEN,
/**
* Represents a {@link Channel}'s {@link Channel#isBound() bound} property
*/
BOUND,
/**
* Represents a {@link Channel}'s {@link Channel#isConnected() connected}
* property
*/
CONNECTED,
/**
* Represents a {@link Channel}'s {@link Channel#getInterestOps() interestOps}
* property
*/
INTEREST_OPS
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelStateEvent.java 0000664 0000000 0000000 00000003004 12255541277 0030422 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelEvent} which represents the change of the {@link Channel}
* state. It can mean the notification of a change or the request for a
* change, depending on whether it is an upstream event or a downstream event
* respectively. Please refer to the {@link ChannelEvent} documentation to
* find out what an upstream event and a downstream event are and what
* fundamental differences they have.
*
* @apiviz.has org.jboss.netty.channel.ChannelState
*/
public interface ChannelStateEvent extends ChannelEvent {
/**
* Returns the changed property of the {@link Channel}.
*/
ChannelState getState();
/**
* Returns the value of the changed property of the {@link Channel}.
* Please refer to {@link ChannelState} documentation to find out the
* allowed values for each property.
*/
Object getValue();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChannelUpstreamHandler.java 0000664 0000000 0000000 00000007304 12255541277 0031445 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.util.concurrent.Executor;
import org.jboss.netty.handler.execution.ExecutionHandler;
/**
* Handles or intercepts an upstream {@link ChannelEvent}, and sends a
* {@link ChannelEvent} to the next handler in a {@link ChannelPipeline}.
*
* The most common use case of this interface is to intercept an I/O event
* generated by I/O workers to transform the received messages or execute
* the relevant business logic.
*
*
{@link SimpleChannelUpstreamHandler}
*
* In most cases, you will get to use a {@link SimpleChannelUpstreamHandler} to
* implement an upstream handler because it provides an individual handler
* method for each event type. You might want to implement this interface
* directly though if you want to handle various types of events in more
* generic way.
*
*
Firing an event to the next handler
*
* You can forward the received event upstream or downstream. In most cases,
* {@link ChannelUpstreamHandler} will send the event upstream (i.e. inbound)
* although it is legal to send the event downstream (i.e. outbound):
*
*
* // Sending the event upstream (inbound)
* void handleUpstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
* ...
* ctx.sendUpstream(e);
* ...
* }
*
* // Sending the event downstream (outbound)
* void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
* ...
* ctx.sendDownstream(new {@link DownstreamMessageEvent}(...));
* ...
* }
*
*
* Using the helper class to send an event
*
* You will also find various helper methods in {@link Channels} to be useful
* to generate and send an artificial or manipulated event.
*
*
State management
*
* Please refer to {@link ChannelHandler}.
*
* Thread safety
*
* {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
* will be invoked sequentially by the same thread (i.e. an I/O thread) and
* therefore a handler does not need to worry about being invoked with a new
* upstream event before the previous upstream event is finished.
*
* This does not necessarily mean that there's a dedicated thread per
* {@link Channel}; the I/O thread of some transport can serve more than one
* {@link Channel} (e.g. NIO transport), while the I/O thread of other
* transports can serve only one (e.g. OIO transport).
*
* However, if you add an {@link ExecutionHandler} to a {@link ChannelPipeline},
* this behavior changes depending on what {@link Executor} was employed to
* dispatch the events. Please refer to {@link ExecutionHandler} for more
* information.
*
* @apiviz.exclude ^org\.jboss\.netty\.handler\..*$
*/
public interface ChannelUpstreamHandler extends ChannelHandler {
/**
* Handles the specified upstream event.
*
* @param ctx the context object for this handler
* @param e the upstream event to process or intercept
*/
void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/Channels.java 0000664 0000000 0000000 00000076657 12255541277 0026632 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
import java.util.Map;
import org.jboss.netty.util.internal.ConversionUtil;
/**
* A helper class which provides various convenience methods related with
* {@link Channel}, {@link ChannelHandler}, and {@link ChannelPipeline}.
*
*
Factory methods
*
* It is always recommended to use the factory methods provided by
* {@link Channels} rather than calling the constructor of the implementation
* types.
*
* {@link #pipeline()}
* {@link #pipeline(ChannelPipeline)}
* {@link #pipelineFactory(ChannelPipeline)}
* {@link #succeededFuture(Channel)}
* {@link #failedFuture(Channel, Throwable)}
*
*
* Upstream and downstream event generation
*
* Various event generation methods are provided to simplify the generation of
* upstream events and downstream events. It is always recommended to use the
* event generation methods provided by {@link Channels} rather than calling
* {@link ChannelHandlerContext#sendUpstream(ChannelEvent)} or
* {@link ChannelHandlerContext#sendDownstream(ChannelEvent)} by yourself.
* @apiviz.landmark
*/
public final class Channels {
// pipeline factory methods
/**
* Creates a new {@link ChannelPipeline}.
*/
public static ChannelPipeline pipeline() {
return new DefaultChannelPipeline();
}
/**
* Creates a new {@link ChannelPipeline} which contains the specified
* {@link ChannelHandler}s. The names of the specified handlers are
* generated automatically; the first handler's name is {@code "0"},
* the second handler's name is {@code "1"}, the third handler's name is
* {@code "2"}, and so on.
*/
public static ChannelPipeline pipeline(ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
ChannelPipeline newPipeline = pipeline();
for (int i = 0; i < handlers.length; i ++) {
ChannelHandler h = handlers[i];
if (h == null) {
break;
}
newPipeline.addLast(ConversionUtil.toString(i), h);
}
return newPipeline;
}
/**
* Creates a new {@link ChannelPipeline} which contains the same entries
* with the specified {@code pipeline}. Please note that only the names
* and the references of the {@link ChannelHandler}s will be copied; a new
* {@link ChannelHandler} instance will never be created.
*/
public static ChannelPipeline pipeline(ChannelPipeline pipeline) {
ChannelPipeline newPipeline = pipeline();
for (Map.Entry e: pipeline.toMap().entrySet()) {
newPipeline.addLast(e.getKey(), e.getValue());
}
return newPipeline;
}
/**
* Creates a new {@link ChannelPipelineFactory} which creates a new
* {@link ChannelPipeline} which contains the same entries with the
* specified {@code pipeline}. Please note that only the names and the
* references of the {@link ChannelHandler}s will be copied; a new
* {@link ChannelHandler} instance will never be created.
*/
public static ChannelPipelineFactory pipelineFactory(
final ChannelPipeline pipeline) {
return new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return pipeline(pipeline);
}
};
}
// future factory methods
/**
* Creates a new non-cancellable {@link ChannelFuture} for the specified
* {@link Channel}.
*/
public static ChannelFuture future(Channel channel) {
return future(channel, false);
}
/**
* Creates a new {@link ChannelFuture} for the specified {@link Channel}.
*
* @param cancellable {@code true} if and only if the returned future
* can be canceled by {@link ChannelFuture#cancel()}
*/
public static ChannelFuture future(Channel channel, boolean cancellable) {
return new DefaultChannelFuture(channel, cancellable);
}
/**
* Creates a new {@link ChannelFuture} which is already succeeded for the
* specified {@link Channel}.
*/
public static ChannelFuture succeededFuture(Channel channel) {
if (channel instanceof AbstractChannel) {
return ((AbstractChannel) channel).getSucceededFuture();
} else {
return new SucceededChannelFuture(channel);
}
}
/**
* Creates a new {@link ChannelFuture} which has failed already for the
* specified {@link Channel}.
*
* @param cause the cause of the failure
*/
public static ChannelFuture failedFuture(Channel channel, Throwable cause) {
return new FailedChannelFuture(channel, cause);
}
// event emission methods
/**
* Sends a {@code "channelOpen"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}. If the specified channel has a parent,
* a {@code "childChannelOpen"} event will be sent, too.
*/
public static void fireChannelOpen(Channel channel) {
// Notify the parent handler.
if (channel.getParent() != null) {
fireChildChannelStateChanged(channel.getParent(), channel);
}
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(
channel, ChannelState.OPEN, Boolean.TRUE));
}
/**
* Sends a {@code "channelOpen"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* Please note that this method does not trigger a
* {@code "childChannelOpen"} event unlike {@link #fireChannelOpen(Channel)}
* method.
*/
public static void fireChannelOpen(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.OPEN, Boolean.TRUE));
}
/**
* Sends a {@code "channelBound"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param localAddress
* the local address where the specified channel is bound
*/
public static void fireChannelBound(Channel channel, SocketAddress localAddress) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(
channel, ChannelState.BOUND, localAddress));
}
/**
* Sends a {@code "channelBound"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param localAddress
* the local address where the specified channel is bound
*/
public static void fireChannelBound(ChannelHandlerContext ctx, SocketAddress localAddress) {
ctx.sendUpstream(new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.BOUND, localAddress));
}
/**
* Sends a {@code "channelConnected"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param remoteAddress
* the remote address where the specified channel is connected
*/
public static void fireChannelConnected(Channel channel, SocketAddress remoteAddress) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(
channel, ChannelState.CONNECTED, remoteAddress));
}
/**
* Sends a {@code "channelConnected"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param remoteAddress
* the remote address where the specified channel is connected
*/
public static void fireChannelConnected(ChannelHandlerContext ctx, SocketAddress remoteAddress) {
ctx.sendUpstream(new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.CONNECTED, remoteAddress));
}
/**
* Sends a {@code "messageReceived"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param message the received message
*/
public static void fireMessageReceived(Channel channel, Object message) {
fireMessageReceived(channel, message, null);
}
/**
* Sends a {@code "messageReceived"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} belongs.
*
* @param message the received message
* @param remoteAddress the remote address where the received message
* came from
*/
public static void fireMessageReceived(Channel channel, Object message, SocketAddress remoteAddress) {
channel.getPipeline().sendUpstream(
new UpstreamMessageEvent(channel, message, remoteAddress));
}
/**
* Sends a {@code "messageReceived"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param message the received message
*/
public static void fireMessageReceived(ChannelHandlerContext ctx, Object message) {
ctx.sendUpstream(new UpstreamMessageEvent(ctx.getChannel(), message, null));
}
/**
* Sends a {@code "messageReceived"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param message the received message
* @param remoteAddress the remote address where the received message
* came from
*/
public static void fireMessageReceived(
ChannelHandlerContext ctx, Object message, SocketAddress remoteAddress) {
ctx.sendUpstream(new UpstreamMessageEvent(
ctx.getChannel(), message, remoteAddress));
}
/**
* Sends a {@code "writeComplete"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} in the next io-thread.
*/
public static ChannelFuture fireWriteCompleteLater(final Channel channel, final long amount) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireWriteComplete(channel, amount);
}
});
}
/**
* Sends a {@code "writeComplete"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*/
public static void fireWriteComplete(Channel channel, long amount) {
if (amount == 0) {
return;
}
channel.getPipeline().sendUpstream(
new DefaultWriteCompletionEvent(channel, amount));
}
/**
* Sends a {@code "writeComplete"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireWriteComplete(ChannelHandlerContext ctx, long amount) {
ctx.sendUpstream(new DefaultWriteCompletionEvent(ctx.getChannel(), amount));
}
/**
* Sends a {@code "channelInterestChanged"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelInterestChangedLater(final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelInterestChanged(channel);
}
});
}
/**
* Sends a {@code "channelInterestChanged"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*/
public static void fireChannelInterestChanged(Channel channel) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(
channel, ChannelState.INTEREST_OPS, Channel.OP_READ));
}
/**
* Sends a {@code "channelInterestChanged"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelInterestChanged(
ChannelHandlerContext ctx) {
ctx.sendUpstream(
new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.INTEREST_OPS, Channel.OP_READ));
}
/**
* Sends a {@code "channelDisconnected"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelDisconnectedLater(final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelDisconnected(channel);
}
});
}
/**
* Sends a {@code "channelDisconnected"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*/
public static void fireChannelDisconnected(Channel channel) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(
channel, ChannelState.CONNECTED, null));
}
/**
* Sends a {@code "channelDisconnected"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelDisconnected(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.CONNECTED, null));
}
/**
* Sends a {@code "channelUnbound"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelUnboundLater(final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelUnbound(channel);
}
});
}
/**
* Sends a {@code "channelUnbound"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*/
public static void fireChannelUnbound(Channel channel) {
channel.getPipeline().sendUpstream(new UpstreamChannelStateEvent(
channel, ChannelState.BOUND, null));
}
/**
* Sends a {@code "channelUnbound"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelUnbound(ChannelHandlerContext ctx) {
ctx.sendUpstream(new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.BOUND, null));
}
/**
* Sends a {@code "channelClosed"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireChannelClosedLater(final Channel channel) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireChannelClosed(channel);
}
});
}
/**
* Sends a {@code "channelClosed"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*/
public static void fireChannelClosed(Channel channel) {
channel.getPipeline().sendUpstream(
new UpstreamChannelStateEvent(
channel, ChannelState.OPEN, Boolean.FALSE));
// Notify the parent handler.
if (channel.getParent() != null) {
fireChildChannelStateChanged(channel.getParent(), channel);
}
}
/**
* Sends a {@code "channelClosed"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireChannelClosed(ChannelHandlerContext ctx) {
ctx.sendUpstream(
new UpstreamChannelStateEvent(
ctx.getChannel(), ChannelState.OPEN, Boolean.FALSE));
}
/**
* Sends a {@code "exceptionCaught"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel} once the io-thread runs again.
*/
public static ChannelFuture fireExceptionCaughtLater(final Channel channel, final Throwable cause) {
return channel.getPipeline().execute(new Runnable() {
public void run() {
fireExceptionCaught(channel, cause);
}
});
}
/**
* Sends a {@code "exceptionCaught"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext} once the io-thread runs again.
*/
public static ChannelFuture fireExceptionCaughtLater(final ChannelHandlerContext ctx, final Throwable cause) {
return ctx.getPipeline().execute(new Runnable() {
public void run() {
fireExceptionCaught(ctx, cause);
}
});
}
/**
* Sends a {@code "exceptionCaught"} event to the first
* {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*/
public static void fireExceptionCaught(Channel channel, Throwable cause) {
channel.getPipeline().sendUpstream(
new DefaultExceptionEvent(channel, cause));
}
/**
* Sends a {@code "exceptionCaught"} event to the
* {@link ChannelUpstreamHandler} which is placed in the closest upstream
* from the handler associated with the specified
* {@link ChannelHandlerContext}.
*/
public static void fireExceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
ctx.sendUpstream(new DefaultExceptionEvent(ctx.getChannel(), cause));
}
private static void fireChildChannelStateChanged(
Channel channel, Channel childChannel) {
channel.getPipeline().sendUpstream(
new DefaultChildChannelStateEvent(channel, childChannel));
}
/**
* Sends a {@code "bind"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to bind
* @param localAddress the local address to bind to
*
* @return the {@link ChannelFuture} which will be notified when the
* bind operation is done
*/
public static ChannelFuture bind(Channel channel, SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(
channel, future, ChannelState.BOUND, localAddress));
return future;
}
/**
* Sends a {@code "bind"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified when the bind
* operation is done
* @param localAddress the local address to bind to
*/
public static void bind(
ChannelHandlerContext ctx, ChannelFuture future, SocketAddress localAddress) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
ctx.sendDownstream(new DownstreamChannelStateEvent(
ctx.getChannel(), future, ChannelState.BOUND, localAddress));
}
/**
* Sends a {@code "unbind"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified when the unbind
* operation is done
*/
public static void unbind(ChannelHandlerContext ctx, ChannelFuture future) {
ctx.sendDownstream(new DownstreamChannelStateEvent(
ctx.getChannel(), future, ChannelState.BOUND, null));
}
/**
* Sends a {@code "unbind"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to unbind
*
* @return the {@link ChannelFuture} which will be notified when the
* unbind operation is done
*/
public static ChannelFuture unbind(Channel channel) {
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(
channel, future, ChannelState.BOUND, null));
return future;
}
/**
* Sends a {@code "connect"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to attempt a connection
* @param remoteAddress the remote address to connect to
*
* @return the {@link ChannelFuture} which will be notified when the
* connection attempt is done
*/
public static ChannelFuture connect(Channel channel, SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
ChannelFuture future = future(channel, true);
channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(
channel, future, ChannelState.CONNECTED, remoteAddress));
return future;
}
/**
* Sends a {@code "connect"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified when the connection
* attempt is done
* @param remoteAddress the remote address to connect to
*/
public static void connect(
ChannelHandlerContext ctx, ChannelFuture future, SocketAddress remoteAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
ctx.sendDownstream(new DownstreamChannelStateEvent(
ctx.getChannel(), future, ChannelState.CONNECTED, remoteAddress));
}
/**
* Sends a {@code "write"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to write a message
* @param message the message to write to the channel
*
* @return the {@link ChannelFuture} which will be notified when the
* write operation is done
*/
public static ChannelFuture write(Channel channel, Object message) {
return write(channel, message, null);
}
/**
* Sends a {@code "write"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified when the write
* operation is done
*/
public static void write(
ChannelHandlerContext ctx, ChannelFuture future, Object message) {
write(ctx, future, message, null);
}
/**
* Sends a {@code "write"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to write a message
* @param message the message to write to the channel
* @param remoteAddress the destination of the message.
* {@code null} to use the default remote address
*
* @return the {@link ChannelFuture} which will be notified when the
* write operation is done
*/
public static ChannelFuture write(Channel channel, Object message, SocketAddress remoteAddress) {
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(
new DownstreamMessageEvent(channel, future, message, remoteAddress));
return future;
}
/**
* Sends a {@code "write"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified when the write
* operation is done
* @param message the message to write to the channel
* @param remoteAddress the destination of the message.
* {@code null} to use the default remote address.
*/
public static void write(
ChannelHandlerContext ctx, ChannelFuture future,
Object message, SocketAddress remoteAddress) {
ctx.sendDownstream(
new DownstreamMessageEvent(ctx.getChannel(), future, message, remoteAddress));
}
/**
* Sends a {@code "setInterestOps"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to change its interestOps
* @param interestOps the new interestOps
*
* @return the {@link ChannelFuture} which will be notified when the
* interestOps is changed
*/
public static ChannelFuture setInterestOps(Channel channel, int interestOps) {
validateInterestOps(interestOps);
interestOps = filterDownstreamInterestOps(interestOps);
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(
channel, future, ChannelState.INTEREST_OPS, interestOps));
return future;
}
/**
* Sends a {@code "setInterestOps"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified when the interestOps is
* changed.
*/
public static void setInterestOps(
ChannelHandlerContext ctx, ChannelFuture future, int interestOps) {
validateInterestOps(interestOps);
interestOps = filterDownstreamInterestOps(interestOps);
ctx.sendDownstream(
new DownstreamChannelStateEvent(
ctx.getChannel(), future, ChannelState.INTEREST_OPS, interestOps));
}
/**
* Sends a {@code "disconnect"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to disconnect
*
* @return the {@link ChannelFuture} which will be notified on disconnection
*/
public static ChannelFuture disconnect(Channel channel) {
ChannelFuture future = future(channel);
channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(
channel, future, ChannelState.CONNECTED, null));
return future;
}
/**
* Sends a {@code "disconnect"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified on disconnection
*/
public static void disconnect(
ChannelHandlerContext ctx, ChannelFuture future) {
ctx.sendDownstream(new DownstreamChannelStateEvent(
ctx.getChannel(), future, ChannelState.CONNECTED, null));
}
/**
* Sends a {@code "close"} request to the last
* {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of
* the specified {@link Channel}.
*
* @param channel the channel to close
*
* @return the {@link ChannelFuture} which will be notified on closure
*/
public static ChannelFuture close(Channel channel) {
ChannelFuture future = channel.getCloseFuture();
channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(
channel, future, ChannelState.OPEN, Boolean.FALSE));
return future;
}
/**
* Sends a {@code "close"} request to the
* {@link ChannelDownstreamHandler} which is placed in the closest
* downstream from the handler associated with the specified
* {@link ChannelHandlerContext}.
*
* @param ctx the context
* @param future the future which will be notified on closure
*/
public static void close(
ChannelHandlerContext ctx, ChannelFuture future) {
ctx.sendDownstream(new DownstreamChannelStateEvent(
ctx.getChannel(), future, ChannelState.OPEN, Boolean.FALSE));
}
private static void validateInterestOps(int interestOps) {
switch (interestOps) {
case Channel.OP_NONE:
case Channel.OP_READ:
case Channel.OP_WRITE:
case Channel.OP_READ_WRITE:
break;
default:
throw new IllegalArgumentException(
"Invalid interestOps: " + interestOps);
}
}
private static int filterDownstreamInterestOps(int interestOps) {
return interestOps & ~Channel.OP_WRITE;
}
private Channels() {
// Unused
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ChildChannelStateEvent.java 0000664 0000000 0000000 00000002670 12255541277 0031376 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelEvent} which represents the notification of the state of
* a child {@link Channel}. This event is for going upstream only. Please
* refer to the {@link ChannelEvent} documentation to find out what an upstream
* event and a downstream event are and what fundamental differences they have.
*/
public interface ChildChannelStateEvent extends ChannelEvent {
/**
* Returns the parent {@link Channel} which is associated
* with this event. Please note that you should use {@link #getChildChannel()}
* to get the {@link Channel} created or accepted by the parent {@link Channel}.
*/
Channel getChannel();
/**
* Returns the child {@link Channel} whose state has been changed.
*/
Channel getChildChannel();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/CompleteChannelFuture.java 0000664 0000000 0000000 00000006354 12255541277 0031316 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* A skeletal {@link ChannelFuture} implementation which represents a
* {@link ChannelFuture} which has been completed already.
*/
public abstract class CompleteChannelFuture implements ChannelFuture {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(CompleteChannelFuture.class);
private final Channel channel;
/**
* Creates a new instance.
*
* @param channel the {@link Channel} associated with this future
*/
protected CompleteChannelFuture(Channel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
this.channel = channel;
}
public void addListener(ChannelFutureListener listener) {
try {
listener.operationComplete(this);
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn(
"An exception was thrown by " +
ChannelFutureListener.class.getSimpleName() + '.', t);
}
}
}
public void removeListener(ChannelFutureListener listener) {
// NOOP
}
public ChannelFuture await() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
return this;
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
return true;
}
public boolean await(long timeoutMillis) throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
return true;
}
public ChannelFuture awaitUninterruptibly() {
return this;
}
public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
return true;
}
public boolean awaitUninterruptibly(long timeoutMillis) {
return true;
}
public Channel getChannel() {
return channel;
}
public boolean isDone() {
return true;
}
public boolean setProgress(long amount, long current, long total) {
return false;
}
public boolean setFailure(Throwable cause) {
return false;
}
public boolean setSuccess() {
return false;
}
public boolean cancel() {
return false;
}
public boolean isCancelled() {
return false;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ConnectTimeoutException.java 0000664 0000000 0000000 00000002111 12255541277 0031664 0 ustar 00root root 0000000 0000000 /*
* Copyright 2013 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.ConnectException;
/**
* {@link ConnectException} which will be thrown if a connection could
* not be established because of a connection timeout.
*/
public class ConnectTimeoutException extends ConnectException {
private static final long serialVersionUID = 2317065249988317463L;
public ConnectTimeoutException(String msg) {
super(msg);
}
public ConnectTimeoutException() {
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultChannelConfig.java 0000664 0000000 0000000 00000005462 12255541277 0031064 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.buffer.HeapChannelBufferFactory;
import org.jboss.netty.channel.socket.SocketChannelConfig;
import org.jboss.netty.util.internal.ConversionUtil;
import java.util.Map;
import java.util.Map.Entry;
/**
* The default {@link SocketChannelConfig} implementation.
*/
public class DefaultChannelConfig implements ChannelConfig {
private volatile ChannelBufferFactory bufferFactory = HeapChannelBufferFactory.getInstance();
private volatile int connectTimeoutMillis = 10000; // 10 seconds
public void setOptions(Map options) {
for (Entry e: options.entrySet()) {
setOption(e.getKey(), e.getValue());
}
}
public boolean setOption(String key, Object value) {
if (key == null) {
throw new NullPointerException("key");
}
if ("pipelineFactory".equals(key)) {
setPipelineFactory((ChannelPipelineFactory) value);
} else if ("connectTimeoutMillis".equals(key)) {
setConnectTimeoutMillis(ConversionUtil.toInt(value));
} else if ("bufferFactory".equals(key)) {
setBufferFactory((ChannelBufferFactory) value);
} else {
return false;
}
return true;
}
public int getConnectTimeoutMillis() {
return connectTimeoutMillis;
}
public ChannelBufferFactory getBufferFactory() {
return bufferFactory;
}
public void setBufferFactory(ChannelBufferFactory bufferFactory) {
if (bufferFactory == null) {
throw new NullPointerException("bufferFactory");
}
this.bufferFactory = bufferFactory;
}
public ChannelPipelineFactory getPipelineFactory() {
return null;
}
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
if (connectTimeoutMillis < 0) {
throw new IllegalArgumentException("connectTimeoutMillis: " + connectTimeoutMillis);
}
this.connectTimeoutMillis = connectTimeoutMillis;
}
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
// Unused
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultChannelFuture.java 0000664 0000000 0000000 00000033636 12255541277 0031135 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.DeadLockProofWorker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.*;
/**
* The default {@link ChannelFuture} implementation. It is recommended to
* use {@link Channels#future(Channel)} and {@link Channels#future(Channel, boolean)}
* to create a new {@link ChannelFuture} rather than calling the constructor
* explicitly.
*/
public class DefaultChannelFuture implements ChannelFuture {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(DefaultChannelFuture.class);
private static final Throwable CANCELLED = new Throwable();
private static volatile boolean useDeadLockChecker = true;
private static boolean disabledDeadLockCheckerOnce;
/**
* Returns {@code true} if and only if the dead lock checker is enabled.
*/
public static boolean isUseDeadLockChecker() {
return useDeadLockChecker;
}
/**
* Enables or disables the dead lock checker. It is not recommended to
* disable the dead lock checker. Disable it at your own risk!
*/
public static void setUseDeadLockChecker(boolean useDeadLockChecker) {
if (!useDeadLockChecker && !disabledDeadLockCheckerOnce) {
disabledDeadLockCheckerOnce = true;
if (logger.isDebugEnabled()) {
logger.debug(
"The dead lock checker in " +
DefaultChannelFuture.class.getSimpleName() +
" has been disabled as requested at your own risk.");
}
}
DefaultChannelFuture.useDeadLockChecker = useDeadLockChecker;
}
private final Channel channel;
private final boolean cancellable;
private ChannelFutureListener firstListener;
private List otherListeners;
private List progressListeners;
private boolean done;
private Throwable cause;
private int waiters;
/**
* Creates a new instance.
*
* @param channel
* the {@link Channel} associated with this future
* @param cancellable
* {@code true} if and only if this future can be canceled
*/
public DefaultChannelFuture(Channel channel, boolean cancellable) {
this.channel = channel;
this.cancellable = cancellable;
}
public Channel getChannel() {
return channel;
}
public synchronized boolean isDone() {
return done;
}
public synchronized boolean isSuccess() {
return done && cause == null;
}
public synchronized Throwable getCause() {
if (cause != CANCELLED) {
return cause;
} else {
return null;
}
}
public synchronized boolean isCancelled() {
return cause == CANCELLED;
}
public void addListener(ChannelFutureListener listener) {
if (listener == null) {
throw new NullPointerException("listener");
}
boolean notifyNow = false;
synchronized (this) {
if (done) {
notifyNow = true;
} else {
if (firstListener == null) {
firstListener = listener;
} else {
if (otherListeners == null) {
otherListeners = new ArrayList(1);
}
otherListeners.add(listener);
}
if (listener instanceof ChannelFutureProgressListener) {
if (progressListeners == null) {
progressListeners = new ArrayList(1);
}
progressListeners.add((ChannelFutureProgressListener) listener);
}
}
}
if (notifyNow) {
notifyListener(listener);
}
}
public void removeListener(ChannelFutureListener listener) {
if (listener == null) {
throw new NullPointerException("listener");
}
synchronized (this) {
if (!done) {
if (listener == firstListener) {
if (otherListeners != null && !otherListeners.isEmpty()) {
firstListener = otherListeners.remove(0);
} else {
firstListener = null;
}
} else if (otherListeners != null) {
otherListeners.remove(listener);
}
if (listener instanceof ChannelFutureProgressListener) {
progressListeners.remove(listener);
}
}
}
}
@Deprecated
public ChannelFuture rethrowIfFailed() throws Exception {
if (!isDone()) {
return this;
}
Throwable cause = getCause();
if (cause == null) {
return this;
}
if (cause instanceof Exception) {
throw (Exception) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(cause);
}
public ChannelFuture sync() throws InterruptedException {
await();
rethrowIfFailed0();
return this;
}
public ChannelFuture syncUninterruptibly() {
awaitUninterruptibly();
rethrowIfFailed0();
return this;
}
private void rethrowIfFailed0() {
Throwable cause = getCause();
if (cause == null) {
return;
}
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw new ChannelException(cause);
}
public ChannelFuture await() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
synchronized (this) {
while (!done) {
checkDeadLock();
waiters++;
try {
wait();
} finally {
waiters--;
}
}
}
return this;
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return await0(unit.toNanos(timeout), true);
}
public boolean await(long timeoutMillis) throws InterruptedException {
return await0(MILLISECONDS.toNanos(timeoutMillis), true);
}
public ChannelFuture awaitUninterruptibly() {
boolean interrupted = false;
synchronized (this) {
while (!done) {
checkDeadLock();
waiters++;
try {
wait();
} catch (InterruptedException e) {
interrupted = true;
} finally {
waiters--;
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
return this;
}
public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
try {
return await0(unit.toNanos(timeout), false);
} catch (InterruptedException e) {
throw new InternalError();
}
}
public boolean awaitUninterruptibly(long timeoutMillis) {
try {
return await0(MILLISECONDS.toNanos(timeoutMillis), false);
} catch (InterruptedException e) {
throw new InternalError();
}
}
private boolean await0(long timeoutNanos, boolean interruptable) throws InterruptedException {
if (interruptable && Thread.interrupted()) {
throw new InterruptedException();
}
long startTime = timeoutNanos <= 0 ? 0 : System.nanoTime();
long waitTime = timeoutNanos;
boolean interrupted = false;
try {
synchronized (this) {
if (done || waitTime <= 0) {
return done;
}
checkDeadLock();
waiters++;
try {
for (;;) {
try {
wait(waitTime / 1000000, (int) (waitTime % 1000000));
} catch (InterruptedException e) {
if (interruptable) {
throw e;
} else {
interrupted = true;
}
}
if (done) {
return true;
} else {
waitTime = timeoutNanos - (System.nanoTime() - startTime);
if (waitTime <= 0) {
return done;
}
}
}
} finally {
waiters--;
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
private static void checkDeadLock() {
if (isUseDeadLockChecker() && DeadLockProofWorker.PARENT.get() != null) {
throw new IllegalStateException(
"await*() in I/O thread causes a dead lock or " +
"sudden performance drop. Use addListener() instead or " +
"call await*() from a different thread.");
}
}
public boolean setSuccess() {
synchronized (this) {
// Allow only once.
if (done) {
return false;
}
done = true;
if (waiters > 0) {
notifyAll();
}
}
notifyListeners();
return true;
}
public boolean setFailure(Throwable cause) {
synchronized (this) {
// Allow only once.
if (done) {
return false;
}
this.cause = cause;
done = true;
if (waiters > 0) {
notifyAll();
}
}
notifyListeners();
return true;
}
public boolean cancel() {
if (!cancellable) {
return false;
}
synchronized (this) {
// Allow only once.
if (done) {
return false;
}
cause = CANCELLED;
done = true;
if (waiters > 0) {
notifyAll();
}
}
notifyListeners();
return true;
}
private void notifyListeners() {
// This method doesn't need synchronization because:
// 1) This method is always called after synchronized (this) block.
// Hence any listener list modification happens-before this method.
// 2) This method is called only when 'done' is true. Once 'done'
// becomes true, the listener list is never modified - see add/removeListener()
if (firstListener != null) {
notifyListener(firstListener);
firstListener = null;
if (otherListeners != null) {
for (ChannelFutureListener l: otherListeners) {
notifyListener(l);
}
otherListeners = null;
}
}
}
private void notifyListener(ChannelFutureListener l) {
try {
l.operationComplete(this);
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn(
"An exception was thrown by " +
ChannelFutureListener.class.getSimpleName() + '.', t);
}
}
}
public boolean setProgress(long amount, long current, long total) {
ChannelFutureProgressListener[] plisteners;
synchronized (this) {
// Do not generate progress event after completion.
if (done) {
return false;
}
Collection progressListeners =
this.progressListeners;
if (progressListeners == null || progressListeners.isEmpty()) {
// Nothing to notify - no need to create an empty array.
return true;
}
plisteners = progressListeners.toArray(
new ChannelFutureProgressListener[progressListeners.size()]);
}
for (ChannelFutureProgressListener pl: plisteners) {
notifyProgressListener(pl, amount, current, total);
}
return true;
}
private void notifyProgressListener(
ChannelFutureProgressListener l,
long amount, long current, long total) {
try {
l.operationProgressed(this, amount, current, total);
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn(
"An exception was thrown by " +
ChannelFutureProgressListener.class.getSimpleName() + '.', t);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultChannelPipeline.java 0000664 0000000 0000000 00000062563 12255541277 0031431 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.RejectedExecutionException;
/**
* The default {@link ChannelPipeline} implementation. It is recommended
* to use {@link Channels#pipeline()} to create a new {@link ChannelPipeline}
* instance rather than calling the constructor directly.
*/
public class DefaultChannelPipeline implements ChannelPipeline {
static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class);
static final ChannelSink discardingSink = new DiscardingChannelSink();
private volatile Channel channel;
private volatile ChannelSink sink;
private volatile DefaultChannelHandlerContext head;
private volatile DefaultChannelHandlerContext tail;
private final Map name2ctx =
new HashMap(4);
public Channel getChannel() {
return channel;
}
public ChannelSink getSink() {
ChannelSink sink = this.sink;
if (sink == null) {
return discardingSink;
}
return sink;
}
public void attach(Channel channel, ChannelSink sink) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (sink == null) {
throw new NullPointerException("sink");
}
if (this.channel != null || this.sink != null) {
throw new IllegalStateException("attached already");
}
this.channel = channel;
this.sink = sink;
}
public boolean isAttached() {
return sink != null;
}
public synchronized void addFirst(String name, ChannelHandler handler) {
if (name2ctx.isEmpty()) {
init(name, handler);
} else {
checkDuplicateName(name);
DefaultChannelHandlerContext oldHead = head;
DefaultChannelHandlerContext newHead = new DefaultChannelHandlerContext(null, oldHead, name, handler);
callBeforeAdd(newHead);
oldHead.prev = newHead;
head = newHead;
name2ctx.put(name, newHead);
callAfterAdd(newHead);
}
}
public synchronized void addLast(String name, ChannelHandler handler) {
if (name2ctx.isEmpty()) {
init(name, handler);
} else {
checkDuplicateName(name);
DefaultChannelHandlerContext oldTail = tail;
DefaultChannelHandlerContext newTail = new DefaultChannelHandlerContext(oldTail, null, name, handler);
callBeforeAdd(newTail);
oldTail.next = newTail;
tail = newTail;
name2ctx.put(name, newTail);
callAfterAdd(newTail);
}
}
public synchronized void addBefore(String baseName, String name, ChannelHandler handler) {
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
if (ctx == head) {
addFirst(name, handler);
} else {
checkDuplicateName(name);
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(ctx.prev, ctx, name, handler);
callBeforeAdd(newCtx);
ctx.prev.next = newCtx;
ctx.prev = newCtx;
name2ctx.put(name, newCtx);
callAfterAdd(newCtx);
}
}
public synchronized void addAfter(String baseName, String name, ChannelHandler handler) {
DefaultChannelHandlerContext ctx = getContextOrDie(baseName);
if (ctx == tail) {
addLast(name, handler);
} else {
checkDuplicateName(name);
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(ctx, ctx.next, name, handler);
callBeforeAdd(newCtx);
ctx.next.prev = newCtx;
ctx.next = newCtx;
name2ctx.put(name, newCtx);
callAfterAdd(newCtx);
}
}
public synchronized void remove(ChannelHandler handler) {
remove(getContextOrDie(handler));
}
public synchronized ChannelHandler remove(String name) {
return remove(getContextOrDie(name)).getHandler();
}
@SuppressWarnings("unchecked")
public synchronized T remove(Class handlerType) {
return (T) remove(getContextOrDie(handlerType)).getHandler();
}
private DefaultChannelHandlerContext remove(DefaultChannelHandlerContext ctx) {
if (head == tail) {
callBeforeRemove(ctx);
head = tail = null;
name2ctx.clear();
callAfterRemove(ctx);
} else if (ctx == head) {
removeFirst();
} else if (ctx == tail) {
removeLast();
} else {
callBeforeRemove(ctx);
DefaultChannelHandlerContext prev = ctx.prev;
DefaultChannelHandlerContext next = ctx.next;
prev.next = next;
next.prev = prev;
name2ctx.remove(ctx.getName());
callAfterRemove(ctx);
}
return ctx;
}
public synchronized ChannelHandler removeFirst() {
if (name2ctx.isEmpty()) {
throw new NoSuchElementException();
}
DefaultChannelHandlerContext oldHead = head;
if (oldHead == null) {
throw new NoSuchElementException();
}
callBeforeRemove(oldHead);
if (oldHead.next == null) {
head = tail = null;
name2ctx.clear();
} else {
oldHead.next.prev = null;
head = oldHead.next;
name2ctx.remove(oldHead.getName());
}
callAfterRemove(oldHead);
return oldHead.getHandler();
}
public synchronized ChannelHandler removeLast() {
if (name2ctx.isEmpty()) {
throw new NoSuchElementException();
}
DefaultChannelHandlerContext oldTail = tail;
if (oldTail == null) {
throw new NoSuchElementException();
}
callBeforeRemove(oldTail);
if (oldTail.prev == null) {
head = tail = null;
name2ctx.clear();
} else {
oldTail.prev.next = null;
tail = oldTail.prev;
name2ctx.remove(oldTail.getName());
}
callAfterRemove(oldTail);
return oldTail.getHandler();
}
public synchronized void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) {
replace(getContextOrDie(oldHandler), newName, newHandler);
}
public synchronized ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) {
return replace(getContextOrDie(oldName), newName, newHandler);
}
@SuppressWarnings("unchecked")
public synchronized T replace(
Class oldHandlerType, String newName, ChannelHandler newHandler) {
return (T) replace(getContextOrDie(oldHandlerType), newName, newHandler);
}
private ChannelHandler replace(DefaultChannelHandlerContext ctx, String newName, ChannelHandler newHandler) {
if (ctx == head) {
removeFirst();
addFirst(newName, newHandler);
} else if (ctx == tail) {
removeLast();
addLast(newName, newHandler);
} else {
boolean sameName = ctx.getName().equals(newName);
if (!sameName) {
checkDuplicateName(newName);
}
DefaultChannelHandlerContext prev = ctx.prev;
DefaultChannelHandlerContext next = ctx.next;
DefaultChannelHandlerContext newCtx = new DefaultChannelHandlerContext(prev, next, newName, newHandler);
callBeforeRemove(ctx);
callBeforeAdd(newCtx);
prev.next = newCtx;
next.prev = newCtx;
if (!sameName) {
name2ctx.remove(ctx.getName());
}
name2ctx.put(newName, newCtx);
ChannelHandlerLifeCycleException removeException = null;
ChannelHandlerLifeCycleException addException = null;
boolean removed = false;
try {
callAfterRemove(ctx);
removed = true;
} catch (ChannelHandlerLifeCycleException e) {
removeException = e;
}
boolean added = false;
try {
callAfterAdd(newCtx);
added = true;
} catch (ChannelHandlerLifeCycleException e) {
addException = e;
}
if (!removed && !added) {
logger.warn(removeException.getMessage(), removeException);
logger.warn(addException.getMessage(), addException);
throw new ChannelHandlerLifeCycleException(
"Both " + ctx.getHandler().getClass().getName() +
".afterRemove() and " + newCtx.getHandler().getClass().getName() +
".afterAdd() failed; see logs.");
} else if (!removed) {
throw removeException;
} else if (!added) {
throw addException;
}
}
return ctx.getHandler();
}
private static void callBeforeAdd(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.beforeAdd(ctx);
} catch (Throwable t) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".beforeAdd() has thrown an exception; not adding.", t);
}
}
private void callAfterAdd(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.afterAdd(ctx);
} catch (Throwable t) {
boolean removed = false;
try {
remove((DefaultChannelHandlerContext) ctx);
removed = true;
} catch (Throwable t2) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to remove a handler: " + ctx.getName(), t2);
}
}
if (removed) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".afterAdd() has thrown an exception; removed.", t);
} else {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".afterAdd() has thrown an exception; also failed to remove.", t);
}
}
}
private static void callBeforeRemove(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.beforeRemove(ctx);
} catch (Throwable t) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".beforeRemove() has thrown an exception; not removing.", t);
}
}
private static void callAfterRemove(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.afterRemove(ctx);
} catch (Throwable t) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".afterRemove() has thrown an exception.", t);
}
}
public synchronized ChannelHandler getFirst() {
DefaultChannelHandlerContext head = this.head;
if (head == null) {
return null;
}
return head.getHandler();
}
public synchronized ChannelHandler getLast() {
DefaultChannelHandlerContext tail = this.tail;
if (tail == null) {
return null;
}
return tail.getHandler();
}
public synchronized ChannelHandler get(String name) {
DefaultChannelHandlerContext ctx = name2ctx.get(name);
if (ctx == null) {
return null;
} else {
return ctx.getHandler();
}
}
public synchronized T get(Class handlerType) {
ChannelHandlerContext ctx = getContext(handlerType);
if (ctx == null) {
return null;
} else {
@SuppressWarnings("unchecked")
T handler = (T) ctx.getHandler();
return handler;
}
}
public synchronized ChannelHandlerContext getContext(String name) {
if (name == null) {
throw new NullPointerException("name");
}
return name2ctx.get(name);
}
public synchronized ChannelHandlerContext getContext(ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
if (name2ctx.isEmpty()) {
return null;
}
DefaultChannelHandlerContext ctx = head;
for (;;) {
if (ctx.getHandler() == handler) {
return ctx;
}
ctx = ctx.next;
if (ctx == null) {
break;
}
}
return null;
}
public synchronized ChannelHandlerContext getContext(
Class extends ChannelHandler> handlerType) {
if (handlerType == null) {
throw new NullPointerException("handlerType");
}
if (name2ctx.isEmpty()) {
return null;
}
DefaultChannelHandlerContext ctx = head;
for (;;) {
if (handlerType.isAssignableFrom(ctx.getHandler().getClass())) {
return ctx;
}
ctx = ctx.next;
if (ctx == null) {
break;
}
}
return null;
}
public List getNames() {
List list = new ArrayList();
if (name2ctx.isEmpty()) {
return list;
}
DefaultChannelHandlerContext ctx = head;
for (;;) {
list.add(ctx.getName());
ctx = ctx.next;
if (ctx == null) {
break;
}
}
return list;
}
public Map toMap() {
Map map = new LinkedHashMap();
if (name2ctx.isEmpty()) {
return map;
}
DefaultChannelHandlerContext ctx = head;
for (;;) {
map.put(ctx.getName(), ctx.getHandler());
ctx = ctx.next;
if (ctx == null) {
break;
}
}
return map;
}
/**
* Returns the {@link String} representation of this pipeline.
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(getClass().getSimpleName());
buf.append('{');
DefaultChannelHandlerContext ctx = head;
if (ctx != null) {
for (;;) {
buf.append('(');
buf.append(ctx.getName());
buf.append(" = ");
buf.append(ctx.getHandler().getClass().getName());
buf.append(')');
ctx = ctx.next;
if (ctx == null) {
break;
}
buf.append(", ");
}
}
buf.append('}');
return buf.toString();
}
public void sendUpstream(ChannelEvent e) {
DefaultChannelHandlerContext head = getActualUpstreamContext(this.head);
if (head == null) {
if (logger.isWarnEnabled()) {
logger.warn(
"The pipeline contains no upstream handlers; discarding: " + e);
}
return;
}
sendUpstream(head, e);
}
void sendUpstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
try {
((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
} catch (Throwable t) {
notifyHandlerException(e, t);
}
}
public void sendDownstream(ChannelEvent e) {
DefaultChannelHandlerContext tail = getActualDownstreamContext(this.tail);
if (tail == null) {
try {
getSink().eventSunk(this, e);
return;
} catch (Throwable t) {
notifyHandlerException(e, t);
return;
}
}
sendDownstream(tail, e);
}
void sendDownstream(DefaultChannelHandlerContext ctx, ChannelEvent e) {
if (e instanceof UpstreamMessageEvent) {
throw new IllegalArgumentException("cannot send an upstream event to downstream");
}
try {
((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
} catch (Throwable t) {
// Unlike an upstream event, a downstream event usually has an
// incomplete future which is supposed to be updated by ChannelSink.
// However, if an exception is raised before the event reaches at
// ChannelSink, the future is not going to be updated, so we update
// here.
e.getFuture().setFailure(t);
notifyHandlerException(e, t);
}
}
private DefaultChannelHandlerContext getActualUpstreamContext(DefaultChannelHandlerContext ctx) {
if (ctx == null) {
return null;
}
DefaultChannelHandlerContext realCtx = ctx;
while (!realCtx.canHandleUpstream()) {
realCtx = realCtx.next;
if (realCtx == null) {
return null;
}
}
return realCtx;
}
private DefaultChannelHandlerContext getActualDownstreamContext(DefaultChannelHandlerContext ctx) {
if (ctx == null) {
return null;
}
DefaultChannelHandlerContext realCtx = ctx;
while (!realCtx.canHandleDownstream()) {
realCtx = realCtx.prev;
if (realCtx == null) {
return null;
}
}
return realCtx;
}
public ChannelFuture execute(Runnable task) {
return getSink().execute(this, task);
}
protected void notifyHandlerException(ChannelEvent e, Throwable t) {
if (e instanceof ExceptionEvent) {
if (logger.isWarnEnabled()) {
logger.warn(
"An exception was thrown by a user handler " +
"while handling an exception event (" + e + ')', t);
}
return;
}
ChannelPipelineException pe;
if (t instanceof ChannelPipelineException) {
pe = (ChannelPipelineException) t;
} else {
pe = new ChannelPipelineException(t);
}
try {
sink.exceptionCaught(this, e, pe);
} catch (Exception e1) {
if (logger.isWarnEnabled()) {
logger.warn("An exception was thrown by an exception handler.", e1);
}
}
}
private void init(String name, ChannelHandler handler) {
DefaultChannelHandlerContext ctx = new DefaultChannelHandlerContext(null, null, name, handler);
callBeforeAdd(ctx);
head = tail = ctx;
name2ctx.clear();
name2ctx.put(name, ctx);
callAfterAdd(ctx);
}
private void checkDuplicateName(String name) {
if (name2ctx.containsKey(name)) {
throw new IllegalArgumentException("Duplicate handler name: " + name);
}
}
private DefaultChannelHandlerContext getContextOrDie(String name) {
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) getContext(name);
if (ctx == null) {
throw new NoSuchElementException(name);
} else {
return ctx;
}
}
private DefaultChannelHandlerContext getContextOrDie(ChannelHandler handler) {
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) getContext(handler);
if (ctx == null) {
throw new NoSuchElementException(handler.getClass().getName());
} else {
return ctx;
}
}
private DefaultChannelHandlerContext getContextOrDie(Class extends ChannelHandler> handlerType) {
DefaultChannelHandlerContext ctx = (DefaultChannelHandlerContext) getContext(handlerType);
if (ctx == null) {
throw new NoSuchElementException(handlerType.getName());
} else {
return ctx;
}
}
private final class DefaultChannelHandlerContext implements ChannelHandlerContext {
volatile DefaultChannelHandlerContext next;
volatile DefaultChannelHandlerContext prev;
private final String name;
private final ChannelHandler handler;
private final boolean canHandleUpstream;
private final boolean canHandleDownstream;
private volatile Object attachment;
DefaultChannelHandlerContext(
DefaultChannelHandlerContext prev, DefaultChannelHandlerContext next,
String name, ChannelHandler handler) {
if (name == null) {
throw new NullPointerException("name");
}
if (handler == null) {
throw new NullPointerException("handler");
}
canHandleUpstream = handler instanceof ChannelUpstreamHandler;
canHandleDownstream = handler instanceof ChannelDownstreamHandler;
if (!canHandleUpstream && !canHandleDownstream) {
throw new IllegalArgumentException(
"handler must be either " +
ChannelUpstreamHandler.class.getName() + " or " +
ChannelDownstreamHandler.class.getName() + '.');
}
this.prev = prev;
this.next = next;
this.name = name;
this.handler = handler;
}
public Channel getChannel() {
return getPipeline().getChannel();
}
public ChannelPipeline getPipeline() {
return DefaultChannelPipeline.this;
}
public boolean canHandleDownstream() {
return canHandleDownstream;
}
public boolean canHandleUpstream() {
return canHandleUpstream;
}
public ChannelHandler getHandler() {
return handler;
}
public String getName() {
return name;
}
public Object getAttachment() {
return attachment;
}
public void setAttachment(Object attachment) {
this.attachment = attachment;
}
public void sendDownstream(ChannelEvent e) {
DefaultChannelHandlerContext prev = getActualDownstreamContext(this.prev);
if (prev == null) {
try {
getSink().eventSunk(DefaultChannelPipeline.this, e);
} catch (Throwable t) {
notifyHandlerException(e, t);
}
} else {
DefaultChannelPipeline.this.sendDownstream(prev, e);
}
}
public void sendUpstream(ChannelEvent e) {
DefaultChannelHandlerContext next = getActualUpstreamContext(this.next);
if (next != null) {
DefaultChannelPipeline.this.sendUpstream(next, e);
}
}
}
private static final class DiscardingChannelSink implements ChannelSink {
DiscardingChannelSink() {
}
public void eventSunk(ChannelPipeline pipeline, ChannelEvent e) {
if (logger.isWarnEnabled()) {
logger.warn("Not attached yet; discarding: " + e);
}
}
public void exceptionCaught(ChannelPipeline pipeline,
ChannelEvent e, ChannelPipelineException cause) throws Exception {
throw cause;
}
public ChannelFuture execute(ChannelPipeline pipeline, Runnable task) {
if (logger.isWarnEnabled()) {
logger.warn("Not attached yet; rejecting: " + task);
}
return Channels.failedFuture(pipeline.getChannel(), new RejectedExecutionException("Not attached yet"));
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultChildChannelStateEvent.java 0000664 0000000 0000000 00000003737 12255541277 0032710 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import static org.jboss.netty.channel.Channels.*;
/**
* The default {@link ChildChannelStateEvent} implementation.
*/
public class DefaultChildChannelStateEvent implements ChildChannelStateEvent {
private final Channel parentChannel;
private final Channel childChannel;
/**
* Creates a new instance.
*/
public DefaultChildChannelStateEvent(Channel parentChannel, Channel childChannel) {
if (parentChannel == null) {
throw new NullPointerException("parentChannel");
}
if (childChannel == null) {
throw new NullPointerException("childChannel");
}
this.parentChannel = parentChannel;
this.childChannel = childChannel;
}
public Channel getChannel() {
return parentChannel;
}
public ChannelFuture getFuture() {
return succeededFuture(getChannel());
}
public Channel getChildChannel() {
return childChannel;
}
@Override
public String toString() {
String channelString = getChannel().toString();
StringBuilder buf = new StringBuilder(channelString.length() + 32);
buf.append(channelString);
buf.append(getChildChannel().isOpen()? " CHILD_OPEN: " : " CHILD_CLOSED: ");
buf.append(getChildChannel().getId());
return buf.toString();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultExceptionEvent.java 0000664 0000000 0000000 00000003304 12255541277 0031317 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.util.internal.StackTraceSimplifier;
/**
* The default {@link ExceptionEvent} implementation.
*/
public class DefaultExceptionEvent implements ExceptionEvent {
private final Channel channel;
private final Throwable cause;
/**
* Creates a new instance.
*/
public DefaultExceptionEvent(Channel channel, Throwable cause) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (cause == null) {
throw new NullPointerException("cause");
}
this.channel = channel;
this.cause = cause;
StackTraceSimplifier.simplify(cause);
}
public Channel getChannel() {
return channel;
}
public ChannelFuture getFuture() {
return succeededFuture(getChannel());
}
public Throwable getCause() {
return cause;
}
@Override
public String toString() {
return getChannel().toString() + " EXCEPTION: " + cause;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultFileRegion.java 0000664 0000000 0000000 00000004761 12255541277 0030412 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
public class DefaultFileRegion implements FileRegion {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultFileRegion.class);
private final FileChannel file;
private final long position;
private final long count;
private final boolean releaseAfterTransfer;
public DefaultFileRegion(FileChannel file, long position, long count) {
this(file, position, count, false);
}
public DefaultFileRegion(FileChannel file, long position, long count, boolean releaseAfterTransfer) {
this.file = file;
this.position = position;
this.count = count;
this.releaseAfterTransfer = releaseAfterTransfer;
}
public long getPosition() {
return position;
}
public long getCount() {
return count;
}
public boolean releaseAfterTransfer() {
return releaseAfterTransfer;
}
public long transferTo(WritableByteChannel target, long position) throws IOException {
long count = this.count - position;
if (count < 0 || position < 0) {
throw new IllegalArgumentException(
"position out of range: " + position +
" (expected: 0 - " + (this.count - 1) + ')');
}
if (count == 0) {
return 0L;
}
return file.transferTo(this.position + position, count, target);
}
public void releaseExternalResources() {
try {
file.close();
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close a file.", e);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultServerChannelConfig.java 0000664 0000000 0000000 00000005336 12255541277 0032253 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.buffer.HeapChannelBufferFactory;
import org.jboss.netty.channel.socket.ServerSocketChannelConfig;
import java.util.Map;
import java.util.Map.Entry;
/**
* The default {@link ServerSocketChannelConfig} implementation.
*/
public class DefaultServerChannelConfig implements ChannelConfig {
private volatile ChannelPipelineFactory pipelineFactory;
private volatile ChannelBufferFactory bufferFactory = HeapChannelBufferFactory.getInstance();
public void setOptions(Map options) {
for (Entry e: options.entrySet()) {
setOption(e.getKey(), e.getValue());
}
}
/**
* Sets an individual option. You can override this method to support
* additional configuration parameters.
*/
public boolean setOption(String key, Object value) {
if (key == null) {
throw new NullPointerException("key");
}
if ("pipelineFactory".equals(key)) {
setPipelineFactory((ChannelPipelineFactory) value);
} else if ("bufferFactory".equals(key)) {
setBufferFactory((ChannelBufferFactory) value);
} else {
return false;
}
return true;
}
public ChannelPipelineFactory getPipelineFactory() {
return pipelineFactory;
}
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
if (pipelineFactory == null) {
throw new NullPointerException("pipelineFactory");
}
this.pipelineFactory = pipelineFactory;
}
public ChannelBufferFactory getBufferFactory() {
return bufferFactory;
}
public void setBufferFactory(ChannelBufferFactory bufferFactory) {
if (bufferFactory == null) {
throw new NullPointerException("bufferFactory");
}
this.bufferFactory = bufferFactory;
}
public int getConnectTimeoutMillis() {
return 0;
}
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
// Unused
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DefaultWriteCompletionEvent.java 0000664 0000000 0000000 00000003675 12255541277 0032520 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import static org.jboss.netty.channel.Channels.*;
/**
* The default {@link WriteCompletionEvent} implementation.
*/
public class DefaultWriteCompletionEvent implements WriteCompletionEvent {
private final Channel channel;
private final long writtenAmount;
/**
* Creates a new instance.
*/
public DefaultWriteCompletionEvent(Channel channel, long writtenAmount) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (writtenAmount <= 0) {
throw new IllegalArgumentException(
"writtenAmount must be a positive integer: " + writtenAmount);
}
this.channel = channel;
this.writtenAmount = writtenAmount;
}
public Channel getChannel() {
return channel;
}
public ChannelFuture getFuture() {
return succeededFuture(getChannel());
}
public long getWrittenAmount() {
return writtenAmount;
}
@Override
public String toString() {
String channelString = getChannel().toString();
StringBuilder buf = new StringBuilder(channelString.length() + 32);
buf.append(channelString);
buf.append(" WRITTEN_AMOUNT: ");
buf.append(getWrittenAmount());
return buf.toString();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DownstreamChannelStateEvent.java 0000664 0000000 0000000 00000005766 12255541277 0032507 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* The default downstream {@link ChannelStateEvent} implementation.
*/
public class DownstreamChannelStateEvent implements ChannelStateEvent {
private final Channel channel;
private final ChannelFuture future;
private final ChannelState state;
private final Object value;
/**
* Creates a new instance.
*/
public DownstreamChannelStateEvent(
Channel channel, ChannelFuture future,
ChannelState state, Object value) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (future == null) {
throw new NullPointerException("future");
}
if (state == null) {
throw new NullPointerException("state");
}
this.channel = channel;
this.future = future;
this.state = state;
this.value = value;
}
public Channel getChannel() {
return channel;
}
public ChannelFuture getFuture() {
return future;
}
public ChannelState getState() {
return state;
}
public Object getValue() {
return value;
}
@Override
public String toString() {
String channelString = getChannel().toString();
StringBuilder buf = new StringBuilder(channelString.length() + 64);
buf.append(channelString);
switch (getState()) {
case OPEN:
if (Boolean.TRUE.equals(getValue())) {
buf.append(" OPEN");
} else {
buf.append(" CLOSE");
}
break;
case BOUND:
if (getValue() != null) {
buf.append(" BIND: ");
buf.append(getValue());
} else {
buf.append(" UNBIND");
}
break;
case CONNECTED:
if (getValue() != null) {
buf.append(" CONNECT: ");
buf.append(getValue());
} else {
buf.append(" DISCONNECT");
}
break;
case INTEREST_OPS:
buf.append(" CHANGE_INTEREST: ");
buf.append(getValue());
break;
default:
buf.append(' ');
buf.append(getState().name());
buf.append(": ");
buf.append(getValue());
}
return buf.toString();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/DownstreamMessageEvent.java 0000664 0000000 0000000 00000004736 12255541277 0031516 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
import org.jboss.netty.util.internal.StringUtil;
/**
* The default downstream {@link MessageEvent} implementation.
*/
public class DownstreamMessageEvent implements MessageEvent {
private final Channel channel;
private final ChannelFuture future;
private final Object message;
private final SocketAddress remoteAddress;
/**
* Creates a new instance.
*/
public DownstreamMessageEvent(
Channel channel, ChannelFuture future,
Object message, SocketAddress remoteAddress) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (future == null) {
throw new NullPointerException("future");
}
if (message == null) {
throw new NullPointerException("message");
}
this.channel = channel;
this.future = future;
this.message = message;
if (remoteAddress != null) {
this.remoteAddress = remoteAddress;
} else {
this.remoteAddress = channel.getRemoteAddress();
}
}
public Channel getChannel() {
return channel;
}
public ChannelFuture getFuture() {
return future;
}
public Object getMessage() {
return message;
}
public SocketAddress getRemoteAddress() {
return remoteAddress;
}
@Override
public String toString() {
if (getRemoteAddress() == getChannel().getRemoteAddress()) {
return getChannel().toString() + " WRITE: " +
StringUtil.stripControlCharacters(getMessage());
} else {
return getChannel().toString() + " WRITE: " +
StringUtil.stripControlCharacters(getMessage()) + " to " +
getRemoteAddress();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ExceptionEvent.java 0000664 0000000 0000000 00000002205 12255541277 0030011 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelEvent} which represents the notification of an exception
* raised by a {@link ChannelHandler} or an I/O thread. This event is for
* going upstream only. Please refer to the {@link ChannelEvent} documentation
* to find out what an upstream event and a downstream event are and what
* fundamental differences they have.
*/
public interface ExceptionEvent extends ChannelEvent {
/**
* Returns the raised exception.
*/
Throwable getCause();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/FailedChannelFuture.java 0000664 0000000 0000000 00000004317 12255541277 0030727 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* The {@link CompleteChannelFuture} which is failed already. It is
* recommended to use {@link Channels#failedFuture(Channel, Throwable)}
* instead of calling the constructor of this future.
*/
public class FailedChannelFuture extends CompleteChannelFuture {
private final Throwable cause;
/**
* Creates a new instance.
*
* @param channel the {@link Channel} associated with this future
* @param cause the cause of failure
*/
public FailedChannelFuture(Channel channel, Throwable cause) {
super(channel);
if (cause == null) {
throw new NullPointerException("cause");
}
this.cause = cause;
}
public Throwable getCause() {
return cause;
}
public boolean isSuccess() {
return false;
}
@Deprecated
public ChannelFuture rethrowIfFailed() throws Exception {
if (cause instanceof Exception) {
throw (Exception) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(cause);
}
public ChannelFuture sync() throws InterruptedException {
rethrow();
return this;
}
public ChannelFuture syncUninterruptibly() {
rethrow();
return this;
}
private void rethrow() {
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw new ChannelException(cause);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/FileRegion.java 0000664 0000000 0000000 00000007031 12255541277 0027076 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import org.jboss.netty.util.ExternalResourceReleasable;
/**
* A region of a file that is sent via a {@link Channel} which supports
* zero-copy file transfer .
*
* Upgrade your JDK / JRE
*
* {@link FileChannel#transferTo(long, long, WritableByteChannel)} has at least
* four known bugs in the old versions of Sun JDK and perhaps its derived ones.
* Please upgrade your JDK to 1.6.0_18 or later version if you are going to use
* zero-copy file transfer.
*
* 5103988
* - FileChannel.transferTo() should return -1 for EAGAIN instead throws IOException
* 6253145
* - FileChannel.transferTo() on Linux fails when going beyond 2GB boundary
* 6427312
* - FileChannel.transferTo() throws IOException "system call interrupted"
* 6470086
* - FileChannel.transferTo(2147483647, 1, channel) causes "Value too large" exception
*
*
* Check your operating system and JDK / JRE
*
* If your operating system (or JDK / JRE) does not support zero-copy file
* transfer, sending a file with {@link FileRegion} might fail or yield worse
* performance. For example, sending a large file doesn't work well in Windows.
*
* Not all transports support it
*
* Currently, the NIO transport is the only transport that supports {@link FileRegion}.
* Attempting to write a {@link FileRegion} to non-NIO {@link Channel} will trigger
* a {@link ClassCastException} or a similar exception.
*/
public interface FileRegion extends ExternalResourceReleasable {
// FIXME Make sure all transports support writing a FileRegion
// Even if zero copy cannot be achieved, all transports should emulate it.
/**
* Returns the offset in the file where the transfer began.
*/
long getPosition();
/**
* Returns the number of bytes to transfer.
*/
long getCount();
/**
* Transfers the content of this file region to the specified channel.
*
* @param target the destination of the transfer
* @param position the relative offset of the file where the transfer
* begins from. For example, 0 will make the
* transfer start from {@link #getPosition()}th byte and
* {@link #getCount()} - 1 will make the last
* byte of the region transferred.
*/
long transferTo(WritableByteChannel target, long position) throws IOException;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/FixedReceiveBufferSizePredictor.java 0000664 0000000 0000000 00000002770 12255541277 0033263 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* The {@link ReceiveBufferSizePredictor} that always yields the same buffer
* size prediction. This predictor ignores the feed back from the I/O thread.
*/
public class FixedReceiveBufferSizePredictor implements
ReceiveBufferSizePredictor {
private final int bufferSize;
/**
* Creates a new predictor that always returns the same prediction of
* the specified buffer size.
*/
public FixedReceiveBufferSizePredictor(int bufferSize) {
if (bufferSize <= 0) {
throw new IllegalArgumentException(
"bufferSize must greater than 0: " + bufferSize);
}
this.bufferSize = bufferSize;
}
public int nextReceiveBufferSize() {
return bufferSize;
}
public void previousReceiveBufferSize(int previousReceiveBufferSize) {
// Ignore
}
}
FixedReceiveBufferSizePredictorFactory.java 0000664 0000000 0000000 00000002606 12255541277 0034532 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* The {@link ReceiveBufferSizePredictorFactory} that returns a
* {@link FixedReceiveBufferSizePredictor} with the pre-defined configuration.
*/
public class FixedReceiveBufferSizePredictorFactory implements
ReceiveBufferSizePredictorFactory {
private final ReceiveBufferSizePredictor predictor;
/**
* Creates a new factory that returns a {@link FixedReceiveBufferSizePredictor}
* which always returns the same prediction of the specified buffer size.
*/
public FixedReceiveBufferSizePredictorFactory(int bufferSize) {
predictor = new FixedReceiveBufferSizePredictor(bufferSize);
}
public ReceiveBufferSizePredictor getPredictor() throws Exception {
return predictor;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/LifeCycleAwareChannelHandler.java 0000664 0000000 0000000 00000003126 12255541277 0032462 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelHandler} that is notified when it is added to or removed
* from a {@link ChannelPipeline}.
*
* Invalid access to the {@link ChannelHandlerContext}
*
* Calling {@link ChannelHandlerContext#sendUpstream(ChannelEvent)} or
* {@link ChannelHandlerContext#sendDownstream(ChannelEvent)} in
* {@link #beforeAdd(ChannelHandlerContext)} or {@link #afterRemove(ChannelHandlerContext)}
* might lead to an unexpected behavior. It is because the context object
* might not have been fully added to the pipeline or the context object is not
* a part of the pipeline anymore respectively.
*/
public interface LifeCycleAwareChannelHandler extends ChannelHandler {
void beforeAdd(ChannelHandlerContext ctx) throws Exception;
void afterAdd(ChannelHandlerContext ctx) throws Exception;
void beforeRemove(ChannelHandlerContext ctx) throws Exception;
void afterRemove(ChannelHandlerContext ctx) throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/MessageEvent.java 0000664 0000000 0000000 00000002536 12255541277 0027446 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
/**
* A {@link ChannelEvent} which represents the transmission or reception of a
* message. It can mean the notification of a received message or the request
* for writing a message, depending on whether it is an upstream event or a
* downstream event respectively. Please refer to the {@link ChannelEvent}
* documentation to find out what an upstream event and a downstream event are
* and what fundamental differences they have.
*/
public interface MessageEvent extends ChannelEvent {
/**
* Returns the message.
*/
Object getMessage();
/**
* Returns the remote address of the message.
*/
SocketAddress getRemoteAddress();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ReceiveBufferSizePredictor.java 0000664 0000000 0000000 00000003703 12255541277 0032300 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.buffer.ChannelBuffer;
/**
* Predicts the number of readable bytes in the receive buffer of a
* {@link Channel}.
*
* It calculates the close-to-optimal capacity of the {@link ChannelBuffer}
* for the next read operation depending on the actual number of read bytes
* in the previous read operation. More accurate the prediction is, more
* effective the memory utilization will be.
*
* Once a read operation is performed and the actual number of read bytes is
* known, an I/O thread will call {@link #previousReceiveBufferSize(int)} to
* update the predictor so it can predict more accurately next time.
*/
public interface ReceiveBufferSizePredictor {
/**
* Predicts the capacity of the {@link ChannelBuffer} for the next
* read operation depending on the actual number of read bytes in the
* previous read operation.
*
* @return the expected number of readable bytes this time
*/
int nextReceiveBufferSize();
/**
* Updates this predictor by specifying the actual number of read bytes
* in the previous read operation.
*
* @param previousReceiveBufferSize
* the actual number of read bytes in the previous read operation
*/
void previousReceiveBufferSize(int previousReceiveBufferSize);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ReceiveBufferSizePredictorFactory.java0000664 0000000 0000000 00000002004 12255541277 0033621 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* Creates a new {@link ReceiveBufferSizePredictor}.
*
* @apiviz.has org.jboss.netty.channel.ReceiveBufferSizePredictor oneway - - creates
*/
public interface ReceiveBufferSizePredictorFactory {
/**
* Returns a newly created {@link ReceiveBufferSizePredictor}.
*/
ReceiveBufferSizePredictor getPredictor() throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ServerChannel.java 0000664 0000000 0000000 00000001745 12255541277 0027620 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.channel.socket.ServerSocketChannel;
/**
* A {@link Channel} that accepts an incoming connection attempt and creates
* its child {@link Channel}s by accepting them. {@link ServerSocketChannel} is
* a good example.
*/
public interface ServerChannel extends Channel {
// This is a tag interface.
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/ServerChannelFactory.java 0000664 0000000 0000000 00000001662 12255541277 0031146 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelFactory} that creates a {@link ServerChannel}.
*
* @apiviz.has org.jboss.netty.channel.ServerChannel oneway - - creates
*/
public interface ServerChannelFactory extends ChannelFactory {
ServerChannel newChannel(ChannelPipeline pipeline);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/SimpleChannelDownstreamHandler.java 0000664 0000000 0000000 00000012530 12255541277 0033137 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
/**
* A {@link ChannelDownstreamHandler} which provides an individual handler
* method for each event type. This handler down-casts the received downstream
* event into more meaningful sub-type event and calls an appropriate handler
* method with the down-cast event. The names of the methods starts with the
* name of the operation and ends with {@code "Requested"}
* (e.g. {@link #writeRequested(ChannelHandlerContext, MessageEvent) writeRequested}.)
*
* Please use {@link SimpleChannelHandler} if you need to implement both
* {@link ChannelUpstreamHandler} and {@link ChannelDownstreamHandler}.
*
*
Overriding the {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream} method
*
* You can override the {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream}
* method just like overriding an ordinary Java method. Please make sure to
* call {@code super.handleDownstream()} so that other handler methods are
* invoked properly:
*
* public class MyChannelHandler extends {@link SimpleChannelDownstreamHandler} {
*
* {@code @Override}
* public void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
*
* // Log all channel state changes.
* if (e instanceof {@link MessageEvent}) {
* logger.info("Writing:: " + e);
* }
*
* super.handleDownstream(ctx, e);
* }
* }
*
* Caution:
*
* Use the *Later(..) methods of the {@link Channels} class if you want to send an upstream event
* from a {@link ChannelDownstreamHandler} otherwise you may run into threading issues.
*
*/
public class SimpleChannelDownstreamHandler implements ChannelDownstreamHandler {
/**
* {@inheritDoc} Down-casts the received downstream event into more
* meaningful sub-type event and calls an appropriate handler method with
* the down-casted event.
*/
public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
if (e instanceof MessageEvent) {
writeRequested(ctx, (MessageEvent) e);
} else if (e instanceof ChannelStateEvent) {
ChannelStateEvent evt = (ChannelStateEvent) e;
switch (evt.getState()) {
case OPEN:
if (!Boolean.TRUE.equals(evt.getValue())) {
closeRequested(ctx, evt);
}
break;
case BOUND:
if (evt.getValue() != null) {
bindRequested(ctx, evt);
} else {
unbindRequested(ctx, evt);
}
break;
case CONNECTED:
if (evt.getValue() != null) {
connectRequested(ctx, evt);
} else {
disconnectRequested(ctx, evt);
}
break;
case INTEREST_OPS:
setInterestOpsRequested(ctx, evt);
break;
default:
ctx.sendDownstream(e);
}
} else {
ctx.sendDownstream(e);
}
}
/**
* Invoked when {@link Channel#write(Object)} is called.
*/
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#bind(SocketAddress)} was called.
*/
public void bindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#connect(SocketAddress)} was called.
*/
public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#setInterestOps(int)} was called.
*/
public void setInterestOpsRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#disconnect()} was called.
*/
public void disconnectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#unbind()} was called.
*/
public void unbindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#close()} was called.
*/
public void closeRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/SimpleChannelHandler.java 0000664 0000000 0000000 00000026704 12255541277 0031103 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import java.net.SocketAddress;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
/**
* A {@link ChannelHandler} which provides an individual handler method
* for each event type. This handler down-casts the received upstream or
* or downstream event into more meaningful sub-type event and calls an
* appropriate handler method with the down-cast event. For an upstream
* event, the names of the methods are identical to the upstream event names,
* as introduced in the {@link ChannelEvent} documentation. For a
* downstream event, the names of the methods starts with the name of the
* operation and ends with {@code "Requested"}
* (e.g. {@link #writeRequested(ChannelHandlerContext, MessageEvent) writeRequested}.)
*
* Please use {@link SimpleChannelUpstreamHandler} or
* {@link SimpleChannelDownstreamHandler} if you want to intercept only
* upstream or downstream events.
*
*
Overriding the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
* and {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream} method
*
* You can override the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
* and {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream}
* method just like overriding an ordinary Java method. Please make sure to
* call {@code super.handleUpstream()} or {@code super.handleDownstream()} so
* that other handler methods are invoked properly:
*
* public class MyChannelHandler extends {@link SimpleChannelHandler} {
*
* {@code @Override}
* public void handleUpstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
*
* // Log all channel state changes.
* if (e instanceof {@link ChannelStateEvent}) {
* logger.info("Channel state changed: " + e);
* }
*
* super.handleUpstream(ctx, e);
* }
*
* {@code @Override}
* public void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
*
* // Log all channel state changes.
* if (e instanceof {@link MessageEvent}) {
* logger.info("Writing:: " + e);
* }
*
* super.handleDownstream(ctx, e);
* }
* }
*/
public class SimpleChannelHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(SimpleChannelHandler.class.getName());
/**
* {@inheritDoc} Down-casts the received upstream event into more
* meaningful sub-type event and calls an appropriate handler method with
* the down-casted event.
*/
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof MessageEvent) {
messageReceived(ctx, (MessageEvent) e);
} else if (e instanceof WriteCompletionEvent) {
WriteCompletionEvent evt = (WriteCompletionEvent) e;
writeComplete(ctx, evt);
} else if (e instanceof ChildChannelStateEvent) {
ChildChannelStateEvent evt = (ChildChannelStateEvent) e;
if (evt.getChildChannel().isOpen()) {
childChannelOpen(ctx, evt);
} else {
childChannelClosed(ctx, evt);
}
} else if (e instanceof ChannelStateEvent) {
ChannelStateEvent evt = (ChannelStateEvent) e;
switch (evt.getState()) {
case OPEN:
if (Boolean.TRUE.equals(evt.getValue())) {
channelOpen(ctx, evt);
} else {
channelClosed(ctx, evt);
}
break;
case BOUND:
if (evt.getValue() != null) {
channelBound(ctx, evt);
} else {
channelUnbound(ctx, evt);
}
break;
case CONNECTED:
if (evt.getValue() != null) {
channelConnected(ctx, evt);
} else {
channelDisconnected(ctx, evt);
}
break;
case INTEREST_OPS:
channelInterestChanged(ctx, evt);
break;
default:
ctx.sendUpstream(e);
}
} else if (e instanceof ExceptionEvent) {
exceptionCaught(ctx, (ExceptionEvent) e);
} else {
ctx.sendUpstream(e);
}
}
/**
* Invoked when a message object (e.g: {@link ChannelBuffer}) was received
* from a remote peer.
*/
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when an exception was raised by an I/O thread or a
* {@link ChannelHandler}.
*/
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
if (this == ctx.getPipeline().getLast()) {
logger.warn(
"EXCEPTION, please implement " + getClass().getName() +
".exceptionCaught() for proper handling.", e.getCause());
}
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} is open, but not bound nor connected.
*/
public void channelOpen(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} is open and bound to a local address,
* but not connected.
*/
public void channelBound(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} is open, bound to a local address, and
* connected to a remote address.
*/
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel}'s {@link Channel#getInterestOps() interestOps}
* was changed.
*/
public void channelInterestChanged(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} was disconnected from its remote peer.
*/
public void channelDisconnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} was unbound from the current local address.
*/
public void channelUnbound(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} was closed and all its related resources
* were released.
*/
public void channelClosed(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when something was written into a {@link Channel}.
*/
public void writeComplete(
ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a child {@link Channel} was open.
* (e.g. a server channel accepted a connection)
*/
public void childChannelOpen(
ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a child {@link Channel} was closed.
* (e.g. the accepted connection was closed)
*/
public void childChannelClosed(
ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* {@inheritDoc} Down-casts the received downstream event into more
* meaningful sub-type event and calls an appropriate handler method with
* the down-casted event.
*/
public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
if (e instanceof MessageEvent) {
writeRequested(ctx, (MessageEvent) e);
} else if (e instanceof ChannelStateEvent) {
ChannelStateEvent evt = (ChannelStateEvent) e;
switch (evt.getState()) {
case OPEN:
if (!Boolean.TRUE.equals(evt.getValue())) {
closeRequested(ctx, evt);
}
break;
case BOUND:
if (evt.getValue() != null) {
bindRequested(ctx, evt);
} else {
unbindRequested(ctx, evt);
}
break;
case CONNECTED:
if (evt.getValue() != null) {
connectRequested(ctx, evt);
} else {
disconnectRequested(ctx, evt);
}
break;
case INTEREST_OPS:
setInterestOpsRequested(ctx, evt);
break;
default:
ctx.sendDownstream(e);
}
} else {
ctx.sendDownstream(e);
}
}
/**
* Invoked when {@link Channel#write(Object)} is called.
*/
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#bind(SocketAddress)} was called.
*/
public void bindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#connect(SocketAddress)} was called.
*/
public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#setInterestOps(int)} was called.
*/
public void setInterestOpsRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#disconnect()} was called.
*/
public void disconnectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#unbind()} was called.
*/
public void unbindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
/**
* Invoked when {@link Channel#close()} was called.
*/
public void closeRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendDownstream(e);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/SimpleChannelUpstreamHandler.java 0000664 0000000 0000000 00000022053 12255541277 0032615 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.util.List;
/**
* A {@link ChannelUpstreamHandler} which provides an individual handler method
* for each event type. This handler down-casts the received upstream event
* into more meaningful sub-type event and calls an appropriate handler method
* with the down-cast event. The names of the methods are identical to the
* upstream event names, as introduced in the {@link ChannelEvent} documentation.
*
* Please use {@link SimpleChannelHandler} if you need to implement both
* {@link ChannelUpstreamHandler} and {@link ChannelDownstreamHandler}.
*
*
Overriding the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream} method
*
* You can override the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream}
* method just like overriding an ordinary Java method. Please make sure to
* call {@code super.handleUpstream()} so that other handler methods are invoked
* properly:
*
* public class MyChannelHandler extends {@link SimpleChannelUpstreamHandler} {
*
* {@code @Override}
* public void handleUpstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
*
* // Log all channel state changes.
* if (e instanceof {@link ChannelStateEvent}) {
* logger.info("Channel state changed: " + e);
* }
*
* super.handleUpstream(ctx, e);
* }
* }
*/
public class SimpleChannelUpstreamHandler implements ChannelUpstreamHandler {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(SimpleChannelUpstreamHandler.class.getName());
/**
* {@inheritDoc} Down-casts the received upstream event into more
* meaningful sub-type event and calls an appropriate handler method with
* the down-casted event.
*/
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof MessageEvent) {
messageReceived(ctx, (MessageEvent) e);
} else if (e instanceof WriteCompletionEvent) {
WriteCompletionEvent evt = (WriteCompletionEvent) e;
writeComplete(ctx, evt);
} else if (e instanceof ChildChannelStateEvent) {
ChildChannelStateEvent evt = (ChildChannelStateEvent) e;
if (evt.getChildChannel().isOpen()) {
childChannelOpen(ctx, evt);
} else {
childChannelClosed(ctx, evt);
}
} else if (e instanceof ChannelStateEvent) {
ChannelStateEvent evt = (ChannelStateEvent) e;
switch (evt.getState()) {
case OPEN:
if (Boolean.TRUE.equals(evt.getValue())) {
channelOpen(ctx, evt);
} else {
channelClosed(ctx, evt);
}
break;
case BOUND:
if (evt.getValue() != null) {
channelBound(ctx, evt);
} else {
channelUnbound(ctx, evt);
}
break;
case CONNECTED:
if (evt.getValue() != null) {
channelConnected(ctx, evt);
} else {
channelDisconnected(ctx, evt);
}
break;
case INTEREST_OPS:
channelInterestChanged(ctx, evt);
break;
default:
ctx.sendUpstream(e);
}
} else if (e instanceof ExceptionEvent) {
exceptionCaught(ctx, (ExceptionEvent) e);
} else {
ctx.sendUpstream(e);
}
}
/**
* Invoked when a message object (e.g: {@link ChannelBuffer}) was received
* from a remote peer.
*/
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when an exception was raised by an I/O thread or a
* {@link ChannelHandler}.
*/
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
ChannelPipeline pipeline = ctx.getPipeline();
ChannelHandler last = pipeline.getLast();
if (!(last instanceof ChannelUpstreamHandler) && ctx instanceof DefaultChannelPipeline) {
// The names comes in the order of which they are insert when using DefaultChannelPipeline
List names = ctx.getPipeline().getNames();
for (int i = names.size() - 1; i >= 0; i--) {
ChannelHandler handler = ctx.getPipeline().get(names.get(i));
if (handler instanceof ChannelUpstreamHandler) {
// find the last handler
last = handler;
break;
}
}
}
if (this == last) {
logger.warn(
"EXCEPTION, please implement " + getClass().getName() +
".exceptionCaught() for proper handling.", e.getCause());
}
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} is open, but not bound nor connected.
*
*
* Be aware that this event is fired from within the Boss-Thread so you should not
* execute any heavy operation in there as it will block the dispatching to other workers!
*/
public void channelOpen(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} is open and bound to a local address,
* but not connected.
*
*
* Be aware that this event is fired from within the Boss-Thread so you should not
* execute any heavy operation in there as it will block the dispatching to other workers!
*/
public void channelBound(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} is open, bound to a local address, and
* connected to a remote address.
*
*
* Be aware that this event is fired from within the Boss-Thread so you should not
* execute any heavy operation in there as it will block the dispatching to other workers!
*/
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel}'s {@link Channel#getInterestOps() interestOps}
* was changed.
*/
public void channelInterestChanged(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} was disconnected from its remote peer.
*/
public void channelDisconnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} was unbound from the current local address.
*/
public void channelUnbound(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a {@link Channel} was closed and all its related resources
* were released.
*/
public void channelClosed(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when something was written into a {@link Channel}.
*/
public void writeComplete(
ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a child {@link Channel} was open.
* (e.g. a server channel accepted a connection)
*/
public void childChannelOpen(
ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
/**
* Invoked when a child {@link Channel} was closed.
* (e.g. the accepted connection was closed)
*/
public void childChannelClosed(
ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception {
ctx.sendUpstream(e);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/StaticChannelPipeline.java 0000664 0000000 0000000 00000042174 12255541277 0031270 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.ConversionUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* A {@link ChannelPipeline} that might perform better at the cost of
* disabled dynamic insertion and removal of {@link ChannelHandler}s.
* An attempt to insert, remove, or replace a handler in this pipeline will
* trigger an {@link UnsupportedOperationException}.
*
* @deprecated use {@link DefaultChannelPipeline}
*/
@Deprecated
public class StaticChannelPipeline implements ChannelPipeline {
// FIXME Code duplication with DefaultChannelPipeline
static final InternalLogger logger = InternalLoggerFactory.getInstance(StaticChannelPipeline.class);
private volatile Channel channel;
private volatile ChannelSink sink;
private final StaticChannelHandlerContext[] contexts;
private final int lastIndex;
private final Map name2ctx =
new HashMap(4);
/**
* Creates a new pipeline from the specified handlers.
* The names of the specified handlers are generated automatically;
* the first handler's name is {@code "0"}, the second handler's name is
* {@code "1"}, the third handler's name is {@code "2"}, and so on.
*/
public StaticChannelPipeline(ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
if (handlers.length == 0) {
throw new IllegalArgumentException("no handlers specified");
}
// Get the number of first non-null handlers.
StaticChannelHandlerContext[] contexts =
new StaticChannelHandlerContext[handlers.length];
int nContexts;
for (nContexts = 0; nContexts < contexts.length; nContexts ++) {
ChannelHandler h = handlers[nContexts];
if (h == null) {
break;
}
}
if (nContexts == contexts.length) {
this.contexts = contexts;
lastIndex = contexts.length - 1;
} else {
this.contexts = contexts =
new StaticChannelHandlerContext[nContexts];
lastIndex = nContexts - 1;
}
// Initialize the first non-null handlers only.
for (int i = 0; i < nContexts; i ++) {
ChannelHandler h = handlers[i];
String name = ConversionUtil.toString(i);
StaticChannelHandlerContext ctx =
new StaticChannelHandlerContext(i, name, h);
contexts[i] = ctx;
name2ctx.put(name, ctx);
}
for (ChannelHandlerContext ctx: contexts) {
callBeforeAdd(ctx);
callAfterAdd(ctx);
}
}
public ChannelFuture execute(Runnable task) {
return getSink().execute(this, task);
}
public Channel getChannel() {
return channel;
}
public ChannelSink getSink() {
ChannelSink sink = this.sink;
if (sink == null) {
return DefaultChannelPipeline.discardingSink;
}
return sink;
}
public void attach(Channel channel, ChannelSink sink) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (sink == null) {
throw new NullPointerException("sink");
}
if (this.channel != null || this.sink != null) {
throw new IllegalStateException("attached already");
}
this.channel = channel;
this.sink = sink;
}
public boolean isAttached() {
return sink != null;
}
public void addFirst(String name, ChannelHandler handler) {
throw new UnsupportedOperationException();
}
public void addLast(String name, ChannelHandler handler) {
throw new UnsupportedOperationException();
}
public void addBefore(String baseName, String name, ChannelHandler handler) {
throw new UnsupportedOperationException();
}
public void addAfter(String baseName, String name, ChannelHandler handler) {
throw new UnsupportedOperationException();
}
public void remove(ChannelHandler handler) {
throw new UnsupportedOperationException();
}
public ChannelHandler remove(String name) {
throw new UnsupportedOperationException();
}
public T remove(Class handlerType) {
throw new UnsupportedOperationException();
}
public ChannelHandler removeFirst() {
throw new UnsupportedOperationException();
}
public ChannelHandler removeLast() {
throw new UnsupportedOperationException();
}
public void replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler) {
throw new UnsupportedOperationException();
}
public ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler) {
throw new UnsupportedOperationException();
}
public T replace(
Class oldHandlerType, String newName, ChannelHandler newHandler) {
throw new UnsupportedOperationException();
}
private static void callBeforeAdd(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.beforeAdd(ctx);
} catch (Throwable t) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".beforeAdd() has thrown an exception; not adding.", t);
}
}
private static void callAfterAdd(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.afterAdd(ctx);
} catch (Throwable t) {
boolean removed = false;
try {
callBeforeRemove(ctx);
callAfterRemove(ctx);
removed = true;
} catch (Throwable t2) {
logger.warn("Failed to remove a handler: " + ctx.getName(), t2);
}
if (removed) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".afterAdd() has thrown an exception; removed.", t);
} else {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".afterAdd() has thrown an exception; also failed to remove.", t);
}
}
}
private static void callBeforeRemove(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.beforeRemove(ctx);
} catch (Throwable t) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".beforeRemove() has thrown an exception; not removing.", t);
}
}
private static void callAfterRemove(ChannelHandlerContext ctx) {
if (!(ctx.getHandler() instanceof LifeCycleAwareChannelHandler)) {
return;
}
LifeCycleAwareChannelHandler h =
(LifeCycleAwareChannelHandler) ctx.getHandler();
try {
h.afterRemove(ctx);
} catch (Throwable t) {
throw new ChannelHandlerLifeCycleException(
h.getClass().getName() +
".afterRemove() has thrown an exception.", t);
}
}
public ChannelHandler getFirst() {
return contexts[0].getHandler();
}
public ChannelHandler getLast() {
return contexts[contexts.length - 1].getHandler();
}
public ChannelHandler get(String name) {
StaticChannelHandlerContext ctx = name2ctx.get(name);
if (ctx == null) {
return null;
} else {
return ctx.getHandler();
}
}
public T get(Class handlerType) {
ChannelHandlerContext ctx = getContext(handlerType);
if (ctx == null) {
return null;
} else {
@SuppressWarnings("unchecked")
T handler = (T) ctx.getHandler();
return handler;
}
}
public ChannelHandlerContext getContext(String name) {
if (name == null) {
throw new NullPointerException("name");
}
return name2ctx.get(name);
}
public ChannelHandlerContext getContext(ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
for (StaticChannelHandlerContext ctx: contexts) {
if (ctx.getHandler() == handler) {
return ctx;
}
}
return null;
}
public ChannelHandlerContext getContext(Class extends ChannelHandler> handlerType) {
if (handlerType == null) {
throw new NullPointerException("handlerType");
}
for (StaticChannelHandlerContext ctx: contexts) {
if (handlerType.isAssignableFrom(ctx.getHandler().getClass())) {
return ctx;
}
}
return null;
}
public List getNames() {
List list = new ArrayList();
for (StaticChannelHandlerContext ctx: contexts) {
list.add(ctx.getName());
}
return list;
}
public Map toMap() {
Map map = new LinkedHashMap();
for (StaticChannelHandlerContext ctx: contexts) {
map.put(ctx.getName(), ctx.getHandler());
}
return map;
}
/**
* Returns the {@link String} representation of this pipeline.
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(getClass().getSimpleName());
buf.append('{');
for (StaticChannelHandlerContext ctx: contexts) {
buf.append('(');
buf.append(ctx.getName());
buf.append(" = ");
buf.append(ctx.getHandler().getClass().getName());
buf.append(')');
buf.append(", ");
}
buf.replace(buf.length() - 2, buf.length(), "}");
return buf.toString();
}
public void sendUpstream(ChannelEvent e) {
StaticChannelHandlerContext head = getActualUpstreamContext(0);
if (head == null) {
logger.warn(
"The pipeline contains no upstream handlers; discarding: " + e);
return;
}
sendUpstream(head, e);
}
void sendUpstream(StaticChannelHandlerContext ctx, ChannelEvent e) {
try {
((ChannelUpstreamHandler) ctx.getHandler()).handleUpstream(ctx, e);
} catch (Throwable t) {
notifyHandlerException(e, t);
}
}
public void sendDownstream(ChannelEvent e) {
StaticChannelHandlerContext tail = getActualDownstreamContext(lastIndex);
if (tail == null) {
try {
getSink().eventSunk(this, e);
return;
} catch (Throwable t) {
notifyHandlerException(e, t);
return;
}
}
sendDownstream(tail, e);
}
void sendDownstream(StaticChannelHandlerContext ctx, ChannelEvent e) {
if (e instanceof UpstreamMessageEvent) {
throw new IllegalArgumentException("cannot send an upstream event to downstream");
}
try {
((ChannelDownstreamHandler) ctx.getHandler()).handleDownstream(ctx, e);
} catch (Throwable t) {
// Unlike an upstream event, a downstream event usually has an
// incomplete future which is supposed to be updated by ChannelSink.
// However, if an exception is raised before the event reaches at
// ChannelSink, the future is not going to be updated, so we update
// here.
e.getFuture().setFailure(t);
notifyHandlerException(e, t);
}
}
private StaticChannelHandlerContext getActualUpstreamContext(int index) {
for (int i = index; i < contexts.length; i ++) {
StaticChannelHandlerContext ctx = contexts[i];
if (ctx.canHandleUpstream()) {
return ctx;
}
}
return null;
}
private StaticChannelHandlerContext getActualDownstreamContext(int index) {
for (int i = index; i >= 0; i --) {
StaticChannelHandlerContext ctx = contexts[i];
if (ctx.canHandleDownstream()) {
return ctx;
}
}
return null;
}
protected void notifyHandlerException(ChannelEvent e, Throwable t) {
if (e instanceof ExceptionEvent) {
logger.warn(
"An exception was thrown by a user handler " +
"while handling an exception event (" + e + ')', t);
return;
}
ChannelPipelineException pe;
if (t instanceof ChannelPipelineException) {
pe = (ChannelPipelineException) t;
} else {
pe = new ChannelPipelineException(t);
}
try {
sink.exceptionCaught(this, e, pe);
} catch (Exception e1) {
logger.warn("An exception was thrown by an exception handler.", e1);
}
}
private final class StaticChannelHandlerContext implements ChannelHandlerContext {
private final int index;
private final String name;
private final ChannelHandler handler;
private final boolean canHandleUpstream;
private final boolean canHandleDownstream;
private volatile Object attachment;
StaticChannelHandlerContext(
int index, String name, ChannelHandler handler) {
if (name == null) {
throw new NullPointerException("name");
}
if (handler == null) {
throw new NullPointerException("handler");
}
canHandleUpstream = handler instanceof ChannelUpstreamHandler;
canHandleDownstream = handler instanceof ChannelDownstreamHandler;
if (!canHandleUpstream && !canHandleDownstream) {
throw new IllegalArgumentException(
"handler must be either " +
ChannelUpstreamHandler.class.getName() + " or " +
ChannelDownstreamHandler.class.getName() + '.');
}
this.index = index;
this.name = name;
this.handler = handler;
}
public Channel getChannel() {
return getPipeline().getChannel();
}
public ChannelPipeline getPipeline() {
return StaticChannelPipeline.this;
}
public boolean canHandleDownstream() {
return canHandleDownstream;
}
public boolean canHandleUpstream() {
return canHandleUpstream;
}
public ChannelHandler getHandler() {
return handler;
}
public String getName() {
return name;
}
public Object getAttachment() {
return attachment;
}
public void setAttachment(Object attachment) {
this.attachment = attachment;
}
public void sendDownstream(ChannelEvent e) {
StaticChannelHandlerContext prev = getActualDownstreamContext(index - 1);
if (prev == null) {
try {
getSink().eventSunk(StaticChannelPipeline.this, e);
} catch (Throwable t) {
notifyHandlerException(e, t);
}
} else {
StaticChannelPipeline.this.sendDownstream(prev, e);
}
}
public void sendUpstream(ChannelEvent e) {
StaticChannelHandlerContext next = getActualUpstreamContext(index + 1);
if (next != null) {
StaticChannelPipeline.this.sendUpstream(next, e);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/SucceededChannelFuture.java 0000664 0000000 0000000 00000003005 12255541277 0031420 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* The {@link CompleteChannelFuture} which is succeeded already. It is
* recommended to use {@link Channels#succeededFuture(Channel)} instead of
* calling the constructor of this future.
*/
public class SucceededChannelFuture extends CompleteChannelFuture {
/**
* Creates a new instance.
*
* @param channel the {@link Channel} associated with this future
*/
public SucceededChannelFuture(Channel channel) {
super(channel);
}
public Throwable getCause() {
return null;
}
public boolean isSuccess() {
return true;
}
@Deprecated
public ChannelFuture rethrowIfFailed() throws Exception {
return this;
}
public ChannelFuture sync() throws InterruptedException {
return this;
}
public ChannelFuture syncUninterruptibly() {
return this;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/UpstreamChannelStateEvent.java 0000664 0000000 0000000 00000005472 12255541277 0032156 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import static org.jboss.netty.channel.Channels.*;
/**
* The default upstream {@link ChannelStateEvent} implementation.
*/
public class UpstreamChannelStateEvent implements ChannelStateEvent {
private final Channel channel;
private final ChannelState state;
private final Object value;
/**
* Creates a new instance.
*/
public UpstreamChannelStateEvent(
Channel channel, ChannelState state, Object value) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (state == null) {
throw new NullPointerException("state");
}
this.channel = channel;
this.state = state;
this.value = value;
}
public Channel getChannel() {
return channel;
}
public ChannelFuture getFuture() {
return succeededFuture(getChannel());
}
public ChannelState getState() {
return state;
}
public Object getValue() {
return value;
}
@Override
public String toString() {
String channelString = getChannel().toString();
StringBuilder buf = new StringBuilder(channelString.length() + 64);
buf.append(channelString);
switch (getState()) {
case OPEN:
if (Boolean.TRUE.equals(getValue())) {
buf.append(" OPEN");
} else {
buf.append(" CLOSED");
}
break;
case BOUND:
if (getValue() != null) {
buf.append(" BOUND: ");
buf.append(getValue());
} else {
buf.append(" UNBOUND");
}
break;
case CONNECTED:
if (getValue() != null) {
buf.append(" CONNECTED: ");
buf.append(getValue());
} else {
buf.append(" DISCONNECTED");
}
break;
case INTEREST_OPS:
buf.append(" INTEREST_CHANGED");
break;
default:
buf.append(getState().name());
buf.append(": ");
buf.append(getValue());
}
return buf.toString();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/UpstreamMessageEvent.java 0000664 0000000 0000000 00000004544 12255541277 0031170 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
import static org.jboss.netty.channel.Channels.*;
import java.net.SocketAddress;
import org.jboss.netty.util.internal.StringUtil;
/**
* The default upstream {@link MessageEvent} implementation.
*/
public class UpstreamMessageEvent implements MessageEvent {
private final Channel channel;
private final Object message;
private final SocketAddress remoteAddress;
/**
* Creates a new instance.
*/
public UpstreamMessageEvent(
Channel channel, Object message, SocketAddress remoteAddress) {
if (channel == null) {
throw new NullPointerException("channel");
}
if (message == null) {
throw new NullPointerException("message");
}
this.channel = channel;
this.message = message;
if (remoteAddress != null) {
this.remoteAddress = remoteAddress;
} else {
this.remoteAddress = channel.getRemoteAddress();
}
}
public Channel getChannel() {
return channel;
}
public ChannelFuture getFuture() {
return succeededFuture(getChannel());
}
public Object getMessage() {
return message;
}
public SocketAddress getRemoteAddress() {
return remoteAddress;
}
@Override
public String toString() {
if (getRemoteAddress() == getChannel().getRemoteAddress()) {
return getChannel().toString() + " RECEIVED: " +
StringUtil.stripControlCharacters(getMessage());
} else {
return getChannel().toString() + " RECEIVED: " +
StringUtil.stripControlCharacters(getMessage()) + " from " +
getRemoteAddress();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/WriteCompletionEvent.java 0000664 0000000 0000000 00000002376 12255541277 0031210 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel;
/**
* A {@link ChannelEvent} which represents the notification of the completion
* of a write request on a {@link Channel}. This event is for going upstream
* only. Please refer to the {@link ChannelEvent} documentation to find out
* what an upstream event and a downstream event are and what fundamental
* differences they have.
*/
public interface WriteCompletionEvent extends ChannelEvent {
/**
* Returns the amount of data written.
*
* @return the number of written bytes or messages, depending on the
* type of the transport
*/
long getWrittenAmount();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/ 0000775 0000000 0000000 00000000000 12255541277 0025343 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/ChannelGroup.java 0000664 0000000 0000000 00000016162 12255541277 0030601 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.group;
import java.net.SocketAddress;
import java.util.Set;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ServerChannel;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.util.CharsetUtil;
/**
* A thread-safe {@link Set} that contains open {@link Channel}s and provides
* various bulk operations on them. Using {@link ChannelGroup}, you can
* categorize {@link Channel}s into a meaningful group (e.g. on a per-service
* or per-state basis.) A closed {@link Channel} is automatically removed from
* the collection, so that you don't need to worry about the life cycle of the
* added {@link Channel}. A {@link Channel} can belong to more than one
* {@link ChannelGroup}.
*
* Broadcast a message to multiple {@link Channel}s
*
* If you need to broadcast a message to more than one {@link Channel}, you can
* add the {@link Channel}s associated with the recipients and call {@link ChannelGroup#write(Object)}:
*
* {@link ChannelGroup} recipients = new {@link DefaultChannelGroup}();
* recipients.add(channelA);
* recipients.add(channelB);
* ..
* recipients.write({@link ChannelBuffers}.copiedBuffer(
* "Service will shut down for maintenance in 5 minutes.",
* {@link CharsetUtil}.UTF_8));
*
*
* Simplify shutdown process with {@link ChannelGroup}
*
* If both {@link ServerChannel}s and non-{@link ServerChannel}s exist in the
* same {@link ChannelGroup}, any requested I/O operations on the group are
* performed for the {@link ServerChannel}s first and then for the others.
*
* This rule is very useful when you shut down a server in one shot:
*
*
* {@link ChannelGroup} allChannels = new {@link DefaultChannelGroup}();
*
* public static void main(String[] args) throws Exception {
* {@link ServerBootstrap} b = new {@link ServerBootstrap}(..);
* ...
*
* // Start the server
* b.getPipeline().addLast("handler", new MyHandler());
* {@link Channel} serverChannel = b.bind(..);
* allChannels.add(serverChannel);
*
* ... Wait until the shutdown signal reception ...
*
* // Close the serverChannel and then all accepted connections.
* allChannels.close().awaitUninterruptibly();
* b.releaseExternalResources();
* }
*
* public class MyHandler extends {@link SimpleChannelUpstreamHandler} {
* {@code @Override}
* public void channelOpen({@link ChannelHandlerContext} ctx, {@link ChannelStateEvent} e) {
* // Add all open channels to the global group so that they are
* // closed on shutdown.
* allChannels.add(e.getChannel());
* }
* }
*
* @apiviz.landmark
* @apiviz.has org.jboss.netty.channel.group.ChannelGroupFuture oneway - - returns
*/
public interface ChannelGroup extends Set, Comparable {
/**
* Returns the name of this group. A group name is purely for helping
* you to distinguish one group from others.
*/
String getName();
/**
* Returns the {@link Channel} whose ID matches the specified integer.
*
* @return the matching {@link Channel} if found. {@code null} otherwise.
*/
Channel find(Integer id);
/**
* Calls {@link Channel#setInterestOps(int)} for all {@link Channel}s in
* this group with the specified {@code interestOps}. Please note that
* this operation is asynchronous as {@link Channel#setInterestOps(int)} is.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture setInterestOps(int interestOps);
/**
* Calls {@link Channel#setReadable(boolean)} for all {@link Channel}s in
* this group with the specified boolean flag. Please note that this
* operation is asynchronous as {@link Channel#setReadable(boolean)} is.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture setReadable(boolean readable);
/**
* Writes the specified {@code message} to all {@link Channel}s in this
* group. If the specified {@code message} is an instance of
* {@link ChannelBuffer}, it is automatically
* {@linkplain ChannelBuffer#duplicate() duplicated} to avoid a race
* condition. Please note that this operation is asynchronous as
* {@link Channel#write(Object)} is.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture write(Object message);
/**
* Writes the specified {@code message} with the specified
* {@code remoteAddress} to all {@link Channel}s in this group. If the
* specified {@code message} is an instance of {@link ChannelBuffer}, it is
* automatically {@linkplain ChannelBuffer#duplicate() duplicated} to avoid
* a race condition. Please note that this operation is asynchronous as
* {@link Channel#write(Object, SocketAddress)} is.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture write(Object message, SocketAddress remoteAddress);
/**
* Disconnects all {@link Channel}s in this group from their remote peers.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture disconnect();
/**
* Unbinds all {@link Channel}s in this group from their local address.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture unbind();
/**
* Closes all {@link Channel}s in this group. If the {@link Channel} is
* connected to a remote peer or bound to a local address, it is
* automatically disconnected and unbound.
*
* @return the {@link ChannelGroupFuture} instance that notifies when
* the operation is done for all channels
*/
ChannelGroupFuture close();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/ChannelGroupFuture.java 0000664 0000000 0000000 00000023546 12255541277 0032000 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.group;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.execution.ExecutionHandler;
/**
* The result of an asynchronous {@link ChannelGroup} operation.
* {@link ChannelGroupFuture} is composed of {@link ChannelFuture}s which
* represent the outcome of the individual I/O operations that affect the
* {@link Channel}s in the {@link ChannelGroup}.
*
*
* All I/O operations in {@link ChannelGroup} are asynchronous. It means any
* I/O calls will return immediately with no guarantee that the requested I/O
* operations have been completed at the end of the call. Instead, you will be
* returned with a {@link ChannelGroupFuture} instance which tells you when the
* requested I/O operations have succeeded, failed, or cancelled.
*
* Various methods are provided to let you check if the I/O operations has been
* completed, wait for the completion, and retrieve the result of the I/O
* operation. It also allows you to add more than one
* {@link ChannelGroupFutureListener} so you can get notified when the I/O
* operation have been completed.
*
*
Prefer {@link #addListener(ChannelGroupFutureListener)} to {@link #await()}
*
* It is recommended to prefer {@link #addListener(ChannelGroupFutureListener)} to
* {@link #await()} wherever possible to get notified when I/O operations are
* done and to do any follow-up tasks.
*
* {@link #addListener(ChannelGroupFutureListener)} is non-blocking. It simply
* adds the specified {@link ChannelGroupFutureListener} to the
* {@link ChannelGroupFuture}, and I/O thread will notify the listeners when
* the I/O operations associated with the future is done.
* {@link ChannelGroupFutureListener} yields the best performance and resource
* utilization because it does not block at all, but it could be tricky to
* implement a sequential logic if you are not used to event-driven programming.
*
* By contrast, {@link #await()} is a blocking operation. Once called, the
* caller thread blocks until all I/O operations are done. It is easier to
* implement a sequential logic with {@link #await()}, but the caller thread
* blocks unnecessarily until all I/O operations are done and there's relatively
* expensive cost of inter-thread notification. Moreover, there's a chance of
* dead lock in a particular circumstance, which is described below.
*
*
Do not call {@link #await()} inside {@link ChannelHandler}
*
* The event handler methods in {@link ChannelHandler} is often called by
* an I/O thread unless an {@link ExecutionHandler} is in the
* {@link ChannelPipeline}. If {@link #await()} is called by an event handler
* method, which is called by the I/O thread, the I/O operation it is waiting
* for might never be complete because {@link #await()} can block the I/O
* operation it is waiting for, which is a dead lock.
*
* // BAD - NEVER DO THIS
* {@code @Override}
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
* if (e.getMessage() instanceof ShutdownMessage) {
* {@link ChannelGroup} allChannels = MyServer.getAllChannels();
* {@link ChannelGroupFuture} future = allChannels.close();
* future.awaitUninterruptibly();
* // Perform post-shutdown operation
* // ...
* }
* }
*
* // GOOD
* {@code @Override}
* public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
* if (e.getMessage() instanceof ShutdownMessage) {
* {@link ChannelGroup} allChannels = MyServer.getAllChannels();
* {@link ChannelGroupFuture} future = allChannels.close();
* future.addListener(new {@link ChannelGroupFutureListener}() {
* public void operationComplete({@link ChannelGroupFuture} future) {
* // Perform post-closure operation
* // ...
* }
* });
* }
* }
*
*
* In spite of the disadvantages mentioned above, there are certainly the cases
* where it is more convenient to call {@link #await()}. In such a case, please
* make sure you do not call {@link #await()} in an I/O thread. Otherwise,
* {@link IllegalStateException} will be raised to prevent a dead lock.
* @apiviz.owns org.jboss.netty.channel.group.ChannelGroupFutureListener - - notifies
*/
public interface ChannelGroupFuture extends Iterable {
/**
* Returns the {@link ChannelGroup} which is associated with this future.
*/
ChannelGroup getGroup();
/**
* Returns the {@link ChannelFuture} of the individual I/O operation which
* is associated with the {@link Channel} whose ID matches the specified
* integer.
*
* @return the matching {@link ChannelFuture} if found.
* {@code null} otherwise.
*/
ChannelFuture find(Integer channelId);
/**
* Returns the {@link ChannelFuture} of the individual I/O operation which
* is associated with the specified {@link Channel}.
*
* @return the matching {@link ChannelFuture} if found.
* {@code null} otherwise.
*/
ChannelFuture find(Channel channel);
/**
* Returns {@code true} if and only if this future is
* complete, regardless of whether the operation was successful, failed,
* or canceled.
*/
boolean isDone();
/**
* Returns {@code true} if and only if all I/O operations associated with
* this future were successful without any failure.
*/
boolean isCompleteSuccess();
/**
* Returns {@code true} if and only if the I/O operations associated with
* this future were partially successful with some failure.
*/
boolean isPartialSuccess();
/**
* Returns {@code true} if and only if all I/O operations associated with
* this future have failed without any success.
*/
boolean isCompleteFailure();
/**
* Returns {@code true} if and only if the I/O operations associated with
* this future have failed partially with some success.
*/
boolean isPartialFailure();
/**
* Adds the specified listener to this future. The
* specified listener is notified when this future is
* {@linkplain #isDone() done}. If this future is already
* completed, the specified listener is notified immediately.
*/
void addListener(ChannelGroupFutureListener listener);
/**
* Removes the specified listener from this future.
* The specified listener is no longer notified when this
* future is {@linkplain #isDone() done}. If this
* future is already completed, this method has no effect
* and returns silently.
*/
void removeListener(ChannelGroupFutureListener listener);
/**
* Waits for this future to be completed.
*
* @throws InterruptedException
* if the current thread was interrupted
*/
ChannelGroupFuture await() throws InterruptedException;
/**
* Waits for this future to be completed without
* interruption. This method catches an {@link InterruptedException} and
* discards it silently.
*/
ChannelGroupFuture awaitUninterruptibly();
/**
* Waits for this future to be completed within the
* specified time limit.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*
* @throws InterruptedException
* if the current thread was interrupted
*/
boolean await(long timeout, TimeUnit unit) throws InterruptedException;
/**
* Waits for this future to be completed within the
* specified time limit.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*
* @throws InterruptedException
* if the current thread was interrupted
*/
boolean await(long timeoutMillis) throws InterruptedException;
/**
* Waits for this future to be completed within the
* specified time limit without interruption. This method catches an
* {@link InterruptedException} and discards it silently.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*/
boolean awaitUninterruptibly(long timeout, TimeUnit unit);
/**
* Waits for this future to be completed within the
* specified time limit without interruption. This method catches an
* {@link InterruptedException} and discards it silently.
*
* @return {@code true} if and only if the future was completed within
* the specified time limit
*/
boolean awaitUninterruptibly(long timeoutMillis);
/**
* Returns the {@link Iterator} that enumerates all {@link ChannelFuture}s
* which are associated with this future. Please note that the returned
* {@link Iterator} is is unmodifiable, which means a {@link ChannelFuture}
* cannot be removed from this future.
*/
Iterator iterator();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/ChannelGroupFutureListener.java 0000664 0000000 0000000 00000002564 12255541277 0033503 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.group;
import java.util.EventListener;
/**
* Listens to the result of a {@link ChannelGroupFuture}. The result of the
* asynchronous {@link ChannelGroup} I/O operations is notified once this
* listener is added by calling {@link ChannelGroupFuture#addListener(ChannelGroupFutureListener)}
* and all I/O operations are complete.
*/
public interface ChannelGroupFutureListener extends EventListener {
/**
* Invoked when all I/O operations associated with the
* {@link ChannelGroupFuture} have been completed.
*
* @param future The source {@link ChannelGroupFuture} which called this
* callback.
*/
void operationComplete(ChannelGroupFuture future) throws Exception;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/CombinedIterator.java 0000664 0000000 0000000 00000003660 12255541277 0031445 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.group;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
*/
final class CombinedIterator implements Iterator {
private final Iterator i1;
private final Iterator i2;
private Iterator currentIterator;
CombinedIterator(Iterator i1, Iterator i2) {
if (i1 == null) {
throw new NullPointerException("i1");
}
if (i2 == null) {
throw new NullPointerException("i2");
}
this.i1 = i1;
this.i2 = i2;
currentIterator = i1;
}
public boolean hasNext() {
for (;;) {
if (currentIterator.hasNext()) {
return true;
}
if (currentIterator == i1) {
currentIterator = i2;
} else {
return false;
}
}
}
public E next() {
for (;;) {
try {
E e = currentIterator.next();
return e;
} catch (NoSuchElementException e) {
if (currentIterator == i1) {
currentIterator = i2;
} else {
throw e;
}
}
}
}
public void remove() {
currentIterator.remove();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/DefaultChannelGroup.java 0000664 0000000 0000000 00000023073 12255541277 0032105 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.group;
import java.net.SocketAddress;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ServerChannel;
import org.jboss.netty.util.internal.ConcurrentHashMap;
/**
* The default {@link ChannelGroup} implementation.
* @apiviz.landmark
*/
public class DefaultChannelGroup extends AbstractSet implements ChannelGroup {
private static final AtomicInteger nextId = new AtomicInteger();
private final String name;
private final ConcurrentMap serverChannels = new ConcurrentHashMap();
private final ConcurrentMap nonServerChannels = new ConcurrentHashMap();
private final ChannelFutureListener remover = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
remove(future.getChannel());
}
};
/**
* Creates a new group with a generated name.
*/
public DefaultChannelGroup() {
this("group-0x" + Integer.toHexString(nextId.incrementAndGet()));
}
/**
* Creates a new group with the specified {@code name}. Please note that
* different groups can have the same name, which means no duplicate check
* is done against group names.
*/
public DefaultChannelGroup(String name) {
if (name == null) {
throw new NullPointerException("name");
}
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean isEmpty() {
return nonServerChannels.isEmpty() && serverChannels.isEmpty();
}
@Override
public int size() {
return nonServerChannels.size() + serverChannels.size();
}
public Channel find(Integer id) {
Channel c = nonServerChannels.get(id);
if (c != null) {
return c;
} else {
return serverChannels.get(id);
}
}
@Override
public boolean contains(Object o) {
if (o instanceof Integer) {
return nonServerChannels.containsKey(o) || serverChannels.containsKey(o);
} else if (o instanceof Channel) {
Channel c = (Channel) o;
if (o instanceof ServerChannel) {
return serverChannels.containsKey(c.getId());
} else {
return nonServerChannels.containsKey(c.getId());
}
} else {
return false;
}
}
@Override
public boolean add(Channel channel) {
ConcurrentMap map =
channel instanceof ServerChannel? serverChannels : nonServerChannels;
boolean added = map.putIfAbsent(channel.getId(), channel) == null;
if (added) {
channel.getCloseFuture().addListener(remover);
}
return added;
}
@Override
public boolean remove(Object o) {
Channel c = null;
if (o instanceof Integer) {
c = nonServerChannels.remove(o);
if (c == null) {
c = serverChannels.remove(o);
}
} else if (o instanceof Channel) {
c = (Channel) o;
if (c instanceof ServerChannel) {
c = serverChannels.remove(c.getId());
} else {
c = nonServerChannels.remove(c.getId());
}
}
if (c == null) {
return false;
}
c.getCloseFuture().removeListener(remover);
return true;
}
@Override
public void clear() {
nonServerChannels.clear();
serverChannels.clear();
}
@Override
public Iterator iterator() {
return new CombinedIterator(
serverChannels.values().iterator(),
nonServerChannels.values().iterator());
}
@Override
public Object[] toArray() {
Collection channels = new ArrayList(size());
channels.addAll(serverChannels.values());
channels.addAll(nonServerChannels.values());
return channels.toArray();
}
@Override
public T[] toArray(T[] a) {
Collection channels = new ArrayList(size());
channels.addAll(serverChannels.values());
channels.addAll(nonServerChannels.values());
return channels.toArray(a);
}
public ChannelGroupFuture close() {
Map futures =
new LinkedHashMap(size());
for (Channel c: serverChannels.values()) {
futures.put(c.getId(), c.close().awaitUninterruptibly());
}
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.close());
}
return new DefaultChannelGroupFuture(this, futures);
}
public ChannelGroupFuture disconnect() {
Map futures =
new LinkedHashMap(size());
for (Channel c: serverChannels.values()) {
futures.put(c.getId(), c.disconnect().awaitUninterruptibly());
}
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.disconnect());
}
return new DefaultChannelGroupFuture(this, futures);
}
public ChannelGroupFuture setInterestOps(int interestOps) {
Map futures =
new LinkedHashMap(size());
for (Channel c: serverChannels.values()) {
futures.put(c.getId(), c.setInterestOps(interestOps).awaitUninterruptibly());
}
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.setInterestOps(interestOps));
}
return new DefaultChannelGroupFuture(this, futures);
}
public ChannelGroupFuture setReadable(boolean readable) {
Map futures =
new LinkedHashMap(size());
for (Channel c: serverChannels.values()) {
futures.put(c.getId(), c.setReadable(readable).awaitUninterruptibly());
}
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.setReadable(readable));
}
return new DefaultChannelGroupFuture(this, futures);
}
public ChannelGroupFuture unbind() {
Map futures =
new LinkedHashMap(size());
for (Channel c: serverChannels.values()) {
futures.put(c.getId(), c.unbind().awaitUninterruptibly());
}
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.unbind());
}
return new DefaultChannelGroupFuture(this, futures);
}
public ChannelGroupFuture write(Object message) {
Map futures =
new LinkedHashMap(size());
if (message instanceof ChannelBuffer) {
ChannelBuffer buf = (ChannelBuffer) message;
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.write(buf.duplicate()));
}
} else {
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.write(message));
}
}
return new DefaultChannelGroupFuture(this, futures);
}
public ChannelGroupFuture write(Object message, SocketAddress remoteAddress) {
Map futures =
new LinkedHashMap(size());
if (message instanceof ChannelBuffer) {
ChannelBuffer buf = (ChannelBuffer) message;
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.write(buf.duplicate(), remoteAddress));
}
} else {
for (Channel c: nonServerChannels.values()) {
futures.put(c.getId(), c.write(message, remoteAddress));
}
}
return new DefaultChannelGroupFuture(this, futures);
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public boolean equals(Object o) {
return this == o;
}
public int compareTo(ChannelGroup o) {
int v = getName().compareTo(o.getName());
if (v != 0) {
return v;
}
return System.identityHashCode(this) - System.identityHashCode(o);
}
@Override
public String toString() {
return getClass().getSimpleName() +
"(name: " + getName() + ", size: " + size() + ')';
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/DefaultChannelGroupFuture.java 0000664 0000000 0000000 00000026227 12255541277 0033304 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.group;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.DeadLockProofWorker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.*;
/**
* The default {@link ChannelGroupFuture} implementation.
*/
public class DefaultChannelGroupFuture implements ChannelGroupFuture {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(DefaultChannelGroupFuture.class);
private final ChannelGroup group;
final Map futures;
private ChannelGroupFutureListener firstListener;
private List otherListeners;
private boolean done;
int successCount;
int failureCount;
private int waiters;
private final ChannelFutureListener childListener = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
boolean success = future.isSuccess();
boolean callSetDone;
synchronized (DefaultChannelGroupFuture.this) {
if (success) {
successCount ++;
} else {
failureCount ++;
}
callSetDone = successCount + failureCount == futures.size();
assert successCount + failureCount <= futures.size();
}
if (callSetDone) {
setDone();
}
}
};
/**
* Creates a new instance.
*/
public DefaultChannelGroupFuture(ChannelGroup group, Collection futures) {
if (group == null) {
throw new NullPointerException("group");
}
if (futures == null) {
throw new NullPointerException("futures");
}
this.group = group;
Map futureMap = new LinkedHashMap();
for (ChannelFuture f: futures) {
futureMap.put(f.getChannel().getId(), f);
}
this.futures = Collections.unmodifiableMap(futureMap);
for (ChannelFuture f: this.futures.values()) {
f.addListener(childListener);
}
// Done on arrival?
if (this.futures.isEmpty()) {
setDone();
}
}
DefaultChannelGroupFuture(ChannelGroup group, Map futures) {
this.group = group;
this.futures = Collections.unmodifiableMap(futures);
for (ChannelFuture f: this.futures.values()) {
f.addListener(childListener);
}
// Done on arrival?
if (this.futures.isEmpty()) {
setDone();
}
}
public ChannelGroup getGroup() {
return group;
}
public ChannelFuture find(Integer channelId) {
return futures.get(channelId);
}
public ChannelFuture find(Channel channel) {
return futures.get(channel.getId());
}
public Iterator iterator() {
return futures.values().iterator();
}
public synchronized boolean isDone() {
return done;
}
public synchronized boolean isCompleteSuccess() {
return successCount == futures.size();
}
public synchronized boolean isPartialSuccess() {
return successCount != 0 && successCount != futures.size();
}
public synchronized boolean isPartialFailure() {
return failureCount != 0 && failureCount != futures.size();
}
public synchronized boolean isCompleteFailure() {
int futureCnt = futures.size();
return futureCnt != 0 && failureCount == futureCnt;
}
public void addListener(ChannelGroupFutureListener listener) {
if (listener == null) {
throw new NullPointerException("listener");
}
boolean notifyNow = false;
synchronized (this) {
if (done) {
notifyNow = true;
} else {
if (firstListener == null) {
firstListener = listener;
} else {
if (otherListeners == null) {
otherListeners = new ArrayList(1);
}
otherListeners.add(listener);
}
}
}
if (notifyNow) {
notifyListener(listener);
}
}
public void removeListener(ChannelGroupFutureListener listener) {
if (listener == null) {
throw new NullPointerException("listener");
}
synchronized (this) {
if (!done) {
if (listener == firstListener) {
if (otherListeners != null && !otherListeners.isEmpty()) {
firstListener = otherListeners.remove(0);
} else {
firstListener = null;
}
} else if (otherListeners != null) {
otherListeners.remove(listener);
}
}
}
}
public ChannelGroupFuture await() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
synchronized (this) {
while (!done) {
checkDeadLock();
waiters++;
try {
wait();
} finally {
waiters--;
}
}
}
return this;
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return await0(unit.toNanos(timeout), true);
}
public boolean await(long timeoutMillis) throws InterruptedException {
return await0(MILLISECONDS.toNanos(timeoutMillis), true);
}
public ChannelGroupFuture awaitUninterruptibly() {
boolean interrupted = false;
synchronized (this) {
while (!done) {
checkDeadLock();
waiters++;
try {
wait();
} catch (InterruptedException e) {
interrupted = true;
} finally {
waiters--;
}
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
return this;
}
public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
try {
return await0(unit.toNanos(timeout), false);
} catch (InterruptedException e) {
throw new InternalError();
}
}
public boolean awaitUninterruptibly(long timeoutMillis) {
try {
return await0(MILLISECONDS.toNanos(timeoutMillis), false);
} catch (InterruptedException e) {
throw new InternalError();
}
}
private boolean await0(long timeoutNanos, boolean interruptable) throws InterruptedException {
if (interruptable && Thread.interrupted()) {
throw new InterruptedException();
}
long startTime = timeoutNanos <= 0 ? 0 : System.nanoTime();
long waitTime = timeoutNanos;
boolean interrupted = false;
try {
synchronized (this) {
if (done || waitTime <= 0) {
return done;
}
checkDeadLock();
waiters++;
try {
for (;;) {
try {
wait(waitTime / 1000000, (int) (waitTime % 1000000));
} catch (InterruptedException e) {
if (interruptable) {
throw e;
} else {
interrupted = true;
}
}
if (done) {
return true;
} else {
waitTime = timeoutNanos - (System.nanoTime() - startTime);
if (waitTime <= 0) {
return done;
}
}
}
} finally {
waiters--;
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
private static void checkDeadLock() {
if (DeadLockProofWorker.PARENT.get() != null) {
throw new IllegalStateException(
"await*() in I/O thread causes a dead lock or " +
"sudden performance drop. Use addListener() instead or " +
"call await*() from a different thread.");
}
}
boolean setDone() {
synchronized (this) {
// Allow only once.
if (done) {
return false;
}
done = true;
if (waiters > 0) {
notifyAll();
}
}
notifyListeners();
return true;
}
private void notifyListeners() {
// This method doesn't need synchronization because:
// 1) This method is always called after synchronized (this) block.
// Hence any listener list modification happens-before this method.
// 2) This method is called only when 'done' is true. Once 'done'
// becomes true, the listener list is never modified - see add/removeListener()
if (firstListener != null) {
notifyListener(firstListener);
firstListener = null;
if (otherListeners != null) {
for (ChannelGroupFutureListener l: otherListeners) {
notifyListener(l);
}
otherListeners = null;
}
}
}
private void notifyListener(ChannelGroupFutureListener l) {
try {
l.operationComplete(this);
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn(
"An exception was thrown by " +
ChannelFutureListener.class.getSimpleName() + '.', t);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/group/package-info.java 0000664 0000000 0000000 00000001613 12255541277 0030533 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* A channel registry which helps a user maintain the list of open
* {@link org.jboss.netty.channel.Channel}s and perform bulk operations on them.
*
* @apiviz.exclude ^java
* @apiviz.exclude \.DefaultChannelGroupFuture$
*/
package org.jboss.netty.channel.group;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/ 0000775 0000000 0000000 00000000000 12255541277 0025301 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/DefaultLocalChannel.java 0000664 0000000 0000000 00000015242 12255541277 0032000 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import static org.jboss.netty.channel.Channels.*;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.NotYetConnectedException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.netty.channel.AbstractChannel;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.DefaultChannelConfig;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.util.internal.ThreadLocalBoolean;
/**
*/
final class DefaultLocalChannel extends AbstractChannel implements LocalChannel {
// TODO Move the state management up to AbstractChannel to remove duplication.
private static final int ST_OPEN = 0;
private static final int ST_BOUND = 1;
private static final int ST_CONNECTED = 2;
private static final int ST_CLOSED = -1;
final AtomicInteger state = new AtomicInteger(ST_OPEN);
private final ChannelConfig config;
private final ThreadLocalBoolean delivering = new ThreadLocalBoolean();
final Queue writeBuffer = new ConcurrentLinkedQueue();
volatile DefaultLocalChannel pairedChannel;
volatile LocalAddress localAddress;
volatile LocalAddress remoteAddress;
DefaultLocalChannel(
LocalServerChannel parent, ChannelFactory factory, ChannelPipeline pipeline,
ChannelSink sink, DefaultLocalChannel pairedChannel) {
super(parent, factory, pipeline, sink);
this.pairedChannel = pairedChannel;
config = new DefaultChannelConfig();
// TODO Move the state variable to AbstractChannel so that we don't need
// to add many listeners.
getCloseFuture().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
state.set(ST_CLOSED);
}
});
fireChannelOpen(this);
}
public ChannelConfig getConfig() {
return config;
}
@Override
public boolean isOpen() {
return state.get() >= ST_OPEN;
}
public boolean isBound() {
return state.get() >= ST_BOUND;
}
public boolean isConnected() {
return state.get() == ST_CONNECTED;
}
void setBound() throws ClosedChannelException {
if (!state.compareAndSet(ST_OPEN, ST_BOUND)) {
switch (state.get()) {
case ST_CLOSED:
throw new ClosedChannelException();
default:
throw new ChannelException("already bound");
}
}
}
void setConnected() {
if (state.get() != ST_CLOSED) {
state.set(ST_CONNECTED);
}
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
public LocalAddress getLocalAddress() {
return localAddress;
}
public LocalAddress getRemoteAddress() {
return remoteAddress;
}
void closeNow(ChannelFuture future) {
LocalAddress localAddress = this.localAddress;
try {
// Close the self.
if (!setClosed()) {
return;
}
DefaultLocalChannel pairedChannel = this.pairedChannel;
if (pairedChannel != null) {
this.pairedChannel = null;
fireChannelDisconnected(this);
fireChannelUnbound(this);
}
fireChannelClosed(this);
// Close the peer.
if (pairedChannel == null || !pairedChannel.setClosed()) {
return;
}
DefaultLocalChannel me = pairedChannel.pairedChannel;
if (me != null) {
pairedChannel.pairedChannel = null;
fireChannelDisconnected(pairedChannel);
fireChannelUnbound(pairedChannel);
}
fireChannelClosed(pairedChannel);
} finally {
future.setSuccess();
if (localAddress != null && getParent() == null) {
LocalChannelRegistry.unregister(localAddress);
}
}
}
void flushWriteBuffer() {
DefaultLocalChannel pairedChannel = this.pairedChannel;
if (pairedChannel != null) {
if (pairedChannel.isConnected()) {
// Channel is open and connected and channelConnected event has
// been fired.
if (!delivering.get()) {
delivering.set(true);
try {
for (;;) {
MessageEvent e = writeBuffer.poll();
if (e == null) {
break;
}
fireMessageReceived(pairedChannel, e.getMessage());
e.getFuture().setSuccess();
fireWriteComplete(this, 1);
}
} finally {
delivering.set(false);
}
}
} else {
// Channel is open and connected but channelConnected event has
// not been fired yet.
}
} else {
// Channel is closed or not connected yet - notify as failures.
Exception cause;
if (isOpen()) {
cause = new NotYetConnectedException();
} else {
cause = new ClosedChannelException();
}
for (;;) {
MessageEvent e = writeBuffer.poll();
if (e == null) {
break;
}
e.getFuture().setFailure(cause);
fireExceptionCaught(this, cause);
}
}
}
}
DefaultLocalClientChannelFactory.java 0000664 0000000 0000000 00000003005 12255541277 0034402 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
/**
* The default {@link LocalClientChannelFactory} implementation.
* @apiviz.landmark
*/
public class DefaultLocalClientChannelFactory implements LocalClientChannelFactory {
private final ChannelSink sink;
/**
* Creates a new instance.
*/
public DefaultLocalClientChannelFactory() {
sink = new LocalClientChannelSink();
}
public LocalChannel newChannel(ChannelPipeline pipeline) {
return new DefaultLocalChannel(null, this, pipeline, sink, null);
}
/**
* Does nothing because this implementation does not require any external
* resources.
*/
public void releaseExternalResources() {
// No external resources.
}
public void shutdown() {
// nothing to shutdown
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/DefaultLocalServerChannel.java 0000664 0000000 0000000 00000003731 12255541277 0033167 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import static org.jboss.netty.channel.Channels.*;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jboss.netty.channel.AbstractServerChannel;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.DefaultServerChannelConfig;
/**
*/
final class DefaultLocalServerChannel extends AbstractServerChannel
implements LocalServerChannel {
final ChannelConfig channelConfig;
final AtomicBoolean bound = new AtomicBoolean();
volatile LocalAddress localAddress;
DefaultLocalServerChannel(ChannelFactory factory, ChannelPipeline pipeline, ChannelSink sink) {
super(factory, pipeline, sink);
channelConfig = new DefaultServerChannelConfig();
fireChannelOpen(this);
}
public ChannelConfig getConfig() {
return channelConfig;
}
public boolean isBound() {
return isOpen() && bound.get();
}
public LocalAddress getLocalAddress() {
return isBound()? localAddress : null;
}
public LocalAddress getRemoteAddress() {
return null;
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
}
DefaultLocalServerChannelFactory.java 0000664 0000000 0000000 00000003246 12255541277 0034441 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.group.DefaultChannelGroup;
/**
* The default {@link LocalServerChannelFactory} implementation.
* @apiviz.landmark
*/
public class DefaultLocalServerChannelFactory implements LocalServerChannelFactory {
private final DefaultChannelGroup group = new DefaultChannelGroup();
private final ChannelSink sink = new LocalServerChannelSink();
public LocalServerChannel newChannel(ChannelPipeline pipeline) {
LocalServerChannel channel = new DefaultLocalServerChannel(this, pipeline, sink);
group.add(channel);
return channel;
}
/**
* Release all the previous created channels.
* This takes care of calling {@link LocalChannelRegistry#unregister(LocalAddress)} for each of them.
*/
public void releaseExternalResources() {
group.close().awaitUninterruptibly();
}
public void shutdown() {
// nothing to shutdown
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalAddress.java 0000664 0000000 0000000 00000007505 12255541277 0030513 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import java.net.SocketAddress;
/**
* An endpoint in the local transport. Each endpoint is identified by a unique
* case-insensitive string, except for the pre-defined value called
* {@code "ephemeral"}.
*
* Ephemeral Address
*
* An ephemeral address is an anonymous address which is assigned temporarily
* and is released as soon as the connection is closed. All ephemeral addresses
* have the same ID, {@code "ephemeral"}, but they are not equal to each other.
* @apiviz.landmark
*/
public final class LocalAddress extends SocketAddress implements Comparable {
private static final long serialVersionUID = -3601961747680808645L;
public static final String EPHEMERAL = "ephemeral";
private final String id;
private final boolean ephemeral;
/**
* Creates a new instance with the specified ID.
*/
public LocalAddress(int id) {
this(String.valueOf(id));
}
/**
* Creates a new instance with the specified ID.
*/
public LocalAddress(String id) {
if (id == null) {
throw new NullPointerException("id");
}
id = id.trim().toLowerCase();
if (id.length() == 0) {
throw new IllegalArgumentException("empty id");
}
this.id = id;
ephemeral = "ephemeral".equals(id);
}
/**
* Returns the ID of this address.
*/
public String getId() {
return id;
}
/**
* Returns {@code true} if and only if this address is ephemeral.
*/
public boolean isEphemeral() {
return ephemeral;
}
@Override
public int hashCode() {
if (ephemeral) {
return System.identityHashCode(this);
} else {
return id.hashCode();
}
}
@Override
public boolean equals(Object o) {
if (!(o instanceof LocalAddress)) {
return false;
}
if (ephemeral) {
return this == o;
} else {
return getId().equals(((LocalAddress) o).getId());
}
}
// FIXME: This comparison is broken! Assign distinct port numbers for
// ephemeral ports, just like O/S does for port number 0. It will
// break backward compatibility though.
public int compareTo(LocalAddress o) {
if (ephemeral) {
if (o.ephemeral) {
if (this == o) {
return 0;
}
int a = System.identityHashCode(this);
int b = System.identityHashCode(o);
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
throw new Error(
"Two different ephemeral addresses have " +
"same identityHashCode.");
}
} else {
return 1;
}
} else {
if (o.ephemeral) {
return -1;
} else {
return getId().compareTo(o.getId());
}
}
}
@Override
public String toString() {
return "local:" + getId();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalChannel.java 0000664 0000000 0000000 00000001575 12255541277 0030477 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.Channel;
/**
* A {@link Channel} for the local transport.
*/
public interface LocalChannel extends Channel {
LocalAddress getLocalAddress();
LocalAddress getRemoteAddress();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalChannelRegistry.java 0000664 0000000 0000000 00000002715 12255541277 0032225 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import java.util.concurrent.ConcurrentMap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.util.internal.ConcurrentHashMap;
/**
*/
final class LocalChannelRegistry {
private static final ConcurrentMap map =
new ConcurrentHashMap();
static boolean isRegistered(LocalAddress address) {
return map.containsKey(address);
}
static Channel getChannel(LocalAddress address) {
return map.get(address);
}
static boolean register(LocalAddress address, Channel channel) {
return map.putIfAbsent(address, channel) == null;
}
static boolean unregister(LocalAddress address) {
return map.remove(address) != null;
}
private LocalChannelRegistry() {
// Unused
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalClientChannelFactory.java 0000664 0000000 0000000 00000001725 12255541277 0033163 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
/**
* A {@link ChannelFactory} that creates a client-side {@link LocalChannel}.
*/
public interface LocalClientChannelFactory extends ChannelFactory {
LocalChannel newChannel(ChannelPipeline pipeline);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalClientChannelSink.java 0000664 0000000 0000000 00000013426 12255541277 0032461 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.AbstractChannelSink;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.io.IOException;
import java.net.ConnectException;
import static org.jboss.netty.channel.Channels.*;
/**
*/
final class LocalClientChannelSink extends AbstractChannelSink {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(LocalClientChannelSink.class);
public void eventSunk(ChannelPipeline pipeline, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
ChannelStateEvent event = (ChannelStateEvent) e;
DefaultLocalChannel channel =
(DefaultLocalChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.closeNow(future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (LocalAddress) value);
} else {
channel.closeNow(future);
}
break;
case CONNECTED:
if (value != null) {
connect(channel, future, (LocalAddress) value);
} else {
channel.closeNow(future);
}
break;
case INTEREST_OPS:
// Unsupported - discard silently.
future.setSuccess();
break;
}
} else if (e instanceof MessageEvent) {
MessageEvent event = (MessageEvent) e;
DefaultLocalChannel channel = (DefaultLocalChannel) event.getChannel();
boolean offered = channel.writeBuffer.offer(event);
assert offered;
channel.flushWriteBuffer();
}
}
private static void bind(DefaultLocalChannel channel, ChannelFuture future, LocalAddress localAddress) {
try {
if (!LocalChannelRegistry.register(localAddress, channel)) {
throw new ChannelException("address already in use: " + localAddress);
}
channel.setBound();
channel.localAddress = localAddress;
future.setSuccess();
fireChannelBound(channel, localAddress);
} catch (Throwable t) {
LocalChannelRegistry.unregister(localAddress);
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
private void connect(DefaultLocalChannel channel, ChannelFuture future, LocalAddress remoteAddress) {
Channel remoteChannel = LocalChannelRegistry.getChannel(remoteAddress);
if (!(remoteChannel instanceof DefaultLocalServerChannel)) {
future.setFailure(new ConnectException(
"connection refused: " + remoteAddress));
return;
}
DefaultLocalServerChannel serverChannel = (DefaultLocalServerChannel) remoteChannel;
ChannelPipeline pipeline;
try {
pipeline = serverChannel.getConfig().getPipelineFactory().getPipeline();
} catch (Exception e) {
future.setFailure(e);
fireExceptionCaught(channel, e);
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to initialize an accepted socket.", e);
}
return;
}
future.setSuccess();
DefaultLocalChannel acceptedChannel = new DefaultLocalChannel(
serverChannel, serverChannel.getFactory(), pipeline, this, channel);
channel.pairedChannel = acceptedChannel;
// check if the channel was bound before. See #276
if (!channel.isBound()) {
bind(channel, succeededFuture(channel), new LocalAddress(LocalAddress.EPHEMERAL));
}
channel.remoteAddress = serverChannel.getLocalAddress();
channel.setConnected();
fireChannelConnected(channel, serverChannel.getLocalAddress());
acceptedChannel.localAddress = serverChannel.getLocalAddress();
try {
acceptedChannel.setBound();
} catch (IOException e) {
throw new Error(e);
}
fireChannelBound(acceptedChannel, channel.getRemoteAddress());
acceptedChannel.remoteAddress = channel.getLocalAddress();
acceptedChannel.setConnected();
fireChannelConnected(acceptedChannel, channel.getLocalAddress());
// Flush something that was written in channelBound / channelConnected
channel.flushWriteBuffer();
acceptedChannel.flushWriteBuffer();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalServerChannel.java 0000664 0000000 0000000 00000001625 12255541277 0031662 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.ServerChannel;
/**
* A {@link ServerChannel} for the local transport.
*/
public interface LocalServerChannel extends ServerChannel {
LocalAddress getLocalAddress();
LocalAddress getRemoteAddress();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalServerChannelFactory.java 0000664 0000000 0000000 00000001747 12255541277 0033217 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ServerChannelFactory;
/**
* A {@link ServerChannelFactory} that creates a {@link LocalServerChannel}.
*/
public interface LocalServerChannelFactory extends ServerChannelFactory {
LocalServerChannel newChannel(ChannelPipeline pipeline);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/LocalServerChannelSink.java 0000664 0000000 0000000 00000012031 12255541277 0032500 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.local;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.AbstractChannelSink;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
final class LocalServerChannelSink extends AbstractChannelSink {
public void eventSunk(ChannelPipeline pipeline, ChannelEvent e) throws Exception {
Channel channel = e.getChannel();
if (channel instanceof DefaultLocalServerChannel) {
handleServerChannel(e);
} else if (channel instanceof DefaultLocalChannel) {
handleAcceptedChannel(e);
}
}
private static void handleServerChannel(ChannelEvent e) {
if (!(e instanceof ChannelStateEvent)) {
return;
}
ChannelStateEvent event = (ChannelStateEvent) e;
DefaultLocalServerChannel channel =
(DefaultLocalServerChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
close(channel, future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (LocalAddress) value);
} else {
close(channel, future);
}
break;
}
}
private static void handleAcceptedChannel(ChannelEvent e) {
if (e instanceof ChannelStateEvent) {
ChannelStateEvent event = (ChannelStateEvent) e;
DefaultLocalChannel channel = (DefaultLocalChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.closeNow(future);
}
break;
case BOUND:
case CONNECTED:
if (value == null) {
channel.closeNow(future);
}
break;
case INTEREST_OPS:
// Unsupported - discard silently.
future.setSuccess();
break;
}
} else if (e instanceof MessageEvent) {
MessageEvent event = (MessageEvent) e;
DefaultLocalChannel channel = (DefaultLocalChannel) event.getChannel();
boolean offered = channel.writeBuffer.offer(event);
assert offered;
channel.flushWriteBuffer();
}
}
private static void bind(DefaultLocalServerChannel channel, ChannelFuture future, LocalAddress localAddress) {
try {
if (!LocalChannelRegistry.register(localAddress, channel)) {
throw new ChannelException("address already in use: " + localAddress);
}
if (!channel.bound.compareAndSet(false, true)) {
throw new ChannelException("already bound");
}
channel.localAddress = localAddress;
future.setSuccess();
fireChannelBound(channel, localAddress);
} catch (Throwable t) {
LocalChannelRegistry.unregister(localAddress);
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
private static void close(DefaultLocalServerChannel channel, ChannelFuture future) {
try {
if (channel.setClosed()) {
future.setSuccess();
LocalAddress localAddress = channel.localAddress;
if (channel.bound.compareAndSet(true, false)) {
channel.localAddress = null;
LocalChannelRegistry.unregister(localAddress);
fireChannelUnbound(channel);
}
fireChannelClosed(channel);
} else {
future.setSuccess();
}
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/local/package-info.java 0000664 0000000 0000000 00000001531 12255541277 0030470 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* A virtual transport that enables the communication between the two
* parties in the same virtual machine.
*
* @apiviz.exclude ^java\.lang\.
* @apiviz.exclude Channel$
*/
package org.jboss.netty.channel.local;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/package-info.java 0000664 0000000 0000000 00000002634 12255541277 0027403 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* The core channel API which is asynchronous and event-driven abstraction of
* various transports such as a
* NIO Channel .
*
* @apiviz.landmark
* @apiviz.exclude ^java
* @apiviz.exclude ^org\.jboss\.netty\.channel\.[^\.]+\.
* @apiviz.exclude ^org\.jboss\.netty\.(bootstrap|handler|util)\.
* @apiviz.exclude \.(Abstract|Default|Static).*$
* @apiviz.exclude \.(Downstream|Upstream).*Event$
* @apiviz.exclude \.[A-Za-z]+ChannelFuture$
* @apiviz.exclude \.ChannelPipelineFactory$
* @apiviz.exclude \.ChannelHandlerContext$
* @apiviz.exclude \.ChannelSink$
* @apiviz.exclude \.ChannelLocal$
* @apiviz.exclude \.[^\.]+ReceiveBufferSizePredictor(Factory)?$
* @apiviz.exclude \.FileRegion$
*/
package org.jboss.netty.channel;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/ 0000775 0000000 0000000 00000000000 12255541277 0025477 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/ChannelRunnableWrapper.java 0000664 0000000 0000000 00000003000 12255541277 0032733 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.DefaultChannelFuture;
public class ChannelRunnableWrapper extends DefaultChannelFuture implements Runnable {
private final Runnable task;
private boolean started;
public ChannelRunnableWrapper(Channel channel, Runnable task) {
super(channel, true);
this.task = task;
}
public void run() {
synchronized (this) {
if (!isCancelled()) {
started = true;
} else {
return;
}
}
try {
task.run();
setSuccess();
} catch (Throwable t) {
setFailure(t);
}
}
@Override
public synchronized boolean cancel() {
if (started) {
return false;
}
return super.cancel();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/ClientSocketChannelFactory.java0000664 0000000 0000000 00000002054 12255541277 0033553 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
/**
* A {@link ChannelFactory} which creates a client-side {@link SocketChannel}.
*
* @apiviz.has org.jboss.netty.channel.socket.SocketChannel oneway - - creates
*/
public interface ClientSocketChannelFactory extends ChannelFactory {
SocketChannel newChannel(ChannelPipeline pipeline);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/DatagramChannel.java 0000664 0000000 0000000 00000003423 12255541277 0031355 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
/**
* A UDP/IP {@link Channel} which is created by {@link DatagramChannelFactory}.
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.socket.DatagramChannelConfig
*/
public interface DatagramChannel extends Channel {
DatagramChannelConfig getConfig();
InetSocketAddress getLocalAddress();
InetSocketAddress getRemoteAddress();
/**
* Joins a multicast group.
*/
ChannelFuture joinGroup(InetAddress multicastAddress);
/**
* Joins the specified multicast group at the specified interface.
*/
ChannelFuture joinGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface);
/**
* Leaves a multicast group.
*/
ChannelFuture leaveGroup(InetAddress multicastAddress);
/**
* Leaves a multicast group on a specified local interface.
*/
ChannelFuture leaveGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/DatagramChannelConfig.java 0000664 0000000 0000000 00000015226 12255541277 0032507 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.StandardSocketOptions;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictor;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import org.jboss.netty.channel.ReceiveBufferSizePredictorFactory;
/**
* A {@link ChannelConfig} for a {@link DatagramChannel}.
*
* Available options
*
* In addition to the options provided by {@link ChannelConfig},
* {@link DatagramChannelConfig} allows the following options in the option map:
*
*
*
* Name Associated setter method
*
* {@code "broadcast"} {@link #setBroadcast(boolean)}
*
* {@code "interface"} {@link #setInterface(InetAddress)}
*
* {@code "loopbackModeDisabled"} {@link #setLoopbackModeDisabled(boolean)}
*
* {@code "networkInterface"} {@link #setNetworkInterface(NetworkInterface)}
*
* {@code "reuseAddress"} {@link #setReuseAddress(boolean)}
*
* {@code "receiveBufferSize"} {@link #setReceiveBufferSize(int)}
*
* {@code "receiveBufferSizePredictor"}
* {@link #setReceiveBufferSizePredictor(ReceiveBufferSizePredictor)}
*
* {@code "receiveBufferSizePredictorFactory"}
* {@link #setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory)}
*
* {@code "sendBufferSize"} {@link #setSendBufferSize(int)}
*
* {@code "timeToLive"} {@link #setTimeToLive(int)}
*
* {@code "trafficClass"} {@link #setTrafficClass(int)}
*
*
*/
public interface DatagramChannelConfig extends ChannelConfig {
/**
* Gets the {@link StandardSocketOptions#SO_SNDBUF} option.
*/
int getSendBufferSize();
/**
* Sets the {@link StandardSocketOptions#SO_SNDBUF} option.
*/
void setSendBufferSize(int sendBufferSize);
/**
* Gets the {@link StandardSocketOptions#SO_RCVBUF} option.
*/
int getReceiveBufferSize();
/**
* Sets the {@link StandardSocketOptions#SO_RCVBUF} option.
*/
void setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the {@link StandardSocketOptions#IP_TOS} option.
*/
int getTrafficClass();
/**
* Gets the {@link StandardSocketOptions#IP_TOS} option.
*/
void setTrafficClass(int trafficClass);
/**
* Gets the {@link StandardSocketOptions#SO_REUSEADDR} option.
*/
boolean isReuseAddress();
/**
* Sets the {@link StandardSocketOptions#SO_REUSEADDR} option.
*/
void setReuseAddress(boolean reuseAddress);
/**
* Gets the {@link StandardSocketOptions#SO_BROADCAST} option.
*/
boolean isBroadcast();
/**
* Sets the {@link StandardSocketOptions#SO_BROADCAST} option.
*/
void setBroadcast(boolean broadcast);
/**
* Gets the {@link StandardSocketOptions#IP_MULTICAST_LOOP} option.
*/
boolean isLoopbackModeDisabled();
/**
* Sets the {@link StandardSocketOptions#IP_MULTICAST_LOOP} option.
*
* @param loopbackModeDisabled
* {@code true} if and only if the loopback mode has been disabled
*/
void setLoopbackModeDisabled(boolean loopbackModeDisabled);
/**
* Gets the {@link StandardSocketOptions#IP_MULTICAST_TTL} option.
*/
int getTimeToLive();
/**
* Sets the {@link StandardSocketOptions#IP_MULTICAST_TTL} option.
*/
void setTimeToLive(int ttl);
/**
* Gets the address of the network interface used for multicast packets.
*/
InetAddress getInterface();
/**
* Sets the address of the network interface used for multicast packets.
*/
void setInterface(InetAddress interfaceAddress);
/**
* Gets the {@link StandardSocketOptions#IP_MULTICAST_IF} option.
*/
NetworkInterface getNetworkInterface();
/**
* Sets the {@link StandardSocketOptions#IP_MULTICAST_IF} option.
*/
void setNetworkInterface(NetworkInterface networkInterface);
/**
* Returns the {@link ReceiveBufferSizePredictor} which predicts the
* number of readable bytes in the socket receive buffer. The default
* predictor is {@link FixedReceiveBufferSizePredictor}(768) .
*/
ReceiveBufferSizePredictor getReceiveBufferSizePredictor();
/**
* Sets the {@link ReceiveBufferSizePredictor} which predicts the
* number of readable bytes in the socket receive buffer. The default
* predictor is {@link FixedReceiveBufferSizePredictor}(768) .
*/
void setReceiveBufferSizePredictor(ReceiveBufferSizePredictor predictor);
/**
* Returns the {@link ReceiveBufferSizePredictorFactory} which creates a new
* {@link ReceiveBufferSizePredictor} when a new channel is created and
* no {@link ReceiveBufferSizePredictor} was set. If no predictor was set
* for the channel, {@link #setReceiveBufferSizePredictor(ReceiveBufferSizePredictor)}
* will be called with the new predictor. The default factory is
* {@link FixedReceiveBufferSizePredictorFactory}(768) .
*/
ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory();
/**
* Sets the {@link ReceiveBufferSizePredictor} which creates a new
* {@link ReceiveBufferSizePredictor} when a new channel is created and
* no {@link ReceiveBufferSizePredictor} was set. If no predictor was set
* for the channel, {@link #setReceiveBufferSizePredictor(ReceiveBufferSizePredictor)}
* will be called with the new predictor. The default factory is
* {@link FixedReceiveBufferSizePredictorFactory}(768) .
*/
void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/DatagramChannelFactory.java 0000664 0000000 0000000 00000002042 12255541277 0032701 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
/**
* A {@link ChannelFactory} which creates a {@link DatagramChannel}.
*
* @apiviz.has org.jboss.netty.channel.socket.DatagramChannel oneway - - creates
*/
public interface DatagramChannelFactory extends ChannelFactory {
DatagramChannel newChannel(ChannelPipeline pipeline);
}
DefaultDatagramChannelConfig.java 0000664 0000000 0000000 00000023250 12255541277 0033731 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.DefaultChannelConfig;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import org.jboss.netty.channel.ReceiveBufferSizePredictorFactory;
import org.jboss.netty.util.internal.ConversionUtil;
/**
* The default {@link DatagramChannelConfig} implementation.
*/
public class DefaultDatagramChannelConfig extends DefaultChannelConfig
implements DatagramChannelConfig {
private static final ReceiveBufferSizePredictorFactory DEFAULT_PREDICTOR_FACTORY =
new FixedReceiveBufferSizePredictorFactory(768);
private final DatagramSocket socket;
private volatile ReceiveBufferSizePredictor predictor;
private volatile ReceiveBufferSizePredictorFactory predictorFactory = DEFAULT_PREDICTOR_FACTORY;
/**
* Creates a new instance.
*/
public DefaultDatagramChannelConfig(DatagramSocket socket) {
if (socket == null) {
throw new NullPointerException("socket");
}
this.socket = socket;
}
@Override
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("broadcast".equals(key)) {
setBroadcast(ConversionUtil.toBoolean(value));
} else if ("receiveBufferSize".equals(key)) {
setReceiveBufferSize(ConversionUtil.toInt(value));
} else if ("sendBufferSize".equals(key)) {
setSendBufferSize(ConversionUtil.toInt(value));
} else if ("receiveBufferSizePredictorFactory".equals(key)) {
setReceiveBufferSizePredictorFactory((ReceiveBufferSizePredictorFactory) value);
} else if ("receiveBufferSizePredictor".equals(key)) {
setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
} else if ("reuseAddress".equals(key)) {
setReuseAddress(ConversionUtil.toBoolean(value));
} else if ("loopbackModeDisabled".equals(key)) {
setLoopbackModeDisabled(ConversionUtil.toBoolean(value));
} else if ("interface".equals(key)) {
setInterface((InetAddress) value);
} else if ("networkInterface".equals(key)) {
setNetworkInterface((NetworkInterface) value);
} else if ("timeToLive".equals(key)) {
setTimeToLive(ConversionUtil.toInt(value));
} else if ("trafficClass".equals(key)) {
setTrafficClass(ConversionUtil.toInt(value));
} else {
return false;
}
return true;
}
public boolean isBroadcast() {
try {
return socket.getBroadcast();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setBroadcast(boolean broadcast) {
try {
socket.setBroadcast(broadcast);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public InetAddress getInterface() {
if (socket instanceof MulticastSocket) {
try {
return ((MulticastSocket) socket).getInterface();
} catch (SocketException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public void setInterface(InetAddress interfaceAddress) {
if (socket instanceof MulticastSocket) {
try {
((MulticastSocket) socket).setInterface(interfaceAddress);
} catch (SocketException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public boolean isLoopbackModeDisabled() {
if (socket instanceof MulticastSocket) {
try {
return ((MulticastSocket) socket).getLoopbackMode();
} catch (SocketException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public void setLoopbackModeDisabled(boolean loopbackModeDisabled) {
if (socket instanceof MulticastSocket) {
try {
((MulticastSocket) socket).setLoopbackMode(loopbackModeDisabled);
} catch (SocketException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public NetworkInterface getNetworkInterface() {
if (socket instanceof MulticastSocket) {
try {
return ((MulticastSocket) socket).getNetworkInterface();
} catch (SocketException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public void setNetworkInterface(NetworkInterface networkInterface) {
if (socket instanceof MulticastSocket) {
try {
((MulticastSocket) socket).setNetworkInterface(networkInterface);
} catch (SocketException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public boolean isReuseAddress() {
try {
return socket.getReuseAddress();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setReuseAddress(boolean reuseAddress) {
try {
socket.setReuseAddress(reuseAddress);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getReceiveBufferSize() {
try {
return socket.getReceiveBufferSize();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setReceiveBufferSize(int receiveBufferSize) {
try {
socket.setReceiveBufferSize(receiveBufferSize);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getSendBufferSize() {
try {
return socket.getSendBufferSize();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setSendBufferSize(int sendBufferSize) {
try {
socket.setSendBufferSize(sendBufferSize);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getTimeToLive() {
if (socket instanceof MulticastSocket) {
try {
return ((MulticastSocket) socket).getTimeToLive();
} catch (IOException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public void setTimeToLive(int ttl) {
if (socket instanceof MulticastSocket) {
try {
((MulticastSocket) socket).setTimeToLive(ttl);
} catch (IOException e) {
throw new ChannelException(e);
}
} else {
throw new UnsupportedOperationException();
}
}
public int getTrafficClass() {
try {
return socket.getTrafficClass();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setTrafficClass(int trafficClass) {
try {
socket.setTrafficClass(trafficClass);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public ReceiveBufferSizePredictor getReceiveBufferSizePredictor() {
ReceiveBufferSizePredictor predictor = this.predictor;
if (predictor == null) {
try {
this.predictor = predictor = getReceiveBufferSizePredictorFactory().getPredictor();
} catch (Exception e) {
throw new ChannelException(
"Failed to create a new " +
ReceiveBufferSizePredictor.class.getSimpleName() + '.',
e);
}
}
return predictor;
}
public void setReceiveBufferSizePredictor(
ReceiveBufferSizePredictor predictor) {
if (predictor == null) {
throw new NullPointerException("predictor");
}
this.predictor = predictor;
}
public ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory() {
return predictorFactory;
}
public void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory) {
if (predictorFactory == null) {
throw new NullPointerException("predictorFactory");
}
this.predictorFactory = predictorFactory;
}
}
DefaultServerSocketChannelConfig.java 0000664 0000000 0000000 00000006327 12255541277 0034636 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.ServerSocket;
import java.net.SocketException;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.DefaultServerChannelConfig;
import org.jboss.netty.util.internal.ConversionUtil;
/**
* The default {@link ServerSocketChannelConfig} implementation.
*/
public class DefaultServerSocketChannelConfig extends DefaultServerChannelConfig
implements ServerSocketChannelConfig {
private final ServerSocket socket;
private volatile int backlog;
/**
* Creates a new instance.
*/
public DefaultServerSocketChannelConfig(ServerSocket socket) {
if (socket == null) {
throw new NullPointerException("socket");
}
this.socket = socket;
}
@Override
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("receiveBufferSize".equals(key)) {
setReceiveBufferSize(ConversionUtil.toInt(value));
} else if ("reuseAddress".equals(key)) {
setReuseAddress(ConversionUtil.toBoolean(value));
} else if ("backlog".equals(key)) {
setBacklog(ConversionUtil.toInt(value));
} else {
return false;
}
return true;
}
public boolean isReuseAddress() {
try {
return socket.getReuseAddress();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setReuseAddress(boolean reuseAddress) {
try {
socket.setReuseAddress(reuseAddress);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getReceiveBufferSize() {
try {
return socket.getReceiveBufferSize();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setReceiveBufferSize(int receiveBufferSize) {
try {
socket.setReceiveBufferSize(receiveBufferSize);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
socket.setPerformancePreferences(connectionTime, latency, bandwidth);
}
public int getBacklog() {
return backlog;
}
public void setBacklog(int backlog) {
if (backlog < 0) {
throw new IllegalArgumentException("backlog: " + backlog);
}
this.backlog = backlog;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/DefaultSocketChannelConfig.java0000664 0000000 0000000 00000012611 12255541277 0033517 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.DefaultChannelConfig;
import org.jboss.netty.util.internal.ConversionUtil;
import java.net.Socket;
import java.net.SocketException;
/**
* The default {@link SocketChannelConfig} implementation.
*/
public class DefaultSocketChannelConfig extends DefaultChannelConfig
implements SocketChannelConfig {
private final Socket socket;
/**
* Creates a new instance.
*/
public DefaultSocketChannelConfig(Socket socket) {
if (socket == null) {
throw new NullPointerException("socket");
}
this.socket = socket;
}
@Override
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("receiveBufferSize".equals(key)) {
setReceiveBufferSize(ConversionUtil.toInt(value));
} else if ("sendBufferSize".equals(key)) {
setSendBufferSize(ConversionUtil.toInt(value));
} else if ("tcpNoDelay".equals(key)) {
setTcpNoDelay(ConversionUtil.toBoolean(value));
} else if ("keepAlive".equals(key)) {
setKeepAlive(ConversionUtil.toBoolean(value));
} else if ("reuseAddress".equals(key)) {
setReuseAddress(ConversionUtil.toBoolean(value));
} else if ("soLinger".equals(key)) {
setSoLinger(ConversionUtil.toInt(value));
} else if ("trafficClass".equals(key)) {
setTrafficClass(ConversionUtil.toInt(value));
} else {
return false;
}
return true;
}
public int getReceiveBufferSize() {
try {
return socket.getReceiveBufferSize();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getSendBufferSize() {
try {
return socket.getSendBufferSize();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getSoLinger() {
try {
return socket.getSoLinger();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public int getTrafficClass() {
try {
return socket.getTrafficClass();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public boolean isKeepAlive() {
try {
return socket.getKeepAlive();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public boolean isReuseAddress() {
try {
return socket.getReuseAddress();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public boolean isTcpNoDelay() {
try {
return socket.getTcpNoDelay();
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setKeepAlive(boolean keepAlive) {
try {
socket.setKeepAlive(keepAlive);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setPerformancePreferences(
int connectionTime, int latency, int bandwidth) {
socket.setPerformancePreferences(connectionTime, latency, bandwidth);
}
public void setReceiveBufferSize(int receiveBufferSize) {
try {
socket.setReceiveBufferSize(receiveBufferSize);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setReuseAddress(boolean reuseAddress) {
try {
socket.setReuseAddress(reuseAddress);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setSendBufferSize(int sendBufferSize) {
try {
socket.setSendBufferSize(sendBufferSize);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setSoLinger(int soLinger) {
try {
if (soLinger < 0) {
socket.setSoLinger(false, 0);
} else {
socket.setSoLinger(true, soLinger);
}
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setTcpNoDelay(boolean tcpNoDelay) {
try {
socket.setTcpNoDelay(tcpNoDelay);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
public void setTrafficClass(int trafficClass) {
try {
socket.setTrafficClass(trafficClass);
} catch (SocketException e) {
throw new ChannelException(e);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/InternetProtocolFamily.java 0000664 0000000 0000000 00000001411 12255541277 0033013 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
/**
* Internet Protocol (IP) families
*/
public enum InternetProtocolFamily {
IPv4,
IPv6
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/ServerSocketChannel.java 0000664 0000000 0000000 00000002157 12255541277 0032257 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.InetSocketAddress;
import org.jboss.netty.channel.ServerChannel;
/**
* A TCP/IP {@link ServerChannel} which accepts incoming TCP/IP connections.
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.socket.ServerSocketChannelConfig
*/
public interface ServerSocketChannel extends ServerChannel {
ServerSocketChannelConfig getConfig();
InetSocketAddress getLocalAddress();
InetSocketAddress getRemoteAddress();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/ServerSocketChannelConfig.java 0000664 0000000 0000000 00000004720 12255541277 0033403 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.ServerSocket;
import java.net.StandardSocketOptions;
import org.jboss.netty.channel.ChannelConfig;
/**
* A {@link ChannelConfig} for a {@link ServerSocketChannel}.
*
* Available options
*
* In addition to the options provided by {@link ChannelConfig},
* {@link ServerSocketChannelConfig} allows the following options in the
* option map:
*
*
*
* Name Associated setter method
*
* {@code "backlog"} {@link #setBacklog(int)}
*
* {@code "reuseAddress"} {@link #setReuseAddress(boolean)}
*
* {@code "receiveBufferSize"} {@link #setReceiveBufferSize(int)}
*
*
*/
public interface ServerSocketChannelConfig extends ChannelConfig {
/**
* Gets the backlog value to specify when the channel binds to a local
* address.
*/
int getBacklog();
/**
* Sets the backlog value to specify when the channel binds to a local
* address.
*/
void setBacklog(int backlog);
/**
* Gets the {@link StandardSocketOptions#SO_REUSEADDR} option.
*/
boolean isReuseAddress();
/**
* Sets the {@link StandardSocketOptions#SO_REUSEADDR} option.
*/
void setReuseAddress(boolean reuseAddress);
/**
* Gets the {@link StandardSocketOptions#SO_RCVBUF} option.
*/
int getReceiveBufferSize();
/**
* Sets the {@link StandardSocketOptions#SO_RCVBUF} option.
*/
void setReceiveBufferSize(int receiveBufferSize);
/**
* Sets the performance preferences as specified in
* {@link ServerSocket#setPerformancePreferences(int, int, int)}.
*/
void setPerformancePreferences(int connectionTime, int latency, int bandwidth);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/ServerSocketChannelFactory.java0000664 0000000 0000000 00000002155 12255541277 0033605 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ServerChannelFactory;
/**
* A {@link ChannelFactory} which creates a {@link ServerSocketChannel}.
*
* @apiviz.has org.jboss.netty.channel.socket.ServerSocketChannel oneway - - creates
*/
public interface ServerSocketChannelFactory extends ServerChannelFactory {
ServerSocketChannel newChannel(ChannelPipeline pipeline);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/SocketChannel.java 0000664 0000000 0000000 00000002225 12255541277 0031064 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.InetSocketAddress;
import org.jboss.netty.channel.Channel;
/**
* A TCP/IP socket {@link Channel} which was either accepted by
* {@link ServerSocketChannel} or created by {@link ClientSocketChannelFactory}.
*
* @apiviz.landmark
* @apiviz.composedOf org.jboss.netty.channel.socket.SocketChannelConfig
*/
public interface SocketChannel extends Channel {
SocketChannelConfig getConfig();
InetSocketAddress getLocalAddress();
InetSocketAddress getRemoteAddress();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/SocketChannelConfig.java 0000664 0000000 0000000 00000007222 12255541277 0032214 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
import java.net.Socket;
import java.net.StandardSocketOptions;
import org.jboss.netty.channel.ChannelConfig;
/**
* A {@link ChannelConfig} for a {@link SocketChannel}.
*
* Available options
*
* In addition to the options provided by {@link ChannelConfig},
* {@link SocketChannelConfig} allows the following options in the option map:
*
*
*
* Name Associated setter method
*
* {@code "keepAlive"} {@link #setKeepAlive(boolean)}
*
* {@code "reuseAddress"} {@link #setReuseAddress(boolean)}
*
* {@code "soLinger"} {@link #setSoLinger(int)}
*
* {@code "tcpNoDelay"} {@link #setTcpNoDelay(boolean)}
*
* {@code "receiveBufferSize"} {@link #setReceiveBufferSize(int)}
*
* {@code "sendBufferSize"} {@link #setSendBufferSize(int)}
*
* {@code "trafficClass"} {@link #setTrafficClass(int)}
*
*
*/
public interface SocketChannelConfig extends ChannelConfig {
/**
* Gets the {@link StandardSocketOptions#TCP_NODELAY} option.
*/
boolean isTcpNoDelay();
/**
* Sets the {@link StandardSocketOptions#TCP_NODELAY} option.
*/
void setTcpNoDelay(boolean tcpNoDelay);
/**
* Gets the {@link StandardSocketOptions#SO_LINGER} option.
*/
int getSoLinger();
/**
* Sets the {@link StandardSocketOptions#SO_LINGER} option.
*/
void setSoLinger(int soLinger);
/**
* Gets the {@link StandardSocketOptions#SO_SNDBUF} option.
*/
int getSendBufferSize();
/**
* Sets the {@link StandardSocketOptions#SO_SNDBUF} option.
*/
void setSendBufferSize(int sendBufferSize);
/**
* Gets the {@link StandardSocketOptions#SO_RCVBUF} option.
*/
int getReceiveBufferSize();
/**
* Sets the {@link StandardSocketOptions#SO_RCVBUF} option.
*/
void setReceiveBufferSize(int receiveBufferSize);
/**
* Gets the {@link StandardSocketOptions#SO_KEEPALIVE} option.
*/
boolean isKeepAlive();
/**
* Sets the {@link StandardSocketOptions#SO_KEEPALIVE} option.
*/
void setKeepAlive(boolean keepAlive);
/**
* Gets the {@link StandardSocketOptions#IP_TOS} option.
*/
int getTrafficClass();
/**
* Sets the {@link StandardSocketOptions#IP_TOS} option.
*/
void setTrafficClass(int trafficClass);
/**
* Gets the {@link StandardSocketOptions#SO_REUSEADDR} option.
*/
boolean isReuseAddress();
/**
* Sets the {@link StandardSocketOptions#SO_REUSEADDR} option.
*/
void setReuseAddress(boolean reuseAddress);
/**
* Sets the performance preferences as specified in
* {@link Socket#setPerformancePreferences(int, int, int)}.
*/
void setPerformancePreferences(
int connectionTime, int latency, int bandwidth);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/Worker.java 0000664 0000000 0000000 00000002046 12255541277 0027615 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket;
/**
* A {@link Worker} is responsible to dispatch IO operations
*
*/
public interface Worker extends Runnable {
/**
* Execute the given {@link Runnable} in the IO-Thread. This may be now or
* later once the IO-Thread do some other work.
*
* @param task
* the {@link Runnable} to execute
*/
void executeInIoThread(Runnable task);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http/ 0000775 0000000 0000000 00000000000 12255541277 0026456 5 ustar 00root root 0000000 0000000 HttpTunnelingClientSocketChannel.java 0000664 0000000 0000000 00000036715 12255541277 0035662 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import static org.jboss.netty.channel.Channels.*;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.NotYetConnectedException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.AbstractChannel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.DefaultChannelPipeline;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.handler.codec.http.DefaultHttpChunk;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpRequestEncoder;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.ssl.SslHandler;
/**
*/
class HttpTunnelingClientSocketChannel extends AbstractChannel
implements SocketChannel {
final HttpTunnelingSocketChannelConfig config;
volatile boolean requestHeaderWritten;
final Object interestOpsLock = new Object();
final SocketChannel realChannel;
private final ServletChannelHandler handler = new ServletChannelHandler();
HttpTunnelingClientSocketChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink, ClientSocketChannelFactory clientSocketChannelFactory) {
super(null, factory, pipeline, sink);
config = new HttpTunnelingSocketChannelConfig(this);
DefaultChannelPipeline channelPipeline = new DefaultChannelPipeline();
channelPipeline.addLast("decoder", new HttpResponseDecoder());
channelPipeline.addLast("encoder", new HttpRequestEncoder());
channelPipeline.addLast("handler", handler);
realChannel = clientSocketChannelFactory.newChannel(channelPipeline);
fireChannelOpen(this);
}
public HttpTunnelingSocketChannelConfig getConfig() {
return config;
}
public InetSocketAddress getLocalAddress() {
return realChannel.getLocalAddress();
}
public InetSocketAddress getRemoteAddress() {
return realChannel.getRemoteAddress();
}
public boolean isBound() {
return realChannel.isBound();
}
public boolean isConnected() {
return realChannel.isConnected();
}
@Override
public int getInterestOps() {
return realChannel.getInterestOps();
}
@Override
public boolean isWritable() {
return realChannel.isWritable();
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
return super.write(message, null);
} else {
return getUnsupportedOperationFuture();
}
}
void bindReal(final SocketAddress localAddress, final ChannelFuture future) {
realChannel.bind(localAddress).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
void connectReal(final SocketAddress remoteAddress, final ChannelFuture future) {
final SocketChannel virtualChannel = this;
realChannel.connect(remoteAddress).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
final String serverName = config.getServerName();
final int serverPort = ((InetSocketAddress) remoteAddress).getPort();
final String serverPath = config.getServerPath();
if (f.isSuccess()) {
// Configure SSL
SSLContext sslContext = config.getSslContext();
ChannelFuture sslHandshakeFuture = null;
if (sslContext != null) {
// Create a new SSLEngine from the specified SSLContext.
SSLEngine engine;
if (serverName != null) {
engine = sslContext.createSSLEngine(serverName, serverPort);
} else {
engine = sslContext.createSSLEngine();
}
// Configure the SSLEngine.
engine.setUseClientMode(true);
engine.setEnableSessionCreation(config.isEnableSslSessionCreation());
String[] enabledCipherSuites = config.getEnabledSslCipherSuites();
if (enabledCipherSuites != null) {
engine.setEnabledCipherSuites(enabledCipherSuites);
}
String[] enabledProtocols = config.getEnabledSslProtocols();
if (enabledProtocols != null) {
engine.setEnabledProtocols(enabledProtocols);
}
SslHandler sslHandler = new SslHandler(engine);
realChannel.getPipeline().addFirst("ssl", sslHandler);
sslHandshakeFuture = sslHandler.handshake();
}
// Send the HTTP request.
final HttpRequest req = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.POST, serverPath);
if (serverName != null) {
req.headers().set(HttpHeaders.Names.HOST, serverName);
}
req.headers().set(HttpHeaders.Names.CONTENT_TYPE, "application/octet-stream");
req.headers().set(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
req.headers().set(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING, HttpHeaders.Values.BINARY);
req.headers().set(HttpHeaders.Names.USER_AGENT, HttpTunnelingClientSocketChannel.class.getName());
if (sslHandshakeFuture == null) {
realChannel.write(req);
requestHeaderWritten = true;
future.setSuccess();
fireChannelConnected(virtualChannel, remoteAddress);
} else {
sslHandshakeFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
realChannel.write(req);
requestHeaderWritten = true;
future.setSuccess();
fireChannelConnected(virtualChannel, remoteAddress);
} else {
future.setFailure(f.getCause());
fireExceptionCaught(virtualChannel, f.getCause());
}
}
});
}
} else {
future.setFailure(f.getCause());
fireExceptionCaught(virtualChannel, f.getCause());
}
}
});
}
void writeReal(final ChannelBuffer a, final ChannelFuture future) {
if (!requestHeaderWritten) {
throw new NotYetConnectedException();
}
final int size = a.readableBytes();
final ChannelFuture f;
if (size == 0) {
f = realChannel.write(ChannelBuffers.EMPTY_BUFFER);
} else {
f = realChannel.write(new DefaultHttpChunk(a));
}
f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
if (size != 0) {
fireWriteComplete(HttpTunnelingClientSocketChannel.this, size);
}
} else {
future.setFailure(f.getCause());
}
}
});
}
private ChannelFuture writeLastChunk() {
if (!requestHeaderWritten) {
return failedFuture(this, new NotYetConnectedException());
} else {
return realChannel.write(HttpChunk.LAST_CHUNK);
}
}
void setInterestOpsReal(final int interestOps, final ChannelFuture future) {
realChannel.setInterestOps(interestOps).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
void disconnectReal(final ChannelFuture future) {
writeLastChunk().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
realChannel.disconnect().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
});
}
void unbindReal(final ChannelFuture future) {
writeLastChunk().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
realChannel.unbind().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
}
});
}
});
}
void closeReal(final ChannelFuture future) {
writeLastChunk().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
realChannel.close().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
// Note: If 'future' refers to the closeFuture,
// setSuccess() and setFailure() do nothing.
// AbstractChannel.setClosed() should be called instead.
// (See AbstractChannel.ChannelCloseFuture)
if (f.isSuccess()) {
future.setSuccess();
} else {
future.setFailure(f.getCause());
}
// Notify the closeFuture.
setClosed();
}
});
}
});
}
final class ServletChannelHandler extends SimpleChannelUpstreamHandler {
private volatile boolean readingChunks;
final SocketChannel virtualChannel = HttpTunnelingClientSocketChannel.this;
@Override
public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
fireChannelBound(virtualChannel, (SocketAddress) e.getValue());
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (!readingChunks) {
HttpResponse res = (HttpResponse) e.getMessage();
if (res.getStatus().getCode() != HttpResponseStatus.OK.getCode()) {
throw new ChannelException("Unexpected HTTP response status: " + res.getStatus());
}
if (res.isChunked()) {
readingChunks = true;
} else {
ChannelBuffer content = res.getContent();
if (content.readable()) {
fireMessageReceived(HttpTunnelingClientSocketChannel.this, content);
}
// Reached to the end of response - close the request.
closeReal(succeededFuture(virtualChannel));
}
} else {
HttpChunk chunk = (HttpChunk) e.getMessage();
if (!chunk.isLast()) {
fireMessageReceived(HttpTunnelingClientSocketChannel.this, chunk.getContent());
} else {
readingChunks = false;
// Reached to the end of response - close the request.
closeReal(succeededFuture(virtualChannel));
}
}
}
@Override
public void channelInterestChanged(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
fireChannelInterestChanged(virtualChannel);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
fireChannelDisconnected(virtualChannel);
}
@Override
public void channelUnbound(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
fireChannelUnbound(virtualChannel);
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
fireChannelClosed(virtualChannel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
fireExceptionCaught(virtualChannel, e.getCause());
realChannel.close();
}
}
}
HttpTunnelingClientSocketChannelFactory.java 0000664 0000000 0000000 00000004045 12255541277 0037201 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel;
/**
* Creates a client-side {@link SocketChannel} which connects to an
* {@link HttpTunnelingServlet} to communicate with the server application
* behind the {@link HttpTunnelingServlet}. Please refer to the
* package summary for
* the detailed usage.
* @apiviz.landmark
*/
public class HttpTunnelingClientSocketChannelFactory implements ClientSocketChannelFactory {
private final ChannelSink sink = new HttpTunnelingClientSocketPipelineSink();
private final ClientSocketChannelFactory clientSocketChannelFactory;
/**
* Creates a new instance.
*/
public HttpTunnelingClientSocketChannelFactory(ClientSocketChannelFactory clientSocketChannelFactory) {
this.clientSocketChannelFactory = clientSocketChannelFactory;
}
public SocketChannel newChannel(ChannelPipeline pipeline) {
return new HttpTunnelingClientSocketChannel(this, pipeline, sink, clientSocketChannelFactory);
}
public void releaseExternalResources() {
clientSocketChannelFactory.releaseExternalResources();
}
public void shutdown() {
clientSocketChannelFactory.shutdown();
}
}
HttpTunnelingClientSocketPipelineSink.java 0000664 0000000 0000000 00000005102 12255541277 0036666 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import java.net.SocketAddress;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.AbstractChannelSink;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
final class HttpTunnelingClientSocketPipelineSink extends AbstractChannelSink {
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
HttpTunnelingClientSocketChannel channel = (HttpTunnelingClientSocketChannel) e.getChannel();
ChannelFuture future = e.getFuture();
if (e instanceof ChannelStateEvent) {
ChannelStateEvent stateEvent = (ChannelStateEvent) e;
ChannelState state = stateEvent.getState();
Object value = stateEvent.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.closeReal(future);
}
break;
case BOUND:
if (value != null) {
channel.bindReal((SocketAddress) value, future);
} else {
channel.unbindReal(future);
}
break;
case CONNECTED:
if (value != null) {
channel.connectReal((SocketAddress) value, future);
} else {
channel.closeReal(future);
}
break;
case INTEREST_OPS:
channel.setInterestOpsReal(((Integer) value).intValue(), future);
break;
}
} else if (e instanceof MessageEvent) {
channel.writeReal((ChannelBuffer) ((MessageEvent) e).getMessage(), future);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http/HttpTunnelingServlet.java 0000664 0000000 0000000 00000021452 12255541277 0033475 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import java.io.EOFException;
import java.io.IOException;
import java.io.PushbackInputStream;
import java.net.SocketAddress;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.local.DefaultLocalClientChannelFactory;
import org.jboss.netty.channel.local.LocalAddress;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
/**
* An {@link HttpServlet} that proxies an incoming data to the actual server
* and vice versa. Please refer to the
* package summary for
* the detailed usage.
* @apiviz.landmark
*/
public class HttpTunnelingServlet extends HttpServlet {
private static final long serialVersionUID = 4259910275899756070L;
private static final String ENDPOINT = "endpoint";
static final InternalLogger logger = InternalLoggerFactory.getInstance(HttpTunnelingServlet.class);
private volatile SocketAddress remoteAddress;
private volatile ChannelFactory channelFactory;
@Override
public void init() throws ServletException {
ServletConfig config = getServletConfig();
String endpoint = config.getInitParameter(ENDPOINT);
if (endpoint == null) {
throw new ServletException("init-param '" + ENDPOINT + "' must be specified.");
}
try {
remoteAddress = parseEndpoint(endpoint.trim());
} catch (ServletException e) {
throw e;
} catch (Exception e) {
throw new ServletException("Failed to parse an endpoint.", e);
}
try {
channelFactory = createChannelFactory(remoteAddress);
} catch (ServletException e) {
throw e;
} catch (Exception e) {
throw new ServletException("Failed to create a channel factory.", e);
}
// Stuff for testing purpose
//ServerBootstrap b = new ServerBootstrap(new DefaultLocalServerChannelFactory());
//b.getPipeline().addLast("logger", new LoggingHandler(getClass(), InternalLogLevel.INFO, true));
//b.getPipeline().addLast("handler", new EchoHandler());
//b.bind(remoteAddress);
}
protected SocketAddress parseEndpoint(String endpoint) throws Exception {
if (endpoint.startsWith("local:")) {
return new LocalAddress(endpoint.substring(6).trim());
} else {
throw new ServletException(
"Invalid or unknown endpoint: " + endpoint);
}
}
protected ChannelFactory createChannelFactory(SocketAddress remoteAddress) throws Exception {
if (remoteAddress instanceof LocalAddress) {
return new DefaultLocalClientChannelFactory();
} else {
throw new ServletException(
"Unsupported remote address type: " +
remoteAddress.getClass().getName());
}
}
@Override
public void destroy() {
try {
destroyChannelFactory(channelFactory);
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to destroy a channel factory.", e);
}
}
}
protected void destroyChannelFactory(ChannelFactory factory) throws Exception {
factory.releaseExternalResources();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
if (!"POST".equalsIgnoreCase(req.getMethod())) {
if (logger.isWarnEnabled()) {
logger.warn("Unallowed method: " + req.getMethod());
}
res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
final ChannelPipeline pipeline = Channels.pipeline();
final ServletOutputStream out = res.getOutputStream();
final OutboundConnectionHandler handler = new OutboundConnectionHandler(out);
pipeline.addLast("handler", handler);
Channel channel = channelFactory.newChannel(pipeline);
ChannelFuture future = channel.connect(remoteAddress).awaitUninterruptibly();
if (!future.isSuccess()) {
if (logger.isWarnEnabled()) {
Throwable cause = future.getCause();
logger.warn("Endpoint unavailable: " + cause.getMessage(), cause);
}
res.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
ChannelFuture lastWriteFuture = null;
try {
res.setStatus(HttpServletResponse.SC_OK);
res.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/octet-stream");
res.setHeader(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING, HttpHeaders.Values.BINARY);
// Initiate chunked encoding by flushing the headers.
out.flush();
PushbackInputStream in =
new PushbackInputStream(req.getInputStream());
while (channel.isConnected()) {
ChannelBuffer buffer;
try {
buffer = read(in);
} catch (EOFException e) {
break;
}
if (buffer == null) {
break;
}
lastWriteFuture = channel.write(buffer);
}
} finally {
if (lastWriteFuture == null) {
channel.close();
} else {
lastWriteFuture.addListener(ChannelFutureListener.CLOSE);
}
}
}
private static ChannelBuffer read(PushbackInputStream in) throws IOException {
byte[] buf;
int readBytes;
int bytesToRead = in.available();
if (bytesToRead > 0) {
buf = new byte[bytesToRead];
readBytes = in.read(buf);
} else if (bytesToRead == 0) {
int b = in.read();
if (b < 0 || in.available() < 0) {
return null;
}
in.unread(b);
bytesToRead = in.available();
buf = new byte[bytesToRead];
readBytes = in.read(buf);
} else {
return null;
}
assert readBytes > 0;
ChannelBuffer buffer;
if (readBytes == buf.length) {
buffer = ChannelBuffers.wrappedBuffer(buf);
} else {
// A rare case, but it sometimes happen.
buffer = ChannelBuffers.wrappedBuffer(buf, 0, readBytes);
}
return buffer;
}
private static final class OutboundConnectionHandler extends SimpleChannelUpstreamHandler {
private final ServletOutputStream out;
public OutboundConnectionHandler(ServletOutputStream out) {
this.out = out;
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
synchronized (this) {
buffer.readBytes(out, buffer.readableBytes());
out.flush();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
if (logger.isWarnEnabled()) {
logger.warn("Unexpected exception while HTTP tunneling", e.getCause());
}
e.getChannel().close();
}
}
}
HttpTunnelingSocketChannelConfig.java 0000664 0000000 0000000 00000024210 12255541277 0035634 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.http;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.channel.socket.SocketChannelConfig;
import org.jboss.netty.util.internal.ConversionUtil;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import java.util.Map;
import java.util.Map.Entry;
/**
* The {@link ChannelConfig} of a client-side HTTP tunneling
* {@link SocketChannel}. A {@link SocketChannel} created by
* {@link HttpTunnelingClientSocketChannelFactory} will return an instance of
* this configuration type for {@link SocketChannel#getConfig()}.
*
* Available options
*
* In addition to the options provided by {@link SocketChannelConfig},
* {@link HttpTunnelingSocketChannelConfig} allows the following options in
* the option map:
*
*
*
* Name Associated setter method
*
* {@code "sslContext"} {@link #setSslContext(SSLContext)}
*
* {@code "enabledSslCiperSuites"} {@link #setEnabledSslCipherSuites(String[])}
*
* {@code "enabledSslProtocols"} {@link #setEnabledSslProtocols(String[])}
*
* {@code "enableSslSessionCreation"} {@link #setEnableSslSessionCreation(boolean)}
*
*
* @apiviz.landmark
*/
public final class HttpTunnelingSocketChannelConfig implements SocketChannelConfig {
private final HttpTunnelingClientSocketChannel channel;
private volatile String serverName;
private volatile String serverPath = "/netty-tunnel";
private volatile SSLContext sslContext;
private volatile String[] enabledSslCipherSuites;
private volatile String[] enabledSslProtocols;
private volatile boolean enableSslSessionCreation = true;
/**
* Creates a new instance.
*/
HttpTunnelingSocketChannelConfig(HttpTunnelingClientSocketChannel channel) {
this.channel = channel;
}
/**
* Returns the host name of the HTTP server. If {@code null}, the
* {@code "Host"} header is not sent by the HTTP tunneling client.
*/
public String getServerName() {
return serverName;
}
/**
* Sets the host name of the HTTP server. If {@code null}, the
* {@code "Host"} header is not sent by the HTTP tunneling client.
*/
public void setServerName(String serverName) {
this.serverName = serverName;
}
/**
* Returns the path where the {@link HttpTunnelingServlet} is mapped to.
* The default value is {@code "/netty-tunnel"}.
*/
public String getServerPath() {
return serverPath;
}
/**
* Sets the path where the {@link HttpTunnelingServlet} is mapped to.
* The default value is {@code "/netty-tunnel"}.
*/
public void setServerPath(String serverPath) {
if (serverPath == null) {
throw new NullPointerException("serverPath");
}
this.serverPath = serverPath;
}
/**
* Returns the {@link SSLContext} which is used to establish an HTTPS
* connection. If {@code null}, a plain-text HTTP connection is established.
*/
public SSLContext getSslContext() {
return sslContext;
}
/**
* Sets the {@link SSLContext} which is used to establish an HTTPS connection.
* If {@code null}, a plain-text HTTP connection is established.
*/
public void setSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
}
/**
* Returns the cipher suites enabled for use on an {@link SSLEngine}.
* If {@code null}, the default value will be used.
*
* @see SSLEngine#getEnabledCipherSuites()
*/
public String[] getEnabledSslCipherSuites() {
String[] suites = enabledSslCipherSuites;
if (suites == null) {
return null;
} else {
return suites.clone();
}
}
/**
* Sets the cipher suites enabled for use on an {@link SSLEngine}.
* If {@code null}, the default value will be used.
*
* @see SSLEngine#setEnabledCipherSuites(String[])
*/
public void setEnabledSslCipherSuites(String[] suites) {
if (suites == null) {
enabledSslCipherSuites = null;
} else {
enabledSslCipherSuites = suites.clone();
}
}
/**
* Returns the protocol versions enabled for use on an {@link SSLEngine}.
*
* @see SSLEngine#getEnabledProtocols()
*/
public String[] getEnabledSslProtocols() {
String[] protocols = enabledSslProtocols;
if (protocols == null) {
return null;
} else {
return protocols.clone();
}
}
/**
* Sets the protocol versions enabled for use on an {@link SSLEngine}.
*
* @see SSLEngine#setEnabledProtocols(String[])
*/
public void setEnabledSslProtocols(String[] protocols) {
if (protocols == null) {
enabledSslProtocols = null;
} else {
enabledSslProtocols = protocols.clone();
}
}
/**
* Returns {@code true} if new {@link SSLSession}s may be established by
* an {@link SSLEngine}.
*
* @see SSLEngine#getEnableSessionCreation()
*/
public boolean isEnableSslSessionCreation() {
return enableSslSessionCreation;
}
/**
* Sets whether new {@link SSLSession}s may be established by an
* {@link SSLEngine}.
*
* @see SSLEngine#setEnableSessionCreation(boolean)
*/
public void setEnableSslSessionCreation(boolean flag) {
enableSslSessionCreation = flag;
}
public void setOptions(Map options) {
for (Entry e: options.entrySet()) {
setOption(e.getKey(), e.getValue());
}
}
public boolean setOption(String key, Object value) {
if (channel.realChannel.getConfig().setOption(key, value)) {
return true;
}
if ("serverName".equals(key)) {
setServerName(String.valueOf(value));
} else if ("serverPath".equals(key)) {
setServerPath(String.valueOf(value));
} else if ("sslContext".equals(key)) {
setSslContext((SSLContext) value);
} else if ("enabledSslCipherSuites".equals(key)) {
setEnabledSslCipherSuites(ConversionUtil.toStringArray(value));
} else if ("enabledSslProtocols".equals(key)) {
setEnabledSslProtocols(ConversionUtil.toStringArray(value));
} else if ("enableSslSessionCreation".equals(key)) {
setEnableSslSessionCreation(ConversionUtil.toBoolean(value));
} else {
return false;
}
return true;
}
public int getReceiveBufferSize() {
return channel.realChannel.getConfig().getReceiveBufferSize();
}
public int getSendBufferSize() {
return channel.realChannel.getConfig().getSendBufferSize();
}
public int getSoLinger() {
return channel.realChannel.getConfig().getSoLinger();
}
public int getTrafficClass() {
return channel.realChannel.getConfig().getTrafficClass();
}
public boolean isKeepAlive() {
return channel.realChannel.getConfig().isKeepAlive();
}
public boolean isReuseAddress() {
return channel.realChannel.getConfig().isReuseAddress();
}
public boolean isTcpNoDelay() {
return channel.realChannel.getConfig().isTcpNoDelay();
}
public void setKeepAlive(boolean keepAlive) {
channel.realChannel.getConfig().setKeepAlive(keepAlive);
}
public void setPerformancePreferences(
int connectionTime, int latency, int bandwidth) {
channel.realChannel.getConfig().setPerformancePreferences(connectionTime, latency, bandwidth);
}
public void setReceiveBufferSize(int receiveBufferSize) {
channel.realChannel.getConfig().setReceiveBufferSize(receiveBufferSize);
}
public void setReuseAddress(boolean reuseAddress) {
channel.realChannel.getConfig().setReuseAddress(reuseAddress);
}
public void setSendBufferSize(int sendBufferSize) {
channel.realChannel.getConfig().setSendBufferSize(sendBufferSize);
}
public void setSoLinger(int soLinger) {
channel.realChannel.getConfig().setSoLinger(soLinger);
}
public void setTcpNoDelay(boolean tcpNoDelay) {
channel.realChannel.getConfig().setTcpNoDelay(tcpNoDelay);
}
public void setTrafficClass(int trafficClass) {
channel.realChannel.getConfig().setTrafficClass(trafficClass);
}
public ChannelBufferFactory getBufferFactory() {
return channel.realChannel.getConfig().getBufferFactory();
}
public int getConnectTimeoutMillis() {
return channel.realChannel.getConfig().getConnectTimeoutMillis();
}
public ChannelPipelineFactory getPipelineFactory() {
return channel.realChannel.getConfig().getPipelineFactory();
}
public void setBufferFactory(ChannelBufferFactory bufferFactory) {
channel.realChannel.getConfig().setBufferFactory(bufferFactory);
}
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
channel.realChannel.getConfig().setConnectTimeoutMillis(connectTimeoutMillis);
}
public void setPipelineFactory(ChannelPipelineFactory pipelineFactory) {
channel.realChannel.getConfig().setPipelineFactory(pipelineFactory);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/http/package-info.java 0000664 0000000 0000000 00000010623 12255541277 0031647 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* An HTTP-based client-side {@link org.jboss.netty.channel.socket.SocketChannel}
* and its corresponding server-side Servlet implementation that make your
* existing server application work in a firewalled network.
*
* Deploying the HTTP tunnel as a Servlet
*
* First, {@link org.jboss.netty.channel.socket.http.HttpTunnelingServlet} must be
* configured in a web.xml .
*
*
* <?xml version="1.0" encoding="UTF-8"?>
* <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
* xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
* version="2.4">
*
* <servlet>
* <servlet-name>NettyTunnelingServlet</servlet-name>
* <servlet-class>org.jboss.netty.channel.socket.http.HttpTunnelingServlet </servlet-class>
* <!--
* The name of the channel, this should be a registered local channel.
* See LocalTransportRegister.
* -->
* <init-param>
* <param-name>endpoint </param-name>
* <param-value>local:myLocalServer </param-value>
* </init-param>
* <load-on-startup>1 </load-on-startup>
* </servlet>
*
* <servlet-mapping>
* <servlet-name>NettyTunnelingServlet</servlet-name>
* <url-pattern>/netty-tunnel </url-pattern>
* </servlet-mapping>
* </web-app>
*
*
* Second, you have to bind your Netty-based server application in the same
* Servlet context or shared class loader space using the local transport
* (see {@link org.jboss.netty.channel.local.LocalServerChannelFactory}.)
* You can use your favorite IoC framework such as JBoss Microcontainer, Guice,
* and Spring to do this. The following example shows how to bind an echo
* server to the endpoint specifed above (web.xml ) in JBossAS 5:
*
*
* <bean name="my-local-echo-server"
* class="org.jboss.netty.example.http.tunnel.LocalEchoServerRegistration" />
*
* ...
*
* package org.jboss.netty.example.http.tunnel;
* ...
*
* public class LocalEchoServerRegistration {
*
* private final ChannelFactory factory = new DefaultLocalServerChannelFactory();
* private volatile Channel serverChannel;
*
* public void start() {
* ServerBootstrap serverBootstrap = new ServerBootstrap(factory);
* EchoHandler handler = new EchoHandler();
* serverBootstrap.getPipeline().addLast("handler", handler);
*
* // Note that "myLocalServer" is the endpoint which was specified in web.xml.
* serverChannel = serverBootstrap.bind(new LocalAddress("myLocalServer "));
* }
*
* public void stop() {
* serverChannel.close();
* }
* }
*
*
* Connecting to the HTTP tunnel
*
* Once the tunnel has been configured, your client-side application needs only
* a couple lines of changes.
*
*
* ClientBootstrap b = new ClientBootstrap(
* new HttpTunnelingClientSocketChannelFactory(
* new NioClientSocketChannelFactory(...)) );
*
* // Configure the pipeline (or pipeline factory) here.
* ...
*
* // The host name of the HTTP server
* b.setOption("serverName" , "example.com");
* // The path to the HTTP tunneling Servlet, which was specified in in web.xml
* b.setOption("serverPath" , "contextPath/netty-tunnel ");
* b.connect(new InetSocketAddress("example.com", 80);
*
*
* For more configuration parameters such as HTTPS options,
* refer to {@link org.jboss.netty.channel.socket.http.HttpTunnelingSocketChannelConfig}.
*/
package org.jboss.netty.channel.socket.http;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/ 0000775 0000000 0000000 00000000000 12255541277 0026264 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/AbstractNioBossPool.java 0000664 0000000 0000000 00000011511 12255541277 0033020 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.ExternalResourceReleasable;
import org.jboss.netty.util.internal.ExecutorUtil;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractNioBossPool
implements BossPool, ExternalResourceReleasable {
/**
* The boss pool raises an exception unless all boss threads start and run within this timeout (in seconds.)
*/
private static final int INITIALIZATION_TIMEOUT = 10;
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractNioBossPool.class);
private final Boss[] bosses;
private final AtomicInteger bossIndex = new AtomicInteger();
private final Executor bossExecutor;
private volatile boolean initialized;
/**
* Create a new instance
*
* @param bossExecutor the {@link Executor} to use for the {@link Boss}'s
* @param bossCount the count of {@link Boss}'s to create
*/
AbstractNioBossPool(Executor bossExecutor, int bossCount) {
this(bossExecutor, bossCount, true);
}
AbstractNioBossPool(Executor bossExecutor, int bossCount, boolean autoInit) {
if (bossExecutor == null) {
throw new NullPointerException("bossExecutor");
}
if (bossCount <= 0) {
throw new IllegalArgumentException(
"bossCount (" + bossCount + ") " +
"must be a positive integer.");
}
bosses = new Boss[bossCount];
this.bossExecutor = bossExecutor;
if (autoInit) {
init();
}
}
protected void init() {
if (initialized) {
throw new IllegalStateException("initialized already");
}
initialized = true;
for (int i = 0; i < bosses.length; i++) {
bosses[i] = newBoss(bossExecutor);
}
waitForBossThreads();
}
private void waitForBossThreads() {
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(INITIALIZATION_TIMEOUT);
boolean warn = false;
for (Boss boss: bosses) {
if (!(boss instanceof AbstractNioSelector)) {
continue;
}
AbstractNioSelector selector = (AbstractNioSelector) boss;
long waitTime = deadline - System.nanoTime();
try {
if (waitTime <= 0) {
if (selector.thread == null) {
warn = true;
break;
}
} else if (!selector.startupLatch.await(waitTime, TimeUnit.NANOSECONDS)) {
warn = true;
break;
}
} catch (InterruptedException ignore) {
// Stop waiting for the boss threads and let someone else take care of the interruption.
Thread.currentThread().interrupt();
break;
}
}
if (warn) {
logger.warn(
"Failed to get all boss threads ready within " + INITIALIZATION_TIMEOUT + " second(s). " +
"Make sure to specify the executor which has more threads than the requested bossCount. " +
"If unsure, use Executors.newCachedThreadPool().");
}
}
/**
* Create a new {@link Boss} which uses the given {@link Executor} to service IO
*
*
* @param executor the {@link Executor} to use
* @return worker the new {@link Boss}
*/
protected abstract E newBoss(Executor executor);
@SuppressWarnings("unchecked")
public E nextBoss() {
return (E) bosses[Math.abs(bossIndex.getAndIncrement() % bosses.length)];
}
public void rebuildSelectors() {
for (Boss boss: bosses) {
boss.rebuildSelector();
}
}
public void releaseExternalResources() {
shutdown();
ExecutorUtil.shutdownNow(bossExecutor);
}
public void shutdown() {
for (Boss boss: bosses) {
boss.shutdown();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/AbstractNioChannel.java 0000664 0000000 0000000 00000024363 12255541277 0032641 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.AbstractChannel;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.socket.nio.SocketSendBufferPool.SendBuffer;
import org.jboss.netty.util.internal.ThreadLocalBoolean;
import java.net.InetSocketAddress;
import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Collection;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static org.jboss.netty.channel.Channels.*;
abstract class AbstractNioChannel extends AbstractChannel {
/**
* The {@link AbstractNioWorker}.
*/
final AbstractNioWorker worker;
/**
* Monitor object for synchronizing access to the {@link WriteRequestQueue}.
*/
final Object writeLock = new Object();
/**
* WriteTask that performs write operations.
*/
final Runnable writeTask = new WriteTask();
/**
* Indicates if there is a {@link WriteTask} in the task queue.
*/
final AtomicBoolean writeTaskInTaskQueue = new AtomicBoolean();
/**
* Queue of write {@link MessageEvent}s.
*/
final Queue writeBufferQueue = new WriteRequestQueue();
/**
* Keeps track of the number of bytes that the {@link WriteRequestQueue} currently
* contains.
*/
final AtomicInteger writeBufferSize = new AtomicInteger();
/**
* Keeps track of the highWaterMark.
*/
final AtomicInteger highWaterMarkCounter = new AtomicInteger();
/**
* The current write {@link MessageEvent}
*/
MessageEvent currentWriteEvent;
SendBuffer currentWriteBuffer;
/**
* Boolean that indicates that write operation is in progress.
*/
boolean inWriteNowLoop;
boolean writeSuspended;
private volatile InetSocketAddress localAddress;
volatile InetSocketAddress remoteAddress;
final C channel;
protected AbstractNioChannel(
Integer id, Channel parent, ChannelFactory factory, ChannelPipeline pipeline,
ChannelSink sink, AbstractNioWorker worker, C ch) {
super(id, parent, factory, pipeline, sink);
this.worker = worker;
channel = ch;
}
protected AbstractNioChannel(
Channel parent, ChannelFactory factory,
ChannelPipeline pipeline, ChannelSink sink, AbstractNioWorker worker, C ch) {
super(parent, factory, pipeline, sink);
this.worker = worker;
channel = ch;
}
/**
* Return the {@link AbstractNioWorker} that handle the IO of the
* {@link AbstractNioChannel}
*
* @return worker
*/
public AbstractNioWorker getWorker() {
return worker;
}
public InetSocketAddress getLocalAddress() {
InetSocketAddress localAddress = this.localAddress;
if (localAddress == null) {
try {
localAddress = getLocalSocketAddress();
if (localAddress.getAddress().isAnyLocalAddress()) {
// Don't cache on a wildcard address so the correct one
// will be cached once the channel is connected/bound
return localAddress;
}
this.localAddress = localAddress;
} catch (Throwable t) {
// Sometimes fails on a closed socket in Windows.
return null;
}
}
return localAddress;
}
public InetSocketAddress getRemoteAddress() {
InetSocketAddress remoteAddress = this.remoteAddress;
if (remoteAddress == null) {
try {
this.remoteAddress = remoteAddress =
getRemoteSocketAddress();
} catch (Throwable t) {
// Sometimes fails on a closed socket in Windows.
return null;
}
}
return remoteAddress;
}
public abstract NioChannelConfig getConfig();
int getRawInterestOps() {
return super.getInterestOps();
}
void setRawInterestOpsNow(int interestOps) {
setInterestOpsNow(interestOps);
}
@Override
public int getInterestOps() {
if (!isOpen()) {
return Channel.OP_WRITE;
}
int interestOps = getRawInterestOps();
int writeBufferSize = this.writeBufferSize.get();
if (writeBufferSize != 0) {
if (highWaterMarkCounter.get() > 0) {
int lowWaterMark = getConfig().getWriteBufferLowWaterMark();
if (writeBufferSize >= lowWaterMark) {
interestOps |= Channel.OP_WRITE;
} else {
interestOps &= ~Channel.OP_WRITE;
}
} else {
int highWaterMark = getConfig().getWriteBufferHighWaterMark();
if (writeBufferSize >= highWaterMark) {
interestOps |= Channel.OP_WRITE;
} else {
interestOps &= ~Channel.OP_WRITE;
}
}
} else {
interestOps &= ~Channel.OP_WRITE;
}
return interestOps;
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
abstract InetSocketAddress getLocalSocketAddress() throws Exception;
abstract InetSocketAddress getRemoteSocketAddress() throws Exception;
private final class WriteRequestQueue implements Queue {
private final ThreadLocalBoolean notifying = new ThreadLocalBoolean();
private final Queue queue;
public WriteRequestQueue() {
queue = new ConcurrentLinkedQueue();
}
public MessageEvent remove() {
return queue.remove();
}
public MessageEvent element() {
return queue.element();
}
public MessageEvent peek() {
return queue.peek();
}
public int size() {
return queue.size();
}
public boolean isEmpty() {
return queue.isEmpty();
}
public Iterator iterator() {
return queue.iterator();
}
public Object[] toArray() {
return queue.toArray();
}
public T[] toArray(T[] a) {
return queue.toArray(a);
}
public boolean containsAll(Collection> c) {
return queue.containsAll(c);
}
public boolean addAll(Collection extends MessageEvent> c) {
return queue.addAll(c);
}
public boolean removeAll(Collection> c) {
return queue.removeAll(c);
}
public boolean retainAll(Collection> c) {
return queue.retainAll(c);
}
public void clear() {
queue.clear();
}
public boolean add(MessageEvent e) {
return queue.add(e);
}
public boolean remove(Object o) {
return queue.remove(o);
}
public boolean contains(Object o) {
return queue.contains(o);
}
public boolean offer(MessageEvent e) {
boolean success = queue.offer(e);
assert success;
int messageSize = getMessageSize(e);
int newWriteBufferSize = writeBufferSize.addAndGet(messageSize);
int highWaterMark = getConfig().getWriteBufferHighWaterMark();
if (newWriteBufferSize >= highWaterMark) {
if (newWriteBufferSize - messageSize < highWaterMark) {
highWaterMarkCounter.incrementAndGet();
if (!notifying.get()) {
notifying.set(Boolean.TRUE);
fireChannelInterestChanged(AbstractNioChannel.this);
notifying.set(Boolean.FALSE);
}
}
}
return true;
}
public MessageEvent poll() {
MessageEvent e = queue.poll();
if (e != null) {
int messageSize = getMessageSize(e);
int newWriteBufferSize = writeBufferSize.addAndGet(-messageSize);
int lowWaterMark = getConfig().getWriteBufferLowWaterMark();
if (newWriteBufferSize == 0 || newWriteBufferSize < lowWaterMark) {
if (newWriteBufferSize + messageSize >= lowWaterMark) {
highWaterMarkCounter.decrementAndGet();
if (isConnected() && !notifying.get()) {
notifying.set(Boolean.TRUE);
fireChannelInterestChanged(AbstractNioChannel.this);
notifying.set(Boolean.FALSE);
}
}
}
}
return e;
}
private int getMessageSize(MessageEvent e) {
Object m = e.getMessage();
if (m instanceof ChannelBuffer) {
return ((ChannelBuffer) m).readableBytes();
}
return 0;
}
}
private final class WriteTask implements Runnable {
WriteTask() {
}
public void run() {
writeTaskInTaskQueue.set(false);
worker.writeFromTaskLoop(AbstractNioChannel.this);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/AbstractNioChannelSink.java0000664 0000000 0000000 00000003624 12255541277 0033463 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.AbstractChannelSink;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.socket.ChannelRunnableWrapper;
public abstract class AbstractNioChannelSink extends AbstractChannelSink {
@Override
public ChannelFuture execute(ChannelPipeline pipeline, final Runnable task) {
Channel ch = pipeline.getChannel();
if (ch instanceof AbstractNioChannel>) {
AbstractNioChannel> channel = (AbstractNioChannel>) ch;
ChannelRunnableWrapper wrapper = new ChannelRunnableWrapper(pipeline.getChannel(), task);
channel.worker.executeInIoThread(wrapper);
return wrapper;
}
return super.execute(pipeline, task);
}
@Override
protected boolean isFireExceptionCaughtLater(ChannelEvent event, Throwable actualCause) {
Channel channel = event.getChannel();
boolean fireLater = false;
if (channel instanceof AbstractNioChannel>) {
fireLater = !AbstractNioWorker.isIoThread((AbstractNioChannel>) channel);
}
return fireLater;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/AbstractNioSelector.java 0000664 0000000 0000000 00000036253 12255541277 0033052 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import org.jboss.netty.util.internal.DeadLockProofWorker;
import java.io.IOException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.ConcurrentModificationException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
abstract class AbstractNioSelector implements NioSelector {
private static final AtomicInteger nextId = new AtomicInteger();
private final int id = nextId.incrementAndGet();
/**
* Internal Netty logger.
*/
protected static final InternalLogger logger = InternalLoggerFactory
.getInstance(AbstractNioSelector.class);
private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization.
/**
* Executor used to execute {@link Runnable}s such as channel registration
* task.
*/
private final Executor executor;
/**
* If this worker has been started thread will be a reference to the thread
* used when starting. i.e. the current thread when the run method is executed.
*/
protected volatile Thread thread;
/**
* Count down to 0 when the I/O thread starts and {@link #thread} is set to non-null.
*/
final CountDownLatch startupLatch = new CountDownLatch(1);
/**
* The NIO {@link Selector}.
*/
protected volatile Selector selector;
/**
* Boolean that controls determines if a blocked Selector.select should
* break out of its selection process. In our case we use a timeone for
* the select method and the select method will block for that time unless
* waken up.
*/
protected final AtomicBoolean wakenUp = new AtomicBoolean();
private final Queue taskQueue = new ConcurrentLinkedQueue();
private volatile int cancelledKeys; // should use AtomicInteger but we just need approximation
private final CountDownLatch shutdownLatch = new CountDownLatch(1);
private volatile boolean shutdown;
AbstractNioSelector(Executor executor) {
this(executor, null);
}
AbstractNioSelector(Executor executor, ThreadNameDeterminer determiner) {
this.executor = executor;
openSelector(determiner);
}
public void register(Channel channel, ChannelFuture future) {
Runnable task = createRegisterTask(channel, future);
registerTask(task);
}
protected final void registerTask(Runnable task) {
taskQueue.add(task);
Selector selector = this.selector;
if (selector != null) {
if (wakenUp.compareAndSet(false, true)) {
selector.wakeup();
}
} else {
if (taskQueue.remove(task)) {
// the selector was null this means the Worker has already been shutdown.
throw new RejectedExecutionException("Worker has already been shutdown");
}
}
}
protected final boolean isIoThread() {
return Thread.currentThread() == thread;
}
public void rebuildSelector() {
if (!isIoThread()) {
taskQueue.add(new Runnable() {
public void run() {
rebuildSelector();
}
});
return;
}
final Selector oldSelector = selector;
final Selector newSelector;
if (oldSelector == null) {
return;
}
try {
newSelector = SelectorUtil.open();
} catch (Exception e) {
logger.warn("Failed to create a new Selector.", e);
return;
}
// Register all channels to the new Selector.
int nChannels = 0;
for (;;) {
try {
for (SelectionKey key: oldSelector.keys()) {
try {
if (key.channel().keyFor(newSelector) != null) {
continue;
}
int interestOps = key.interestOps();
key.cancel();
key.channel().register(newSelector, interestOps, key.attachment());
nChannels ++;
} catch (Exception e) {
logger.warn("Failed to re-register a Channel to the new Selector,", e);
close(key);
}
}
} catch (ConcurrentModificationException e) {
// Probably due to concurrent modification of the key set.
continue;
}
break;
}
selector = newSelector;
try {
// time to close the old selector as everything else is registered to the new one
oldSelector.close();
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close the old Selector.", t);
}
}
logger.info("Migrated " + nChannels + " channel(s) to the new Selector,");
}
public void run() {
thread = Thread.currentThread();
startupLatch.countDown();
int selectReturnsImmediately = 0;
Selector selector = this.selector;
if (selector == null) {
return;
}
// use 80% of the timeout for measure
final long minSelectTimeout = SelectorUtil.SELECT_TIMEOUT_NANOS * 80 / 100;
boolean wakenupFromLoop = false;
for (;;) {
wakenUp.set(false);
try {
long beforeSelect = System.nanoTime();
int selected = select(selector);
if (SelectorUtil.EPOLL_BUG_WORKAROUND && selected == 0 && !wakenupFromLoop && !wakenUp.get()) {
long timeBlocked = System.nanoTime() - beforeSelect;
if (timeBlocked < minSelectTimeout) {
boolean notConnected = false;
// loop over all keys as the selector may was unblocked because of a closed channel
for (SelectionKey key: selector.keys()) {
SelectableChannel ch = key.channel();
try {
if (ch instanceof DatagramChannel && !ch.isOpen() ||
ch instanceof SocketChannel && !((SocketChannel) ch).isConnected()) {
notConnected = true;
// cancel the key just to be on the safe side
key.cancel();
}
} catch (CancelledKeyException e) {
// ignore
}
}
if (notConnected) {
selectReturnsImmediately = 0;
} else {
// returned before the minSelectTimeout elapsed with nothing select.
// this may be the cause of the jdk epoll(..) bug, so increment the counter
// which we use later to see if its really the jdk bug.
selectReturnsImmediately ++;
}
} else {
selectReturnsImmediately = 0;
}
if (selectReturnsImmediately == 1024) {
// The selector returned immediately for 10 times in a row,
// so recreate one selector as it seems like we hit the
// famous epoll(..) jdk bug.
rebuildSelector();
selector = this.selector;
selectReturnsImmediately = 0;
wakenupFromLoop = false;
// try to select again
continue;
}
} else {
// reset counter
selectReturnsImmediately = 0;
}
// 'wakenUp.compareAndSet(false, true)' is always evaluated
// before calling 'selector.wakeup()' to reduce the wake-up
// overhead. (Selector.wakeup() is an expensive operation.)
//
// However, there is a race condition in this approach.
// The race condition is triggered when 'wakenUp' is set to
// true too early.
//
// 'wakenUp' is set to true too early if:
// 1) Selector is waken up between 'wakenUp.set(false)' and
// 'selector.select(...)'. (BAD)
// 2) Selector is waken up between 'selector.select(...)' and
// 'if (wakenUp.get()) { ... }'. (OK)
//
// In the first case, 'wakenUp' is set to true and the
// following 'selector.select(...)' will wake up immediately.
// Until 'wakenUp' is set to false again in the next round,
// 'wakenUp.compareAndSet(false, true)' will fail, and therefore
// any attempt to wake up the Selector will fail, too, causing
// the following 'selector.select(...)' call to block
// unnecessarily.
//
// To fix this problem, we wake up the selector again if wakenUp
// is true immediately after selector.select(...).
// It is inefficient in that it wakes up the selector for both
// the first case (BAD - wake-up required) and the second case
// (OK - no wake-up required).
if (wakenUp.get()) {
wakenupFromLoop = true;
selector.wakeup();
} else {
wakenupFromLoop = false;
}
cancelledKeys = 0;
processTaskQueue();
selector = this.selector; // processTaskQueue() can call rebuildSelector()
if (shutdown) {
this.selector = null;
// process one time again
processTaskQueue();
for (SelectionKey k: selector.keys()) {
close(k);
}
try {
selector.close();
} catch (IOException e) {
logger.warn(
"Failed to close a selector.", e);
}
shutdownLatch.countDown();
break;
} else {
process(selector);
}
} catch (Throwable t) {
logger.warn(
"Unexpected exception in the selector loop.", t);
// Prevent possible consecutive immediate failures that lead to
// excessive CPU consumption.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore.
}
}
}
}
/**
* Start the {@link AbstractNioWorker} and return the {@link Selector} that will be used for
* the {@link AbstractNioChannel}'s when they get registered
*/
private void openSelector(ThreadNameDeterminer determiner) {
try {
selector = SelectorUtil.open();
} catch (Throwable t) {
throw new ChannelException("Failed to create a selector.", t);
}
// Start the worker thread with the new Selector.
boolean success = false;
try {
DeadLockProofWorker.start(executor, newThreadRenamingRunnable(id, determiner));
success = true;
} finally {
if (!success) {
// Release the Selector if the execution fails.
try {
selector.close();
} catch (Throwable t) {
logger.warn("Failed to close a selector.", t);
}
selector = null;
// The method will return to the caller at this point.
}
}
assert selector != null && selector.isOpen();
}
private void processTaskQueue() {
for (;;) {
final Runnable task = taskQueue.poll();
if (task == null) {
break;
}
task.run();
try {
cleanUpCancelledKeys();
} catch (IOException e) {
// Ignore
}
}
}
protected final void increaseCancelledKeys() {
cancelledKeys ++;
}
protected final boolean cleanUpCancelledKeys() throws IOException {
if (cancelledKeys >= CLEANUP_INTERVAL) {
cancelledKeys = 0;
selector.selectNow();
return true;
}
return false;
}
public void shutdown() {
if (isIoThread()) {
throw new IllegalStateException("Must not be called from a I/O-Thread to prevent deadlocks!");
}
Selector selector = this.selector;
shutdown = true;
if (selector != null) {
selector.wakeup();
}
try {
shutdownLatch.await();
} catch (InterruptedException e) {
logger.error("Interrupted while wait for resources to be released #" + id);
Thread.currentThread().interrupt();
}
}
protected abstract void process(Selector selector) throws IOException;
protected int select(Selector selector) throws IOException {
return SelectorUtil.select(selector);
}
protected abstract void close(SelectionKey k);
protected abstract ThreadRenamingRunnable newThreadRenamingRunnable(int id, ThreadNameDeterminer determiner);
protected abstract Runnable createRegisterTask(Channel channel, ChannelFuture future);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/AbstractNioWorker.java 0000664 0000000 0000000 00000045211 12255541277 0032535 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.socket.Worker;
import org.jboss.netty.channel.socket.nio.SocketSendBufferPool.SendBuffer;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import java.io.IOException;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.Executor;
import static org.jboss.netty.channel.Channels.*;
abstract class AbstractNioWorker extends AbstractNioSelector implements Worker {
protected final SocketSendBufferPool sendBufferPool = new SocketSendBufferPool();
AbstractNioWorker(Executor executor) {
super(executor);
}
AbstractNioWorker(Executor executor, ThreadNameDeterminer determiner) {
super(executor, determiner);
}
public void executeInIoThread(Runnable task) {
executeInIoThread(task, false);
}
/**
* Execute the {@link Runnable} in a IO-Thread
*
* @param task
* the {@link Runnable} to execute
* @param alwaysAsync
* {@code true} if the {@link Runnable} should be executed
* in an async fashion even if the current Thread == IO Thread
*/
public void executeInIoThread(Runnable task, boolean alwaysAsync) {
if (!alwaysAsync && isIoThread()) {
task.run();
} else {
registerTask(task);
}
}
@Override
protected void close(SelectionKey k) {
AbstractNioChannel> ch = (AbstractNioChannel>) k.attachment();
close(ch, succeededFuture(ch));
}
@Override
protected ThreadRenamingRunnable newThreadRenamingRunnable(int id, ThreadNameDeterminer determiner) {
return new ThreadRenamingRunnable(this, "New I/O worker #" + id, determiner);
}
@Override
public void run() {
super.run();
sendBufferPool.releaseExternalResources();
}
@Override
protected void process(Selector selector) throws IOException {
Set selectedKeys = selector.selectedKeys();
// check if the set is empty and if so just return to not create garbage by
// creating a new Iterator every time even if there is nothing to process.
// See https://github.com/netty/netty/issues/597
if (selectedKeys.isEmpty()) {
return;
}
for (Iterator i = selectedKeys.iterator(); i.hasNext();) {
SelectionKey k = i.next();
i.remove();
try {
int readyOps = k.readyOps();
if ((readyOps & SelectionKey.OP_READ) != 0 || readyOps == 0) {
if (!read(k)) {
// Connection already closed - no need to handle write.
continue;
}
}
if ((readyOps & SelectionKey.OP_WRITE) != 0) {
writeFromSelectorLoop(k);
}
} catch (CancelledKeyException e) {
close(k);
}
if (cleanUpCancelledKeys()) {
break; // break the loop to avoid ConcurrentModificationException
}
}
}
void writeFromUserCode(final AbstractNioChannel> channel) {
if (!channel.isConnected()) {
cleanUpWriteBuffer(channel);
return;
}
if (scheduleWriteIfNecessary(channel)) {
return;
}
// From here, we are sure Thread.currentThread() == workerThread.
if (channel.writeSuspended) {
return;
}
if (channel.inWriteNowLoop) {
return;
}
write0(channel);
}
void writeFromTaskLoop(AbstractNioChannel> ch) {
if (!ch.writeSuspended) {
write0(ch);
}
}
void writeFromSelectorLoop(final SelectionKey k) {
AbstractNioChannel> ch = (AbstractNioChannel>) k.attachment();
ch.writeSuspended = false;
write0(ch);
}
protected abstract boolean scheduleWriteIfNecessary(AbstractNioChannel> channel);
protected void write0(AbstractNioChannel> channel) {
boolean open = true;
boolean addOpWrite = false;
boolean removeOpWrite = false;
boolean iothread = isIoThread(channel);
long writtenBytes = 0;
final SocketSendBufferPool sendBufferPool = this.sendBufferPool;
final WritableByteChannel ch = channel.channel;
final Queue writeBuffer = channel.writeBufferQueue;
final int writeSpinCount = channel.getConfig().getWriteSpinCount();
List causes = null;
synchronized (channel.writeLock) {
channel.inWriteNowLoop = true;
for (;;) {
MessageEvent evt = channel.currentWriteEvent;
SendBuffer buf = null;
ChannelFuture future = null;
try {
if (evt == null) {
if ((channel.currentWriteEvent = evt = writeBuffer.poll()) == null) {
removeOpWrite = true;
channel.writeSuspended = false;
break;
}
future = evt.getFuture();
channel.currentWriteBuffer = buf = sendBufferPool.acquire(evt.getMessage());
} else {
future = evt.getFuture();
buf = channel.currentWriteBuffer;
}
long localWrittenBytes = 0;
for (int i = writeSpinCount; i > 0; i --) {
localWrittenBytes = buf.transferTo(ch);
if (localWrittenBytes != 0) {
writtenBytes += localWrittenBytes;
break;
}
if (buf.finished()) {
break;
}
}
if (buf.finished()) {
// Successful write - proceed to the next message.
buf.release();
channel.currentWriteEvent = null;
channel.currentWriteBuffer = null;
// Mark the event object for garbage collection.
//noinspection UnusedAssignment
evt = null;
buf = null;
future.setSuccess();
} else {
// Not written fully - perhaps the kernel buffer is full.
addOpWrite = true;
channel.writeSuspended = true;
if (writtenBytes > 0) {
// Notify progress listeners if necessary.
future.setProgress(
localWrittenBytes,
buf.writtenBytes(), buf.totalBytes());
}
break;
}
} catch (AsynchronousCloseException e) {
// Doesn't need a user attention - ignore.
} catch (Throwable t) {
if (buf != null) {
buf.release();
}
channel.currentWriteEvent = null;
channel.currentWriteBuffer = null;
// Mark the event object for garbage collection.
//noinspection UnusedAssignment
buf = null;
//noinspection UnusedAssignment
evt = null;
if (future != null) {
future.setFailure(t);
}
if (iothread) {
// An exception was thrown from within a write in the iothread. We store a reference to it
// in a list for now and notify the handlers in the chain after the writeLock was released
// to prevent possible deadlock.
// See #1310
if (causes == null) {
causes = new ArrayList(1);
}
causes.add(t);
} else {
fireExceptionCaughtLater(channel, t);
}
if (t instanceof IOException) {
// close must be handled from outside the write lock to fix a possible deadlock
// which can happen when MemoryAwareThreadPoolExecutor is used and the limit is exceed
// and a close is triggered while the lock is hold. This is because the close(..)
// may try to submit a task to handle it via the ExecutorHandler which then deadlocks.
// See #1310
open = false;
}
}
}
channel.inWriteNowLoop = false;
// Initially, the following block was executed after releasing
// the writeLock, but there was a race condition, and it has to be
// executed before releasing the writeLock:
//
// https://issues.jboss.org/browse/NETTY-410
//
if (open) {
if (addOpWrite) {
setOpWrite(channel);
} else if (removeOpWrite) {
clearOpWrite(channel);
}
}
}
if (causes != null) {
for (Throwable cause: causes) {
// notify about cause now as it was triggered in the write loop
fireExceptionCaught(channel, cause);
}
}
if (!open) {
// close the channel now
close(channel, succeededFuture(channel));
}
if (iothread) {
fireWriteComplete(channel, writtenBytes);
} else {
fireWriteCompleteLater(channel, writtenBytes);
}
}
static boolean isIoThread(AbstractNioChannel> channel) {
return Thread.currentThread() == channel.worker.thread;
}
protected void setOpWrite(AbstractNioChannel> channel) {
Selector selector = this.selector;
SelectionKey key = channel.channel.keyFor(selector);
if (key == null) {
return;
}
if (!key.isValid()) {
close(key);
return;
}
int interestOps = channel.getRawInterestOps();
if ((interestOps & SelectionKey.OP_WRITE) == 0) {
interestOps |= SelectionKey.OP_WRITE;
key.interestOps(interestOps);
channel.setRawInterestOpsNow(interestOps);
}
}
protected void clearOpWrite(AbstractNioChannel> channel) {
Selector selector = this.selector;
SelectionKey key = channel.channel.keyFor(selector);
if (key == null) {
return;
}
if (!key.isValid()) {
close(key);
return;
}
int interestOps = channel.getRawInterestOps();
if ((interestOps & SelectionKey.OP_WRITE) != 0) {
interestOps &= ~SelectionKey.OP_WRITE;
key.interestOps(interestOps);
channel.setRawInterestOpsNow(interestOps);
}
}
protected void close(AbstractNioChannel> channel, ChannelFuture future) {
boolean connected = channel.isConnected();
boolean bound = channel.isBound();
boolean iothread = isIoThread(channel);
try {
channel.channel.close();
increaseCancelledKeys();
if (channel.setClosed()) {
future.setSuccess();
if (connected) {
if (iothread) {
fireChannelDisconnected(channel);
} else {
fireChannelDisconnectedLater(channel);
}
}
if (bound) {
if (iothread) {
fireChannelUnbound(channel);
} else {
fireChannelUnboundLater(channel);
}
}
cleanUpWriteBuffer(channel);
if (iothread) {
fireChannelClosed(channel);
} else {
fireChannelClosedLater(channel);
}
} else {
future.setSuccess();
}
} catch (Throwable t) {
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
protected static void cleanUpWriteBuffer(AbstractNioChannel> channel) {
Exception cause = null;
boolean fireExceptionCaught = false;
// Clean up the stale messages in the write buffer.
synchronized (channel.writeLock) {
MessageEvent evt = channel.currentWriteEvent;
if (evt != null) {
// Create the exception only once to avoid the excessive overhead
// caused by fillStackTrace.
if (channel.isOpen()) {
cause = new NotYetConnectedException();
} else {
cause = new ClosedChannelException();
}
ChannelFuture future = evt.getFuture();
if (channel.currentWriteBuffer != null) {
channel.currentWriteBuffer.release();
channel.currentWriteBuffer = null;
}
channel.currentWriteEvent = null;
// Mark the event object for garbage collection.
//noinspection UnusedAssignment
evt = null;
future.setFailure(cause);
fireExceptionCaught = true;
}
Queue writeBuffer = channel.writeBufferQueue;
for (;;) {
evt = writeBuffer.poll();
if (evt == null) {
break;
}
// Create the exception only once to avoid the excessive overhead
// caused by fillStackTrace.
if (cause == null) {
if (channel.isOpen()) {
cause = new NotYetConnectedException();
} else {
cause = new ClosedChannelException();
}
fireExceptionCaught = true;
}
evt.getFuture().setFailure(cause);
}
}
if (fireExceptionCaught) {
if (isIoThread(channel)) {
fireExceptionCaught(channel, cause);
} else {
fireExceptionCaughtLater(channel, cause);
}
}
}
void setInterestOps(final AbstractNioChannel> channel, final ChannelFuture future, final int interestOps) {
boolean iothread = isIoThread(channel);
if (!iothread) {
channel.getPipeline().execute(new Runnable() {
public void run() {
setInterestOps(channel, future, interestOps);
}
});
return;
}
boolean changed = false;
try {
Selector selector = this.selector;
SelectionKey key = channel.channel.keyFor(selector);
// Override OP_WRITE flag - a user cannot change this flag.
int newInterestOps = interestOps & ~Channel.OP_WRITE | channel.getRawInterestOps() & Channel.OP_WRITE;
if (key == null || selector == null) {
if (channel.getRawInterestOps() != newInterestOps) {
changed = true;
}
// Not registered to the worker yet.
// Set the rawInterestOps immediately; RegisterTask will pick it up.
channel.setRawInterestOpsNow(newInterestOps);
future.setSuccess();
if (changed) {
if (iothread) {
fireChannelInterestChanged(channel);
} else {
fireChannelInterestChangedLater(channel);
}
}
return;
}
if (channel.getRawInterestOps() != newInterestOps) {
key.interestOps(newInterestOps);
if (Thread.currentThread() != thread &&
wakenUp.compareAndSet(false, true)) {
selector.wakeup();
}
channel.setRawInterestOpsNow(newInterestOps);
}
future.setSuccess();
if (changed) {
fireChannelInterestChanged(channel);
}
} catch (CancelledKeyException e) {
// setInterestOps() was called on a closed channel.
ClosedChannelException cce = new ClosedChannelException();
future.setFailure(cce);
fireExceptionCaught(channel, cce);
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
/**
* Read is called when a Selector has been notified that the underlying channel
* was something to be read. The channel would previously have registered its interest
* in read operations.
*
* @param k The selection key which contains the Selector registration information.
*/
protected abstract boolean read(SelectionKey k);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/AbstractNioWorkerPool.java 0000664 0000000 0000000 00000013320 12255541277 0033363 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.socket.Worker;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.ExternalResourceReleasable;
import org.jboss.netty.util.internal.ExecutorUtil;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Abstract base class for {@link WorkerPool} implementations that create the {@link Worker}'s
* up-front and return them in a "fair" fashion when calling {@link #nextWorker()}
*/
public abstract class AbstractNioWorkerPool
implements WorkerPool, ExternalResourceReleasable {
/**
* The worker pool raises an exception unless all worker threads start and run within this timeout (in seconds.)
*/
private static final int INITIALIZATION_TIMEOUT = 10;
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractNioWorkerPool.class);
private final AbstractNioWorker[] workers;
private final AtomicInteger workerIndex = new AtomicInteger();
private final Executor workerExecutor;
private volatile boolean initialized;
/**
* Create a new instance
*
* @param workerExecutor the {@link Executor} to use for the {@link Worker}'s
* @param workerCount the count of {@link Worker}'s to create
*/
AbstractNioWorkerPool(Executor workerExecutor, int workerCount) {
this(workerExecutor, workerCount, true);
}
AbstractNioWorkerPool(Executor workerExecutor, int workerCount, boolean autoInit) {
if (workerExecutor == null) {
throw new NullPointerException("workerExecutor");
}
if (workerCount <= 0) {
throw new IllegalArgumentException(
"workerCount (" + workerCount + ") " + "must be a positive integer.");
}
workers = new AbstractNioWorker[workerCount];
this.workerExecutor = workerExecutor;
if (autoInit) {
init();
}
}
protected void init() {
if (initialized) {
throw new IllegalStateException("initialized already");
}
initialized = true;
for (int i = 0; i < workers.length; i++) {
workers[i] = newWorker(workerExecutor);
}
waitForWorkerThreads();
}
private void waitForWorkerThreads() {
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(INITIALIZATION_TIMEOUT);
boolean warn = false;
for (AbstractNioSelector worker: workers) {
long waitTime = deadline - System.nanoTime();
try {
if (waitTime <= 0) {
if (worker.thread == null) {
warn = true;
break;
}
} else if (!worker.startupLatch.await(waitTime, TimeUnit.NANOSECONDS)) {
warn = true;
break;
}
} catch (InterruptedException ignore) {
// Stop waiting for the worker threads and let someone else take care of the interruption.
Thread.currentThread().interrupt();
break;
}
}
if (warn) {
logger.warn(
"Failed to get all worker threads ready within " + INITIALIZATION_TIMEOUT + " second(s). " +
"Make sure to specify the executor which has more threads than the requested workerCount. " +
"If unsure, use Executors.newCachedThreadPool().");
}
}
/**
* Only here for backward compability and will be removed in later releases. Please use
* {@link #newWorker(Executor)}
*
*
* @param executor the {@link Executor} to use
* @return worker the new {@link Worker}
* @deprecated use {@link #newWorker(Executor)}
*/
@Deprecated
protected E createWorker(Executor executor) {
throw new IllegalStateException("This will be removed. Override this and the newWorker(..) method!");
}
/**
* Create a new {@link Worker} which uses the given {@link Executor} to service IO.
*
* This method will be made abstract in further releases (once {@link #createWorker(Executor)}
* was removed).
*
*
* @param executor the {@link Executor} to use
* @return worker the new {@link Worker}
*/
@SuppressWarnings("deprecation")
protected E newWorker(Executor executor) {
return createWorker(executor);
}
@SuppressWarnings("unchecked")
public E nextWorker() {
return (E) workers[Math.abs(workerIndex.getAndIncrement() % workers.length)];
}
public void rebuildSelectors() {
for (AbstractNioWorker worker: workers) {
worker.rebuildSelector();
}
}
public void releaseExternalResources() {
shutdown();
ExecutorUtil.shutdownNow(workerExecutor);
}
public void shutdown() {
for (AbstractNioWorker worker: workers) {
worker.shutdown();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/Boss.java 0000664 0000000 0000000 00000001421 12255541277 0030033 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
/**
* Serves the boss tasks like connecting/accepting
*/
public interface Boss extends NioSelector {
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/BossPool.java 0000664 0000000 0000000 00000001566 12255541277 0030677 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
/**
* A Pool that holds {@link Boss} instances
*/
public interface BossPool extends NioSelectorPool {
/**
* Return the next {@link Boss} to use
*
*/
E nextBoss();
}
DefaultNioDatagramChannelConfig.java 0000664 0000000 0000000 00000020622 12255541277 0035164 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.StandardSocketOptions;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;
import java.util.Map;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.socket.DefaultDatagramChannelConfig;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.ConversionUtil;
import org.jboss.netty.util.internal.DetectionUtil;
/**
* The default {@link NioSocketChannelConfig} implementation.
*/
class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
implements NioDatagramChannelConfig {
private static final InternalLogger logger =
InternalLoggerFactory
.getInstance(DefaultNioDatagramChannelConfig.class);
private volatile int writeBufferHighWaterMark = 64 * 1024;
private volatile int writeBufferLowWaterMark = 32 * 1024;
private volatile int writeSpinCount = 16;
private final DatagramChannel channel;
DefaultNioDatagramChannelConfig(DatagramChannel channel) {
super(channel.socket());
this.channel = channel;
}
@Override
public void setOptions(Map options) {
super.setOptions(options);
if (getWriteBufferHighWaterMark() < getWriteBufferLowWaterMark()) {
// Recover the integrity of the configuration with a sensible value.
setWriteBufferLowWaterMark0(getWriteBufferHighWaterMark() >>> 1);
if (logger.isWarnEnabled()) {
// Notify the user about misconfiguration.
logger.warn("writeBufferLowWaterMark cannot be greater than "
+ "writeBufferHighWaterMark; setting to the half of the "
+ "writeBufferHighWaterMark.");
}
}
}
@Override
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("writeBufferHighWaterMark".equals(key)) {
setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
} else if ("writeBufferLowWaterMark".equals(key)) {
setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
} else if ("writeSpinCount".equals(key)) {
setWriteSpinCount(ConversionUtil.toInt(value));
} else {
return false;
}
return true;
}
public int getWriteBufferHighWaterMark() {
return writeBufferHighWaterMark;
}
public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
throw new IllegalArgumentException(
"writeBufferHighWaterMark cannot be less than " +
"writeBufferLowWaterMark (" +
getWriteBufferLowWaterMark() + "): " +
writeBufferHighWaterMark);
}
setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
}
private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
if (writeBufferHighWaterMark < 0) {
throw new IllegalArgumentException("writeBufferHighWaterMark: " +
writeBufferHighWaterMark);
}
this.writeBufferHighWaterMark = writeBufferHighWaterMark;
}
public int getWriteBufferLowWaterMark() {
return writeBufferLowWaterMark;
}
public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
throw new IllegalArgumentException(
"writeBufferLowWaterMark cannot be greater than " +
"writeBufferHighWaterMark (" +
getWriteBufferHighWaterMark() + "): " +
writeBufferLowWaterMark);
}
setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
}
private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
if (writeBufferLowWaterMark < 0) {
throw new IllegalArgumentException("writeBufferLowWaterMark: " +
writeBufferLowWaterMark);
}
this.writeBufferLowWaterMark = writeBufferLowWaterMark;
}
public int getWriteSpinCount() {
return writeSpinCount;
}
public void setWriteSpinCount(int writeSpinCount) {
if (writeSpinCount <= 0) {
throw new IllegalArgumentException(
"writeSpinCount must be a positive integer.");
}
this.writeSpinCount = writeSpinCount;
}
@Override
public void setNetworkInterface(NetworkInterface networkInterface) {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
try {
channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}
@Override
public NetworkInterface getNetworkInterface() {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
try {
return channel.getOption(StandardSocketOptions.IP_MULTICAST_IF);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}
@Override
public int getTimeToLive() {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
try {
return channel.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}
@Override
public void setTimeToLive(int ttl) {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
try {
channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}
@Override
public InetAddress getInterface() {
NetworkInterface inf = getNetworkInterface();
if (inf == null) {
return null;
} else {
Enumeration addresses = inf.getInetAddresses();
if (addresses.hasMoreElements()) {
return addresses.nextElement();
}
return null;
}
}
@Override
public void setInterface(InetAddress interfaceAddress) {
try {
setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddress));
} catch (SocketException e) {
throw new ChannelException(e);
}
}
@Override
public boolean isLoopbackModeDisabled() {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
try {
return channel.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}
@Override
public void setLoopbackModeDisabled(boolean loopbackModeDisabled) {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
try {
channel.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, loopbackModeDisabled);
} catch (IOException e) {
throw new ChannelException(e);
}
}
}
}
DefaultNioSocketChannelConfig.java 0000664 0000000 0000000 00000015634 12255541277 0034703 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.net.Socket;
import java.util.Map;
import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import org.jboss.netty.channel.ReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.socket.DefaultSocketChannelConfig;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.ConversionUtil;
/**
* The default {@link NioSocketChannelConfig} implementation.
*/
class DefaultNioSocketChannelConfig extends DefaultSocketChannelConfig
implements NioSocketChannelConfig {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(DefaultNioSocketChannelConfig.class);
private static final ReceiveBufferSizePredictorFactory DEFAULT_PREDICTOR_FACTORY =
new AdaptiveReceiveBufferSizePredictorFactory();
private volatile int writeBufferHighWaterMark = 64 * 1024;
private volatile int writeBufferLowWaterMark = 32 * 1024;
private volatile ReceiveBufferSizePredictor predictor;
private volatile ReceiveBufferSizePredictorFactory predictorFactory = DEFAULT_PREDICTOR_FACTORY;
private volatile int writeSpinCount = 16;
DefaultNioSocketChannelConfig(Socket socket) {
super(socket);
}
@Override
public void setOptions(Map options) {
super.setOptions(options);
if (getWriteBufferHighWaterMark() < getWriteBufferLowWaterMark()) {
// Recover the integrity of the configuration with a sensible value.
setWriteBufferLowWaterMark0(getWriteBufferHighWaterMark() >>> 1);
if (logger.isWarnEnabled()) {
// Notify the user about misconfiguration.
logger.warn(
"writeBufferLowWaterMark cannot be greater than " +
"writeBufferHighWaterMark; setting to the half of the " +
"writeBufferHighWaterMark.");
}
}
}
@Override
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("writeBufferHighWaterMark".equals(key)) {
setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
} else if ("writeBufferLowWaterMark".equals(key)) {
setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
} else if ("writeSpinCount".equals(key)) {
setWriteSpinCount(ConversionUtil.toInt(value));
} else if ("receiveBufferSizePredictorFactory".equals(key)) {
setReceiveBufferSizePredictorFactory((ReceiveBufferSizePredictorFactory) value);
} else if ("receiveBufferSizePredictor".equals(key)) {
setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
} else {
return false;
}
return true;
}
public int getWriteBufferHighWaterMark() {
return writeBufferHighWaterMark;
}
public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
throw new IllegalArgumentException(
"writeBufferHighWaterMark cannot be less than " +
"writeBufferLowWaterMark (" + getWriteBufferLowWaterMark() + "): " +
writeBufferHighWaterMark);
}
setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
}
private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
if (writeBufferHighWaterMark < 0) {
throw new IllegalArgumentException(
"writeBufferHighWaterMark: " + writeBufferHighWaterMark);
}
this.writeBufferHighWaterMark = writeBufferHighWaterMark;
}
public int getWriteBufferLowWaterMark() {
return writeBufferLowWaterMark;
}
public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
throw new IllegalArgumentException(
"writeBufferLowWaterMark cannot be greater than " +
"writeBufferHighWaterMark (" + getWriteBufferHighWaterMark() + "): " +
writeBufferLowWaterMark);
}
setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
}
private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
if (writeBufferLowWaterMark < 0) {
throw new IllegalArgumentException(
"writeBufferLowWaterMark: " + writeBufferLowWaterMark);
}
this.writeBufferLowWaterMark = writeBufferLowWaterMark;
}
public int getWriteSpinCount() {
return writeSpinCount;
}
public void setWriteSpinCount(int writeSpinCount) {
if (writeSpinCount <= 0) {
throw new IllegalArgumentException(
"writeSpinCount must be a positive integer.");
}
this.writeSpinCount = writeSpinCount;
}
public ReceiveBufferSizePredictor getReceiveBufferSizePredictor() {
ReceiveBufferSizePredictor predictor = this.predictor;
if (predictor == null) {
try {
this.predictor = predictor = getReceiveBufferSizePredictorFactory().getPredictor();
} catch (Exception e) {
throw new ChannelException(
"Failed to create a new " +
ReceiveBufferSizePredictor.class.getSimpleName() + '.',
e);
}
}
return predictor;
}
public void setReceiveBufferSizePredictor(
ReceiveBufferSizePredictor predictor) {
if (predictor == null) {
throw new NullPointerException("predictor");
}
this.predictor = predictor;
}
public ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory() {
return predictorFactory;
}
public void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory) {
if (predictorFactory == null) {
throw new NullPointerException("predictorFactory");
}
this.predictorFactory = predictorFactory;
}
}
NioAcceptedSocketChannel.java 0000664 0000000 0000000 00000002623 12255541277 0033673 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import static org.jboss.netty.channel.Channels.*;
import java.nio.channels.SocketChannel;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
final class NioAcceptedSocketChannel extends NioSocketChannel {
final Thread bossThread;
NioAcceptedSocketChannel(
ChannelFactory factory, ChannelPipeline pipeline,
Channel parent, ChannelSink sink,
SocketChannel socket, NioWorker worker, Thread bossThread) {
super(parent, factory, pipeline, sink, socket, worker);
this.bossThread = bossThread;
setConnected();
fireChannelOpen(this);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioChannelConfig.java 0000664 0000000 0000000 00000006351 12255541277 0032300 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelConfig;
/**
* Special {@link ChannelConfig} sub-type which offers extra methods which are useful for NIO.
*
*/
public interface NioChannelConfig extends ChannelConfig {
/**
* Returns the high water mark of the write buffer. If the number of bytes
* queued in the write buffer exceeds this value, {@link Channel#isWritable()}
* will start to return {@code false}.
*/
int getWriteBufferHighWaterMark();
/**
* Sets the high water mark of the write buffer. If the number of bytes
* queued in the write buffer exceeds this value, {@link Channel#isWritable()}
* will start to return {@code false}.
*/
void setWriteBufferHighWaterMark(int writeBufferHighWaterMark);
/**
* Returns the low water mark of the write buffer. Once the number of bytes
* queued in the write buffer exceeded the
* {@linkplain #setWriteBufferHighWaterMark(int) high water mark} and then
* dropped down below this value, {@link Channel#isWritable()} will start to return
* {@code true} again.
*/
int getWriteBufferLowWaterMark();
/**
* Sets the low water mark of the write buffer. Once the number of bytes
* queued in the write buffer exceeded the
* {@linkplain #setWriteBufferHighWaterMark(int) high water mark} and then
* dropped down below this value, {@link Channel#isWritable()} will start toreturn
* {@code true} again.
*/
void setWriteBufferLowWaterMark(int writeBufferLowWaterMark);
/**
* Returns the maximum loop count for a write operation until
* {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value.
* It is similar to what a spin lock is used for in concurrency programming.
* It improves memory utilization and write throughput depending on
* the platform that JVM runs on. The default value is {@code 16}.
*/
int getWriteSpinCount();
/**
* Sets the maximum loop count for a write operation until
* {@link WritableByteChannel#write(ByteBuffer)} returns a non-zero value.
* It is similar to what a spin lock is used for in concurrency programming.
* It improves memory utilization and write throughput depending on
* the platform that JVM runs on. The default value is {@code 16}.
*
* @throws IllegalArgumentException
* if the specified value is {@code 0} or less than {@code 0}
*/
void setWriteSpinCount(int writeSpinCount);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioClientBoss.java 0000664 0000000 0000000 00000016221 12255541277 0031644 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ConnectTimeoutException;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.Timer;
import org.jboss.netty.util.TimerTask;
import java.io.IOException;
import java.net.ConnectException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import static org.jboss.netty.channel.Channels.*;
/**
* {@link Boss} implementation that handles the connection attempts of clients
*/
public final class NioClientBoss extends AbstractNioSelector implements Boss {
private final TimerTask wakeupTask = new TimerTask() {
public void run(Timeout timeout) throws Exception {
// This is needed to prevent a possible race that can lead to a NPE
// when the selector is closed before this is run
//
// See https://github.com/netty/netty/issues/685
Selector selector = NioClientBoss.this.selector;
if (selector != null) {
if (wakenUp.compareAndSet(false, true)) {
selector.wakeup();
}
}
}
};
private final Timer timer;
NioClientBoss(Executor bossExecutor, Timer timer, ThreadNameDeterminer determiner) {
super(bossExecutor, determiner);
this.timer = timer;
}
@Override
protected ThreadRenamingRunnable newThreadRenamingRunnable(int id, ThreadNameDeterminer determiner) {
return new ThreadRenamingRunnable(this, "New I/O boss #" + id, determiner);
}
@Override
protected Runnable createRegisterTask(Channel channel, ChannelFuture future) {
return new RegisterTask(this, (NioClientSocketChannel) channel);
}
@Override
protected void process(Selector selector) {
processSelectedKeys(selector.selectedKeys());
// Handle connection timeout every 10 milliseconds approximately.
long currentTimeNanos = System.nanoTime();
processConnectTimeout(selector.keys(), currentTimeNanos);
}
private void processSelectedKeys(Set selectedKeys) {
// check if the set is empty and if so just return to not create garbage by
// creating a new Iterator every time even if there is nothing to process.
// See https://github.com/netty/netty/issues/597
if (selectedKeys.isEmpty()) {
return;
}
for (Iterator i = selectedKeys.iterator(); i.hasNext();) {
SelectionKey k = i.next();
i.remove();
if (!k.isValid()) {
close(k);
continue;
}
try {
if (k.isConnectable()) {
connect(k);
}
} catch (Throwable t) {
NioClientSocketChannel ch = (NioClientSocketChannel) k.attachment();
ch.connectFuture.setFailure(t);
fireExceptionCaught(ch, t);
k.cancel(); // Some JDK implementations run into an infinite loop without this.
ch.worker.close(ch, succeededFuture(ch));
}
}
}
private static void processConnectTimeout(Set keys, long currentTimeNanos) {
ConnectException cause = null;
for (SelectionKey k: keys) {
if (!k.isValid()) {
// Comment the close call again as it gave us major problems
// with ClosedChannelExceptions.
//
// See:
// * https://github.com/netty/netty/issues/142
// * https://github.com/netty/netty/issues/138
//
// close(k);
continue;
}
NioClientSocketChannel ch = (NioClientSocketChannel) k.attachment();
if (ch.connectDeadlineNanos > 0 &&
currentTimeNanos >= ch.connectDeadlineNanos) {
if (cause == null) {
cause = new ConnectTimeoutException("connection timed out: " + ch.requestedRemoteAddress);
}
ch.connectFuture.setFailure(cause);
fireExceptionCaught(ch, cause);
ch.worker.close(ch, succeededFuture(ch));
}
}
}
private static void connect(SelectionKey k) throws IOException {
NioClientSocketChannel ch = (NioClientSocketChannel) k.attachment();
try {
if (ch.channel.finishConnect()) {
k.cancel();
if (ch.timoutTimer != null) {
ch.timoutTimer.cancel();
}
ch.worker.register(ch, ch.connectFuture);
}
} catch (ConnectException e) {
ConnectException newE = new ConnectException(e.getMessage() + ": " + ch.requestedRemoteAddress);
newE.setStackTrace(e.getStackTrace());
throw newE;
}
}
@Override
protected void close(SelectionKey k) {
NioClientSocketChannel ch = (NioClientSocketChannel) k.attachment();
ch.worker.close(ch, succeededFuture(ch));
}
private final class RegisterTask implements Runnable {
private final NioClientBoss boss;
private final NioClientSocketChannel channel;
RegisterTask(NioClientBoss boss, NioClientSocketChannel channel) {
this.boss = boss;
this.channel = channel;
}
public void run() {
int timeout = channel.getConfig().getConnectTimeoutMillis();
if (timeout > 0) {
if (!channel.isConnected()) {
channel.timoutTimer = timer.newTimeout(wakeupTask,
timeout, TimeUnit.MILLISECONDS);
}
}
try {
channel.channel.register(
boss.selector, SelectionKey.OP_CONNECT, channel);
} catch (ClosedChannelException e) {
channel.worker.close(channel, succeededFuture(channel));
}
int connectTimeout = channel.getConfig().getConnectTimeoutMillis();
if (connectTimeout > 0) {
channel.connectDeadlineNanos = System.nanoTime() + connectTimeout * 1000000L;
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioClientBossPool.java 0000664 0000000 0000000 00000005273 12255541277 0032503 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.Timer;
import java.util.concurrent.Executor;
/**
* Holds {@link NioClientBoss} instances to use
*/
public class NioClientBossPool extends AbstractNioBossPool {
private final ThreadNameDeterminer determiner;
private final Timer timer;
private boolean stopTimer;
/**
* Create a new instance
*
* @param bossExecutor the Executor to use for server the {@link NioClientBoss}
* @param bossCount the number of {@link NioClientBoss} instances this {@link NioClientBossPool} will hold
* @param timer the Timer to use for handle connect timeouts
* @param determiner the {@link ThreadNameDeterminer} to use for name the threads. Use {@code null}
* if you not want to set one explicit.
*/
public NioClientBossPool(Executor bossExecutor, int bossCount, Timer timer, ThreadNameDeterminer determiner) {
super(bossExecutor, bossCount, false);
this.determiner = determiner;
this.timer = timer;
init();
}
/**
* Create a new instance using a new {@link HashedWheelTimer} and no {@link ThreadNameDeterminer}
*
* @param bossExecutor the Executor to use for server the {@link NioClientBoss}
* @param bossCount the number of {@link NioClientBoss} instances this {@link NioClientBoss} will hold
*/
public NioClientBossPool(Executor bossExecutor, int bossCount) {
this(bossExecutor, bossCount, new HashedWheelTimer(), null);
stopTimer = true;
}
@Override
protected NioClientBoss newBoss(Executor executor) {
return new NioClientBoss(executor, timer, determiner);
}
@Override
public void shutdown() {
super.shutdown();
if (stopTimer) {
timer.stop();
}
}
@Override
public void releaseExternalResources() {
super.releaseExternalResources();
timer.stop();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioClientSocketChannel.java0000664 0000000 0000000 00000005431 12255541277 0033460 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.Timeout;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;
import static org.jboss.netty.channel.Channels.*;
final class NioClientSocketChannel extends NioSocketChannel {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioClientSocketChannel.class);
private static SocketChannel newSocket() {
SocketChannel socket;
try {
socket = SocketChannel.open();
} catch (IOException e) {
throw new ChannelException("Failed to open a socket.", e);
}
boolean success = false;
try {
socket.configureBlocking(false);
success = true;
} catch (IOException e) {
throw new ChannelException("Failed to enter non-blocking mode.", e);
} finally {
if (!success) {
try {
socket.close();
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.",
e);
}
}
}
}
return socket;
}
volatile ChannelFuture connectFuture;
volatile boolean boundManually;
// Does not need to be volatile as it's accessed by only one thread.
long connectDeadlineNanos;
volatile SocketAddress requestedRemoteAddress;
volatile Timeout timoutTimer;
NioClientSocketChannel(
ChannelFactory factory, ChannelPipeline pipeline,
ChannelSink sink, NioWorker worker) {
super(null, factory, pipeline, sink, newSocket(), worker);
fireChannelOpen(this);
}
}
NioClientSocketChannelFactory.java 0000664 0000000 0000000 00000021477 12255541277 0034741 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.nio.channels.Selector;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.util.ExternalResourceReleasable;
import org.jboss.netty.util.Timer;
/**
* A {@link ClientSocketChannelFactory} which creates a client-side NIO-based
* {@link SocketChannel}. It utilizes the non-blocking I/O mode which was
* introduced with NIO to serve many number of concurrent connections
* efficiently.
*
* How threads work
*
* There are two types of threads in a {@link NioClientSocketChannelFactory};
* one is boss thread and the other is worker thread.
*
*
Boss thread
*
* One {@link NioClientSocketChannelFactory} has one boss thread. It makes
* a connection attempt on request. Once a connection attempt succeeds,
* the boss thread passes the connected {@link Channel} to one of the worker
* threads that the {@link NioClientSocketChannelFactory} manages.
*
*
Worker threads
*
* One {@link NioClientSocketChannelFactory} can have one or more worker
* threads. A worker thread performs non-blocking read and write for one or
* more {@link Channel}s in a non-blocking mode.
*
*
Life cycle of threads and graceful shutdown
*
* All threads are acquired from the {@link Executor}s which were specified
* when a {@link NioClientSocketChannelFactory} was created. A boss thread is
* acquired from the {@code bossExecutor}, and worker threads are acquired from
* the {@code workerExecutor}. Therefore, you should make sure the specified
* {@link Executor}s are able to lend the sufficient number of threads.
* It is the best bet to specify {@linkplain Executors#newCachedThreadPool() a cached thread pool}.
*
* Both boss and worker threads are acquired lazily, and then released when
* there's nothing left to process. All the related resources such as
* {@link Selector} are also released when the boss and worker threads are
* released. Therefore, to shut down a service gracefully, you should do the
* following:
*
*
* close all channels created by the factory usually using
* {@link ChannelGroup#close()}, and
* call {@link #releaseExternalResources()}.
*
*
* Please make sure not to shut down the executor until all channels are
* closed. Otherwise, you will end up with a {@link RejectedExecutionException}
* and the related resources might not be released properly.
*
* @apiviz.landmark
*/
public class NioClientSocketChannelFactory implements ClientSocketChannelFactory {
private static final int DEFAULT_BOSS_COUNT = 1;
private final BossPool bossPool;
private final WorkerPool workerPool;
private final NioClientSocketPipelineSink sink;
private boolean releasePools;
/**
* Creates a new {@link NioClientSocketChannelFactory} which uses {@link Executors#newCachedThreadPool()}
* for the worker and boss executors.
*
* See {@link #NioClientSocketChannelFactory(Executor, Executor)}
*/
public NioClientSocketChannelFactory() {
this(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
releasePools = true;
}
/**
* Creates a new instance. Calling this constructor is same with calling
* {@link #NioClientSocketChannelFactory(Executor, Executor, int, int)} with
* 1 and (2 * the number of available processors in the machine) for
* bossCount and workerCount respectively. The number of
* available processors is obtained by {@link Runtime#availableProcessors()}.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss thread
* @param workerExecutor
* the {@link Executor} which will execute the worker threads
*/
public NioClientSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor) {
this(bossExecutor, workerExecutor, DEFAULT_BOSS_COUNT, SelectorUtil.DEFAULT_IO_THREADS);
}
/**
* Creates a new instance. Calling this constructor is same with calling
* {@link #NioClientSocketChannelFactory(Executor, Executor, int, int)} with
* 1 as bossCount .
*
* @param bossExecutor
* the {@link Executor} which will execute the boss thread
* @param workerExecutor
* the {@link Executor} which will execute the worker threads
* @param workerCount
* the maximum number of I/O worker threads
*/
public NioClientSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor, int workerCount) {
this(bossExecutor, workerExecutor, DEFAULT_BOSS_COUNT, workerCount);
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss thread
* @param workerExecutor
* the {@link Executor} which will execute the worker threads
* @param bossCount
* the maximum number of boss threads
* @param workerCount
* the maximum number of I/O worker threads
*/
public NioClientSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor,
int bossCount, int workerCount) {
this(bossExecutor, bossCount, new NioWorkerPool(workerExecutor, workerCount));
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss thread
* @param bossCount
* the maximum number of boss threads
* @param workerPool
* the {@link WorkerPool} to use to do the IO
*/
public NioClientSocketChannelFactory(
Executor bossExecutor, int bossCount,
WorkerPool workerPool) {
this(new NioClientBossPool(bossExecutor, bossCount), workerPool);
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss thread
* @param bossCount
* the maximum number of boss threads
* @param workerPool
* the {@link WorkerPool} to use to do the IO
* @param timer
* the {@link Timer} to use to handle the connection timeouts
*/
public NioClientSocketChannelFactory(
Executor bossExecutor, int bossCount,
WorkerPool workerPool, Timer timer) {
this(new NioClientBossPool(bossExecutor, bossCount, timer, null), workerPool);
}
/**
* Creates a new instance.
*
* @param bossPool
* the {@link BossPool} to use to handle the connects
* @param workerPool
* the {@link WorkerPool} to use to do the IO
*/
public NioClientSocketChannelFactory(
BossPool bossPool,
WorkerPool workerPool) {
if (bossPool == null) {
throw new NullPointerException("bossPool");
}
if (workerPool == null) {
throw new NullPointerException("workerPool");
}
this.bossPool = bossPool;
this.workerPool = workerPool;
sink = new NioClientSocketPipelineSink(bossPool);
}
public SocketChannel newChannel(ChannelPipeline pipeline) {
return new NioClientSocketChannel(this, pipeline, sink, workerPool.nextWorker());
}
public void shutdown() {
bossPool.shutdown();
workerPool.shutdown();
if (releasePools) {
releasePools();
}
}
public void releaseExternalResources() {
shutdown();
releasePools();
}
private void releasePools() {
if (bossPool instanceof ExternalResourceReleasable) {
((ExternalResourceReleasable) bossPool).releaseExternalResources();
}
if (workerPool instanceof ExternalResourceReleasable) {
((ExternalResourceReleasable) workerPool).releaseExternalResources();
}
}
}
NioClientSocketPipelineSink.java 0000664 0000000 0000000 00000012203 12255541277 0034416 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.net.ConnectException;
import java.net.SocketAddress;
import java.nio.channels.ClosedChannelException;
import static org.jboss.netty.channel.Channels.*;
class NioClientSocketPipelineSink extends AbstractNioChannelSink {
static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioClientSocketPipelineSink.class);
private final BossPool bossPool;
NioClientSocketPipelineSink(BossPool bossPool) {
this.bossPool = bossPool;
}
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
ChannelStateEvent event = (ChannelStateEvent) e;
NioClientSocketChannel channel =
(NioClientSocketChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.worker.close(channel, future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (SocketAddress) value);
} else {
channel.worker.close(channel, future);
}
break;
case CONNECTED:
if (value != null) {
connect(channel, future, (SocketAddress) value);
} else {
channel.worker.close(channel, future);
}
break;
case INTEREST_OPS:
channel.worker.setInterestOps(channel, future, ((Integer) value).intValue());
break;
}
} else if (e instanceof MessageEvent) {
MessageEvent event = (MessageEvent) e;
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
boolean offered = channel.writeBufferQueue.offer(event);
assert offered;
channel.worker.writeFromUserCode(channel);
}
}
private static void bind(
NioClientSocketChannel channel, ChannelFuture future,
SocketAddress localAddress) {
try {
channel.channel.socket().bind(localAddress);
channel.boundManually = true;
channel.setBound();
future.setSuccess();
fireChannelBound(channel, channel.getLocalAddress());
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
private void connect(
final NioClientSocketChannel channel, final ChannelFuture cf,
SocketAddress remoteAddress) {
channel.requestedRemoteAddress = remoteAddress;
try {
if (channel.channel.connect(remoteAddress)) {
channel.worker.register(channel, cf);
} else {
channel.getCloseFuture().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f)
throws Exception {
if (!cf.isDone()) {
cf.setFailure(new ClosedChannelException());
}
}
});
cf.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
channel.connectFuture = cf;
nextBoss().register(channel, cf);
}
} catch (Throwable t) {
if (t instanceof ConnectException) {
Throwable newT = new ConnectException(t.getMessage() + ": " + remoteAddress);
newT.setStackTrace(t.getStackTrace());
t = newT;
}
cf.setFailure(t);
fireExceptionCaught(channel, t);
channel.worker.close(channel, succeededFuture(channel));
}
}
private NioClientBoss nextBoss() {
return bossPool.nextBoss();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramChannel.java 0000664 0000000 0000000 00000025251 12255541277 0032613 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.DatagramChannelConfig;
import org.jboss.netty.channel.socket.InternetProtocolFamily;
import org.jboss.netty.util.internal.DetectionUtil;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static org.jboss.netty.channel.Channels.*;
/**
* Provides an NIO based {@link org.jboss.netty.channel.socket.DatagramChannel}.
*/
public class NioDatagramChannel extends AbstractNioChannel
implements org.jboss.netty.channel.socket.DatagramChannel {
/**
* The {@link DatagramChannelConfig}.
*/
private final NioDatagramChannelConfig config;
private Map> memberships;
NioDatagramChannel(final ChannelFactory factory,
final ChannelPipeline pipeline, final ChannelSink sink,
final NioDatagramWorker worker, InternetProtocolFamily family) {
super(null, factory, pipeline, sink, worker, openNonBlockingChannel(family));
config = new DefaultNioDatagramChannelConfig(channel);
fireChannelOpen(this);
}
private static DatagramChannel openNonBlockingChannel(InternetProtocolFamily family) {
try {
final DatagramChannel channel;
// check if we are on java 7 or if the family was not specified
if (DetectionUtil.javaVersion() < 7 || family == null) {
channel = DatagramChannel.open();
} else {
// This block only works on java7++, but we checked before if we have it.
//
// Use the ProtocolFamilyConvert for conversion to prevent NoClassDefFoundError.
//
// See #368
switch (family) {
case IPv4:
channel = DatagramChannel.open(ProtocolFamilyConverter.convert(family));
break;
case IPv6:
channel = DatagramChannel.open(ProtocolFamilyConverter.convert(family));
break;
default:
throw new IllegalArgumentException();
}
}
channel.configureBlocking(false);
return channel;
} catch (final IOException e) {
throw new ChannelException("Failed to open a DatagramChannel.", e);
}
}
@Override
public NioDatagramWorker getWorker() {
return (NioDatagramWorker) super.getWorker();
}
public boolean isBound() {
return isOpen() && channel.socket().isBound();
}
public boolean isConnected() {
return channel.isConnected();
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
@Override
public NioDatagramChannelConfig getConfig() {
return config;
}
DatagramChannel getDatagramChannel() {
return channel;
}
public ChannelFuture joinGroup(InetAddress multicastAddress) {
try {
return joinGroup(
multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), null);
} catch (SocketException e) {
return failedFuture(this, e);
}
}
public ChannelFuture joinGroup(InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
return joinGroup(multicastAddress.getAddress(), networkInterface, null);
}
/**
* Joins the specified multicast group at the specified interface using the specified source.
*/
public ChannelFuture joinGroup(
InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source) {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
}
if (multicastAddress == null) {
throw new NullPointerException("multicastAddress");
}
if (networkInterface == null) {
throw new NullPointerException("networkInterface");
}
try {
MembershipKey key;
if (source == null) {
key = channel.join(multicastAddress, networkInterface);
} else {
key = channel.join(multicastAddress, networkInterface, source);
}
synchronized (this) {
if (memberships == null) {
memberships = new HashMap>();
}
List keys = memberships.get(multicastAddress);
if (keys == null) {
keys = new ArrayList();
memberships.put(multicastAddress, keys);
}
keys.add(key);
}
} catch (Throwable e) {
return failedFuture(this, e);
}
return succeededFuture(this);
}
public ChannelFuture leaveGroup(InetAddress multicastAddress) {
try {
return leaveGroup(
multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), null);
} catch (SocketException e) {
return failedFuture(this, e);
}
}
public ChannelFuture leaveGroup(InetSocketAddress multicastAddress,
NetworkInterface networkInterface) {
return leaveGroup(multicastAddress.getAddress(), networkInterface, null);
}
/**
* Leave the specified multicast group at the specified interface using the specified source.
*/
public ChannelFuture leaveGroup(InetAddress multicastAddress,
NetworkInterface networkInterface, InetAddress source) {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
if (multicastAddress == null) {
throw new NullPointerException("multicastAddress");
}
if (networkInterface == null) {
throw new NullPointerException("networkInterface");
}
synchronized (this) {
if (memberships != null) {
List keys = memberships.get(multicastAddress);
if (keys != null) {
Iterator keyIt = keys.iterator();
while (keyIt.hasNext()) {
MembershipKey key = keyIt.next();
if (networkInterface.equals(key.networkInterface())) {
if (source == null && key.sourceAddress() == null ||
source != null && source.equals(key.sourceAddress())) {
key.drop();
keyIt.remove();
}
}
}
if (keys.isEmpty()) {
memberships.remove(multicastAddress);
}
}
}
}
return succeededFuture(this);
}
}
/**
* Block the given sourceToBlock address for the given multicastAddress on the given networkInterface
*
*/
public ChannelFuture block(InetAddress multicastAddress,
NetworkInterface networkInterface, InetAddress sourceToBlock) {
if (DetectionUtil.javaVersion() < 7) {
throw new UnsupportedOperationException();
} else {
if (multicastAddress == null) {
throw new NullPointerException("multicastAddress");
}
if (sourceToBlock == null) {
throw new NullPointerException("sourceToBlock");
}
if (networkInterface == null) {
throw new NullPointerException("networkInterface");
}
synchronized (this) {
if (memberships != null) {
List keys = memberships.get(multicastAddress);
for (MembershipKey key: keys) {
if (networkInterface.equals(key.networkInterface())) {
try {
key.block(sourceToBlock);
} catch (IOException e) {
return failedFuture(this, e);
}
}
}
}
}
return succeededFuture(this);
}
}
/**
* Block the given sourceToBlock address for the given multicastAddress
*
*/
public ChannelFuture block(InetAddress multicastAddress, InetAddress sourceToBlock) {
try {
block(multicastAddress, NetworkInterface.getByInetAddress(getLocalAddress().getAddress()), sourceToBlock);
} catch (SocketException e) {
return failedFuture(this, e);
}
return succeededFuture(this);
}
@Override
InetSocketAddress getLocalSocketAddress() throws Exception {
return (InetSocketAddress) channel.socket().getLocalSocketAddress();
}
@Override
InetSocketAddress getRemoteSocketAddress() throws Exception {
return (InetSocketAddress) channel.socket().getRemoteSocketAddress();
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
return super.write(message, null);
} else {
return super.write(message, remoteAddress);
}
}
}
NioDatagramChannelConfig.java 0000664 0000000 0000000 00000003261 12255541277 0033657 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.DatagramChannelConfig;
/**
* A {@link DatagramChannelConfig} for a NIO TCP/IP {@link DatagramChannel}.
*
* Available options
*
* In addition to the options provided by {@link ChannelConfig} and
* {@link DatagramChannelConfig}, {@link NioDatagramChannelConfig} allows the
* following options in the option map:
*
*
*
* Name Associated setter method
*
* {@code "writeBufferHighWaterMark"} {@link #setWriteBufferHighWaterMark(int)}
*
* {@code "writeBufferLowWaterMark"} {@link #setWriteBufferLowWaterMark(int)}
*
* {@code "writeSpinCount"} {@link #setWriteSpinCount(int)}
*
*
*/
public interface NioDatagramChannelConfig extends DatagramChannelConfig, NioChannelConfig {
// Tag interface
}
NioDatagramChannelFactory.java 0000664 0000000 0000000 00000022256 12255541277 0034066 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.nio.channels.Selector;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.DatagramChannelFactory;
import org.jboss.netty.channel.socket.InternetProtocolFamily;
import org.jboss.netty.channel.socket.Worker;
import org.jboss.netty.channel.socket.oio.OioDatagramChannelFactory;
import org.jboss.netty.util.ExternalResourceReleasable;
/**
* A {@link DatagramChannelFactory} that creates a NIO-based connectionless
* {@link DatagramChannel}. It utilizes the non-blocking I/O mode which
* was introduced with NIO to serve many number of concurrent connections
* efficiently.
*
* How threads work
*
* There is only one thread type in a {@link NioDatagramChannelFactory};
* worker threads.
*
*
Worker threads
*
* One {@link NioDatagramChannelFactory} can have one or more worker
* threads. A worker thread performs non-blocking read and write for one or
* more {@link DatagramChannel}s in a non-blocking mode.
*
*
Life cycle of threads and graceful shutdown
*
* All worker threads are acquired from the {@link Executor} which was specified
* when a {@link NioDatagramChannelFactory} was created. Therefore, you should
* make sure the specified {@link Executor} is able to lend the sufficient
* number of threads. It is the best bet to specify
* {@linkplain Executors#newCachedThreadPool() a cached thread pool}.
*
* All worker threads are acquired lazily, and then released when there's
* nothing left to process. All the related resources such as {@link Selector}
* are also released when the worker threads are released. Therefore, to shut
* down a service gracefully, you should do the following:
*
*
* close all channels created by the factory usually using
* {@link ChannelGroup#close()}, and
* call {@link #releaseExternalResources()}.
*
*
* Please make sure not to shut down the executor until all channels are
* closed. Otherwise, you will end up with a {@link RejectedExecutionException}
* and the related resources might not be released properly.
*
* Limitation
*
* Multicast is not supported. Please use {@link OioDatagramChannelFactory}
* instead.
*
* @apiviz.landmark
*/
public class NioDatagramChannelFactory implements DatagramChannelFactory {
private final NioDatagramPipelineSink sink;
private final WorkerPool workerPool;
private final InternetProtocolFamily family;
private boolean releasePool;
/**
* Create a new {@link NioDatagramChannelFactory} with a {@link Executors#newCachedThreadPool()}
* and without preferred {@link InternetProtocolFamily}. Please note that the {@link InternetProtocolFamily}
* of the channel will be platform (and possibly configuration) dependent and therefore
* unspecified. Use {@link #NioDatagramChannelFactory(InternetProtocolFamily)} if unsure.
*
* See {@link #NioDatagramChannelFactory(Executor)}
*/
public NioDatagramChannelFactory() {
this((InternetProtocolFamily) null);
}
/**
* Create a new {@link NioDatagramChannelFactory} with a {@link Executors#newCachedThreadPool()}.
*
* See {@link #NioDatagramChannelFactory(Executor)}
*/
public NioDatagramChannelFactory(InternetProtocolFamily family) {
workerPool = new NioDatagramWorkerPool(Executors.newCachedThreadPool(), SelectorUtil.DEFAULT_IO_THREADS);
this.family = family;
sink = new NioDatagramPipelineSink(workerPool);
releasePool = true;
}
/**
* Creates a new instance. Calling this constructor is same with calling
* {@link #NioDatagramChannelFactory(Executor, int)} with 2 * the number of
* available processors in the machine. The number of available processors
* is obtained by {@link Runtime#availableProcessors()}.
*
* Please note that the {@link InternetProtocolFamily} of the channel will be platform (and possibly
* configuration) dependent and therefore unspecified.
* Use {@link #NioDatagramChannelFactory(Executor, InternetProtocolFamily)} if unsure.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
*/
public NioDatagramChannelFactory(final Executor workerExecutor) {
this(workerExecutor, SelectorUtil.DEFAULT_IO_THREADS);
}
/**
* Creates a new instance.
*
* Please note that the {@link InternetProtocolFamily} of the channel will be platform (and possibly
* configuration) dependent and therefore unspecified.
* Use {@link #NioDatagramChannelFactory(Executor, int, InternetProtocolFamily)} if unsure.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param workerCount
* the maximum number of I/O worker threads
*/
public NioDatagramChannelFactory(final Executor workerExecutor, final int workerCount) {
this(new NioDatagramWorkerPool(workerExecutor, workerCount));
}
/**
* Creates a new instance.
*
* Please note that the {@link InternetProtocolFamily} of the channel will be platform (and possibly
* configuration) dependent and therefore unspecified.
* Use {@link #NioDatagramChannelFactory(WorkerPool, InternetProtocolFamily)} if unsure.
*
* @param workerPool
* the {@link WorkerPool} which will be used to obtain the {@link NioDatagramWorker} that execute
* the I/O worker threads
*/
public NioDatagramChannelFactory(WorkerPool workerPool) {
this(workerPool, null);
}
/**
* Creates a new instance. Calling this constructor is same with calling
* {@link #NioDatagramChannelFactory(Executor, int)} with 2 * the number of
* available processors in the machine. The number of available processors
* is obtained by {@link Runtime#availableProcessors()}.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param family
* the {@link InternetProtocolFamily} to use. This should be used for UDP multicast.
* Be aware that this option is only considered when running on java7+
*/
public NioDatagramChannelFactory(final Executor workerExecutor, InternetProtocolFamily family) {
this(workerExecutor, SelectorUtil.DEFAULT_IO_THREADS, family);
}
/**
* Creates a new instance.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param workerCount
* the maximum number of I/O worker threads
* @param family
* the {@link InternetProtocolFamily} to use. This should be used for UDP multicast.
* Be aware that this option is only considered when running on java7+
*/
public NioDatagramChannelFactory(final Executor workerExecutor,
final int workerCount, InternetProtocolFamily family) {
this(new NioDatagramWorkerPool(workerExecutor, workerCount), family);
}
/**
* Creates a new instance.
*
* @param workerPool
* the {@link WorkerPool} which will be used to obtain the {@link Worker} that execute
* the I/O worker threads
* @param family
* the {@link InternetProtocolFamily} to use. This should be used for UDP multicast.
* Be aware that this option is only considered when running on java7+
*/
public NioDatagramChannelFactory(WorkerPool workerPool, InternetProtocolFamily family) {
this.workerPool = workerPool;
this.family = family;
sink = new NioDatagramPipelineSink(workerPool);
}
public DatagramChannel newChannel(final ChannelPipeline pipeline) {
return new NioDatagramChannel(this, pipeline, sink, sink.nextWorker(), family);
}
public void shutdown() {
workerPool.shutdown();
if (releasePool) {
releasePool();
}
}
public void releaseExternalResources() {
shutdown();
releasePool();
}
private void releasePool() {
if (workerPool instanceof ExternalResourceReleasable) {
((ExternalResourceReleasable) workerPool).releaseExternalResources();
}
}
}
NioDatagramPipelineSink.java 0000664 0000000 0000000 00000015043 12255541277 0033554 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import static org.jboss.netty.channel.Channels.*;
import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
/**
* Receives downstream events from a {@link ChannelPipeline}. It contains
* an array of I/O workers.
*/
class NioDatagramPipelineSink extends AbstractNioChannelSink {
private final WorkerPool workerPool;
/**
* Creates a new {@link NioDatagramPipelineSink} with a the number of {@link NioDatagramWorker}s
* specified in workerCount. The {@link NioDatagramWorker}s take care of reading and writing
* for the {@link NioDatagramChannel}.
*
* @param workerExecutor
* the {@link Executor} that will run the {@link NioDatagramWorker}s
* for this sink
* @param workerCount
* the number of {@link NioDatagramWorker}s for this sink
*/
NioDatagramPipelineSink(final WorkerPool workerPool) {
this.workerPool = workerPool;
}
/**
* Handle downstream event.
*
* @param pipeline the {@link ChannelPipeline} that passes down the
* downstream event.
* @param e The downstream event.
*/
public void eventSunk(final ChannelPipeline pipeline, final ChannelEvent e)
throws Exception {
final NioDatagramChannel channel = (NioDatagramChannel) e.getChannel();
final ChannelFuture future = e.getFuture();
if (e instanceof ChannelStateEvent) {
final ChannelStateEvent stateEvent = (ChannelStateEvent) e;
final ChannelState state = stateEvent.getState();
final Object value = stateEvent.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.worker.close(channel, future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (InetSocketAddress) value);
} else {
channel.worker.close(channel, future);
}
break;
case CONNECTED:
if (value != null) {
connect(channel, future, (InetSocketAddress) value);
} else {
NioDatagramWorker.disconnect(channel, future);
}
break;
case INTEREST_OPS:
channel.worker.setInterestOps(channel, future, ((Integer) value).intValue());
break;
}
} else if (e instanceof MessageEvent) {
final MessageEvent event = (MessageEvent) e;
final boolean offered = channel.writeBufferQueue.offer(event);
assert offered;
channel.worker.writeFromUserCode(channel);
}
}
private static void close(NioDatagramChannel channel, ChannelFuture future) {
try {
channel.getDatagramChannel().socket().close();
if (channel.setClosed()) {
future.setSuccess();
if (channel.isBound()) {
fireChannelUnbound(channel);
}
fireChannelClosed(channel);
} else {
future.setSuccess();
}
} catch (final Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
/**
* Will bind the DatagramSocket to the passed-in address.
* Every call bind will spawn a new thread using the that basically in turn
*/
private static void bind(final NioDatagramChannel channel,
final ChannelFuture future, final InetSocketAddress address) {
boolean bound = false;
boolean started = false;
try {
// First bind the DatagramSocket the specified port.
channel.getDatagramChannel().socket().bind(address);
bound = true;
future.setSuccess();
fireChannelBound(channel, address);
channel.worker.register(channel, null);
started = true;
} catch (final Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (!started && bound) {
close(channel, future);
}
}
}
private static void connect(
NioDatagramChannel channel, ChannelFuture future,
InetSocketAddress remoteAddress) {
boolean bound = channel.isBound();
boolean connected = false;
boolean workerStarted = false;
future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
// Clear the cached address so that the next getRemoteAddress() call
// updates the cache.
channel.remoteAddress = null;
try {
channel.getDatagramChannel().connect(remoteAddress);
connected = true;
// Fire events.
future.setSuccess();
if (!bound) {
fireChannelBound(channel, channel.getLocalAddress());
}
fireChannelConnected(channel, channel.getRemoteAddress());
if (!bound) {
channel.worker.register(channel, future);
}
workerStarted = true;
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (connected && !workerStarted) {
channel.worker.close(channel, future);
}
}
}
NioDatagramWorker nextWorker() {
return workerPool.nextWorker();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramWorker.java 0000664 0000000 0000000 00000030662 12255541277 0032516 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Queue;
import java.util.concurrent.Executor;
import static org.jboss.netty.channel.Channels.*;
/**
* A class responsible for registering channels with {@link Selector}.
* It also implements the {@link Selector} loop.
*/
public class NioDatagramWorker extends AbstractNioWorker {
private final SocketReceiveBufferAllocator bufferAllocator = new SocketReceiveBufferAllocator();
/**
* Sole constructor.
*
* @param executor the {@link Executor} used to execute {@link Runnable}s
* such as {@link ChannelRegistionTask}
*/
NioDatagramWorker(final Executor executor) {
super(executor);
}
@Override
protected boolean read(final SelectionKey key) {
final NioDatagramChannel channel = (NioDatagramChannel) key.attachment();
ReceiveBufferSizePredictor predictor =
channel.getConfig().getReceiveBufferSizePredictor();
final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();
final DatagramChannel nioChannel = (DatagramChannel) key.channel();
final int predictedRecvBufSize = predictor.nextReceiveBufferSize();
final ByteBuffer byteBuffer = bufferAllocator.get(predictedRecvBufSize).order(bufferFactory.getDefaultOrder());
boolean failure = true;
SocketAddress remoteAddress = null;
try {
// Receive from the channel in a non blocking mode. We have already been notified that
// the channel is ready to receive.
remoteAddress = nioChannel.receive(byteBuffer);
failure = false;
} catch (ClosedChannelException e) {
// Can happen, and does not need a user attention.
} catch (Throwable t) {
fireExceptionCaught(channel, t);
}
if (remoteAddress != null) {
// Flip the buffer so that we can wrap it.
byteBuffer.flip();
int readBytes = byteBuffer.remaining();
if (readBytes > 0) {
// Update the predictor.
predictor.previousReceiveBufferSize(readBytes);
final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes);
buffer.setBytes(0, byteBuffer);
buffer.writerIndex(readBytes);
// Update the predictor.
predictor.previousReceiveBufferSize(readBytes);
// Notify the interested parties about the newly arrived message.
fireMessageReceived(
channel, buffer, remoteAddress);
}
}
if (failure) {
key.cancel(); // Some JDK implementations run into an infinite loop without this.
close(channel, succeededFuture(channel));
return false;
}
return true;
}
@Override
protected boolean scheduleWriteIfNecessary(final AbstractNioChannel> channel) {
final Thread workerThread = thread;
if (workerThread == null || Thread.currentThread() != workerThread) {
if (channel.writeTaskInTaskQueue.compareAndSet(false, true)) {
// "add" the channels writeTask to the writeTaskQueue.
registerTask(channel.writeTask);
}
return true;
}
return false;
}
static void disconnect(NioDatagramChannel channel, ChannelFuture future) {
boolean connected = channel.isConnected();
boolean iothread = isIoThread(channel);
try {
channel.getDatagramChannel().disconnect();
future.setSuccess();
if (connected) {
if (iothread) {
fireChannelDisconnected(channel);
} else {
fireChannelDisconnectedLater(channel);
}
}
} catch (Throwable t) {
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
@Override
protected Runnable createRegisterTask(Channel channel, ChannelFuture future) {
return new ChannelRegistionTask((NioDatagramChannel) channel, future);
}
/**
* RegisterTask is a task responsible for registering a channel with a
* selector.
*/
private final class ChannelRegistionTask implements Runnable {
private final NioDatagramChannel channel;
private final ChannelFuture future;
ChannelRegistionTask(final NioDatagramChannel channel,
final ChannelFuture future) {
this.channel = channel;
this.future = future;
}
/**
* This runnable's task. Does the actual registering by calling the
* underlying DatagramChannels peer DatagramSocket register method.
*/
public void run() {
final SocketAddress localAddress = channel.getLocalAddress();
if (localAddress == null) {
if (future != null) {
future.setFailure(new ClosedChannelException());
}
close(channel, succeededFuture(channel));
return;
}
try {
channel.getDatagramChannel().register(
selector, channel.getRawInterestOps(), channel);
if (future != null) {
future.setSuccess();
}
} catch (final IOException e) {
if (future != null) {
future.setFailure(e);
}
close(channel, succeededFuture(channel));
if (!(e instanceof ClosedChannelException)) {
throw new ChannelException(
"Failed to register a socket to the selector.", e);
}
}
}
}
@Override
public void writeFromUserCode(final AbstractNioChannel> channel) {
/*
* Note that we are not checking if the channel is connected. Connected
* has a different meaning in UDP and means that the channels socket is
* configured to only send and receive from a given remote peer.
*/
if (!channel.isBound()) {
cleanUpWriteBuffer(channel);
return;
}
if (scheduleWriteIfNecessary(channel)) {
return;
}
// From here, we are sure Thread.currentThread() == workerThread.
if (channel.writeSuspended) {
return;
}
if (channel.inWriteNowLoop) {
return;
}
write0(channel);
}
@Override
protected void write0(final AbstractNioChannel> channel) {
boolean addOpWrite = false;
boolean removeOpWrite = false;
long writtenBytes = 0;
final SocketSendBufferPool sendBufferPool = this.sendBufferPool;
final DatagramChannel ch = ((NioDatagramChannel) channel).getDatagramChannel();
final Queue writeBuffer = channel.writeBufferQueue;
final int writeSpinCount = channel.getConfig().getWriteSpinCount();
synchronized (channel.writeLock) {
// inform the channel that write is in-progress
channel.inWriteNowLoop = true;
// loop forever...
for (;;) {
MessageEvent evt = channel.currentWriteEvent;
SocketSendBufferPool.SendBuffer buf;
if (evt == null) {
if ((channel.currentWriteEvent = evt = writeBuffer.poll()) == null) {
removeOpWrite = true;
channel.writeSuspended = false;
break;
}
channel.currentWriteBuffer = buf = sendBufferPool.acquire(evt.getMessage());
} else {
buf = channel.currentWriteBuffer;
}
try {
long localWrittenBytes = 0;
SocketAddress raddr = evt.getRemoteAddress();
if (raddr == null) {
for (int i = writeSpinCount; i > 0; i --) {
localWrittenBytes = buf.transferTo(ch);
if (localWrittenBytes != 0) {
writtenBytes += localWrittenBytes;
break;
}
if (buf.finished()) {
break;
}
}
} else {
for (int i = writeSpinCount; i > 0; i --) {
localWrittenBytes = buf.transferTo(ch, raddr);
if (localWrittenBytes != 0) {
writtenBytes += localWrittenBytes;
break;
}
if (buf.finished()) {
break;
}
}
}
if (localWrittenBytes > 0 || buf.finished()) {
// Successful write - proceed to the next message.
buf.release();
ChannelFuture future = evt.getFuture();
channel.currentWriteEvent = null;
channel.currentWriteBuffer = null;
evt = null;
buf = null;
future.setSuccess();
} else {
// Not written at all - perhaps the kernel buffer is full.
addOpWrite = true;
channel.writeSuspended = true;
break;
}
} catch (final AsynchronousCloseException e) {
// Doesn't need a user attention - ignore.
} catch (final Throwable t) {
buf.release();
ChannelFuture future = evt.getFuture();
channel.currentWriteEvent = null;
channel.currentWriteBuffer = null;
// Mark the event object for garbage collection.
//noinspection UnusedAssignment
buf = null;
//noinspection UnusedAssignment
evt = null;
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
channel.inWriteNowLoop = false;
// Initially, the following block was executed after releasing
// the writeLock, but there was a race condition, and it has to be
// executed before releasing the writeLock:
//
// https://issues.jboss.org/browse/NETTY-410
//
if (addOpWrite) {
setOpWrite(channel);
} else if (removeOpWrite) {
clearOpWrite(channel);
}
}
fireWriteComplete(channel, writtenBytes);
}
@Override
public void run() {
super.run();
bufferAllocator.releaseExternalResources();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioDatagramWorkerPool.java 0000664 0000000 0000000 00000002206 12255541277 0033341 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.util.concurrent.Executor;
/**
* Default implementation which hands of {@link NioDatagramWorker}'s
*
*
*/
public class NioDatagramWorkerPool extends AbstractNioWorkerPool {
public NioDatagramWorkerPool(Executor executor, int workerCount) {
super(executor, workerCount);
}
@Override
@Deprecated
protected NioDatagramWorker createWorker(Executor executor) {
return new NioDatagramWorker(executor);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioSelector.java 0000664 0000000 0000000 00000002124 12255541277 0031354 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import java.nio.channels.Selector;
public interface NioSelector extends Runnable {
void register(Channel channel, ChannelFuture future);
/**
* Replaces the current {@link Selector} with a new {@link Selector} to work around the infamous epoll 100% CPU
* bug.
*/
void rebuildSelector();
void shutdown();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioSelectorPool.java 0000664 0000000 0000000 00000002053 12255541277 0032207 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.nio.channels.Selector;
public interface NioSelectorPool {
/**
* Replaces the current {@link Selector}s of the {@link Boss}es with new {@link Selector}s to work around the
* infamous epoll 100% CPU bug.
*/
void rebuildSelectors();
/**
* Shutdown the {@link NioSelectorPool} and all internal created resources
*/
void shutdown();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioServerBoss.java 0000664 0000000 0000000 00000016475 12255541277 0031707 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import java.io.IOException;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Executor;
import static org.jboss.netty.channel.Channels.*;
/**
* Boss implementation which handles accepting of new connections
*/
public final class NioServerBoss extends AbstractNioSelector implements Boss {
NioServerBoss(Executor bossExecutor) {
super(bossExecutor);
}
NioServerBoss(Executor bossExecutor, ThreadNameDeterminer determiner) {
super(bossExecutor, determiner);
}
void bind(final NioServerSocketChannel channel, final ChannelFuture future,
final SocketAddress localAddress) {
registerTask(new RegisterTask(channel, future, localAddress));
}
@Override
protected void close(SelectionKey k) {
NioServerSocketChannel ch = (NioServerSocketChannel) k.attachment();
close(ch, succeededFuture(ch));
}
void close(NioServerSocketChannel channel, ChannelFuture future) {
boolean bound = channel.isBound();
try {
channel.socket.close();
increaseCancelledKeys();
if (channel.setClosed()) {
future.setSuccess();
if (bound) {
fireChannelUnbound(channel);
}
fireChannelClosed(channel);
} else {
future.setSuccess();
}
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
@Override
protected void process(Selector selector) {
Set selectedKeys = selector.selectedKeys();
if (selectedKeys.isEmpty()) {
return;
}
for (Iterator i = selectedKeys.iterator(); i.hasNext();) {
SelectionKey k = i.next();
i.remove();
NioServerSocketChannel channel = (NioServerSocketChannel) k.attachment();
try {
// accept connections in a for loop until no new connection is ready
for (;;) {
SocketChannel acceptedSocket = channel.socket.accept();
if (acceptedSocket == null) {
break;
}
registerAcceptedChannel(channel, acceptedSocket, thread);
}
} catch (CancelledKeyException e) {
// Raised by accept() when the server socket was closed.
k.cancel();
channel.close();
} catch (SocketTimeoutException e) {
// Thrown every second to get ClosedChannelException
// raised.
} catch (ClosedChannelException e) {
// Closed as requested.
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to accept a connection.", t);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// Ignore
}
}
}
}
private static void registerAcceptedChannel(NioServerSocketChannel parent, SocketChannel acceptedSocket,
Thread currentThread) {
try {
ChannelSink sink = parent.getPipeline().getSink();
ChannelPipeline pipeline =
parent.getConfig().getPipelineFactory().getPipeline();
NioWorker worker = parent.workerPool.nextWorker();
worker.register(new NioAcceptedSocketChannel(
parent.getFactory(), pipeline, parent, sink
, acceptedSocket,
worker, currentThread), null);
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to initialize an accepted socket.", e);
}
try {
acceptedSocket.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially accepted socket.",
e2);
}
}
}
}
@Override
protected int select(Selector selector) throws IOException {
// Just do a blocking select without any timeout
// as this thread does not execute anything else.
return selector.select();
}
@Override
protected ThreadRenamingRunnable newThreadRenamingRunnable(int id, ThreadNameDeterminer determiner) {
return new ThreadRenamingRunnable(this,
"New I/O server boss #" + id, determiner);
}
@Override
protected Runnable createRegisterTask(Channel channel, ChannelFuture future) {
return new RegisterTask((NioServerSocketChannel) channel, future, null);
}
private final class RegisterTask implements Runnable {
private final NioServerSocketChannel channel;
private final ChannelFuture future;
private final SocketAddress localAddress;
public RegisterTask(final NioServerSocketChannel channel, final ChannelFuture future,
final SocketAddress localAddress) {
this.channel = channel;
this.future = future;
this.localAddress = localAddress;
}
public void run() {
boolean bound = false;
boolean registered = false;
try {
channel.socket.socket().bind(localAddress, channel.getConfig().getBacklog());
bound = true;
future.setSuccess();
fireChannelBound(channel, channel.getLocalAddress());
channel.socket.register(selector, SelectionKey.OP_ACCEPT, channel);
registered = true;
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (!registered && bound) {
close(channel, future);
}
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioServerBossPool.java 0000664 0000000 0000000 00000004147 12255541277 0032532 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.util.ThreadNameDeterminer;
import java.util.concurrent.Executor;
/**
* Holds {@link NioServerBoss} instances to use
*/
public class NioServerBossPool extends AbstractNioBossPool {
private final ThreadNameDeterminer determiner;
/**
* Create a new instance
*
* @param bossExecutor the {@link Executor} to use for server the {@link NioServerBoss}
* @param bossCount the number of {@link NioServerBoss} instances this {@link NioServerBossPool} will hold
* @param determiner the {@link ThreadNameDeterminer} to use for name the threads. Use {@code null}
* if you not want to set one explicit.
*/
public NioServerBossPool(Executor bossExecutor, int bossCount, ThreadNameDeterminer determiner) {
super(bossExecutor, bossCount, false);
this.determiner = determiner;
init();
}
/**
* Create a new instance using no {@link ThreadNameDeterminer}
*
* @param bossExecutor the {@link Executor} to use for server the {@link NioServerBoss}
* @param bossCount the number of {@link NioServerBoss} instances this {@link NioServerBossPool} will hold
*/
public NioServerBossPool(Executor bossExecutor, int bossCount) {
this(bossExecutor, bossCount, null);
}
@Override
protected NioServerBoss newBoss(Executor executor) {
return new NioServerBoss(executor, determiner);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioServerSocketChannel.java0000664 0000000 0000000 00000006346 12255541277 0033516 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import static org.jboss.netty.channel.Channels.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import org.jboss.netty.channel.AbstractServerChannel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.DefaultServerSocketChannelConfig;
import org.jboss.netty.channel.socket.ServerSocketChannelConfig;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
class NioServerSocketChannel extends AbstractServerChannel
implements org.jboss.netty.channel.socket.ServerSocketChannel {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
final ServerSocketChannel socket;
final Boss boss;
final WorkerPool workerPool;
private final ServerSocketChannelConfig config;
NioServerSocketChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink, Boss boss, WorkerPool workerPool) {
super(factory, pipeline, sink);
this.boss = boss;
this.workerPool = workerPool;
try {
socket = ServerSocketChannel.open();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
try {
socket.configureBlocking(false);
} catch (IOException e) {
try {
socket.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
config = new DefaultServerSocketChannelConfig(socket.socket());
fireChannelOpen(this);
}
public ServerSocketChannelConfig getConfig() {
return config;
}
public InetSocketAddress getLocalAddress() {
return (InetSocketAddress) socket.socket().getLocalSocketAddress();
}
public InetSocketAddress getRemoteAddress() {
return null;
}
public boolean isBound() {
return isOpen() && socket.socket().isBound();
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
}
NioServerSocketChannelFactory.java 0000664 0000000 0000000 00000023356 12255541277 0034767 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import java.nio.channels.Selector;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.ServerSocketChannel;
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
import org.jboss.netty.util.ExternalResourceReleasable;
/**
* A {@link ServerSocketChannelFactory} which creates a server-side NIO-based
* {@link ServerSocketChannel}. It utilizes the non-blocking I/O mode which
* was introduced with NIO to serve many number of concurrent connections
* efficiently.
*
* How threads work
*
* There are two types of threads in a {@link NioServerSocketChannelFactory};
* one is boss thread and the other is worker thread.
*
*
Boss threads
*
* Each bound {@link ServerSocketChannel} has its own boss thread.
* For example, if you opened two server ports such as 80 and 443, you will
* have two boss threads. A boss thread accepts incoming connections until
* the port is unbound. Once a connection is accepted successfully, the boss
* thread passes the accepted {@link Channel} to one of the worker
* threads that the {@link NioServerSocketChannelFactory} manages.
*
*
Worker threads
*
* One {@link NioServerSocketChannelFactory} can have one or more worker
* threads. A worker thread performs non-blocking read and write for one or
* more {@link Channel}s in a non-blocking mode.
*
*
Life cycle of threads and graceful shutdown
*
* All threads are acquired from the {@link Executor}s which were specified
* when a {@link NioServerSocketChannelFactory} was created. Boss threads are
* acquired from the {@code bossExecutor}, and worker threads are acquired from
* the {@code workerExecutor}. Therefore, you should make sure the specified
* {@link Executor}s are able to lend the sufficient number of threads.
* It is the best bet to specify {@linkplain Executors#newCachedThreadPool() a cached thread pool}.
*
* Both boss and worker threads are acquired lazily, and then released when
* there's nothing left to process. All the related resources such as
* {@link Selector} are also released when the boss and worker threads are
* released. Therefore, to shut down a service gracefully, you should do the
* following:
*
*
* unbind all channels created by the factory,
* close all child channels accepted by the unbound channels, and
* (these two steps so far is usually done using {@link ChannelGroup#close()})
* call {@link #releaseExternalResources()}.
*
*
* Please make sure not to shut down the executor until all channels are
* closed. Otherwise, you will end up with a {@link RejectedExecutionException}
* and the related resources might not be released properly.
*
* @apiviz.landmark
*/
public class NioServerSocketChannelFactory implements ServerSocketChannelFactory {
private final WorkerPool workerPool;
private final NioServerSocketPipelineSink sink;
private final BossPool bossPool;
private boolean releasePools;
/**
* Create a new {@link NioServerSocketChannelFactory} using {@link Executors#newCachedThreadPool()}
* for the boss and worker.
*
* See {@link #NioServerSocketChannelFactory(Executor, Executor)}
*/
public NioServerSocketChannelFactory() {
this(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
releasePools = true;
}
/**
* Creates a new instance. Calling this constructor is same with calling
* {@link #NioServerSocketChannelFactory(Executor, Executor, int)} with
* the worker executor passed into {@link #getMaxThreads(Executor)}.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
*/
public NioServerSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor) {
this(bossExecutor, workerExecutor, getMaxThreads(workerExecutor));
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param workerCount
* the maximum number of I/O worker threads
*/
public NioServerSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor,
int workerCount) {
this(bossExecutor, 1, workerExecutor, workerCount);
}
/**
* Create a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param bossCount
* the number of boss threads
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param workerCount
* the maximum number of I/O worker threads
*/
public NioServerSocketChannelFactory(
Executor bossExecutor, int bossCount, Executor workerExecutor,
int workerCount) {
this(bossExecutor, bossCount, new NioWorkerPool(workerExecutor, workerCount));
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param workerPool
* the {@link WorkerPool} which will be used to obtain the {@link NioWorker} that execute
* the I/O worker threads
*/
public NioServerSocketChannelFactory(
Executor bossExecutor, WorkerPool workerPool) {
this(bossExecutor, 1 , workerPool);
}
/**
* Create a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param bossCount
* the number of boss threads
* @param workerPool
* the {@link WorkerPool} which will be used to obtain the {@link NioWorker} that execute
* the I/O worker threads
*/
public NioServerSocketChannelFactory(
Executor bossExecutor, int bossCount, WorkerPool workerPool) {
this(new NioServerBossPool(bossExecutor, bossCount, null), workerPool);
}
/**
* Create a new instance.
*
* @param bossPool
* the {@link BossPool} which will be used to obtain the {@link NioServerBoss} that execute
* the I/O for accept new connections
* @param workerPool
* the {@link WorkerPool} which will be used to obtain the {@link NioWorker} that execute
* the I/O worker threads
*/
public NioServerSocketChannelFactory(BossPool bossPool, WorkerPool workerPool) {
if (bossPool == null) {
throw new NullPointerException("bossExecutor");
}
if (workerPool == null) {
throw new NullPointerException("workerPool");
}
this.bossPool = bossPool;
this.workerPool = workerPool;
sink = new NioServerSocketPipelineSink();
}
public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
return new NioServerSocketChannel(this, pipeline, sink, bossPool.nextBoss(), workerPool);
}
public void shutdown() {
bossPool.shutdown();
workerPool.shutdown();
if (releasePools) {
releasePools();
}
}
public void releaseExternalResources() {
shutdown();
releasePools();
}
private void releasePools() {
if (bossPool instanceof ExternalResourceReleasable) {
((ExternalResourceReleasable) bossPool).releaseExternalResources();
}
if (workerPool instanceof ExternalResourceReleasable) {
((ExternalResourceReleasable) workerPool).releaseExternalResources();
}
}
/**
* Returns number of max threads for the {@link NioWorkerPool} to use. If
* the * {@link Executor} is a {@link ThreadPoolExecutor}, check its
* maximum * pool size and return either it's maximum or
* {@link SelectorUtil#DEFAULT_IO_THREADS}, whichever is lower. Note that
* {@link SelectorUtil#DEFAULT_IO_THREADS} is 2 * the number of available
* processors in the machine. The number of available processors is
* obtained by {@link Runtime#availableProcessors()}.
*
* @param executor
* the {@link Executor} which will execute the I/O worker threads
* @return
* number of maximum threads the NioWorkerPool should use
*/
private static int getMaxThreads(Executor executor) {
if (executor instanceof ThreadPoolExecutor) {
final int maxThreads = ((ThreadPoolExecutor) executor).getMaximumPoolSize();
return Math.min(maxThreads, SelectorUtil.DEFAULT_IO_THREADS);
}
return SelectorUtil.DEFAULT_IO_THREADS;
}
}
NioServerSocketPipelineSink.java 0000664 0000000 0000000 00000007164 12255541277 0034460 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import java.net.SocketAddress;
class NioServerSocketPipelineSink extends AbstractNioChannelSink {
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
Channel channel = e.getChannel();
if (channel instanceof NioServerSocketChannel) {
handleServerSocket(e);
} else if (channel instanceof NioSocketChannel) {
handleAcceptedSocket(e);
}
}
private static void handleServerSocket(ChannelEvent e) {
if (!(e instanceof ChannelStateEvent)) {
return;
}
ChannelStateEvent event = (ChannelStateEvent) e;
NioServerSocketChannel channel =
(NioServerSocketChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
((NioServerBoss) channel.boss).close(channel, future);
}
break;
case BOUND:
if (value != null) {
((NioServerBoss) channel.boss).bind(channel, future, (SocketAddress) value);
} else {
((NioServerBoss) channel.boss).close(channel, future);
}
break;
default:
break;
}
}
private static void handleAcceptedSocket(ChannelEvent e) {
if (e instanceof ChannelStateEvent) {
ChannelStateEvent event = (ChannelStateEvent) e;
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
channel.worker.close(channel, future);
}
break;
case BOUND:
case CONNECTED:
if (value == null) {
channel.worker.close(channel, future);
}
break;
case INTEREST_OPS:
channel.worker.setInterestOps(channel, future, ((Integer) value).intValue());
break;
}
} else if (e instanceof MessageEvent) {
MessageEvent event = (MessageEvent) e;
NioSocketChannel channel = (NioSocketChannel) event.getChannel();
boolean offered = channel.writeBufferQueue.offer(event);
assert offered;
channel.worker.writeFromUserCode(channel);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioSocketChannel.java 0000664 0000000 0000000 00000006351 12255541277 0032323 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;
public class NioSocketChannel extends AbstractNioChannel
implements org.jboss.netty.channel.socket.SocketChannel {
private static final int ST_OPEN = 0;
private static final int ST_BOUND = 1;
private static final int ST_CONNECTED = 2;
private static final int ST_CLOSED = -1;
@SuppressWarnings("RedundantFieldInitialization")
volatile int state = ST_OPEN;
private final NioSocketChannelConfig config;
public NioSocketChannel(
Channel parent, ChannelFactory factory,
ChannelPipeline pipeline, ChannelSink sink,
SocketChannel socket, NioWorker worker) {
super(parent, factory, pipeline, sink, worker, socket);
config = new DefaultNioSocketChannelConfig(socket.socket());
}
@Override
public NioWorker getWorker() {
return (NioWorker) super.getWorker();
}
@Override
public NioSocketChannelConfig getConfig() {
return config;
}
@Override
public boolean isOpen() {
return state >= ST_OPEN;
}
public boolean isBound() {
return state >= ST_BOUND;
}
public boolean isConnected() {
return state == ST_CONNECTED;
}
final void setBound() {
assert state == ST_OPEN : "Invalid state: " + state;
state = ST_BOUND;
}
final void setConnected() {
if (state != ST_CLOSED) {
state = ST_CONNECTED;
}
}
@Override
protected boolean setClosed() {
if (super.setClosed()) {
state = ST_CLOSED;
return true;
}
return false;
}
@Override
InetSocketAddress getLocalSocketAddress() throws Exception {
return (InetSocketAddress) channel.socket().getLocalSocketAddress();
}
@Override
InetSocketAddress getRemoteSocketAddress() throws Exception {
return (InetSocketAddress) channel.socket().getRemoteSocketAddress();
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
return super.write(message, null);
} else {
return getUnsupportedOperationFuture();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioSocketChannelConfig.java0000664 0000000 0000000 00000007725 12255541277 0033457 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictor;
import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import org.jboss.netty.channel.ReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.channel.socket.SocketChannelConfig;
/**
* A {@link SocketChannelConfig} for a NIO TCP/IP {@link SocketChannel}.
*
* Available options
*
* In addition to the options provided by {@link ChannelConfig} and
* {@link SocketChannelConfig}, {@link NioSocketChannelConfig} allows the
* following options in the option map:
*
*
*
* Name Associated setter method
*
* {@code "writeBufferHighWaterMark"} {@link #setWriteBufferHighWaterMark(int)}
*
* {@code "writeBufferLowWaterMark"} {@link #setWriteBufferLowWaterMark(int)}
*
* {@code "writeSpinCount"} {@link #setWriteSpinCount(int)}
*
* {@code "receiveBufferSizePredictor"}
* {@link #setReceiveBufferSizePredictor(ReceiveBufferSizePredictor)}
*
* {@code "receiveBufferSizePredictorFactory"}
* {@link #setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory)}
*
*
*/
public interface NioSocketChannelConfig extends SocketChannelConfig, NioChannelConfig {
/**
* Returns the {@link ReceiveBufferSizePredictor} which predicts the
* number of readable bytes in the socket receive buffer. The default
* predictor is {@link AdaptiveReceiveBufferSizePredictor}(64, 1024, 65536) .
*/
ReceiveBufferSizePredictor getReceiveBufferSizePredictor();
/**
* Sets the {@link ReceiveBufferSizePredictor} which predicts the
* number of readable bytes in the socket receive buffer. The default
* predictor is {@link AdaptiveReceiveBufferSizePredictor}(64, 1024, 65536) .
*/
void setReceiveBufferSizePredictor(ReceiveBufferSizePredictor predictor);
/**
* Returns the {@link ReceiveBufferSizePredictorFactory} which creates a new
* {@link ReceiveBufferSizePredictor} when a new channel is created and
* no {@link ReceiveBufferSizePredictor} was set. If no predictor was set
* for the channel, {@link #setReceiveBufferSizePredictor(ReceiveBufferSizePredictor)}
* will be called with the new predictor. The default factory is
* {@link AdaptiveReceiveBufferSizePredictorFactory}(64, 1024, 65536) .
*/
ReceiveBufferSizePredictorFactory getReceiveBufferSizePredictorFactory();
/**
* Sets the {@link ReceiveBufferSizePredictor} which creates a new
* {@link ReceiveBufferSizePredictor} when a new channel is created and
* no {@link ReceiveBufferSizePredictor} was set. If no predictor was set
* for the channel, {@link #setReceiveBufferSizePredictor(ReceiveBufferSizePredictor)}
* will be called with the new predictor. The default factory is
* {@link AdaptiveReceiveBufferSizePredictorFactory}(64, 1024, 65536) .
*/
void setReceiveBufferSizePredictorFactory(ReceiveBufferSizePredictorFactory predictorFactory);
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioWorker.java 0000664 0000000 0000000 00000013774 12255541277 0031062 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferFactory;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import org.jboss.netty.util.ThreadNameDeterminer;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
import static org.jboss.netty.channel.Channels.*;
public class NioWorker extends AbstractNioWorker {
private final SocketReceiveBufferAllocator recvBufferPool = new SocketReceiveBufferAllocator();
public NioWorker(Executor executor) {
super(executor);
}
public NioWorker(Executor executor, ThreadNameDeterminer determiner) {
super(executor, determiner);
}
@Override
protected boolean read(SelectionKey k) {
final SocketChannel ch = (SocketChannel) k.channel();
final NioSocketChannel channel = (NioSocketChannel) k.attachment();
final ReceiveBufferSizePredictor predictor =
channel.getConfig().getReceiveBufferSizePredictor();
final int predictedRecvBufSize = predictor.nextReceiveBufferSize();
final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();
int ret = 0;
int readBytes = 0;
boolean failure = true;
ByteBuffer bb = recvBufferPool.get(predictedRecvBufSize).order(bufferFactory.getDefaultOrder());
try {
while ((ret = ch.read(bb)) > 0) {
readBytes += ret;
if (!bb.hasRemaining()) {
break;
}
}
failure = false;
} catch (ClosedChannelException e) {
// Can happen, and does not need a user attention.
} catch (Throwable t) {
fireExceptionCaught(channel, t);
}
if (readBytes > 0) {
bb.flip();
final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes);
buffer.setBytes(0, bb);
buffer.writerIndex(readBytes);
// Update the predictor.
predictor.previousReceiveBufferSize(readBytes);
// Fire the event.
fireMessageReceived(channel, buffer);
}
if (ret < 0 || failure) {
k.cancel(); // Some JDK implementations run into an infinite loop without this.
close(channel, succeededFuture(channel));
return false;
}
return true;
}
@Override
protected boolean scheduleWriteIfNecessary(final AbstractNioChannel> channel) {
final Thread currentThread = Thread.currentThread();
final Thread workerThread = thread;
if (currentThread != workerThread) {
if (channel.writeTaskInTaskQueue.compareAndSet(false, true)) {
registerTask(channel.writeTask);
}
return true;
}
return false;
}
@Override
protected Runnable createRegisterTask(Channel channel, ChannelFuture future) {
boolean server = !(channel instanceof NioClientSocketChannel);
return new RegisterTask((NioSocketChannel) channel, future, server);
}
private final class RegisterTask implements Runnable {
private final NioSocketChannel channel;
private final ChannelFuture future;
private final boolean server;
RegisterTask(
NioSocketChannel channel, ChannelFuture future, boolean server) {
this.channel = channel;
this.future = future;
this.server = server;
}
public void run() {
SocketAddress localAddress = channel.getLocalAddress();
SocketAddress remoteAddress = channel.getRemoteAddress();
if (localAddress == null || remoteAddress == null) {
if (future != null) {
future.setFailure(new ClosedChannelException());
}
close(channel, succeededFuture(channel));
return;
}
try {
if (server) {
channel.channel.configureBlocking(false);
}
channel.channel.register(
selector, channel.getRawInterestOps(), channel);
if (future != null) {
channel.setConnected();
future.setSuccess();
}
if (server || !((NioClientSocketChannel) channel).boundManually) {
fireChannelBound(channel, localAddress);
}
fireChannelConnected(channel, remoteAddress);
} catch (IOException e) {
if (future != null) {
future.setFailure(e);
}
close(channel, succeededFuture(channel));
if (!(e instanceof ClosedChannelException)) {
throw new ChannelException(
"Failed to register a socket to the selector.", e);
}
}
}
}
@Override
public void run() {
super.run();
recvBufferPool.releaseExternalResources();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/NioWorkerPool.java 0000664 0000000 0000000 00000002660 12255541277 0031704 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.util.ThreadNameDeterminer;
import java.util.concurrent.Executor;
/**
* Default implementation which hands of {@link NioWorker}'s
*
*
*/
public class NioWorkerPool extends AbstractNioWorkerPool {
private final ThreadNameDeterminer determiner;
public NioWorkerPool(Executor workerExecutor, int workerCount) {
this(workerExecutor, workerCount, null);
}
public NioWorkerPool(Executor workerExecutor, int workerCount, ThreadNameDeterminer determiner) {
super(workerExecutor, workerCount, false);
this.determiner = determiner;
init();
}
@Override
@Deprecated
protected NioWorker createWorker(Executor executor) {
return new NioWorker(executor, determiner);
}
}
ProtocolFamilyConverter.java 0000664 0000000 0000000 00000002642 12255541277 0033707 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.socket.InternetProtocolFamily;
import java.net.ProtocolFamily;
import java.net.StandardProtocolFamily;
/**
* Helper class which convert the {@link InternetProtocolFamily}.
*
*
*/
final class ProtocolFamilyConverter {
private ProtocolFamilyConverter() {
// Utility class
}
/**
* Convert the {@link InternetProtocolFamily}. This MUST only be called on jdk version >= 7.
*/
public static ProtocolFamily convert(InternetProtocolFamily family) {
switch (family) {
case IPv4:
return StandardProtocolFamily.INET;
case IPv6:
return StandardProtocolFamily.INET6;
default:
throw new IllegalArgumentException();
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/SelectorUtil.java 0000664 0000000 0000000 00000005737 12255541277 0031561 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.SystemPropertyUtil;
import java.io.IOException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.Selector;
import java.util.concurrent.TimeUnit;
final class SelectorUtil {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(SelectorUtil.class);
static final int DEFAULT_IO_THREADS = Runtime.getRuntime().availableProcessors() * 2;
static final long DEFAULT_SELECT_TIMEOUT = 500;
static final long SELECT_TIMEOUT =
SystemPropertyUtil.getLong("org.jboss.netty.selectTimeout", DEFAULT_SELECT_TIMEOUT);
static final long SELECT_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(SELECT_TIMEOUT);
static final boolean EPOLL_BUG_WORKAROUND =
SystemPropertyUtil.getBoolean("org.jboss.netty.epollBugWorkaround", false);
// Workaround for JDK NIO bug.
//
// See:
// - http://bugs.sun.com/view_bug.do?bug_id=6427854
// - https://github.com/netty/netty/issues/203
static {
String key = "sun.nio.ch.bugLevel";
try {
String buglevel = System.getProperty(key);
if (buglevel == null) {
System.setProperty(key, "");
}
} catch (SecurityException e) {
if (logger.isDebugEnabled()) {
logger.debug("Unable to get/set System Property '" + key + '\'', e);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using select timeout of " + SELECT_TIMEOUT);
logger.debug("Epoll-bug workaround enabled = " + EPOLL_BUG_WORKAROUND);
}
}
static Selector open() throws IOException {
return Selector.open();
}
static int select(Selector selector) throws IOException {
try {
return selector.select(SELECT_TIMEOUT);
} catch (CancelledKeyException e) {
if (logger.isDebugEnabled()) {
logger.debug(
CancelledKeyException.class.getSimpleName() +
" raised by a Selector - JDK bug?", e);
}
// Harmless exception - log anyway
}
return -1;
}
private SelectorUtil() {
// Unused
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/ShareableWorkerPool.java 0000664 0000000 0000000 00000003427 12255541277 0033047 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.socket.Worker;
import org.jboss.netty.util.ExternalResourceReleasable;
/**
* This implementation of a {@link WorkerPool} should be used if you plan to share a
* {@link WorkerPool} between different Factories. You will need to call {@link #destroy()} by your
* own once you want to release any resources of it.
*
*
*/
public final class ShareableWorkerPool implements WorkerPool {
private final WorkerPool wrapped;
public ShareableWorkerPool(WorkerPool wrapped) {
this.wrapped = wrapped;
}
public E nextWorker() {
return wrapped.nextWorker();
}
public void rebuildSelectors() {
wrapped.rebuildSelectors();
}
/**
* Destroy the {@link ShareableWorkerPool} and release all resources. After this is called its not usable anymore
*/
public void destroy() {
wrapped.shutdown();
if (wrapped instanceof ExternalResourceReleasable) {
((ExternalResourceReleasable) wrapped).releaseExternalResources();
}
}
public void shutdown() {
// do nothing
}
}
SocketReceiveBufferAllocator.java 0000664 0000000 0000000 00000004521 12255541277 0034600 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.util.ExternalResourceReleasable;
import org.jboss.netty.util.internal.ByteBufferUtil;
import java.nio.ByteBuffer;
final class SocketReceiveBufferAllocator implements ExternalResourceReleasable {
private ByteBuffer buf;
private int exceedCount;
private final int maxExceedCount;
private final int percentual;
SocketReceiveBufferAllocator() {
this(16, 80);
}
SocketReceiveBufferAllocator(int maxExceedCount, int percentual) {
this.maxExceedCount = maxExceedCount;
this.percentual = percentual;
}
ByteBuffer get(int size) {
if (buf == null) {
return newBuffer(size);
}
if (buf.capacity() < size) {
return newBuffer(size);
}
if (buf.capacity() * percentual / 100 > size) {
if (++exceedCount == maxExceedCount) {
return newBuffer(size);
} else {
buf.clear();
}
} else {
exceedCount = 0;
buf.clear();
}
return buf;
}
private ByteBuffer newBuffer(int size) {
if (buf != null) {
exceedCount = 0;
ByteBufferUtil.destroy(buf);
}
buf = ByteBuffer.allocateDirect(normalizeCapacity(size));
return buf;
}
private static int normalizeCapacity(int capacity) {
// Normalize to multiple of 1024
int q = capacity >>> 10;
int r = capacity & 1023;
if (r != 0) {
q ++;
}
return q << 10;
}
public void releaseExternalResources() {
if (buf != null) {
ByteBufferUtil.destroy(buf);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/SocketSendBufferPool.java 0000664 0000000 0000000 00000025736 12255541277 0033172 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.CompositeChannelBuffer;
import org.jboss.netty.channel.DefaultFileRegion;
import org.jboss.netty.channel.FileRegion;
import org.jboss.netty.util.ExternalResourceReleasable;
import org.jboss.netty.util.internal.ByteBufferUtil;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.WritableByteChannel;
final class SocketSendBufferPool implements ExternalResourceReleasable {
private static final SendBuffer EMPTY_BUFFER = new EmptySendBuffer();
private static final int DEFAULT_PREALLOCATION_SIZE = 65536;
private static final int ALIGN_SHIFT = 4;
private static final int ALIGN_MASK = 15;
private PreallocationRef poolHead;
private Preallocation current = new Preallocation(DEFAULT_PREALLOCATION_SIZE);
SendBuffer acquire(Object message) {
if (message instanceof ChannelBuffer) {
return acquire((ChannelBuffer) message);
}
if (message instanceof FileRegion) {
return acquire((FileRegion) message);
}
throw new IllegalArgumentException(
"unsupported message type: " + message.getClass());
}
private SendBuffer acquire(FileRegion src) {
if (src.getCount() == 0) {
return EMPTY_BUFFER;
}
return new FileSendBuffer(src);
}
private SendBuffer acquire(ChannelBuffer src) {
final int size = src.readableBytes();
if (size == 0) {
return EMPTY_BUFFER;
}
if (src instanceof CompositeChannelBuffer && ((CompositeChannelBuffer) src).useGathering()) {
return new GatheringSendBuffer(src.toByteBuffers());
}
if (src.isDirect()) {
return new UnpooledSendBuffer(src.toByteBuffer());
}
if (src.readableBytes() > DEFAULT_PREALLOCATION_SIZE) {
return new UnpooledSendBuffer(src.toByteBuffer());
}
Preallocation current = this.current;
ByteBuffer buffer = current.buffer;
int remaining = buffer.remaining();
PooledSendBuffer dst;
if (size < remaining) {
int nextPos = buffer.position() + size;
ByteBuffer slice = buffer.duplicate();
buffer.position(align(nextPos));
slice.limit(nextPos);
current.refCnt ++;
dst = new PooledSendBuffer(current, slice);
} else if (size > remaining) {
this.current = current = getPreallocation();
buffer = current.buffer;
ByteBuffer slice = buffer.duplicate();
buffer.position(align(size));
slice.limit(size);
current.refCnt ++;
dst = new PooledSendBuffer(current, slice);
} else { // size == remaining
current.refCnt ++;
this.current = getPreallocation0();
dst = new PooledSendBuffer(current, current.buffer);
}
ByteBuffer dstbuf = dst.buffer;
dstbuf.mark();
src.getBytes(src.readerIndex(), dstbuf);
dstbuf.reset();
return dst;
}
private Preallocation getPreallocation() {
Preallocation current = this.current;
if (current.refCnt == 0) {
current.buffer.clear();
return current;
}
return getPreallocation0();
}
private Preallocation getPreallocation0() {
PreallocationRef ref = poolHead;
if (ref != null) {
do {
Preallocation p = ref.get();
ref = ref.next;
if (p != null) {
poolHead = ref;
return p;
}
} while (ref != null);
poolHead = ref;
}
return new Preallocation(DEFAULT_PREALLOCATION_SIZE);
}
private static int align(int pos) {
int q = pos >>> ALIGN_SHIFT;
int r = pos & ALIGN_MASK;
if (r != 0) {
q ++;
}
return q << ALIGN_SHIFT;
}
private static final class Preallocation {
final ByteBuffer buffer;
int refCnt;
Preallocation(int capacity) {
buffer = ByteBuffer.allocateDirect(capacity);
}
}
private final class PreallocationRef extends SoftReference {
final PreallocationRef next;
PreallocationRef(Preallocation prealloation, PreallocationRef next) {
super(prealloation);
this.next = next;
}
}
interface SendBuffer {
boolean finished();
long writtenBytes();
long totalBytes();
long transferTo(WritableByteChannel ch) throws IOException;
long transferTo(DatagramChannel ch, SocketAddress raddr) throws IOException;
void release();
}
static class UnpooledSendBuffer implements SendBuffer {
final ByteBuffer buffer;
final int initialPos;
UnpooledSendBuffer(ByteBuffer buffer) {
this.buffer = buffer;
initialPos = buffer.position();
}
public final boolean finished() {
return !buffer.hasRemaining();
}
public final long writtenBytes() {
return buffer.position() - initialPos;
}
public final long totalBytes() {
return buffer.limit() - initialPos;
}
public final long transferTo(WritableByteChannel ch) throws IOException {
return ch.write(buffer);
}
public final long transferTo(DatagramChannel ch, SocketAddress raddr) throws IOException {
return ch.send(buffer, raddr);
}
public void release() {
// Unpooled.
}
}
final class PooledSendBuffer extends UnpooledSendBuffer {
private final Preallocation parent;
PooledSendBuffer(Preallocation parent, ByteBuffer buffer) {
super(buffer);
this.parent = parent;
}
@Override
public void release() {
final Preallocation parent = this.parent;
if (-- parent.refCnt == 0) {
parent.buffer.clear();
if (parent != current) {
poolHead = new PreallocationRef(parent, poolHead);
}
}
}
}
static class GatheringSendBuffer implements SendBuffer {
private final ByteBuffer[] buffers;
private final int last;
private long written;
private final int total;
GatheringSendBuffer(ByteBuffer[] buffers) {
this.buffers = buffers;
last = buffers.length - 1;
int total = 0;
for (ByteBuffer buf: buffers) {
total += buf.remaining();
}
this.total = total;
}
public boolean finished() {
return !buffers[last].hasRemaining();
}
public long writtenBytes() {
return written;
}
public long totalBytes() {
return total;
}
public long transferTo(WritableByteChannel ch) throws IOException {
if (ch instanceof GatheringByteChannel) {
long w = ((GatheringByteChannel) ch).write(buffers);
written += w;
return w;
} else {
int send = 0;
for (ByteBuffer buf: buffers) {
if (buf.hasRemaining()) {
int w = ch.write(buf);
if (w == 0) {
break;
} else {
send += w;
}
}
}
written += send;
return send;
}
}
public long transferTo(DatagramChannel ch, SocketAddress raddr) throws IOException {
int send = 0;
for (ByteBuffer buf: buffers) {
if (buf.hasRemaining()) {
int w = ch.send(buf, raddr);
if (w == 0) {
break;
} else {
send += w;
}
}
}
written += send;
return send;
}
public void release() {
// nothing todo
}
}
final class FileSendBuffer implements SendBuffer {
private final FileRegion file;
private long writtenBytes;
FileSendBuffer(FileRegion file) {
this.file = file;
}
public boolean finished() {
return writtenBytes >= file.getCount();
}
public long writtenBytes() {
return writtenBytes;
}
public long totalBytes() {
return file.getCount();
}
public long transferTo(WritableByteChannel ch) throws IOException {
long localWrittenBytes = file.transferTo(ch, writtenBytes);
writtenBytes += localWrittenBytes;
return localWrittenBytes;
}
public long transferTo(DatagramChannel ch, SocketAddress raddr) {
throw new UnsupportedOperationException();
}
public void release() {
if (file instanceof DefaultFileRegion) {
if (((DefaultFileRegion) file).releaseAfterTransfer()) {
// Make sure the FileRegion resource are released otherwise it may cause a FD
// leak or something similar
file.releaseExternalResources();
}
}
}
}
static final class EmptySendBuffer implements SendBuffer {
public boolean finished() {
return true;
}
public long writtenBytes() {
return 0;
}
public long totalBytes() {
return 0;
}
public long transferTo(WritableByteChannel ch) {
return 0;
}
public long transferTo(DatagramChannel ch, SocketAddress raddr) {
return 0;
}
public void release() {
// Unpooled.
}
}
public void releaseExternalResources() {
if (current.buffer != null) {
ByteBufferUtil.destroy(current.buffer);
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/WorkerPool.java 0000664 0000000 0000000 00000001753 12255541277 0031240 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.nio;
import org.jboss.netty.channel.socket.Worker;
/**
* The {@link WorkerPool} is responsible to hand of {@link Worker}'s on demand
*
*/
public interface WorkerPool extends NioSelectorPool {
/**
* Return the next {@link Worker} to use
*
* @return worker
*/
E nextWorker();
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/nio/package-info.java 0000664 0000000 0000000 00000001523 12255541277 0031454 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* NIO -based socket channel
* API implementation - recommended for a large number of connections (>= 1000).
*/
package org.jboss.netty.channel.socket.nio;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/ 0000775 0000000 0000000 00000000000 12255541277 0026265 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/AbstractOioChannel.java 0000664 0000000 0000000 00000006642 12255541277 0032643 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.jboss.netty.channel.AbstractChannel;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.Worker;
abstract class AbstractOioChannel extends AbstractChannel {
private volatile InetSocketAddress localAddress;
volatile InetSocketAddress remoteAddress;
volatile Thread workerThread;
volatile Worker worker;
final Object interestOpsLock = new Object();
AbstractOioChannel(
Channel parent,
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink) {
super(parent, factory, pipeline, sink);
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
@Override
protected void setInterestOpsNow(int interestOps) {
super.setInterestOpsNow(interestOps);
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) {
return super.write(message, null);
} else {
return super.write(message, remoteAddress);
}
}
public boolean isBound() {
return isOpen() && isSocketBound();
}
public boolean isConnected() {
return isOpen() && isSocketConnected();
}
public InetSocketAddress getLocalAddress() {
InetSocketAddress localAddress = this.localAddress;
if (localAddress == null) {
try {
this.localAddress = localAddress = getLocalSocketAddress();
} catch (Throwable t) {
// Sometimes fails on a closed socket in Windows.
return null;
}
}
return localAddress;
}
public InetSocketAddress getRemoteAddress() {
InetSocketAddress remoteAddress = this.remoteAddress;
if (remoteAddress == null) {
try {
this.remoteAddress = remoteAddress =
getRemoteSocketAddress();
} catch (Throwable t) {
// Sometimes fails on a closed socket in Windows.
return null;
}
}
return remoteAddress;
}
abstract boolean isSocketBound();
abstract boolean isSocketConnected();
abstract boolean isSocketClosed();
abstract InetSocketAddress getLocalSocketAddress() throws Exception;
abstract InetSocketAddress getRemoteSocketAddress() throws Exception;
abstract void closeSocket() throws IOException;
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/AbstractOioChannelSink.java0000664 0000000 0000000 00000004042 12255541277 0033460 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.channel.AbstractChannelSink;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.socket.ChannelRunnableWrapper;
import org.jboss.netty.channel.socket.Worker;
public abstract class AbstractOioChannelSink extends AbstractChannelSink {
@Override
public ChannelFuture execute(final ChannelPipeline pipeline, final Runnable task) {
Channel ch = pipeline.getChannel();
if (ch instanceof AbstractOioChannel) {
AbstractOioChannel channel = (AbstractOioChannel) ch;
Worker worker = channel.worker;
if (worker != null) {
ChannelRunnableWrapper wrapper = new ChannelRunnableWrapper(pipeline.getChannel(), task);
channel.worker.executeInIoThread(wrapper);
return wrapper;
}
}
return super.execute(pipeline, task);
}
@Override
protected boolean isFireExceptionCaughtLater(ChannelEvent event, Throwable actualCause) {
Channel channel = event.getChannel();
boolean fireLater = false;
if (channel instanceof AbstractOioChannel) {
fireLater = !AbstractOioWorker.isIoThread((AbstractOioChannel) channel);
}
return fireLater;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/AbstractOioWorker.java 0000664 0000000 0000000 00000021620 12255541277 0032535 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.Worker;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import static org.jboss.netty.channel.Channels.*;
/**
* Abstract base class for Oio-Worker implementations
*
* @param {@link AbstractOioChannel}
*/
abstract class AbstractOioWorker implements Worker {
private final Queue eventQueue = new ConcurrentLinkedQueue();
protected final C channel;
/**
* If this worker has been started thread will be a reference to the thread
* used when starting. i.e. the current thread when the run method is executed.
*/
protected volatile Thread thread;
private volatile boolean done;
protected AbstractOioWorker(C channel) {
this.channel = channel;
channel.worker = this;
}
public void run() {
thread = channel.workerThread = Thread.currentThread();
while (channel.isOpen()) {
synchronized (channel.interestOpsLock) {
while (!channel.isReadable()) {
try {
// notify() is not called at all.
// close() and setInterestOps() calls Thread.interrupt()
channel.interestOpsLock.wait();
} catch (InterruptedException e) {
if (!channel.isOpen()) {
break;
}
}
}
}
boolean cont = false;
try {
cont = process();
} catch (Throwable t) {
boolean readTimeout = t instanceof SocketTimeoutException;
if (!readTimeout && !channel.isSocketClosed()) {
fireExceptionCaught(channel, t);
}
if (readTimeout) {
// the readTimeout was triggered because of the SO_TIMEOUT,
// so just continue with the loop here
cont = true;
}
} finally {
processEventQueue();
}
if (!cont) {
break;
}
}
synchronized (channel.interestOpsLock) {
// Setting the workerThread to null will prevent any channel
// operations from interrupting this thread from now on.
//
//
// Do this while holding the lock to not race with close(...) or
// setInterestOps(...)
channel.workerThread = null;
}
// Clean up.
close(channel, succeededFuture(channel), true);
// Mark the worker event loop as done so we know that we need to run tasks directly and not queue them
// See #287
done = true;
// just to make we don't have something left
processEventQueue();
}
static boolean isIoThread(AbstractOioChannel channel) {
return Thread.currentThread() == channel.workerThread;
}
public void executeInIoThread(Runnable task) {
// check if the current thread is the worker thread
//
// Also check if the event loop of the worker is complete. If so we need to run the task now.
// See #287
if (Thread.currentThread() == thread || done) {
task.run();
} else {
boolean added = eventQueue.offer(task);
if (added) {
// as we set the SO_TIMEOUT to 1 second this task will get picked up in 1 second at latest
}
}
}
private void processEventQueue() {
for (;;) {
final Runnable task = eventQueue.poll();
if (task == null) {
break;
}
task.run();
}
}
/**
* Process the incoming messages and also is responsible for call
* {@link Channels#fireMessageReceived(Channel, Object)} once a message was processed without
* errors.
*
* @return continue returns {@code true} as long as this worker should continue to try
* processing incoming messages
* @throws IOException
*/
abstract boolean process() throws IOException;
static void setInterestOps(
AbstractOioChannel channel, ChannelFuture future, int interestOps) {
boolean iothread = isIoThread(channel);
// Override OP_WRITE flag - a user cannot change this flag.
interestOps &= ~Channel.OP_WRITE;
interestOps |= channel.getInterestOps() & Channel.OP_WRITE;
boolean changed = false;
try {
if (channel.getInterestOps() != interestOps) {
if ((interestOps & Channel.OP_READ) != 0) {
channel.setInterestOpsNow(Channel.OP_READ);
} else {
channel.setInterestOpsNow(Channel.OP_NONE);
}
changed = true;
}
future.setSuccess();
if (changed) {
synchronized (channel.interestOpsLock) {
channel.setInterestOpsNow(interestOps);
// Notify the worker so it stops or continues reading.
Thread currentThread = Thread.currentThread();
Thread workerThread = channel.workerThread;
if (workerThread != null && currentThread != workerThread) {
workerThread.interrupt();
}
}
if (iothread) {
fireChannelInterestChanged(channel);
} else {
fireChannelInterestChangedLater(channel);
}
}
} catch (Throwable t) {
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
static void close(AbstractOioChannel channel, ChannelFuture future) {
close(channel, future, isIoThread(channel));
}
private static void close(AbstractOioChannel channel, ChannelFuture future, boolean iothread) {
boolean connected = channel.isConnected();
boolean bound = channel.isBound();
try {
channel.closeSocket();
if (channel.setClosed()) {
future.setSuccess();
if (connected) {
Thread currentThread = Thread.currentThread();
synchronized (channel.interestOpsLock) {
// We need to do this while hold the lock as otherwise
// we may race and so interrupt the workerThread even
// if we are in the workerThread now.
// This can happen if run() set channel.workerThread to null
// between workerThread != null and currentThread!= workerThread
Thread workerThread = channel.workerThread;
if (workerThread != null && currentThread != workerThread) {
workerThread.interrupt();
}
}
if (iothread) {
fireChannelDisconnected(channel);
} else {
fireChannelDisconnectedLater(channel);
}
}
if (bound) {
if (iothread) {
fireChannelUnbound(channel);
} else {
fireChannelUnboundLater(channel);
}
}
if (iothread) {
fireChannelClosed(channel);
} else {
fireChannelClosedLater(channel);
}
} else {
future.setSuccess();
}
} catch (Throwable t) {
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
}
OioAcceptedSocketChannel.java 0000664 0000000 0000000 00000004072 12255541277 0033675 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import static org.jboss.netty.channel.Channels.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.net.Socket;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
class OioAcceptedSocketChannel extends OioSocketChannel {
private final PushbackInputStream in;
private final OutputStream out;
OioAcceptedSocketChannel(
Channel parent,
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink,
Socket socket) {
super(parent, factory, pipeline, sink, socket);
try {
in = new PushbackInputStream(socket.getInputStream(), 1);
} catch (IOException e) {
throw new ChannelException("Failed to obtain an InputStream.", e);
}
try {
out = socket.getOutputStream();
} catch (IOException e) {
throw new ChannelException("Failed to obtain an OutputStream.", e);
}
fireChannelOpen(this);
fireChannelBound(this, getLocalAddress());
}
@Override
PushbackInputStream getInputStream() {
return in;
}
@Override
OutputStream getOutputStream() {
return out;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/OioClientSocketChannel.java0000664 0000000 0000000 00000002713 12255541277 0033462 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import static org.jboss.netty.channel.Channels.*;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.net.Socket;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
class OioClientSocketChannel extends OioSocketChannel {
volatile PushbackInputStream in;
volatile OutputStream out;
OioClientSocketChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink) {
super(null, factory, pipeline, sink, new Socket());
fireChannelOpen(this);
}
@Override
PushbackInputStream getInputStream() {
return in;
}
@Override
OutputStream getOutputStream() {
return out;
}
}
OioClientSocketChannelFactory.java 0000664 0000000 0000000 00000011374 12255541277 0034736 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.internal.ExecutorUtil;
/**
* A {@link ClientSocketChannelFactory} which creates a client-side blocking
* I/O based {@link SocketChannel}. It utilizes the good old blocking I/O API
* which is known to yield better throughput and latency when there are
* relatively small number of connections to serve.
*
* How threads work
*
* There is only one type of threads in {@link OioClientSocketChannelFactory};
* worker threads.
*
*
Worker threads
*
* Each connected {@link Channel} has a dedicated worker thread, just like a
* traditional blocking I/O thread model.
*
*
Life cycle of threads and graceful shutdown
*
* Worker threads are acquired from the {@link Executor} which was specified
* when a {@link OioClientSocketChannelFactory} was created (i.e. {@code workerExecutor}.)
* Therefore, you should make sure the specified {@link Executor} is able to
* lend the sufficient number of threads.
*
* Worker threads are acquired lazily, and then released when there's nothing
* left to process. All the related resources are also released when the
* worker threads are released. Therefore, to shut down a service gracefully,
* you should do the following:
*
*
* close all channels created by the factory usually using
* {@link ChannelGroup#close()}, and
* call {@link #releaseExternalResources()}.
*
*
* Please make sure not to shut down the executor until all channels are
* closed. Otherwise, you will end up with a {@link RejectedExecutionException}
* and the related resources might not be released properly.
*
* Limitation
*
* A {@link SocketChannel} created by this factory does not support asynchronous
* operations. Any I/O requests such as {@code "connect"} and {@code "write"}
* will be performed in a blocking manner.
*
* @apiviz.landmark
*/
public class OioClientSocketChannelFactory implements ClientSocketChannelFactory {
private final Executor workerExecutor;
final OioClientSocketPipelineSink sink;
private boolean shutdownExecutor;
/**
* Creates a new instance with a {@link Executors#newCachedThreadPool()} as worker executor.
*
* See {@link #OioClientSocketChannelFactory(Executor)}
*/
public OioClientSocketChannelFactory() {
this(Executors.newCachedThreadPool());
shutdownExecutor = true;
}
/**
* Creates a new instance.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
*/
public OioClientSocketChannelFactory(Executor workerExecutor) {
this(workerExecutor, null);
}
/**
* Creates a new instance.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param determiner
* the {@link ThreadNameDeterminer} to set the thread names.
*/
public OioClientSocketChannelFactory(Executor workerExecutor,
ThreadNameDeterminer determiner) {
if (workerExecutor == null) {
throw new NullPointerException("workerExecutor");
}
this.workerExecutor = workerExecutor;
sink = new OioClientSocketPipelineSink(workerExecutor, determiner);
}
public SocketChannel newChannel(ChannelPipeline pipeline) {
return new OioClientSocketChannel(this, pipeline, sink);
}
public void shutdown() {
if (shutdownExecutor) {
ExecutorUtil.shutdownNow(workerExecutor);
}
}
public void releaseExternalResources() {
shutdown();
ExecutorUtil.shutdownNow(workerExecutor);
}
}
OioClientSocketPipelineSink.java 0000664 0000000 0000000 00000012611 12255541277 0034423 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import org.jboss.netty.util.internal.DeadLockProofWorker;
import java.io.PushbackInputStream;
import java.net.ConnectException;
import java.net.SocketAddress;
import java.util.concurrent.Executor;
import static org.jboss.netty.channel.Channels.*;
class OioClientSocketPipelineSink extends AbstractOioChannelSink {
private final Executor workerExecutor;
private final ThreadNameDeterminer determiner;
OioClientSocketPipelineSink(Executor workerExecutor, ThreadNameDeterminer determiner) {
this.workerExecutor = workerExecutor;
this.determiner = determiner;
}
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
OioClientSocketChannel channel = (OioClientSocketChannel) e.getChannel();
ChannelFuture future = e.getFuture();
if (e instanceof ChannelStateEvent) {
ChannelStateEvent stateEvent = (ChannelStateEvent) e;
ChannelState state = stateEvent.getState();
Object value = stateEvent.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
AbstractOioWorker.close(channel, future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (SocketAddress) value);
} else {
AbstractOioWorker.close(channel, future);
}
break;
case CONNECTED:
if (value != null) {
connect(channel, future, (SocketAddress) value);
} else {
AbstractOioWorker.close(channel, future);
}
break;
case INTEREST_OPS:
AbstractOioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
break;
}
} else if (e instanceof MessageEvent) {
OioWorker.write(
channel, future,
((MessageEvent) e).getMessage());
}
}
private static void bind(
OioClientSocketChannel channel, ChannelFuture future,
SocketAddress localAddress) {
try {
channel.socket.bind(localAddress);
future.setSuccess();
fireChannelBound(channel, channel.getLocalAddress());
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
private void connect(
OioClientSocketChannel channel, ChannelFuture future,
SocketAddress remoteAddress) {
boolean bound = channel.isBound();
boolean connected = false;
boolean workerStarted = false;
future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
try {
channel.socket.connect(
remoteAddress, channel.getConfig().getConnectTimeoutMillis());
connected = true;
// Obtain I/O stream.
channel.in = new PushbackInputStream(channel.socket.getInputStream(), 1);
channel.out = channel.socket.getOutputStream();
// Fire events.
future.setSuccess();
if (!bound) {
fireChannelBound(channel, channel.getLocalAddress());
}
fireChannelConnected(channel, channel.getRemoteAddress());
// Start the business.
DeadLockProofWorker.start(
workerExecutor,
new ThreadRenamingRunnable(
new OioWorker(channel),
"Old I/O client worker (" + channel + ')',
determiner));
workerStarted = true;
} catch (Throwable t) {
if (t instanceof ConnectException) {
if (t instanceof ConnectException) {
Throwable newT = new ConnectException(t.getMessage() + ": " + remoteAddress);
newT.setStackTrace(t.getStackTrace());
t = newT;
}
}
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (connected && !workerStarted) {
AbstractOioWorker.close(channel, future);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/OioDatagramChannel.java 0000664 0000000 0000000 00000010557 12255541277 0032620 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.DatagramChannelConfig;
import org.jboss.netty.channel.socket.DefaultDatagramChannelConfig;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import static org.jboss.netty.channel.Channels.*;
final class OioDatagramChannel extends AbstractOioChannel
implements DatagramChannel {
final MulticastSocket socket;
private final DatagramChannelConfig config;
OioDatagramChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink) {
super(null, factory, pipeline, sink);
try {
socket = new MulticastSocket(null);
} catch (IOException e) {
throw new ChannelException("Failed to open a datagram socket.", e);
}
try {
socket.setSoTimeout(10);
socket.setBroadcast(false);
} catch (SocketException e) {
throw new ChannelException(
"Failed to configure the datagram socket timeout.", e);
}
config = new DefaultDatagramChannelConfig(socket);
fireChannelOpen(this);
}
public DatagramChannelConfig getConfig() {
return config;
}
public ChannelFuture joinGroup(InetAddress multicastAddress) {
ensureBound();
try {
socket.joinGroup(multicastAddress);
return succeededFuture(this);
} catch (IOException e) {
return failedFuture(this, e);
}
}
public ChannelFuture joinGroup(
InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
ensureBound();
try {
socket.joinGroup(multicastAddress, networkInterface);
return succeededFuture(this);
} catch (IOException e) {
return failedFuture(this, e);
}
}
private void ensureBound() {
if (!isBound()) {
throw new IllegalStateException(
DatagramChannel.class.getName() +
" must be bound to join a group.");
}
}
public ChannelFuture leaveGroup(InetAddress multicastAddress) {
try {
socket.leaveGroup(multicastAddress);
return succeededFuture(this);
} catch (IOException e) {
return failedFuture(this, e);
}
}
public ChannelFuture leaveGroup(
InetSocketAddress multicastAddress, NetworkInterface networkInterface) {
try {
socket.leaveGroup(multicastAddress, networkInterface);
return succeededFuture(this);
} catch (IOException e) {
return failedFuture(this, e);
}
}
@Override
boolean isSocketBound() {
return socket.isBound();
}
@Override
boolean isSocketConnected() {
return socket.isConnected();
}
@Override
InetSocketAddress getLocalSocketAddress() throws Exception {
return (InetSocketAddress) socket.getLocalSocketAddress();
}
@Override
InetSocketAddress getRemoteSocketAddress() throws Exception {
return (InetSocketAddress) socket.getRemoteSocketAddress();
}
@Override
void closeSocket() {
socket.close();
}
@Override
boolean isSocketClosed() {
return socket.isClosed();
}
}
OioDatagramChannelFactory.java 0000664 0000000 0000000 00000011064 12255541277 0034063 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.DatagramChannelFactory;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.internal.ExecutorUtil;
/**
* A {@link DatagramChannelFactory} which creates a blocking I/O based
* {@link DatagramChannel}. It utilizes the good old blocking I/O API which
* has support for multicast.
*
*
How threads work
*
* There is only one type of threads in {@link OioDatagramChannelFactory};
* worker threads.
*
*
Worker threads
*
* Each {@link Channel} has a dedicated worker thread, just like a
* traditional blocking I/O thread model.
*
*
Life cycle of threads and graceful shutdown
*
* Worker threads are acquired from the {@link Executor} which was specified
* when a {@link OioDatagramChannelFactory} was created (i.e. {@code workerExecutor}.)
* Therefore, you should make sure the specified {@link Executor} is able to
* lend the sufficient number of threads.
*
* Worker threads are acquired lazily, and then released when there's nothing
* left to process. All the related resources are also released when the
* worker threads are released. Therefore, to shut down a service gracefully,
* you should do the following:
*
*
* close all channels created by the factory usually using
* {@link ChannelGroup#close()}, and
* call {@link #releaseExternalResources()}.
*
*
* Please make sure not to shut down the executor until all channels are
* closed. Otherwise, you will end up with a {@link RejectedExecutionException}
* and the related resources might not be released properly.
*
* Limitation
*
* A {@link DatagramChannel} created by this factory does not support asynchronous
* operations. Any I/O requests such as {@code "write"} will be performed in a
* blocking manner.
*
* @apiviz.landmark
*/
public class OioDatagramChannelFactory implements DatagramChannelFactory {
private final Executor workerExecutor;
final OioDatagramPipelineSink sink;
private boolean shutdownExecutor;
/**
* Creates a new instance with a {@link Executors#newCachedThreadPool()}
*
* See {@link #OioDatagramChannelFactory(Executor)}
*/
public OioDatagramChannelFactory() {
this(Executors.newCachedThreadPool());
shutdownExecutor = true;
}
/**
* Creates a new instance.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
*/
public OioDatagramChannelFactory(Executor workerExecutor) {
this(workerExecutor, null);
}
/**
* Creates a new instance.
*
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param determiner
* the {@link ThreadNameDeterminer} to set the thread names.
*/
public OioDatagramChannelFactory(Executor workerExecutor,
ThreadNameDeterminer determiner) {
if (workerExecutor == null) {
throw new NullPointerException("workerExecutor");
}
this.workerExecutor = workerExecutor;
sink = new OioDatagramPipelineSink(workerExecutor, determiner);
}
public DatagramChannel newChannel(ChannelPipeline pipeline) {
return new OioDatagramChannel(this, pipeline, sink);
}
public void shutdown() {
if (shutdownExecutor) {
ExecutorUtil.shutdownNow(workerExecutor);
}
}
public void releaseExternalResources() {
shutdown();
ExecutorUtil.shutdownNow(workerExecutor);
}
}
OioDatagramPipelineSink.java 0000664 0000000 0000000 00000013750 12255541277 0033561 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import static org.jboss.netty.channel.Channels.*;
import java.net.SocketAddress;
import java.util.concurrent.Executor;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import org.jboss.netty.util.internal.DeadLockProofWorker;
class OioDatagramPipelineSink extends AbstractOioChannelSink {
private final Executor workerExecutor;
private final ThreadNameDeterminer determiner;
OioDatagramPipelineSink(Executor workerExecutor, ThreadNameDeterminer determiner) {
this.workerExecutor = workerExecutor;
this.determiner = determiner;
}
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
OioDatagramChannel channel = (OioDatagramChannel) e.getChannel();
ChannelFuture future = e.getFuture();
if (e instanceof ChannelStateEvent) {
ChannelStateEvent stateEvent = (ChannelStateEvent) e;
ChannelState state = stateEvent.getState();
Object value = stateEvent.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
AbstractOioWorker.close(channel, future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (SocketAddress) value);
} else {
AbstractOioWorker.close(channel, future);
}
break;
case CONNECTED:
if (value != null) {
connect(channel, future, (SocketAddress) value);
} else {
OioDatagramWorker.disconnect(channel, future);
}
break;
case INTEREST_OPS:
AbstractOioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
break;
}
} else if (e instanceof MessageEvent) {
MessageEvent evt = (MessageEvent) e;
OioDatagramWorker.write(
channel, future, evt.getMessage(), evt.getRemoteAddress());
}
}
private void bind(
OioDatagramChannel channel, ChannelFuture future,
SocketAddress localAddress) {
boolean bound = false;
boolean workerStarted = false;
try {
channel.socket.bind(localAddress);
bound = true;
// Fire events
future.setSuccess();
fireChannelBound(channel, channel.getLocalAddress());
// Start the business.
DeadLockProofWorker.start(
workerExecutor,
new ThreadRenamingRunnable(
new OioDatagramWorker(channel),
"Old I/O datagram worker (" + channel + ')',
determiner));
workerStarted = true;
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (bound && !workerStarted) {
AbstractOioWorker.close(channel, future);
}
}
}
private void connect(
OioDatagramChannel channel, ChannelFuture future,
SocketAddress remoteAddress) {
boolean bound = channel.isBound();
boolean connected = false;
boolean workerStarted = false;
future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
// Clear the cached address so that the next getRemoteAddress() call
// updates the cache.
channel.remoteAddress = null;
try {
channel.socket.connect(remoteAddress);
connected = true;
// Fire events.
future.setSuccess();
if (!bound) {
fireChannelBound(channel, channel.getLocalAddress());
}
fireChannelConnected(channel, channel.getRemoteAddress());
String threadName = "Old I/O datagram worker (" + channel + ')';
if (!bound) {
// Start the business.
DeadLockProofWorker.start(
workerExecutor,
new ThreadRenamingRunnable(
new OioDatagramWorker(channel), threadName, determiner));
} else {
// Worker started by bind() - just rename.
Thread workerThread = channel.workerThread;
if (workerThread != null) {
try {
workerThread.setName(threadName);
} catch (SecurityException e) {
// Ignore.
}
}
}
workerStarted = true;
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (connected && !workerStarted) {
AbstractOioWorker.close(channel, future);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/OioDatagramWorker.java 0000664 0000000 0000000 00000010245 12255541277 0032513 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ReceiveBufferSizePredictor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import static org.jboss.netty.channel.Channels.*;
class OioDatagramWorker extends AbstractOioWorker {
OioDatagramWorker(OioDatagramChannel channel) {
super(channel);
}
@Override
boolean process() throws IOException {
ReceiveBufferSizePredictor predictor =
channel.getConfig().getReceiveBufferSizePredictor();
byte[] buf = new byte[predictor.nextReceiveBufferSize()];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
channel.socket.receive(packet);
} catch (InterruptedIOException e) {
// Can happen on interruption.
// Keep receiving unless the channel is closed.
return true;
}
fireMessageReceived(
channel,
channel.getConfig().getBufferFactory().getBuffer(buf, 0, packet.getLength()),
packet.getSocketAddress());
return true;
}
static void write(
OioDatagramChannel channel, ChannelFuture future,
Object message, SocketAddress remoteAddress) {
boolean iothread = isIoThread(channel);
try {
ChannelBuffer buf = (ChannelBuffer) message;
int offset = buf.readerIndex();
int length = buf.readableBytes();
ByteBuffer nioBuf = buf.toByteBuffer();
DatagramPacket packet;
if (nioBuf.hasArray()) {
// Avoid copy if the buffer is backed by an array.
packet = new DatagramPacket(
nioBuf.array(), nioBuf.arrayOffset() + offset, length);
} else {
// Otherwise it will be expensive.
byte[] arrayBuf = new byte[length];
buf.getBytes(0, arrayBuf);
packet = new DatagramPacket(arrayBuf, length);
}
if (remoteAddress != null) {
packet.setSocketAddress(remoteAddress);
}
channel.socket.send(packet);
if (iothread) {
fireWriteComplete(channel, length);
} else {
fireWriteCompleteLater(channel, length);
}
future.setSuccess();
} catch (Throwable t) {
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
static void disconnect(OioDatagramChannel channel, ChannelFuture future) {
boolean connected = channel.isConnected();
boolean iothread = isIoThread(channel);
try {
channel.socket.disconnect();
future.setSuccess();
if (connected) {
// Notify.
if (iothread) {
fireChannelDisconnected(channel);
} else {
fireChannelDisconnectedLater(channel);
}
}
} catch (Throwable t) {
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/OioServerSocketChannel.java0000664 0000000 0000000 00000006272 12255541277 0033516 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import static org.jboss.netty.channel.Channels.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.jboss.netty.channel.AbstractServerChannel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.socket.DefaultServerSocketChannelConfig;
import org.jboss.netty.channel.socket.ServerSocketChannel;
import org.jboss.netty.channel.socket.ServerSocketChannelConfig;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
class OioServerSocketChannel extends AbstractServerChannel
implements ServerSocketChannel {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(OioServerSocketChannel.class);
final ServerSocket socket;
final Lock shutdownLock = new ReentrantLock();
private final ServerSocketChannelConfig config;
OioServerSocketChannel(
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink) {
super(factory, pipeline, sink);
try {
socket = new ServerSocket();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
try {
socket.setSoTimeout(1000);
} catch (IOException e) {
try {
socket.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
}
throw new ChannelException(
"Failed to set the server socket timeout.", e);
}
config = new DefaultServerSocketChannelConfig(socket);
fireChannelOpen(this);
}
public ServerSocketChannelConfig getConfig() {
return config;
}
public InetSocketAddress getLocalAddress() {
return (InetSocketAddress) socket.getLocalSocketAddress();
}
public InetSocketAddress getRemoteAddress() {
return null;
}
public boolean isBound() {
return isOpen() && socket.isBound();
}
@Override
protected boolean setClosed() {
return super.setClosed();
}
}
OioServerSocketChannelFactory.java 0000664 0000000 0000000 00000014042 12255541277 0034761 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.socket.ServerSocketChannel;
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.internal.ExecutorUtil;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
/**
* A {@link ServerSocketChannelFactory} which creates a server-side blocking
* I/O based {@link ServerSocketChannel}. It utilizes the good old blocking
* I/O API which is known to yield better throughput and latency when there
* are relatively small number of connections to serve.
*
* How threads work
*
* There are two types of threads in a {@link OioServerSocketChannelFactory};
* one is boss thread and the other is worker thread.
*
*
Boss threads
*
* Each bound {@link ServerSocketChannel} has its own boss thread.
* For example, if you opened two server ports such as 80 and 443, you will
* have two boss threads. A boss thread accepts incoming connections until
* the port is unbound. Once a connection is accepted successfully, the boss
* thread passes the accepted {@link Channel} to one of the worker
* threads that the {@link OioServerSocketChannelFactory} manages.
*
*
Worker threads
*
* Each connected {@link Channel} has a dedicated worker thread, just like a
* traditional blocking I/O thread model.
*
*
Life cycle of threads and graceful shutdown
*
* All threads are acquired from the {@link Executor}s which were specified
* when a {@link OioServerSocketChannelFactory} was created. Boss threads are
* acquired from the {@code bossExecutor}, and worker threads are acquired from
* the {@code workerExecutor}. Therefore, you should make sure the specified
* {@link Executor}s are able to lend the sufficient number of threads.
*
* Both boss and worker threads are acquired lazily, and then released when
* there's nothing left to process. All the related resources are also
* released when the boss and worker threads are released. Therefore, to shut
* down a service gracefully, you should do the following:
*
*
* unbind all channels created by the factory,
* close all child channels accepted by the unbound channels,
* (these two steps so far is usually done using {@link ChannelGroup#close()})
* call {@link #releaseExternalResources()}.
*
*
* Please make sure not to shut down the executor until all channels are
* closed. Otherwise, you will end up with a {@link RejectedExecutionException}
* and the related resources might not be released properly.
*
* Limitation
*
* A {@link ServerSocketChannel} created by this factory and its child channels
* do not support asynchronous operations. Any I/O requests such as
* {@code "write"} will be performed in a blocking manner.
*
* @apiviz.landmark
*/
public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
final Executor bossExecutor;
private final Executor workerExecutor;
private final ChannelSink sink;
private boolean shutdownExecutor;
/**
* Create a new {@link OioServerSocketChannelFactory} with a {@link Executors#newCachedThreadPool()}
* for the boss and worker executor.
*
* See {@link #OioServerSocketChannelFactory(Executor, Executor)}
*/
public OioServerSocketChannelFactory() {
this(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
shutdownExecutor = true;
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
*/
public OioServerSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor) {
this(bossExecutor, workerExecutor, null);
}
/**
* Creates a new instance.
*
* @param bossExecutor
* the {@link Executor} which will execute the boss threads
* @param workerExecutor
* the {@link Executor} which will execute the I/O worker threads
* @param determiner
* the {@link ThreadNameDeterminer} to set the thread names.
*/
public OioServerSocketChannelFactory(Executor bossExecutor, Executor workerExecutor,
ThreadNameDeterminer determiner) {
if (bossExecutor == null) {
throw new NullPointerException("bossExecutor");
}
if (workerExecutor == null) {
throw new NullPointerException("workerExecutor");
}
this.bossExecutor = bossExecutor;
this.workerExecutor = workerExecutor;
sink = new OioServerSocketPipelineSink(workerExecutor, determiner);
}
public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
return new OioServerSocketChannel(this, pipeline, sink);
}
public void shutdown() {
if (shutdownExecutor) {
ExecutorUtil.shutdownNow(workerExecutor);
}
}
public void releaseExternalResources() {
shutdown();
ExecutorUtil.shutdownNow(workerExecutor);
}
}
OioServerSocketPipelineSink.java 0000664 0000000 0000000 00000023130 12255541277 0034451 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import static org.jboss.netty.channel.Channels.*;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.util.concurrent.Executor;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import org.jboss.netty.util.internal.DeadLockProofWorker;
class OioServerSocketPipelineSink extends AbstractOioChannelSink {
static final InternalLogger logger =
InternalLoggerFactory.getInstance(OioServerSocketPipelineSink.class);
final Executor workerExecutor;
private final ThreadNameDeterminer determiner;
OioServerSocketPipelineSink(Executor workerExecutor, ThreadNameDeterminer determiner) {
this.workerExecutor = workerExecutor;
this.determiner = determiner;
}
public void eventSunk(
ChannelPipeline pipeline, ChannelEvent e) throws Exception {
Channel channel = e.getChannel();
if (channel instanceof OioServerSocketChannel) {
handleServerSocket(e);
} else if (channel instanceof OioAcceptedSocketChannel) {
handleAcceptedSocket(e);
}
}
private void handleServerSocket(ChannelEvent e) {
if (!(e instanceof ChannelStateEvent)) {
return;
}
ChannelStateEvent event = (ChannelStateEvent) e;
OioServerSocketChannel channel =
(OioServerSocketChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
close(channel, future);
}
break;
case BOUND:
if (value != null) {
bind(channel, future, (SocketAddress) value);
} else {
close(channel, future);
}
break;
}
}
private static void handleAcceptedSocket(ChannelEvent e) {
if (e instanceof ChannelStateEvent) {
ChannelStateEvent event = (ChannelStateEvent) e;
OioAcceptedSocketChannel channel =
(OioAcceptedSocketChannel) event.getChannel();
ChannelFuture future = event.getFuture();
ChannelState state = event.getState();
Object value = event.getValue();
switch (state) {
case OPEN:
if (Boolean.FALSE.equals(value)) {
AbstractOioWorker.close(channel, future);
}
break;
case BOUND:
case CONNECTED:
if (value == null) {
AbstractOioWorker.close(channel, future);
}
break;
case INTEREST_OPS:
AbstractOioWorker.setInterestOps(channel, future, ((Integer) value).intValue());
break;
}
} else if (e instanceof MessageEvent) {
MessageEvent event = (MessageEvent) e;
OioSocketChannel channel = (OioSocketChannel) event.getChannel();
ChannelFuture future = event.getFuture();
Object message = event.getMessage();
OioWorker.write(channel, future, message);
}
}
private void bind(
OioServerSocketChannel channel, ChannelFuture future,
SocketAddress localAddress) {
boolean bound = false;
boolean bossStarted = false;
try {
channel.socket.bind(localAddress, channel.getConfig().getBacklog());
bound = true;
future.setSuccess();
localAddress = channel.getLocalAddress();
fireChannelBound(channel, localAddress);
Executor bossExecutor =
((OioServerSocketChannelFactory) channel.getFactory()).bossExecutor;
DeadLockProofWorker.start(
bossExecutor,
new ThreadRenamingRunnable(
new Boss(channel),
"Old I/O server boss (" + channel + ')',
determiner));
bossStarted = true;
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
} finally {
if (!bossStarted && bound) {
close(channel, future);
}
}
}
private static void close(OioServerSocketChannel channel, ChannelFuture future) {
boolean bound = channel.isBound();
try {
channel.socket.close();
// Make sure the boss thread is not running so that that the future
// is notified after a new connection cannot be accepted anymore.
// See NETTY-256 for more information.
channel.shutdownLock.lock();
try {
if (channel.setClosed()) {
future.setSuccess();
if (bound) {
fireChannelUnbound(channel);
}
fireChannelClosed(channel);
} else {
future.setSuccess();
}
} finally {
channel.shutdownLock.unlock();
}
} catch (Throwable t) {
future.setFailure(t);
fireExceptionCaught(channel, t);
}
}
private final class Boss implements Runnable {
private final OioServerSocketChannel channel;
Boss(OioServerSocketChannel channel) {
this.channel = channel;
}
public void run() {
channel.shutdownLock.lock();
try {
while (channel.isBound()) {
try {
Socket acceptedSocket = channel.socket.accept();
try {
ChannelPipeline pipeline =
channel.getConfig().getPipelineFactory().getPipeline();
final OioAcceptedSocketChannel acceptedChannel =
new OioAcceptedSocketChannel(
channel,
channel.getFactory(),
pipeline,
OioServerSocketPipelineSink.this,
acceptedSocket);
DeadLockProofWorker.start(
workerExecutor,
new ThreadRenamingRunnable(
new OioWorker(acceptedChannel),
"Old I/O server worker (parentId: " +
channel.getId() + ", " + channel + ')',
determiner));
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to initialize an accepted socket.", e);
}
try {
acceptedSocket.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially accepted socket.",
e2);
}
}
}
} catch (SocketTimeoutException e) {
// Thrown every second to stop when requested.
} catch (Throwable e) {
// Do not log the exception if the server socket was closed
// by a user.
if (!channel.socket.isBound() || channel.socket.isClosed()) {
break;
}
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to accept a connection.", e);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// Ignore
}
}
}
} finally {
channel.shutdownLock.unlock();
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/OioSocketChannel.java 0000664 0000000 0000000 00000005440 12255541277 0032323 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.socket.DefaultSocketChannelConfig;
import org.jboss.netty.channel.socket.SocketChannel;
import org.jboss.netty.channel.socket.SocketChannelConfig;
abstract class OioSocketChannel extends AbstractOioChannel
implements SocketChannel {
final Socket socket;
private final SocketChannelConfig config;
OioSocketChannel(
Channel parent,
ChannelFactory factory,
ChannelPipeline pipeline,
ChannelSink sink,
Socket socket) {
super(parent, factory, pipeline, sink);
this.socket = socket;
try {
socket.setSoTimeout(1000);
} catch (SocketException e) {
throw new ChannelException(
"Failed to configure the OioSocketChannel socket timeout.", e);
}
config = new DefaultSocketChannelConfig(socket);
}
public SocketChannelConfig getConfig() {
return config;
}
abstract PushbackInputStream getInputStream();
abstract OutputStream getOutputStream();
@Override
boolean isSocketBound() {
return socket.isBound();
}
@Override
boolean isSocketConnected() {
return socket.isConnected();
}
@Override
InetSocketAddress getLocalSocketAddress() throws Exception {
return (InetSocketAddress) socket.getLocalSocketAddress();
}
@Override
InetSocketAddress getRemoteSocketAddress() throws Exception {
return (InetSocketAddress) socket.getRemoteSocketAddress();
}
@Override
void closeSocket() throws IOException {
socket.close();
}
@Override
boolean isSocketClosed() {
return socket.isClosed();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/OioWorker.java 0000664 0000000 0000000 00000012105 12255541277 0031047 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.channel.socket.oio;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.DefaultFileRegion;
import org.jboss.netty.channel.FileRegion;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.net.SocketException;
import java.nio.channels.Channels;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.WritableByteChannel;
import java.util.regex.Pattern;
import static org.jboss.netty.channel.Channels.*;
class OioWorker extends AbstractOioWorker {
private static final Pattern SOCKET_CLOSED_MESSAGE = Pattern.compile(
"^.*(?:Socket.*closed).*$", Pattern.CASE_INSENSITIVE);
OioWorker(OioSocketChannel channel) {
super(channel);
}
@Override
public void run() {
boolean fireConnected = channel instanceof OioAcceptedSocketChannel;
if (fireConnected && channel.isOpen()) {
// Fire the channelConnected event for OioAcceptedSocketChannel.
// See #287
fireChannelConnected(channel, channel.getRemoteAddress());
}
super.run();
}
@Override
boolean process() throws IOException {
byte[] buf;
int readBytes;
PushbackInputStream in = channel.getInputStream();
int bytesToRead = in.available();
if (bytesToRead > 0) {
buf = new byte[bytesToRead];
readBytes = in.read(buf);
} else {
int b = in.read();
if (b < 0) {
return false;
}
in.unread(b);
return true;
}
fireMessageReceived(channel, channel.getConfig().getBufferFactory().getBuffer(buf, 0, readBytes));
return true;
}
static void write(
OioSocketChannel channel, ChannelFuture future,
Object message) {
boolean iothread = isIoThread(channel);
OutputStream out = channel.getOutputStream();
if (out == null) {
Exception e = new ClosedChannelException();
future.setFailure(e);
if (iothread) {
fireExceptionCaught(channel, e);
} else {
fireExceptionCaughtLater(channel, e);
}
return;
}
try {
int length = 0;
// Add support to write a FileRegion. This in fact will not give any performance gain
// but at least it not fail and we did the best to emulate it
if (message instanceof FileRegion) {
FileRegion fr = (FileRegion) message;
try {
synchronized (out) {
WritableByteChannel bchannel = Channels.newChannel(out);
long i;
while ((i = fr.transferTo(bchannel, length)) > 0) {
length += i;
if (length >= fr.getCount()) {
break;
}
}
}
} finally {
if (fr instanceof DefaultFileRegion) {
DefaultFileRegion dfr = (DefaultFileRegion) fr;
if (dfr.releaseAfterTransfer()) {
fr.releaseExternalResources();
}
}
}
} else {
ChannelBuffer a = (ChannelBuffer) message;
length = a.readableBytes();
synchronized (out) {
a.getBytes(a.readerIndex(), out, length);
}
}
future.setSuccess();
if (iothread) {
fireWriteComplete(channel, length);
} else {
fireWriteCompleteLater(channel, length);
}
} catch (Throwable t) {
// Convert 'SocketException: Socket closed' to
// ClosedChannelException.
if (t instanceof SocketException &&
SOCKET_CLOSED_MESSAGE.matcher(
String.valueOf(t.getMessage())).matches()) {
t = new ClosedChannelException();
}
future.setFailure(t);
if (iothread) {
fireExceptionCaught(channel, t);
} else {
fireExceptionCaughtLater(channel, t);
}
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/oio/package-info.java 0000664 0000000 0000000 00000001454 12255541277 0031460 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Old blocking I/O based socket channel API implementation - recommended for
* a small number of connections (< 1000).
*/
package org.jboss.netty.channel.socket.oio;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/channel/socket/package-info.java 0000664 0000000 0000000 00000001561 12255541277 0030671 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Abstract TCP and UDP socket interfaces which extend the core channel API.
*
* @apiviz.exclude \.(Abstract|Default).*$
* @apiviz.exclude \.socket\.[a-z]+\.
* @apiviz.exclude \.channel\.[A-Z]
*/
package org.jboss.netty.channel.socket;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/ 0000775 0000000 0000000 00000000000 12255541277 0024561 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/microcontainer/ 0000775 0000000 0000000 00000000000 12255541277 0027575 5 ustar 00root root 0000000 0000000 NettyLoggerConfigurator.java 0000664 0000000 0000000 00000002006 12255541277 0035205 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/microcontainer /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.container.microcontainer;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.logging.JBossLoggerFactory;
/**
* A bean that configures the default {@link InternalLoggerFactory}.
*/
public class NettyLoggerConfigurator {
public NettyLoggerConfigurator() {
InternalLoggerFactory.setDefaultFactory(new JBossLoggerFactory());
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/microcontainer/package-info.java 0000664 0000000 0000000 00000001435 12255541277 0032767 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* JBoss Microcontainer integration.
*
* @apiviz.exclude
*/
package org.jboss.netty.container.microcontainer;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/osgi/ 0000775 0000000 0000000 00000000000 12255541277 0025522 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/osgi/NettyBundleActivator.java 0000664 0000000 0000000 00000003023 12255541277 0032475 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.container.osgi;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.logging.OsgiLoggerFactory;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
/**
* An OSGi {@link BundleActivator} that configures logging.
*/
public class NettyBundleActivator implements BundleActivator {
private OsgiLoggerFactory loggerFactory;
public void start(BundleContext ctx) throws Exception {
// Switch the internal logger to the OSGi LogService.
loggerFactory = new OsgiLoggerFactory(ctx);
InternalLoggerFactory.setDefaultFactory(loggerFactory);
}
public void stop(BundleContext ctx) throws Exception {
if (loggerFactory != null) {
InternalLoggerFactory.setDefaultFactory(loggerFactory.getFallback());
loggerFactory.destroy();
loggerFactory = null;
}
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/osgi/package-info.java 0000664 0000000 0000000 00000001404 12255541277 0030710 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* OSGi framework integration.
*
* @apiviz.exclude
*/
package org.jboss.netty.container.osgi;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/spring/ 0000775 0000000 0000000 00000000000 12255541277 0026063 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/spring/NettyLoggerConfigurator.java 0000664 0000000 0000000 00000002002 12255541277 0033546 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.container.spring;
import org.jboss.netty.logging.CommonsLoggerFactory;
import org.jboss.netty.logging.InternalLoggerFactory;
/**
* A bean that configures the default {@link InternalLoggerFactory}.
*/
public class NettyLoggerConfigurator {
public NettyLoggerConfigurator() {
InternalLoggerFactory.setDefaultFactory(new CommonsLoggerFactory());
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/container/spring/package-info.java 0000664 0000000 0000000 00000001423 12255541277 0031252 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* Spring framework integration.
*
* @apiviz.exclude
*/
package org.jboss.netty.container.spring;
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/ 0000775 0000000 0000000 00000000000 12255541277 0024232 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/discard/ 0000775 0000000 0000000 00000000000 12255541277 0025643 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/discard/DiscardClient.java 0000664 0000000 0000000 00000006110 12255541277 0031214 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.discard;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
/**
* Keeps sending random data to the specified address.
*/
public class DiscardClient {
private final String host;
private final int port;
private final int firstMessageSize;
public DiscardClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public void run() {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new DiscardClientHandler(firstMessageSize));
}
});
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + DiscardClient.class.getSimpleName() +
" []");
return;
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new DiscardClient(host, port, firstMessageSize).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/discard/DiscardClientHandler.java 0000664 0000000 0000000 00000007662 12255541277 0032527 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.discard;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelState;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.WriteCompletionEvent;
/**
* Handles a client-side channel.
*/
public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
DiscardClientHandler.class.getName());
private long transferredBytes;
private final byte[] content;
public DiscardClientHandler(int messageSize) {
if (messageSize <= 0) {
throw new IllegalArgumentException(
"messageSize: " + messageSize);
}
content = new byte[messageSize];
}
public long getTransferredBytes() {
return transferredBytes;
}
@Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
if (((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
logger.info(e.toString());
}
}
// Let SimpleChannelHandler call actual event handler methods below.
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the initial messages.
generateTraffic(e);
}
@Override
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Keep sending messages whenever the current socket buffer has room.
generateTraffic(e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Server is supposed to send nothing. Therefore, do nothing.
}
@Override
public void writeComplete(ChannelHandlerContext ctx, WriteCompletionEvent e) {
transferredBytes += e.getWrittenAmount();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
private void generateTraffic(ChannelStateEvent e) {
// Keep generating traffic until the channel is unwritable.
// A channel becomes unwritable when its internal buffer is full.
// If you keep writing messages ignoring this property,
// you will end up with an OutOfMemoryError.
Channel channel = e.getChannel();
while (channel.isWritable()) {
ChannelBuffer m = nextMessage();
if (m == null) {
break;
}
channel.write(m);
}
}
private ChannelBuffer nextMessage() {
return ChannelBuffers.wrappedBuffer(content);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/discard/DiscardServer.java 0000664 0000000 0000000 00000004105 12255541277 0031246 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.discard;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
/**
* Discards any incoming data.
*/
public class DiscardServer {
private final int port;
public DiscardServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new DiscardServerHandler());
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new DiscardServer(port).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/discard/DiscardServerHandler.java 0000664 0000000 0000000 00000004430 12255541277 0032545 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.discard;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* Handles a server-side channel.
*/
public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
DiscardServerHandler.class.getName());
private long transferredBytes;
public long getTransferredBytes() {
return transferredBytes;
}
@Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
}
// Let SimpleChannelHandler call actual event handler methods below.
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Discard received data silently by doing nothing.
transferredBytes += ((ChannelBuffer) e.getMessage()).readableBytes();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/echo/ 0000775 0000000 0000000 00000000000 12255541277 0025150 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/echo/EchoClient.java 0000664 0000000 0000000 00000006364 12255541277 0030041 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.echo;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
/**
* Sends one message when a connection is open and echoes back any received
* data to the server. Simply put, the echo client initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class EchoClient {
private final String host;
private final int port;
private final int firstMessageSize;
public EchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public void run() {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new EchoClientHandler(firstMessageSize));
}
});
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + EchoClient.class.getSimpleName() +
" []");
return;
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new EchoClient(host, port, firstMessageSize).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/echo/EchoClientHandler.java 0000664 0000000 0000000 00000006006 12255541277 0031330 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.echo;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class EchoClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
EchoClientHandler.class.getName());
private final ChannelBuffer firstMessage;
private final AtomicLong transferredBytes = new AtomicLong();
/**
* Creates a client-side handler.
*/
public EchoClientHandler(int firstMessageSize) {
if (firstMessageSize <= 0) {
throw new IllegalArgumentException(
"firstMessageSize: " + firstMessageSize);
}
firstMessage = ChannelBuffers.buffer(firstMessageSize);
for (int i = 0; i < firstMessage.capacity(); i ++) {
firstMessage.writeByte((byte) i);
}
}
public long getTransferredBytes() {
return transferredBytes.get();
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the first message. Server will not send anything here
// because the firstMessage's capacity is 0.
e.getChannel().write(firstMessage);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/echo/EchoServer.java 0000664 0000000 0000000 00000004107 12255541277 0030062 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.echo;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
/**
* Echoes back any received data from a client.
*/
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new EchoServerHandler());
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new EchoServer(port).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/echo/EchoServerHandler.java 0000664 0000000 0000000 00000004036 12255541277 0031361 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.echo;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* Handler implementation for the echo server.
*/
public class EchoServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
EchoServerHandler.class.getName());
private final AtomicLong transferredBytes = new AtomicLong();
public long getTransferredBytes() {
return transferredBytes.get();
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/ 0000775 0000000 0000000 00000000000 12255541277 0026176 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/BigIntegerDecoder.java 0000664 0000000 0000000 00000004375 12255541277 0032357 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.CorruptedFrameException;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
/**
* Decodes the binary representation of a {@link BigInteger} prepended
* with a magic number ('F' or 0x46) and a 32-bit integer length prefix into a
* {@link BigInteger} instance. For example, { 'F', 0, 0, 0, 1, 42 } will be
* decoded into new BigInteger("42").
*/
public class BigIntegerDecoder extends FrameDecoder {
@Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
// Wait until the length prefix is available.
if (buffer.readableBytes() < 5) {
return null;
}
buffer.markReaderIndex();
// Check the magic number.
int magicNumber = buffer.readUnsignedByte();
if (magicNumber != 'F') {
buffer.resetReaderIndex();
throw new CorruptedFrameException(
"Invalid magic number: " + magicNumber);
}
// Wait until the whole data is available.
int dataLength = buffer.readInt();
if (buffer.readableBytes() < dataLength) {
buffer.resetReaderIndex();
return null;
}
// Convert the received data into a new BigInteger.
byte[] decoded = new byte[dataLength];
buffer.readBytes(decoded);
return new BigInteger(decoded);
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/FactorialClient.java 0000664 0000000 0000000 00000006055 12255541277 0032112 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
/**
* Sends a sequence of integers to a {@link FactorialServer} to calculate
* the factorial of the specified integer.
*/
public class FactorialClient {
private final String host;
private final int port;
private final int count;
public FactorialClient(String host, int port, int count) {
this.host = host;
this.port = port;
this.count = count;
}
public void run() {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new FactorialClientPipelineFactory(count));
// Make a new connection.
ChannelFuture connectFuture =
bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is made successfully.
Channel channel = connectFuture.awaitUninterruptibly().getChannel();
// Get the handler instance to retrieve the answer.
FactorialClientHandler handler =
(FactorialClientHandler) channel.getPipeline().getLast();
// Print out the answer.
System.err.format(
"Factorial of %,d is: %,d", count, handler.getFactorial());
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length != 3) {
System.err.println(
"Usage: " + FactorialClient.class.getSimpleName() +
" ");
return;
}
// Parse options.
String host = args[0];
int port = Integer.parseInt(args[1]);
int count = Integer.parseInt(args[2]);
if (count <= 0) {
throw new IllegalArgumentException("count must be a positive integer.");
}
new FactorialClient(host, port, count).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/FactorialClientHandler.java 0000664 0000000 0000000 00000010175 12255541277 0033406 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* Handler for a client-side channel. This handler maintains stateful
* information which is specific to a certain channel using member variables.
* Therefore, an instance of this handler can cover only one channel. You have
* to create a new handler instance whenever you create a new channel and insert
* this handler to avoid a race condition.
*/
public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
FactorialClientHandler.class.getName());
// Stateful properties
private int i = 1;
private int receivedMessages;
private final int count;
final BlockingQueue answer = new LinkedBlockingQueue();
public FactorialClientHandler(int count) {
this.count = count;
}
public BigInteger getFactorial() {
boolean interrupted = false;
for (;;) {
try {
BigInteger factorial = answer.take();
if (interrupted) {
Thread.currentThread().interrupt();
}
return factorial;
} catch (InterruptedException e) {
interrupted = true;
}
}
}
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
}
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
sendNumbers(e);
}
@Override
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
sendNumbers(e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, final MessageEvent e) {
receivedMessages ++;
if (receivedMessages == count) {
// Offer the answer after closing the connection.
e.getChannel().close().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
boolean offered = answer.offer((BigInteger) e.getMessage());
assert offered;
}
});
}
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
private void sendNumbers(ChannelStateEvent e) {
Channel channel = e.getChannel();
while (channel.isWritable()) {
if (i <= count) {
channel.write(i);
i ++;
} else {
break;
}
}
}
}
FactorialClientPipelineFactory.java 0000664 0000000 0000000 00000003642 12255541277 0035050 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
/**
* Creates a newly configured {@link ChannelPipeline} for a client-side channel.
*/
public class FactorialClientPipelineFactory implements
ChannelPipelineFactory {
private final int count;
public FactorialClientPipelineFactory(int count) {
this.count = count;
}
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();
// Enable stream compression (you can remove these two if unnecessary)
pipeline.addLast("deflater", new ZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("inflater", new ZlibDecoder(ZlibWrapper.GZIP));
// Add the number codec first,
pipeline.addLast("decoder", new BigIntegerDecoder());
pipeline.addLast("encoder", new NumberEncoder());
// and then business logic.
pipeline.addLast("handler", new FactorialClientHandler(count));
return pipeline;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/FactorialServer.java 0000664 0000000 0000000 00000003602 12255541277 0032135 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
/**
* Receives a sequence of integers from a {@link FactorialClient} to calculate
* the factorial of the specified integer.
*/
public class FactorialServer {
private final int port;
public FactorialServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new FactorialServerPipelineFactory());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new FactorialServer(port).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/FactorialServerHandler.java 0000664 0000000 0000000 00000006101 12255541277 0033430 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import java.util.Formatter;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
/**
* Handler for a server-side channel. This handler maintains stateful
* information which is specific to a certain channel using member variables.
* Therefore, an instance of this handler can cover only one channel. You have
* to create a new handler instance whenever you create a new channel and insert
* this handler to avoid a race condition.
*/
public class FactorialServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
FactorialServerHandler.class.getName());
// Stateful properties.
private int lastMultiplier = 1;
private BigInteger factorial = new BigInteger(new byte[] { 1 });
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
}
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Calculate the cumulative factorial and send it to the client.
BigInteger number;
if (e.getMessage() instanceof BigInteger) {
number = (BigInteger) e.getMessage();
} else {
number = new BigInteger(e.getMessage().toString());
}
lastMultiplier = number.intValue();
factorial = factorial.multiply(number);
e.getChannel().write(factorial);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
logger.info(new Formatter().format(
"Factorial of %,d is: %,d", lastMultiplier, factorial).toString());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
FactorialServerPipelineFactory.java 0000664 0000000 0000000 00000003625 12255541277 0035101 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
/**
* Creates a newly configured {@link ChannelPipeline} for a server-side channel.
*/
public class FactorialServerPipelineFactory implements
ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();
// Enable stream compression (you can remove these two if unnecessary)
pipeline.addLast("deflater", new ZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("inflater", new ZlibDecoder(ZlibWrapper.GZIP));
// Add the number codec first,
pipeline.addLast("decoder", new BigIntegerDecoder());
pipeline.addLast("encoder", new NumberEncoder());
// and then business logic.
// Please note we create a handler for every new channel
// because it has stateful properties.
pipeline.addLast("handler", new FactorialServerHandler());
return pipeline;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/factorial/NumberEncoder.java 0000664 0000000 0000000 00000004154 12255541277 0031575 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
/**
* Encodes a {@link Number} into the binary representation prepended with
* a magic number ('F' or 0x46) and a 32-bit length prefix. For example, 42
* will be encoded to { 'F', 0, 0, 0, 1, 42 }.
*/
public class NumberEncoder extends OneToOneEncoder {
@Override
protected Object encode(
ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
if (!(msg instanceof Number)) {
// Ignore what this encoder can't encode.
return msg;
}
// Convert to a BigInteger first for easier implementation.
BigInteger v;
if (msg instanceof BigInteger) {
v = (BigInteger) msg;
} else {
v = new BigInteger(String.valueOf(msg));
}
// Convert the number into a byte array.
byte[] data = v.toByteArray();
int dataLength = data.length;
// Construct a message.
ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
buf.writeByte((byte) 'F'); // magic number
buf.writeInt(dataLength); // data length
buf.writeBytes(data); // data
// Return the constructed message.
return buf;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/ 0000775 0000000 0000000 00000000000 12255541277 0025211 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/file/ 0000775 0000000 0000000 00000000000 12255541277 0026130 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/file/HttpStaticFileServer.java 0000664 0000000 0000000 00000003403 12255541277 0033051 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.file;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class HttpStaticFileServer {
private final int port;
public HttpStaticFileServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpStaticFileServerPipelineFactory());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new HttpStaticFileServer(port).run();
}
}
HttpStaticFileServerHandler.java 0000664 0000000 0000000 00000027243 12255541277 0034300 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/file /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.file;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelFutureProgressListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.DefaultFileRegion;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.FileRegion;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.ssl.SslHandler;
import org.jboss.netty.handler.stream.ChunkedFile;
import org.jboss.netty.util.CharsetUtil;
import javax.activation.MimetypesFileTypeMap;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
/**
* A simple handler that serves incoming HTTP requests to send their respective
* HTTP responses. It also implements {@code 'If-Modified-Since'} header to
* take advantage of browser cache, as described in
* RFC 2616 .
*
* How Browser Caching Works
*
* Web browser caching works with HTTP headers as illustrated by the following
* sample:
*
* Request #1 returns the content of {@code /file1.txt}.
* Contents of {@code /file1.txt} is cached by the browser.
* Request #2 for {@code /file1.txt} does return the contents of the
* file again. Rather, a 304 Not Modified is returned. This tells the
* browser to use the contents stored in its cache.
* The server knows the file has not been modified because the
* {@code If-Modified-Since} date is the same as the file's last
* modified date.
*
*
*
* Request #1 Headers
* ===================
* GET /file1.txt HTTP/1.1
*
* Response #1 Headers
* ===================
* HTTP/1.1 200 OK
* Date: Tue, 01 Mar 2011 22:44:26 GMT
* Last-Modified: Wed, 30 Jun 2010 21:36:48 GMT
* Expires: Tue, 01 Mar 2012 22:44:26 GMT
* Cache-Control: private, max-age=31536000
*
* Request #2 Headers
* ===================
* GET /file1.txt HTTP/1.1
* If-Modified-Since: Wed, 30 Jun 2010 21:36:48 GMT
*
* Response #2 Headers
* ===================
* HTTP/1.1 304 Not Modified
* Date: Tue, 01 Mar 2011 22:44:28 GMT
*
*
*/
public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
public static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
public static final int HTTP_CACHE_SECONDS = 60;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
HttpRequest request = (HttpRequest) e.getMessage();
if (request.getMethod() != GET) {
sendError(ctx, METHOD_NOT_ALLOWED);
return;
}
final String path = sanitizeUri(request.getUri());
if (path == null) {
sendError(ctx, FORBIDDEN);
return;
}
File file = new File(path);
if (file.isHidden() || !file.exists()) {
sendError(ctx, NOT_FOUND);
return;
}
if (!file.isFile()) {
sendError(ctx, FORBIDDEN);
return;
}
// Cache Validation
String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE);
if (ifModifiedSince != null && ifModifiedSince.length() != 0) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
// Only compare up to the second because the datetime format we send to the client does
// not have milliseconds
long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
long fileLastModifiedSeconds = file.lastModified() / 1000;
if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
sendNotModified(ctx);
return;
}
}
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException fnfe) {
sendError(ctx, NOT_FOUND);
return;
}
long fileLength = raf.length();
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
setContentLength(response, fileLength);
setContentTypeHeader(response, file);
setDateAndCacheHeaders(response, file);
Channel ch = e.getChannel();
// Write the initial line and the header.
ch.write(response);
// Write the content.
ChannelFuture writeFuture;
if (ch.getPipeline().get(SslHandler.class) != null) {
// Cannot use zero-copy with HTTPS.
writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192));
} else {
// No encryption - use zero-copy.
final FileRegion region =
new DefaultFileRegion(raf.getChannel(), 0, fileLength);
writeFuture = ch.write(region);
writeFuture.addListener(new ChannelFutureProgressListener() {
public void operationComplete(ChannelFuture future) {
region.releaseExternalResources();
}
public void operationProgressed(
ChannelFuture future, long amount, long current, long total) {
System.out.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
}
});
}
// Decide whether to close the connection or not.
if (!isKeepAlive(request)) {
// Close the connection when the whole content is written out.
writeFuture.addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
Channel ch = e.getChannel();
Throwable cause = e.getCause();
if (cause instanceof TooLongFrameException) {
sendError(ctx, BAD_REQUEST);
return;
}
cause.printStackTrace();
if (ch.isConnected()) {
sendError(ctx, INTERNAL_SERVER_ERROR);
}
}
private static String sanitizeUri(String uri) {
// Decode the path.
try {
uri = URLDecoder.decode(uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
try {
uri = URLDecoder.decode(uri, "ISO-8859-1");
} catch (UnsupportedEncodingException e1) {
throw new Error();
}
}
// Convert file separators.
uri = uri.replace('/', File.separatorChar);
// Simplistic dumb security check.
// You will have to do something serious in the production environment.
if (uri.contains(File.separator + '.') ||
uri.contains('.' + File.separator) ||
uri.startsWith(".") || uri.endsWith(".")) {
return null;
}
// Convert to absolute path.
return System.getProperty("user.dir") + File.separator + uri;
}
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.setContent(ChannelBuffers.copiedBuffer(
"Failure: " + status.toString() + "\r\n",
CharsetUtil.UTF_8));
// Close the connection as soon as the error message is sent.
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
}
/**
* When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
*
* @param ctx
* Context
*/
private static void sendNotModified(ChannelHandlerContext ctx) {
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NOT_MODIFIED);
setDateHeader(response);
// Close the connection as soon as the error message is sent.
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
}
/**
* Sets the Date header for the HTTP response
*
* @param response
* HTTP response
*/
private static void setDateHeader(HttpResponse response) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
Calendar time = new GregorianCalendar();
response.headers().set(DATE, dateFormatter.format(time.getTime()));
}
/**
* Sets the Date and Cache headers for the HTTP Response
*
* @param response
* HTTP response
* @param fileToCache
* file to extract content type
*/
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
// Date header
Calendar time = new GregorianCalendar();
response.headers().set(DATE, dateFormatter.format(time.getTime()));
// Add cache headers
time.add(Calendar.SECOND, HTTP_CACHE_SECONDS);
response.headers().set(EXPIRES, dateFormatter.format(time.getTime()));
response.headers().set(CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);
response.headers().set(
LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
}
/**
* Sets the content type header for the HTTP Response
*
* @param response
* HTTP response
* @param file
* file to extract content type
*/
private static void setContentTypeHeader(HttpResponse response, File file) {
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
response.headers().set(CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
}
}
HttpStaticFileServerPipelineFactory.java 0000664 0000000 0000000 00000004166 12255541277 0036017 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/file /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.file;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.stream.ChunkedWriteHandler;
// Uncomment the following lines if you want HTTPS
//import javax.net.ssl.SSLEngine;
//import org.jboss.netty.example.securechat.SecureChatSslContextFactory;
//import org.jboss.netty.handler.ssl.SslHandler;
public class HttpStaticFileServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Uncomment the following lines if you want HTTPS
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
//engine.setUseClientMode(false);
//pipeline.addLast("ssl", new SslHandler(engine));
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
pipeline.addLast("handler", new HttpStaticFileServerHandler());
return pipeline;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/helloworld/ 0000775 0000000 0000000 00000000000 12255541277 0027364 5 ustar 00root root 0000000 0000000 HttpHelloWorldServer.java 0000664 0000000 0000000 00000004000 12255541277 0034244 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/helloworld /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.helloworld;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* An HTTP server that sends back the content of the received HTTP request
* in a pretty plaintext form.
*/
public class HttpHelloWorldServer {
private final int port;
public HttpHelloWorldServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Enable TCP_NODELAY to handle pipelined requests without latency.
bootstrap.setOption("child.tcpNoDelay", true);
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpHelloWorldServerPipelineFactory());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new HttpHelloWorldServer(port).run();
}
}
HttpHelloWorldServerHandler.java 0000664 0000000 0000000 00000006066 12255541277 0035560 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/helloworld /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.helloworld;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
public class HttpHelloWorldServerHandler extends SimpleChannelUpstreamHandler {
private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Object msg = e.getMessage();
Channel ch = e.getChannel();
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest) msg;
if (is100ContinueExpected(req)) {
Channels.write(ctx, Channels.future(ch), new DefaultHttpResponse(HTTP_1_1, CONTINUE));
}
boolean keepAlive = isKeepAlive(req);
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
response.setContent(ChannelBuffers.wrappedBuffer(CONTENT));
response.headers().set(CONTENT_TYPE, "text/plain");
response.headers().set(CONTENT_LENGTH, response.getContent().readableBytes());
if (!keepAlive) {
ChannelFuture f = Channels.future(ch);
f.addListener(ChannelFutureListener.CLOSE);
Channels.write(ctx, f, response);
} else {
response.headers().set(CONNECTION, Values.KEEP_ALIVE);
Channels.write(ctx, Channels.future(ch), response);
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
e.getCause().printStackTrace();
e.getChannel().close();
}
}
HttpHelloWorldServerPipelineFactory.java 0000664 0000000 0000000 00000004030 12255541277 0037265 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/helloworld /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.helloworld;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpContentCompressor;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import static org.jboss.netty.channel.Channels.*;
public class HttpHelloWorldServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Uncomment the following line if you want HTTPS
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
//engine.setUseClientMode(false);
//pipeline.addLast("ssl", new SslHandler(engine));
pipeline.addLast("decoder", new HttpRequestDecoder());
// Uncomment the following line if you don't want to handle HttpChunks.
//pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
pipeline.addLast("encoder", new HttpResponseEncoder());
// Remove the following line if you don't want automatic content compression.
pipeline.addLast("deflater", new HttpContentCompressor());
pipeline.addLast("handler", new HttpHelloWorldServerHandler());
return pipeline;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/snoop/ 0000775 0000000 0000000 00000000000 12255541277 0026347 5 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/snoop/HttpSnoopClient.java 0000664 0000000 0000000 00000010457 12255541277 0032316 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.snoop;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpVersion;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.concurrent.Executors;
/**
* A simple HTTP client that prints out the content of the HTTP response to
* {@link System#out} to test {@link HttpSnoopServer}.
*/
public class HttpSnoopClient {
private final URI uri;
public HttpSnoopClient(URI uri) {
this.uri = uri;
}
public void run() {
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
String host = uri.getHost() == null? "localhost" : uri.getHost();
int port = uri.getPort();
if (port == -1) {
if ("http".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("https".equalsIgnoreCase(scheme)) {
port = 443;
}
}
if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
System.err.println("Only HTTP(S) is supported.");
return;
}
boolean ssl = "https".equalsIgnoreCase(scheme);
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpSnoopClientPipelineFactory(ssl));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return;
}
// Prepare the HTTP request.
HttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
request.headers().set(HttpHeaders.Names.HOST, host);
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
// Set some example cookies.
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
httpCookieEncoder.addCookie("my-cookie", "foo");
httpCookieEncoder.addCookie("another-cookie", "bar");
request.headers().set(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
// Send the HTTP request.
channel.write(request);
// Wait for the server to close the connection.
channel.getCloseFuture().awaitUninterruptibly();
// Shut down executor threads to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println(
"Usage: " + HttpSnoopClient.class.getSimpleName() +
" ");
return;
}
URI uri = new URI(args[0]);
new HttpSnoopClient(uri).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/snoop/HttpSnoopClientHandler.java0000664 0000000 0000000 00000005316 12255541277 0033612 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.snoop;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.util.CharsetUtil;
public class HttpSnoopClientHandler extends SimpleChannelUpstreamHandler {
private boolean readingChunks;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (!readingChunks) {
HttpResponse response = (HttpResponse) e.getMessage();
System.out.println("STATUS: " + response.getStatus());
System.out.println("VERSION: " + response.getProtocolVersion());
System.out.println();
if (!response.headers().names().isEmpty()) {
for (String name: response.headers().names()) {
for (String value: response.headers().getAll(name)) {
System.out.println("HEADER: " + name + " = " + value);
}
}
System.out.println();
}
if (response.isChunked()) {
readingChunks = true;
System.out.println("CHUNKED CONTENT {");
} else {
ChannelBuffer content = response.getContent();
if (content.readable()) {
System.out.println("CONTENT {");
System.out.println(content.toString(CharsetUtil.UTF_8));
System.out.println("} END OF CONTENT");
}
}
} else {
HttpChunk chunk = (HttpChunk) e.getMessage();
if (chunk.isLast()) {
readingChunks = false;
System.out.println("} END OF CHUNKED CONTENT");
} else {
System.out.print(chunk.getContent().toString(CharsetUtil.UTF_8));
System.out.flush();
}
}
}
}
HttpSnoopClientPipelineFactory.java 0000664 0000000 0000000 00000004272 12255541277 0035253 0 ustar 00root root 0000000 0000000 netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/snoop /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.snoop;
import static org.jboss.netty.channel.Channels.*;
import javax.net.ssl.SSLEngine;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.example.securechat.SecureChatSslContextFactory;
import org.jboss.netty.handler.codec.http.HttpClientCodec;
import org.jboss.netty.handler.codec.http.HttpContentDecompressor;
import org.jboss.netty.handler.ssl.SslHandler;
public class HttpSnoopClientPipelineFactory implements ChannelPipelineFactory {
private final boolean ssl;
public HttpSnoopClientPipelineFactory(boolean ssl) {
this.ssl = ssl;
}
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Enable HTTPS if necessary.
if (ssl) {
SSLEngine engine =
SecureChatSslContextFactory.getClientContext().createSSLEngine();
engine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(engine));
}
pipeline.addLast("codec", new HttpClientCodec());
// Remove the following line if you don't want automatic content decompression.
pipeline.addLast("inflater", new HttpContentDecompressor());
// Uncomment the following line if you don't want to handle HttpChunks.
//pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
pipeline.addLast("handler", new HttpSnoopClientHandler());
return pipeline;
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/snoop/HttpSnoopServer.java 0000664 0000000 0000000 00000003747 12255541277 0032352 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.snoop;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* An HTTP server that sends back the content of the received HTTP request
* in a pretty plaintext form.
*/
public class HttpSnoopServer {
private final int port;
public HttpSnoopServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Enable TCP_NODELAY to handle pipelined requests without latency.
bootstrap.setOption("child.tcpNoDelay", true);
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpSnoopServerPipelineFactory());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new HttpSnoopServer(port).run();
}
}
netty-netty-3.9.0.Final/src/main/java/org/jboss/netty/example/http/snoop/HttpSnoopServerHandler.java0000664 0000000 0000000 00000016751 12255541277 0033647 0 ustar 00root root 0000000 0000000 /*
* Copyright 2012 The Netty Project
*
* 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:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.jboss.netty.example.http.snoop;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpChunkTrailer;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.util.CharsetUtil;
public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
private HttpRequest request;
private boolean readingChunks;
/** Buffer that stores the response content */
private final StringBuilder buf = new StringBuilder();
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (!readingChunks) {
HttpRequest request = this.request = (HttpRequest) e.getMessage();
if (is100ContinueExpected(request)) {
send100Continue(e);
}
buf.setLength(0);
buf.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
buf.append("===================================\r\n");
buf.append("VERSION: " + request.getProtocolVersion() + "\r\n");
buf.append("HOSTNAME: " + getHost(request, "unknown") + "\r\n");
buf.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n");
for (Map.Entry h: request.headers()) {
buf.append("HEADER: " + h.getKey() + " = " + h.getValue() + "\r\n");
}
buf.append("\r\n");
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
Map> params = queryStringDecoder.getParameters();
if (!params.isEmpty()) {
for (Entry> p: params.entrySet()) {
String key = p.getKey();
List