1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.filter.support;
21
22 import java.nio.ByteBuffer;
23
24 import javax.net.ssl.SSLEngine;
25
26 import org.apache.mina.util.Stack;
27
28
29
30
31
32
33
34
35
36 class SSLByteBufferPool {
37 private static final int PACKET_BUFFER_INDEX = 0;
38
39 private static final int APPLICATION_BUFFER_INDEX = 1;
40
41 private static boolean initiated = false;
42
43 private static final String DIRECT_MEMORY_PROP = "mina.sslfilter.directbuffer";
44
45 private static boolean useDirectAllocatedBuffers = true;
46
47 private static int packetBufferSize;
48
49 private static int appBufferSize;
50
51 private static int[] bufferStackSizes;
52
53 private static final Stack[] bufferStacks = new Stack[] { new Stack(),
54 new Stack(), };
55
56
57
58
59
60
61 static synchronized void initiate(SSLEngine sslEngine) {
62 if (!initiated) {
63
64 String prop = System.getProperty(DIRECT_MEMORY_PROP);
65 if (prop != null) {
66 useDirectAllocatedBuffers = Boolean
67 .getBoolean(DIRECT_MEMORY_PROP);
68 }
69
70
71 packetBufferSize = sslEngine.getSession().getPacketBufferSize();
72
73
74
75
76 appBufferSize = packetBufferSize * 2;
77 initiateBufferStacks();
78 initiated = true;
79 }
80 }
81
82
83
84
85
86 static ByteBuffer getPacketBuffer() {
87 if (!initiated) {
88 throw new IllegalStateException("Not initialized");
89 }
90 return allocate(PACKET_BUFFER_INDEX);
91 }
92
93
94
95
96
97 static ByteBuffer getApplicationBuffer() {
98 if (!initiated) {
99 throw new IllegalStateException("Not initialized");
100 }
101 return allocate(APPLICATION_BUFFER_INDEX);
102 }
103
104
105
106
107 private static ByteBuffer allocate(int idx) {
108 Stack stack = bufferStacks[idx];
109
110 ByteBuffer buf;
111 synchronized (stack) {
112 buf = (ByteBuffer) stack.pop();
113 if (buf == null) {
114 buf = createBuffer(bufferStackSizes[idx]);
115 }
116 }
117
118 buf.clear();
119 return buf;
120 }
121
122
123
124
125 public static void release(ByteBuffer buf) {
126
127 org.apache.mina.common.ByteBuffer.wrap(buf).sweep().release();
128
129 int stackIndex = getBufferStackIndex(buf.capacity());
130 if (stackIndex >= PACKET_BUFFER_INDEX) {
131 Stack stack = bufferStacks[getBufferStackIndex(buf.capacity())];
132 synchronized (stack) {
133 stack.push(buf);
134 }
135 }
136 }
137
138
139
140
141
142
143 public static ByteBuffer expandBuffer(ByteBuffer buf, int newCapacity) {
144 ByteBuffer newBuf = createBuffer(newCapacity);
145 buf.flip();
146 newBuf.put(buf);
147 release(buf);
148 return newBuf;
149 }
150
151 private static void initiateBufferStacks() {
152 bufferStackSizes = new int[2];
153 bufferStackSizes[PACKET_BUFFER_INDEX] = packetBufferSize;
154 bufferStackSizes[APPLICATION_BUFFER_INDEX] = appBufferSize;
155 }
156
157 private static int getBufferStackIndex(int size) {
158 if (size == packetBufferSize)
159 return PACKET_BUFFER_INDEX;
160 if (size == appBufferSize)
161 return APPLICATION_BUFFER_INDEX;
162 return -1;
163 }
164
165 private static ByteBuffer createBuffer(int capacity) {
166 if (useDirectAllocatedBuffers) {
167 try {
168 return ByteBuffer.allocateDirect(capacity);
169 } catch (OutOfMemoryError e) {
170 useDirectAllocatedBuffers = false;
171 System.err
172 .println("OutOfMemoryError: No more direct buffers available; trying heap buffer instead");
173 }
174 }
175 return ByteBuffer.allocate(capacity);
176 }
177
178 }