forked from fizzed/cloudhopper-smpp
-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathPdu.java
More file actions
356 lines (309 loc) · 10.9 KB
/
Pdu.java
File metadata and controls
356 lines (309 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
package com.cloudhopper.smpp.pdu;
/*
* #%L
* ch-smpp
* %%
* Copyright (C) 2009 - 2015 Cloudhopper by Twitter
* %%
* Licensed 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.
* #L%
*/
import com.cloudhopper.smpp.type.UnrecoverablePduException;
import com.cloudhopper.smpp.type.RecoverablePduException;
import com.cloudhopper.commons.util.HexUtil;
import com.cloudhopper.smpp.SmppConstants;
import com.cloudhopper.smpp.tlv.Tlv;
import com.cloudhopper.smpp.transcoder.PduTranscoderContext;
import com.cloudhopper.smpp.util.ChannelBufferUtil;
import java.util.ArrayList;
import org.jboss.netty.buffer.ChannelBuffer;
public abstract class Pdu {
private final String name;
private final boolean isRequest;
private Integer commandLength; // we'll know the size not calculated yet if null
private final int commandId;
private int commandStatus;
private Integer sequenceNumber; // we'll know its not assigned yet if null
// optional parameters (there aren't many, no need for a map)
private ArrayList<Tlv> optionalParameters;
// a reference object that a caller can attach to this pdu
private Object referenceObject;
public Pdu(int commandId, String name, boolean isRequest) {
this.name = name;
this.isRequest = isRequest;
this.commandLength = null;
this.commandId = commandId;
this.sequenceNumber = null;
this.referenceObject = null;
}
public void setReferenceObject(Object value) {
this.referenceObject = value;
}
public Object getReferenceObject() {
return this.referenceObject;
}
public String getName() {
return this.name;
}
public boolean isRequest() {
return this.isRequest;
}
public boolean isResponse() {
return !this.isRequest;
}
public boolean hasCommandLengthCalculated() {
return (this.commandLength != null);
}
public void removeCommandLength() {
this.commandLength = null;
}
public void setCommandLength(int value) {
this.commandLength = Integer.valueOf(value);
}
public int getCommandLength() {
if (this.commandLength == null) {
return 0;
} else {
return this.commandLength.intValue();
}
}
/**
* Calculates and sets the commandLength for the PDU based on all currently
* set values and optional parameters.
* @return The calculated PDU command length
*/
public int calculateAndSetCommandLength() {
int len = SmppConstants.PDU_HEADER_LENGTH + this.calculateByteSizeOfBody() + this.calculateByteSizeOfOptionalParameters();
this.setCommandLength(len);
return len;
}
public int getCommandId() {
return this.commandId;
}
public void setCommandStatus(int value) {
this.commandStatus = value;
}
public int getCommandStatus() {
return this.commandStatus;
}
public boolean hasSequenceNumberAssigned() {
return (this.sequenceNumber != null);
}
public void removeSequenceNumber() {
this.sequenceNumber = null;
}
public void setSequenceNumber(int value) {
this.sequenceNumber = Integer.valueOf(value);
}
public int getSequenceNumber() {
if (this.sequenceNumber == null) {
return 0;
} else {
return this.sequenceNumber.intValue();
}
}
public int getOptionalParameterCount() {
if (this.optionalParameters == null) {
return 0;
}
return this.optionalParameters.size();
}
/**
* Gets the current list of optional parameters. If no parameters have been
* added, this will return null.
* @return Null if no parameters added yet, or the list of optional parameters.
*/
public ArrayList<Tlv> getOptionalParameters() {
return this.optionalParameters;
}
/**
* Adds an optional parameter to this PDU. Does not check if the TLV has
* already been added (allows duplicates).
* @param tlv The TLV to add
* @see Pdu#setOptionalParameter(com.cloudhopper.smpp.tlv.Tlv)
*/
public void addOptionalParameter(Tlv tlv) {
if (this.optionalParameters == null) {
this.optionalParameters = new ArrayList<Tlv>();
}
this.optionalParameters.add(tlv);
}
/**
* Removes an optional parameter by tag. Will only remove the first matching
* tag.
* @param tag That tag to remove
* @return Null if no TLV removed, or the TLV removed.
*/
public Tlv removeOptionalParameter(short tag) {
// does this parameter exist?
int i = this.findOptionalParameter(tag);
if (i < 0) {
return null;
} else {
return this.optionalParameters.remove(i);
}
}
/**
* Sets an optional parameter by checking if the tag already exists in our
* list of optional parameters. If it already exists, will replace the old
* value with the new value.
* @param tlv The TLV to add/set
* @return Null if no TLV was replaced, or the TLV replaced.
*/
public Tlv setOptionalParameter(Tlv tlv) {
// does this parameter already exist?
int i = this.findOptionalParameter(tlv.getTag());
if (i < 0) {
// parameter does not yet exist, add it, not replaced
this.addOptionalParameter(tlv);
return null;
} else {
// this parameter already exists, replace it, return old
return this.optionalParameters.set(i, tlv);
}
}
/**
* Checks if an optional parameter by tag exists.
* @param tag The TLV to search for
* @return True if exists, otherwise false
*/
public boolean hasOptionalParameter(short tag) {
return (this.findOptionalParameter(tag) >= 0);
}
protected int findOptionalParameter(short tag) {
if (this.optionalParameters == null) {
return -1;
}
int i = 0;
for (Tlv tlv : this.optionalParameters) {
if (tlv.getTag() == tag) {
return i;
}
i++;
}
// if we get here, we didn't find the parameter by tag
return -1;
}
/**
* Gets a TLV by tag.
* @param tag The TLV tag to search for
* @return The first matching TLV by tag
*/
public Tlv getOptionalParameter(short tag) {
if (this.optionalParameters == null) {
return null;
}
// try to find this parameter's index
int i = this.findOptionalParameter(tag);
if (i < 0) {
return null;
}
return this.optionalParameters.get(i);
}
//
// read & write pdu body
//
abstract protected int calculateByteSizeOfBody();
abstract public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException;
abstract public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException;
abstract protected void appendBodyToString(StringBuilder buffer);
//
// read & write pdu optional parameters
//
protected int calculateByteSizeOfOptionalParameters() {
if (this.optionalParameters == null) {
return 0;
}
int optParamLength = 0;
// otherwise, add length of each tlv
for (Tlv tlv : this.optionalParameters) {
optParamLength += tlv.calculateByteSize();
}
return optParamLength;
}
public void readOptionalParameters(ChannelBuffer buffer, PduTranscoderContext context) throws UnrecoverablePduException, RecoverablePduException {
// if there is any data left, it's part of an optional parameter
while (buffer.readableBytes() > 0) {
Tlv tlv = ChannelBufferUtil.readTlv(buffer);
if (tlv.getTagName() == null) {
tlv.setTagName(context.lookupTlvTagName(tlv.getTag()));
}
this.addOptionalParameter(tlv);
}
}
public void writeOptionalParameters(ChannelBuffer buffer, PduTranscoderContext context) throws UnrecoverablePduException, RecoverablePduException {
if (this.optionalParameters == null) {
return;
}
for (Tlv tlv : this.optionalParameters) {
if (tlv.getTagName() == null) {
tlv.setTagName(context.lookupTlvTagName(tlv.getTag()));
}
ChannelBufferUtil.writeTlv(buffer, tlv);
}
}
protected void appendOptionalParameterToString(StringBuilder buffer) {
if (this.optionalParameters == null) {
return;
}
int i = 0;
for (Tlv tlv : this.optionalParameters) {
if (i != 0) {
buffer.append(" (");
} else {
buffer.append("(");
}
// format 0x0000 0x0000 [00..]
buffer.append(tlv.toString());
buffer.append(")");
i++;
}
}
@Override
public String toString() {
// our guess of the optimal "toString" buffer size
StringBuilder buffer = new StringBuilder(65 + 300 + (getOptionalParameterCount()*20));
// append PDU header
buffer.append("(");
buffer.append(this.name);
buffer.append(": 0x");
buffer.append(HexUtil.toHexString(getCommandLength()));
buffer.append(" 0x");
buffer.append(HexUtil.toHexString(this.commandId));
buffer.append(" 0x");
buffer.append(HexUtil.toHexString(this.commandStatus));
buffer.append(" 0x");
buffer.append(HexUtil.toHexString(getSequenceNumber()));
// for "responses", attempt to lookup the command status message
if (this instanceof PduResponse) {
PduResponse response = (PduResponse)this;
String statusMessage = response.getResultMessage();
if (statusMessage != null) {
buffer.append(" result: \"");
buffer.append(statusMessage);
buffer.append("\"");
} else {
buffer.append(" result: <unmapped>");
}
}
buffer.append(")");
// append PDU body
buffer.append(" (body: ");
this.appendBodyToString(buffer);
// append PDU optional parameters
buffer.append(") (opts: ");
this.appendOptionalParameterToString(buffer);
buffer.append(")");
return buffer.toString();
}
}