Skip to content

Commit 839e0cb

Browse files
RESTCOMM-1856
Motivation: -Fix inbound and outbound smpp encoding Modifications: -Add default inbound and outbound configs for Smpp object -Decode and encode with default encoding when DCS==DEFAULT -Decode content string in Downloader with encoding header or default RVD encoding (UTF-8) Results: -Inbound and outbound smpp connection can be configured with specific character encodings -Any inbound and outbound default and UCS2 messages will be decoded and encoded correctly
1 parent b4163bc commit 839e0cb

7 files changed

Lines changed: 77 additions & 18 deletions

File tree

restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/restcomm.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,11 @@
670670
If no response received for 3 consecutive requests, connection will be killed
671671
and attempted to connect again -->
672672
<enquirelinkdelay>30000</enquirelinkdelay>
673+
<!-- when no values are set, default value from code is UTF-8-->
674+
<!--
675+
<incomingencoding>UTF-8</incomingencoding>
676+
<outgoingencoding>GSM7</outgoingencoding>
677+
-->
673678
</connection>
674679
</connections>
675680
</smpp>

restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/client/Downloader.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import akka.actor.ActorRef;
2323
import akka.event.Logging;
2424
import akka.event.LoggingAdapter;
25+
26+
import org.apache.commons.io.IOUtils;
2527
import org.apache.http.Header;
2628
import org.apache.http.HttpEntity;
2729
import org.apache.http.HttpHeaders;
@@ -39,7 +41,6 @@
3941
import org.restcomm.connect.commons.common.http.CustomHttpClientBuilder;
4042
import org.restcomm.connect.commons.configuration.RestcommConfiguration;
4143
import org.restcomm.connect.commons.faulttolerance.RestcommUntypedActor;
42-
import org.restcomm.connect.commons.util.StringUtils;
4344
import org.xml.sax.InputSource;
4445

4546
import javax.xml.parsers.DocumentBuilder;
@@ -86,6 +87,7 @@ public HttpResponseDescriptor fetch (final HttpRequestDescriptor descriptor) thr
8687
try {
8788
do {
8889
request = request(temp);
90+
//FIXME:should we externalize RVD encoding default?
8991
request.setHeader("http.protocol.content-charset", "UTF-8");
9092
if (descriptor.getTimeout() > 0){
9193
HttpContext httpContext = new BasicHttpContext();
@@ -161,6 +163,7 @@ private HttpResponseDescriptor validateXML (final HttpResponseDescriptor descrip
161163
// parse an XML document into a DOM tree
162164
String xml = descriptor.getContentAsString().trim().replaceAll("&([^;]+(?!(?:\\w|;)))", "&amp;$1");
163165
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
166+
//FIXME:should we externalize RVD encoding default?
164167
parser.parse(new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8"))));
165168
return descriptor;
166169
} catch (final Exception e) {
@@ -218,6 +221,7 @@ public HttpUriRequest request (final HttpRequestDescriptor descriptor) throws Il
218221
} else if ("POST".equalsIgnoreCase(method)) {
219222
final List<NameValuePair> parameters = descriptor.getParameters();
220223
final HttpPost post = new HttpPost(uri);
224+
//FIXME:should we externalize RVD encoding default?
221225
post.setEntity(new UrlEncodedFormEntity(parameters, "UTF-8"));
222226
return post;
223227
} else {
@@ -237,14 +241,17 @@ private HttpResponseDescriptor response (final HttpRequest request, final HttpRe
237241
InputStream stream = entity.getContent();
238242
try {
239243
final Header contentEncoding = entity.getContentEncoding();
240-
if (contentEncoding != null) {
241-
builder.setContentEncoding(contentEncoding.getValue());
244+
//FIXME:should we externalize RVD encoding default?
245+
String encodingValue = "UTF-8";
246+
if (contentEncoding != null && !contentEncoding.getValue().isEmpty()) {
247+
encodingValue = contentEncoding.getValue();
248+
builder.setContentEncoding(encodingValue);
242249
}
243250
final Header contentType = entity.getContentType();
244251
if (contentType != null) {
245252
builder.setContentType(contentType.getValue());
246253
}
247-
builder.setContent(StringUtils.toString(stream));
254+
builder.setContent(IOUtils.toString(stream, encodingValue));
248255
builder.setContentLength(entity.getContentLength());
249256
builder.setIsChunked(entity.isChunked());
250257
} finally {

restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/client/HttpRequestDescriptor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public HttpRequestDescriptor(final URI uri, final String method,
5656
}
5757
final String query = uri.getQuery();
5858
if (query != null) {
59+
//FIXME:should we externalize RVD encoding default?
5960
final List<NameValuePair> other = URLEncodedUtils.parse(uri, "UTF-8");
6061
parameters.addAll(other);
6162
}
@@ -104,6 +105,7 @@ public List<NameValuePair> getParameters() {
104105
}
105106

106107
public String getParametersAsString() {
108+
//FIXME:should we externalize RVD encoding default?
107109
return URLEncodedUtils.format(parameters, "UTF-8");
108110
}
109111

restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/Smpp.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.restcomm.connect.sms.smpp;
22

3+
import com.cloudhopper.commons.charset.Charset;
4+
import com.cloudhopper.commons.charset.CharsetUtil;
35
import com.cloudhopper.smpp.SmppBindType;
46
import com.cloudhopper.smpp.impl.DefaultSmppSession;
57
import com.cloudhopper.smpp.type.Address;
@@ -11,6 +13,7 @@
1113
*/
1214
public class Smpp {
1315

16+
private static final String DEFAULT_SMPP_ENCODING = "UTF-8";
1417
private String name;
1518
private String systemId;
1619
private String peerIp;
@@ -37,6 +40,9 @@ public class Smpp {
3740

3841
private long enquireLinkDelay;
3942

43+
private Charset inboundCharacterEncoding;
44+
private Charset outboundCharacterEncoding;
45+
4046
// not used as of today, but later we can allow users to stop each SMPP
4147
private boolean started = true;
4248

@@ -45,7 +51,7 @@ public class Smpp {
4551
public Smpp(String name, String systemId, String peerIp, int peerPort, SmppBindType smppBindType, String password,
4652
String systemType, byte interfaceVersion, Address address, long connectTimeout, int windowSize,
4753
long windowWaitTimeout, long requestExpiryTimeout, long windowMonitorInterval, boolean countersEnabled,
48-
boolean logBytes, long enquireLinkDelay) {
54+
boolean logBytes, long enquireLinkDelay, String incomingCharacterEncoding, String outgoingCharacterEncoding) {
4955
super();
5056
this.name = name;
5157
this.systemId = systemId;
@@ -64,6 +70,16 @@ public Smpp(String name, String systemId, String peerIp, int peerPort, SmppBindT
6470
this.countersEnabled = countersEnabled;
6571
this.logBytes = logBytes;
6672
this.enquireLinkDelay = enquireLinkDelay;
73+
try {
74+
this.inboundCharacterEncoding = CharsetUtil.map(incomingCharacterEncoding);
75+
} catch (Exception e) {
76+
this.inboundCharacterEncoding = CharsetUtil.map(DEFAULT_SMPP_ENCODING);
77+
}
78+
try {
79+
this.outboundCharacterEncoding = CharsetUtil.map(outgoingCharacterEncoding);
80+
} catch (Exception e) {
81+
this.outboundCharacterEncoding = CharsetUtil.map(DEFAULT_SMPP_ENCODING);
82+
}
6783
}
6884

6985
public String getName() {
@@ -202,6 +218,13 @@ public void setEnquireLinkDelay(long enquireLinkDelay) {
202218
this.enquireLinkDelay = enquireLinkDelay;
203219
}
204220

221+
public Charset getInboundDefaultEncoding() {
222+
return inboundCharacterEncoding;
223+
}
224+
public Charset getOutboundDefaultEncoding() {
225+
return outboundCharacterEncoding;
226+
}
227+
205228
public boolean isStarted() {
206229
return started;
207230
}
@@ -228,7 +251,10 @@ public String toString() {
228251
+ ", interfaceVersion=" + interfaceVersion + ", address=" + address + ", connectTimeout=" + connectTimeout
229252
+ ", windowSize=" + windowSize + ", windowWaitTimeout=" + windowWaitTimeout + ", requestExpiryTimeout="
230253
+ requestExpiryTimeout + ", windowMonitorInterval=" + windowMonitorInterval + ", countersEnabled="
231-
+ countersEnabled + ", logBytes=" + logBytes + ", enquireLinkDelay=" + enquireLinkDelay + "]";
254+
+ countersEnabled + ", logBytes=" + logBytes + ", enquireLinkDelay=" + enquireLinkDelay
255+
+ ", inboundCharacterEncoding=" + inboundCharacterEncoding.toString()
256+
+ ", outboundCharacterEncoding=" + outboundCharacterEncoding.toString()
257+
+ "]";
232258
}
233259

234260
@Override
@@ -255,5 +281,4 @@ public boolean equals(Object obj) {
255281
return false;
256282
return true;
257283
}
258-
259284
}

restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppClientOpsThread.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.cloudhopper.commons.charset.CharsetUtil;
2626
import com.cloudhopper.commons.charset.Charset;
2727
import com.cloudhopper.smpp.PduAsyncResponse;
28+
import com.cloudhopper.smpp.SmppConstants;
2829
import com.cloudhopper.smpp.SmppSession;
2930
import com.cloudhopper.smpp.SmppSessionConfiguration;
3031
import com.cloudhopper.smpp.SmppSessionHandler;
@@ -59,6 +60,10 @@ public class SmppClientOpsThread implements Runnable {
5960
private Object waitObject = new Object();
6061
private final DefaultSmppClient clientBootstrap;
6162
private static SmppSession getSmppSession;
63+
//FIXME: like getSmppSession, this is bad design
64+
//this assumes singular SMPP connection all the time,so it works
65+
private static Charset outboundEncoding;
66+
private static Charset inboundEncoding;
6267
protected volatile boolean started = true;
6368
private static int sipPort;
6469

@@ -294,6 +299,8 @@ protected class ClientSmppSessionHandler implements SmppSessionHandler {
294299
public ClientSmppSessionHandler(Smpp esme) {
295300
super();
296301
this.esme = esme;
302+
inboundEncoding = esme.getInboundDefaultEncoding();
303+
outboundEncoding = esme.getOutboundDefaultEncoding();
297304
}
298305

299306
@Override
@@ -352,18 +359,20 @@ public PduResponse firePduRequestReceived(PduRequest pduRequest) {
352359

353360
DeliverSm deliverSm = (DeliverSm) pduRequest;
354361
try {
355-
String decodedPduMessage = CharsetUtil.CHARSET_MODIFIED_UTF8.decode(deliverSm.getShortMessage());
362+
byte dcs = deliverSm.getDataCoding();
356363
String destSmppAddress = deliverSm.getDestAddress().getAddress();
357364
String sourceSmppAddress = deliverSm.getSourceAddress().getAddress();
358-
Charset charset;
359-
if (DataCoding.DATA_CODING_UCS2 == deliverSm.getDataCoding()) {
360-
charset = CharsetUtil.CHARSET_UCS_2;
361-
} else {
362-
charset = CharsetUtil.CHARSET_GSM;
365+
366+
//this default esme encoding only applies to DCS==0
367+
Charset encoding = esme.getInboundDefaultEncoding();
368+
if(dcs == SmppConstants.DATA_CODING_UCS2) {
369+
encoding = CharsetUtil.CHARSET_UCS_2;
363370
}
371+
372+
String decodedPduMessage = CharsetUtil.decode(deliverSm.getShortMessage(), encoding);
364373
//send received SMPP PDU message to restcomm
365374
try {
366-
sendSmppMessageToRestcomm(decodedPduMessage, destSmppAddress, sourceSmppAddress, charset);
375+
sendSmppMessageToRestcomm(decodedPduMessage, destSmppAddress, sourceSmppAddress, encoding);
367376
} catch (IOException | ServletException e) {
368377
logger.error("Exception while trying to dispatch incoming SMPP message to Restcomm: " + e);
369378
}
@@ -429,4 +438,12 @@ public void sendSmppMessageToRestcomm(String smppMessage, String smppTo, String
429438
SmppInboundMessageEntity smppInboundMessage = new SmppInboundMessageEntity(to, from, inboundMessage, charset);
430439
smppMessageHandler.tell(smppInboundMessage, null);
431440
}
441+
442+
public static Charset getInboundDefaultEncoding() {
443+
return inboundEncoding;
444+
}
445+
446+
public static Charset getOutboundDefaultEncoding() {
447+
return outboundEncoding;
448+
}
432449
}

restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppMessageHandler.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import org.restcomm.smpp.parameter.TlvSet;
6767

6868
import com.cloudhopper.commons.charset.CharsetUtil;
69+
import com.cloudhopper.smpp.SmppConstants;
6970
import com.cloudhopper.smpp.pdu.SubmitSm;
7071
import com.cloudhopper.smpp.tlv.Tlv;
7172
import com.cloudhopper.smpp.type.Address;
@@ -357,11 +358,11 @@ public void outbound(SmppOutboundMessageEntity request) throws SmppInvalidArgume
357358
submit0.setSourceAddress(new Address((byte) smppTonNpiValue, (byte) smppTonNpiValue, request.getSmppFrom()));
358359
submit0.setDestAddress(new Address((byte) smppTonNpiValue, (byte) smppTonNpiValue, request.getSmppTo()));
359360
if (CharsetUtil.CHARSET_UCS_2 == request.getSmppEncoding()) {
360-
submit0.setDataCoding(DataCoding.DATA_CODING_UCS2);
361+
submit0.setDataCoding(SmppConstants.DATA_CODING_UCS2);
361362
textBytes = CharsetUtil.encode(request.getSmppContent(), CharsetUtil.CHARSET_UCS_2);
362363
} else {
363-
submit0.setDataCoding(DataCoding.DATA_CODING_GSM7);
364-
textBytes = CharsetUtil.encode(request.getSmppContent(), request.getSmppEncoding());
364+
submit0.setDataCoding(SmppConstants.DATA_CODING_DEFAULT);
365+
textBytes = CharsetUtil.encode(request.getSmppContent(), SmppClientOpsThread.getOutboundDefaultEncoding());
365366
}
366367

367368
//TODO reverted from https://telestax.atlassian.net/browse/RESTCOMM-1595 as it caused SMS loop at SMSC

restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,12 @@ private void initializeSmppConnections() {
159159
boolean countersEnabled = smppConfiguration.getBoolean("connections.connection(" + count + ").countersenabled");
160160

161161
long enquireLinkDelay = smppConfiguration.getLong("connections.connection(" + count + ").enquirelinkdelay");
162+
String inboundCharacterEncoding = smppConfiguration.getString("connections.connection(" + count + ").inboundencoding");
163+
String outboundCharacterEncoding = smppConfiguration.getString("connections.connection(" + count + ").outboundencoding");
162164

163165
Smpp smpp = new Smpp(name, systemId, peerIp, peerPort, bindtype, password, systemType, interfaceVersion, address,
164166
connectTimeout, windowSize, windowWaitTimeout, requestExpiryTimeout, windowMonitorInterval,
165-
countersEnabled, logBytes, enquireLinkDelay);
167+
countersEnabled, logBytes, enquireLinkDelay, inboundCharacterEncoding, outboundCharacterEncoding);
166168

167169
this.smppList.add(smpp);
168170

0 commit comments

Comments
 (0)