1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.openr66.protocol.localhandler.packet;
21
22 import io.netty.buffer.ByteBuf;
23 import io.netty.buffer.ByteBufAllocator;
24 import io.netty.buffer.Unpooled;
25 import io.netty.util.IllegalReferenceCountException;
26 import org.waarp.common.utility.WaarpNettyUtil;
27 import org.waarp.openr66.protocol.exception.OpenR66ProtocolPacketException;
28 import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
29 import org.waarp.openr66.protocol.networkhandler.packet.NetworkPacket;
30
31 import static org.waarp.openr66.protocol.networkhandler.packet.NetworkPacket.*;
32
33
34
35
36
37
38
39
40
41
42 public abstract class AbstractLocalPacket {
43 protected static final byte[] EMPTY_ARRAY = {};
44 protected static final int LOCAL_HEADER_SIZE = 4 * 3 + 1;
45
46 protected ByteBuf header;
47
48 protected ByteBuf middle;
49
50 protected ByteBuf end;
51
52 protected ByteBuf global = null;
53
54 protected AbstractLocalPacket() {
55 header = null;
56 middle = null;
57 end = null;
58 }
59
60
61
62
63 public abstract boolean hasGlobalBuffer();
64
65
66
67
68
69
70 public abstract void createAllBuffers(final LocalChannelReference lcr,
71 final int networkHeader)
72 throws OpenR66ProtocolPacketException;
73
74
75
76
77
78
79 public void createHeader(final LocalChannelReference lcr)
80 throws OpenR66ProtocolPacketException {
81 throw new IllegalStateException("Should not be called");
82 }
83
84
85
86
87
88
89 public void createMiddle(final LocalChannelReference lcr)
90 throws OpenR66ProtocolPacketException {
91 throw new IllegalStateException("Should not be called");
92 }
93
94
95
96
97
98
99 public void createEnd(final LocalChannelReference lcr)
100 throws OpenR66ProtocolPacketException {
101 throw new IllegalStateException("Should not be called");
102 }
103
104
105
106
107 public abstract byte getType();
108
109 @Override
110 public abstract String toString();
111
112
113
114
115
116
117
118
119 public final ByteBuf getLocalPacket(final LocalChannelReference lcr)
120 throws OpenR66ProtocolPacketException {
121 return getLocalPacketForNetworkPacket(lcr, null);
122 }
123
124
125
126
127
128
129
130
131 public final synchronized ByteBuf getLocalPacketForNetworkPacket(
132 final LocalChannelReference lcr, final NetworkPacket packet)
133 throws OpenR66ProtocolPacketException {
134 try {
135 final ByteBuf buf;
136 final int globalHeader;
137 if (packet != null) {
138 globalHeader = NETWORK_HEADER_SIZE;
139 } else {
140 globalHeader = 0;
141 }
142 if (hasGlobalBuffer()) {
143 if (global == null) {
144 createAllBuffers(lcr, globalHeader);
145 } else {
146 global.readerIndex(0);
147 global.writerIndex(0);
148 }
149 buf = global;
150 } else {
151
152 buf =
153 ByteBufAllocator.DEFAULT.ioBuffer(globalHeader + LOCAL_HEADER_SIZE,
154 globalHeader + LOCAL_HEADER_SIZE);
155 if (header == null) {
156 createHeader(lcr);
157 }
158 if (middle == null) {
159 createMiddle(lcr);
160 }
161 if (end == null) {
162 createEnd(lcr);
163 }
164 }
165 if (packet != null) {
166 final int capacity =
167 LOCAL_HEADER_SIZE + (header != null? header.capacity() : 0) +
168 (middle != null? middle.capacity() : 0) +
169 (end != null? end.capacity() : 0);
170 packet.writeNetworkHeader(buf, capacity);
171 }
172 return getByteBuf(buf);
173 } catch (final IllegalReferenceCountException e) {
174 throw new OpenR66ProtocolPacketException(e);
175 }
176 }
177
178 private ByteBuf getByteBuf(final ByteBuf buf) {
179 final ByteBuf newHeader = header != null? header : Unpooled.EMPTY_BUFFER;
180 final int headerLength = LOCAL_HEADER_SIZE - 4 + newHeader.readableBytes();
181 final ByteBuf newMiddle = middle != null? middle : Unpooled.EMPTY_BUFFER;
182 final int middleLength = newMiddle.readableBytes();
183 final ByteBuf newEnd = end != null? end : Unpooled.EMPTY_BUFFER;
184 final int endLength = newEnd.readableBytes();
185 buf.writeInt(headerLength);
186 buf.writeInt(middleLength);
187 buf.writeInt(endLength);
188 buf.writeByte(getType());
189 if (hasGlobalBuffer()) {
190 buf.writerIndex(buf.capacity());
191 return buf;
192 }
193 return ByteBufAllocator.DEFAULT.compositeDirectBuffer(4)
194 .addComponents(buf, newHeader, newMiddle,
195 newEnd);
196 }
197
198 public synchronized void clear() {
199 if (WaarpNettyUtil.release(global)) {
200 global = null;
201 }
202 if (hasGlobalBuffer()) {
203 return;
204 }
205 if (WaarpNettyUtil.release(header)) {
206 header = null;
207 }
208 if (WaarpNettyUtil.release(middle)) {
209 middle = null;
210 }
211 if (WaarpNettyUtil.release(end)) {
212 end = null;
213 }
214 }
215
216 public final synchronized void retain() {
217 WaarpNettyUtil.retain(global);
218 if (hasGlobalBuffer()) {
219 return;
220 }
221 WaarpNettyUtil.retain(header);
222 WaarpNettyUtil.retain(middle);
223 WaarpNettyUtil.retain(end);
224 }
225 }