From dc8762b5acf2616fe36b24dc2facee585a2a08fc Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 6 Jun 2017 14:31:56 +0800 Subject: [PATCH 01/12] RESTCOMM-884: Voice_2b: Add CreateCallType commons enum. Change references to CallRequest.Type and CreateCall.Type to CreateCallType commons enum --- .../commons/telephony/CreateCallType.java | 5 +++++ .../connect/extension/api/CallRequest.java | 14 +++++------- .../restcomm/connect/http/CallsEndpoint.java | 11 +++++++--- .../connect/http/UssdPushEndpoint.java | 3 ++- .../interpreter/SubVoiceInterpreter.java | 7 ++++-- .../connect/interpreter/VoiceInterpreter.java | 22 +++++++++++-------- .../connect/telephony/api/CallInfo.java | 7 +++--- .../telephony/api/InitializeOutbound.java | 9 ++++---- .../ussd/interpreter/UssdInterpreter.java | 7 ++++-- .../connect/ussd/telephony/UssdCall.java | 5 +++-- 10 files changed, 56 insertions(+), 34 deletions(-) create mode 100755 restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java diff --git a/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java b/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java new file mode 100755 index 0000000000..93b8e5314e --- /dev/null +++ b/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java @@ -0,0 +1,5 @@ +package org.restcomm.connect.commons.telephony; + +public enum CreateCallType { + CLIENT, PSTN, SIP, USSD +} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java index 86db69ceee..c47e2240ba 100644 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java @@ -2,23 +2,21 @@ import org.restcomm.connect.commons.dao.Sid; - +import org.restcomm.connect.commons.telephony.CreateCallType; +//TODO: Remove, obsoleted by Interface usage /** * Created by gvagenas on 27/09/16. */ -public class CallRequest { - public enum Type { - CLIENT, PSTN, SIP, USSD - }; +public class CallRequest extends ExtensionRequest { private final String from; private final String to; - private final Type type; + private final CreateCallType type; private final Sid accountId; private final boolean isFromApi; private final boolean parentCallSidExists; - public CallRequest(String from, String to, Type type, Sid accountId, boolean isFromApi, boolean parentCallSidExists) { + public CallRequest(String from, String to, CreateCallType type, Sid accountId, boolean isFromApi, boolean parentCallSidExists) { this.from = from; this.to = to; this.type = type; @@ -35,7 +33,7 @@ public String getTo() { return to; } - public Type getType() { + public CreateCallType getType() { return type; } diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/CallsEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/CallsEndpoint.java index 5e532a61e1..052f4605bd 100644 --- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/CallsEndpoint.java +++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/CallsEndpoint.java @@ -21,17 +21,20 @@ import akka.actor.ActorRef; import akka.util.Timeout; + import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; import com.thoughtworks.xstream.XStream; + import org.apache.commons.configuration.Configuration; import org.restcomm.connect.commons.amazonS3.RecordingSecurityLevel; import org.restcomm.connect.commons.annotations.concurrency.NotThreadSafe; import org.restcomm.connect.commons.configuration.RestcommConfiguration; import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.dao.AccountsDao; import org.restcomm.connect.dao.CallDetailRecordsDao; import org.restcomm.connect.dao.DaoManager; @@ -59,6 +62,7 @@ import org.restcomm.connect.telephony.api.GetCallInfo; import org.restcomm.connect.telephony.api.Hangup; import org.restcomm.connect.telephony.api.UpdateCallScript; + import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; @@ -71,6 +75,7 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; + import java.net.URI; import java.net.URL; import java.text.ParseException; @@ -379,13 +384,13 @@ protected Response putCall(final String accountSid, final MultivaluedMap future = (Future) ask(ussdCallManager, create, expires); diff --git a/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/SubVoiceInterpreter.java b/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/SubVoiceInterpreter.java index fda7e7d1d7..6625e2a238 100644 --- a/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/SubVoiceInterpreter.java +++ b/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/SubVoiceInterpreter.java @@ -25,6 +25,7 @@ import akka.actor.UntypedActorContext; import akka.event.Logging; import akka.event.LoggingAdapter; + import org.apache.commons.configuration.Configuration; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; @@ -37,6 +38,7 @@ import org.restcomm.connect.commons.fsm.FiniteStateMachine; import org.restcomm.connect.commons.fsm.State; import org.restcomm.connect.commons.fsm.Transition; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.dao.CallDetailRecordsDao; import org.restcomm.connect.dao.DaoManager; import org.restcomm.connect.dao.NotificationsDao; @@ -57,12 +59,13 @@ import org.restcomm.connect.telephony.api.CallResponse; import org.restcomm.connect.telephony.api.CallStateChanged; import org.restcomm.connect.telephony.api.Cancel; -import org.restcomm.connect.telephony.api.CreateCall; + import org.restcomm.connect.telephony.api.DestroyCall; import org.restcomm.connect.telephony.api.Reject; import org.restcomm.connect.tts.api.SpeechSynthesizerResponse; import javax.servlet.sip.SipServletResponse; + import java.io.IOException; import java.net.URI; import java.util.ArrayList; @@ -434,7 +437,7 @@ List parameters() { parameters.add(new BasicNameValuePair("ForwardedFrom", forwardedFrom)); // Adding SIP OUT Headers and SipCallId for // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - if (CreateCall.Type.SIP == callInfo.type()) { + if (CreateCallType.SIP == callInfo.type()) { SipServletResponse lastResponse = callInfo.lastResponse(); if (lastResponse != null) { final int statusCode = lastResponse.getStatus(); diff --git a/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/VoiceInterpreter.java b/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/VoiceInterpreter.java index 520ea6109a..5bc71c75ba 100644 --- a/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/VoiceInterpreter.java +++ b/restcomm/restcomm.interpreter/src/main/java/org/restcomm/connect/interpreter/VoiceInterpreter.java @@ -26,6 +26,7 @@ import akka.event.LoggingAdapter; import akka.pattern.AskTimeoutException; import akka.util.Timeout; + import org.apache.commons.configuration.Configuration; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; @@ -46,6 +47,7 @@ import org.restcomm.connect.commons.fsm.TransitionRollbackException; import org.restcomm.connect.commons.patterns.Observe; import org.restcomm.connect.commons.patterns.StopObserving; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.commons.util.UriUtils; import org.restcomm.connect.dao.CallDetailRecordsDao; import org.restcomm.connect.dao.DaoManager; @@ -106,6 +108,7 @@ import org.restcomm.connect.telephony.api.StopBridge; import org.restcomm.connect.telephony.api.StopConference; import org.restcomm.connect.tts.api.SpeechSynthesizerResponse; + import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; @@ -114,6 +117,7 @@ import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServletResponse; import javax.servlet.sip.SipSession; + import java.io.IOException; import java.math.BigDecimal; import java.net.MalformedURLException; @@ -1472,7 +1476,7 @@ List parameters() { } // logger.info("Type " + callInfo.type()); SipServletResponse lastResponse = callInfo.lastResponse(); - if (CreateCall.Type.SIP == callInfo.type()) { + if (CreateCallType.SIP == callInfo.type()) { // Adding SIP OUT Headers and SipCallId for // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out // logger.info("lastResponse " + lastResponse); @@ -2068,26 +2072,26 @@ else if (CallManagerResponse.class.equals(klass) && !((CallManagerResponse)messa if (Nouns.client.equals(child.name())) { if (call != null && callInfo != null) { create = new CreateCall(e164(callerId(verb)), e164(child.text()), null, null, callInfo.isFromApi(), timeout(verb), - CreateCall.Type.CLIENT, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.CLIENT, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); } else { create = new CreateCall(e164(callerId(verb)), e164(child.text()), null, null, false, timeout(verb), - CreateCall.Type.CLIENT, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.CLIENT, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); } } else if (Nouns.number.equals(child.name())) { if (call != null && callInfo != null) { create = new CreateCall(e164(callerId(verb)), e164(child.text()), null, null, callInfo.isFromApi(), timeout(verb), - CreateCall.Type.PSTN, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.PSTN, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); } else { create = new CreateCall(e164(callerId(verb)), e164(child.text()), null, null, false, timeout(verb), - CreateCall.Type.PSTN, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.PSTN, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); } } else if (Nouns.uri.equals(child.name())) { if (call != null && callInfo != null) { create = new CreateCall(e164(callerId(verb)), e164(child.text()), null, null, callInfo.isFromApi(), timeout(verb), - CreateCall.Type.SIP, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.SIP, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); } else { create = new CreateCall(e164(callerId(verb)), e164(child.text()), null, null, false, timeout(verb), - CreateCall.Type.SIP, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.SIP, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); } } else if (Nouns.SIP.equals(child.name())) { // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out @@ -2112,10 +2116,10 @@ else if (CallManagerResponse.class.equals(klass) && !((CallManagerResponse)messa } if (call != null && callInfo != null) { create = new CreateCall(e164(callerId(verb)), e164(child.text()), username, password, false, timeout(verb), - CreateCall.Type.SIP, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.SIP, accountId, callInfo.sid(), statusCallback, statusCallbackMethod, statusCallbackEvent); } else { create = new CreateCall(e164(callerId(verb)), e164(child.text()), username, password, false, timeout(verb), - CreateCall.Type.SIP, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); + CreateCallType.SIP, accountId, null, statusCallback, statusCallbackMethod, statusCallbackEvent); } } callManager.tell(create, source); diff --git a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CallInfo.java b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CallInfo.java index 156c569984..ccf8fcf13f 100644 --- a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CallInfo.java +++ b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CallInfo.java @@ -25,6 +25,7 @@ import org.joda.time.DateTime; import org.restcomm.connect.commons.annotations.concurrency.Immutable; import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.commons.telephony.CreateCallType; /** * @author quintana.thomas@gmail.com (Thomas Quintana) @@ -34,7 +35,7 @@ public final class CallInfo { private final Sid sid; private CallStateChanged.State state; - private final CreateCall.Type type; + private final CreateCallType type; private final String direction; private final DateTime dateCreated; private final DateTime dateConUpdated; @@ -48,7 +49,7 @@ public final class CallInfo { private boolean muted; private boolean isFromApi; - public CallInfo(final Sid sid, final CallStateChanged.State state, final CreateCall.Type type, final String direction, + public CallInfo(final Sid sid, final CallStateChanged.State state, final CreateCallType type, final String direction, final DateTime dateCreated, final String forwardedFrom, final String fromName, final String from, final String to, final SipServletRequest invite, final SipServletResponse lastResponse, final boolean webrtc, final boolean muted, final boolean isFromApi, final DateTime dateConUpdated) { super(); @@ -81,7 +82,7 @@ public String direction() { return direction; } - public CreateCall.Type type() { + public CreateCallType type() { return type; } diff --git a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/InitializeOutbound.java b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/InitializeOutbound.java index 8bb768e5c2..4a28a101b4 100644 --- a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/InitializeOutbound.java +++ b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/InitializeOutbound.java @@ -24,6 +24,7 @@ import org.restcomm.connect.commons.annotations.concurrency.Immutable; import org.restcomm.connect.dao.DaoManager; import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.commons.telephony.CreateCallType; /** * @author quintana.thomas@gmail.com (Thomas Quintana) @@ -43,7 +44,7 @@ public final class InitializeOutbound { private final boolean isFromApi; private final String apiVersion; private final Sid accountId; - private final CreateCall.Type type; + private final CreateCallType type; private final DaoManager daoManager; private Sid parentCallSid; private final boolean webrtc; @@ -55,7 +56,7 @@ public final class InitializeOutbound { public InitializeOutbound(final String name, final SipURI from, final SipURI to, final String username, final String password, final long timeout, final boolean isFromApi, final String apiVersion, - final Sid accountId, final CreateCall.Type type, final DaoManager daoManager, final boolean webrtc, + final Sid accountId, final CreateCallType type, final DaoManager daoManager, final boolean webrtc, final boolean outboundToIms, final String imsProxyAddress, final int imsProxyPort) { this(name, from, to, username, password, timeout, isFromApi, apiVersion, accountId, type, daoManager, webrtc); this.outboundToIms = outboundToIms; @@ -65,7 +66,7 @@ public InitializeOutbound(final String name, final SipURI from, final SipURI to, public InitializeOutbound(final String name, final SipURI from, final SipURI to, final String username, final String password, final long timeout, final boolean isFromApi, final String apiVersion, - final Sid accountId, final CreateCall.Type type, final DaoManager daoManager, final boolean webrtc) { + final Sid accountId, final CreateCallType type, final DaoManager daoManager, final boolean webrtc) { super(); this.name = name; this.from = from; @@ -118,7 +119,7 @@ public String password() { return password; } - public CreateCall.Type type() { + public CreateCallType type() { return type; } diff --git a/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/interpreter/UssdInterpreter.java b/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/interpreter/UssdInterpreter.java index 8cb32742db..ed4a074577 100644 --- a/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/interpreter/UssdInterpreter.java +++ b/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/interpreter/UssdInterpreter.java @@ -29,6 +29,7 @@ import akka.actor.UntypedActorFactory; import akka.event.Logging; import akka.event.LoggingAdapter; + import org.apache.commons.configuration.Configuration; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; @@ -42,6 +43,7 @@ import org.restcomm.connect.commons.fsm.State; import org.restcomm.connect.commons.fsm.Transition; import org.restcomm.connect.commons.patterns.Observe; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.commons.util.UriUtils; import org.restcomm.connect.dao.CallDetailRecordsDao; import org.restcomm.connect.dao.DaoManager; @@ -67,7 +69,7 @@ import org.restcomm.connect.telephony.api.CallInfo; import org.restcomm.connect.telephony.api.CallResponse; import org.restcomm.connect.telephony.api.CallStateChanged; -import org.restcomm.connect.telephony.api.CreateCall; + import org.restcomm.connect.telephony.api.GetCallInfo; import org.restcomm.connect.ussd.commons.UssdInfoRequest; import org.restcomm.connect.ussd.commons.UssdMessageType; @@ -75,6 +77,7 @@ import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServletResponse; + import java.io.IOException; import java.math.BigDecimal; import java.net.URI; @@ -359,7 +362,7 @@ List parameters() { final String forwardedFrom = info.forwardedFrom(); parameters.add(new BasicNameValuePair("ForwardedFrom", forwardedFrom)); // logger.info("Type " + callInfo.type()); - if (CreateCall.Type.SIP == info.type()) { + if (CreateCallType.SIP == info.type()) { // Adding SIP OUT Headers and SipCallId for // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out SipServletResponse lastResponse = info.lastResponse(); diff --git a/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/telephony/UssdCall.java b/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/telephony/UssdCall.java index 9cecbbe359..c6a5db6460 100644 --- a/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/telephony/UssdCall.java +++ b/restcomm/restcomm.ussd/src/main/java/org/restcomm/connect/ussd/telephony/UssdCall.java @@ -57,11 +57,12 @@ import org.restcomm.connect.commons.patterns.Observe; import org.restcomm.connect.commons.patterns.Observing; import org.restcomm.connect.commons.patterns.StopObserving; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.telephony.api.Answer; import org.restcomm.connect.telephony.api.CallInfo; import org.restcomm.connect.telephony.api.CallResponse; import org.restcomm.connect.telephony.api.CallStateChanged; -import org.restcomm.connect.telephony.api.CreateCall; + import org.restcomm.connect.telephony.api.GetCallInfo; import org.restcomm.connect.telephony.api.GetCallObservers; import org.restcomm.connect.telephony.api.InitializeOutbound; @@ -111,7 +112,7 @@ public class UssdCall extends UntypedActor { private String transport; private String username; private String password; - private CreateCall.Type type; + private CreateCallType type; private long timeout; private SipServletRequest invite; private SipServletRequest outgoingInvite; From 307355e464bdf72616297e208902f46e47aecc82 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 6 Jun 2017 14:34:25 +0800 Subject: [PATCH 02/12] RESTCOMM-884: Voice_2b: Add IExtensionRequest, IExtensionCreateCallRequest, IExtensionCreateSmsSessionRequest interfaces --- .../api/IExtensionCreateCallRequest.java | 70 +++++++++++++++++++ .../IExtensionCreateSmsSessionRequest.java | 8 +++ .../extension/api/IExtensionRequest.java | 8 +++ 3 files changed, 86 insertions(+) create mode 100755 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java create mode 100755 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java create mode 100755 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java new file mode 100755 index 0000000000..63e52c5af4 --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java @@ -0,0 +1,70 @@ +package org.restcomm.connect.extension.api; + +import java.util.ArrayList; +import java.util.Map; + +import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.commons.telephony.CreateCallType; + +public interface IExtensionCreateCallRequest extends IExtensionRequest { + + String getFrom(); + + String getTo(); + + Sid getAccountId(); + + boolean isFromApi(); + + boolean isParentCallSidExists(); + + /** + * @return the CreateCallType + */ + CreateCallType getType(); + + /** + * @return the outboundProxy + */ + String getOutboundProxy(); + + /** + * @param outboundProxy the outboundProxy to set + */ + void setOutboundProxy(String outboundProxy); + + /** + * @return the outboundProxyUsername + */ + String getOutboundProxyUsername(); + + /** + * @param outboundProxyUsername the outboundProxyUsername to set + */ + void setOutboundProxyUsername(String outboundProxyUsername); + + /** + * @return the outboundProxyPassword + */ + String getOutboundProxyPassword(); + + /** + * @param outboundProxyPassword the outboundProxyPassword to set + */ + void setOutboundProxyPassword(String outboundProxyPassword); + + /** + * @return the outboundProxyHeaders + */ + Map> getOutboundProxyHeaders(); + + /** + * @param outboundProxyHeaders the outboundProxyHeaders to set + */ + void setOutboundProxyHeaders(Map> outboundProxyHeaders); + + /** + * @return the Request URI + */ + String getRequestURI(); +} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java new file mode 100755 index 0000000000..40005cfbd7 --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java @@ -0,0 +1,8 @@ +package org.restcomm.connect.extension.api; + +import org.apache.commons.configuration.Configuration; + +public interface IExtensionCreateSmsSessionRequest extends IExtensionRequest { + void setConfiguration(Configuration configuration); + Configuration getConfiguration(); +} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java new file mode 100755 index 0000000000..3bb4279c97 --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java @@ -0,0 +1,8 @@ +package org.restcomm.connect.extension.api; + +public interface IExtensionRequest { + String getAccountSid(); + boolean isAllowed(); + void setAllowed(boolean allowed); + //boolean isFromApi(); +} From ef3d7895c76120d3020a6312f6a2c8e96a7645b9 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 6 Jun 2017 14:38:07 +0800 Subject: [PATCH 03/12] RESTCOMM-884: Voice_2b: Modify executePreOutboundAction to use IExtensionRequest. Decorate ExtensionRequest with IExtensionRequest interface --- .../extension/api/ExtensionRequest.java | 27 +++++++++---------- .../api/RestcommExtensionGeneric.java | 2 +- .../controller/ExtensionController.java | 13 ++++++--- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java index 76231eba0d..8057d9e33f 100755 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java @@ -19,28 +19,25 @@ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.restcomm.connect.extension.api; -import org.apache.commons.configuration.Configuration; - -public class ExtensionRequest { - private Object payload; - private Configuration configuration; +public class ExtensionRequest implements IExtensionRequest{ + private boolean allowed = true; + private String accountSid; public ExtensionRequest() {} - public Object getObject() { - return payload; - } - - public void setObject(Object object) { - this.payload = object; + @Override + public String getAccountSid() { + return this.accountSid; } - public void setConfiguration(Configuration configuration) { - this.configuration = configuration; + @Override + public boolean isAllowed() { + return this.allowed; } - public Configuration getConfiguration() { - return this.configuration; + @Override + public void setAllowed(boolean allowed) { + this.allowed = allowed; } } diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java index 96116be9c6..cc22594066 100644 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java @@ -57,7 +57,7 @@ public interface RestcommExtensionGeneric { * and either block/allow it or modify the session before Restcomm process it * @return ExtensionResponse see ExtensionResponse */ - ExtensionResponse preOutboundAction(ExtensionRequest extensionRequest); + ExtensionResponse preOutboundAction(IExtensionRequest extensionRequest); /** * Method that will be executed AFTER the process of an Outbound session * Implement this method so you will be able to check the Outgoing session diff --git a/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java index 0668660738..ccf4c13e91 100644 --- a/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java +++ b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java @@ -1,8 +1,8 @@ package org.restcomm.connect.extension.controller; -import org.restcomm.connect.extension.api.ExtensionRequest; import org.restcomm.connect.extension.api.ExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; +import org.restcomm.connect.extension.api.IExtensionRequest; import org.restcomm.connect.extension.api.MessageExtensionResponse; import org.restcomm.connect.extension.api.NodeExtensionResponse; import org.restcomm.connect.extension.api.RestcommExtension; @@ -89,7 +89,7 @@ public void registerExtension(final RestcommExtensionGeneric extension) { } } - public ExtensionResponse executePreOutboundAction(final ExtensionRequest er, List extensions) { + public ExtensionResponse executePreOutboundAction(final IExtensionRequest ier, List extensions) { //FIXME: if we have more than one extension in chain // and all of them are successful, we only receive the last // extensionResponse @@ -101,7 +101,7 @@ public ExtensionResponse executePreOutboundAction(final ExtensionRequest er, Lis logger.info( extension.getName()+" is enabled="+extension.isEnabled()); } if (extension.isEnabled()) { - response = extension.preOutboundAction(er); + response = extension.preOutboundAction(ier); //fail fast if (!response.isAllowed()){ break; @@ -112,7 +112,12 @@ public ExtensionResponse executePreOutboundAction(final ExtensionRequest er, Lis return response; } - public ExtensionResponse executePostOutboundAction(final Object er, List extensions) { + public ExtensionResponse executePostOutboundAction(Object er, List extensions) { + ExtensionResponse response = new ExtensionResponse(); + //TODO: implement actual calls + return response; + } + public ExtensionResponse executePostOutboundAction(final IExtensionRequest er, List extensions) { ExtensionResponse response = new ExtensionResponse(); //TODO: implement actual calls return response; From d74996cdb83c493a105d06cc8c1860f4968e0793 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 6 Jun 2017 14:46:25 +0800 Subject: [PATCH 04/12] RESTCOMM-884: Voice_2b: Modify Call constructor to pass in headers. rename preexisting x-headers to rcmlHeaders. Decorate CreateCall with IExtensionCreateCallRequest interface. Modify CM.outbound to use IExtensionCreateCallRequest to extensions. Modify outboundToPstn to use outboundProxy --- restcomm/restcomm.telephony.api/pom.xml | 7 +- .../connect/telephony/api/CreateCall.java | 152 ++++++++++++++++-- restcomm/restcomm.telephony/pom.xml | 7 +- .../org/restcomm/connect/telephony/Call.java | 122 +++++++++++--- .../connect/telephony/CallManager.java | 49 +++--- 5 files changed, 278 insertions(+), 59 deletions(-) diff --git a/restcomm/restcomm.telephony.api/pom.xml b/restcomm/restcomm.telephony.api/pom.xml index ca287f7f45..3a7c9e9987 100644 --- a/restcomm/restcomm.telephony.api/pom.xml +++ b/restcomm/restcomm.telephony.api/pom.xml @@ -35,7 +35,12 @@ ${project.version} provided - + + org.restcomm + restcomm-connect.extension.api + ${project.version} + provided + org.restcomm restcomm-connect.dao diff --git a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java index 2219cbf5b8..e649f07673 100644 --- a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java +++ b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java @@ -21,9 +21,13 @@ import org.restcomm.connect.commons.annotations.concurrency.Immutable; import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.commons.telephony.CreateCallType; +import org.restcomm.connect.extension.api.IExtensionCreateCallRequest; import java.net.URI; +import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author quintana.thomas@gmail.com (Thomas Quintana) @@ -31,28 +35,37 @@ * @author gvagenas@telestax.com */ @Immutable -public final class CreateCall { - public enum Type { - CLIENT, PSTN, SIP, USSD - }; +public final class CreateCall implements IExtensionCreateCallRequest{ private final String from; private final String to; - private final String username; - private final String password; + private String username; + private String password; private final boolean isFromApi; private final int timeout; - private final Type type; + private final CreateCallType callType; private final Sid accountId; private boolean createCDR = true; private final Sid parentCallSid; private final URI statusCallbackUrl; private final String statusCallbackMethod; private final List statusCallbackEvent; + private String outboundProxy; + private String outboundProxyUsername; + private String outboundProxyPassword; + private Map> outboundProxyHeaders; + private boolean allowed = true; public CreateCall(final String from, final String to, final String username, final String password, - final boolean isFromApi, final int timeout, final Type type, final Sid accountId, final Sid parentCallSid, - final URI statusCallbackUrl, final String statusCallbackMethod, final List statusCallbackEvent) { + final boolean isFromApi, final int timeout, final CreateCallType type, final Sid accountId, final Sid parentCallSid, + final URI statusCallbackUrl, final String statusCallbackMethod, final List statusCallbackEvent + ) { + this(from, to, username, password, isFromApi, timeout, type, accountId, parentCallSid, statusCallbackUrl, statusCallbackMethod, statusCallbackEvent, "","","",null); + } + public CreateCall(final String from, final String to, final String username, final String password, + final boolean isFromApi, final int timeout, final CreateCallType type, final Sid accountId, final Sid parentCallSid, + final URI statusCallbackUrl, final String statusCallbackMethod, final List statusCallbackEvent, + final String outboundProxy, final String outboundProxyUsername, final String outboundProxyPassword, final Map> outboundProxyHeaders) { super(); this.from = from; this.to = to; @@ -60,12 +73,16 @@ public CreateCall(final String from, final String to, final String username, fin this.password = password; this.isFromApi = isFromApi; this.timeout = timeout; - this.type = type; + this.callType = type; this.accountId = accountId; this.parentCallSid = parentCallSid; this.statusCallbackUrl = statusCallbackUrl; this.statusCallbackMethod = statusCallbackMethod; this.statusCallbackEvent = statusCallbackEvent; + this.outboundProxy = outboundProxy; + this.outboundProxyUsername = outboundProxyUsername;//FIXME:unused + this.outboundProxyPassword = outboundProxyPassword;//FIXME:unused + this.outboundProxyHeaders = outboundProxyHeaders; } public String from() { @@ -76,16 +93,12 @@ public String to() { return to; } - public boolean isFromApi() { - return isFromApi; - } - public int timeout() { return timeout; } - public Type type() { - return type; + public CreateCallType type() { + return callType; } public Sid accountId() { @@ -95,11 +108,18 @@ public Sid accountId() { public String username() { return username; } + public String setUsername() { + return username; + } public String password() { return password; } + public String setPassword() { + return password; + } + public boolean isCreateCDR() { return createCDR; } @@ -117,4 +137,104 @@ public Sid parentCallSid() { public String statusCallbackMethod() { return statusCallbackMethod; } public List statusCallbackEvent() { return statusCallbackEvent; } + + /** + * @return the outboundProxy + */ + public String getOutboundProxy() { + return outboundProxy; + } + /** + * @param outboundProxy the outboundProxy to set + */ + public void setOutboundProxy(String outboundProxy) { + this.outboundProxy = outboundProxy; + } + /** + * @return the outboundProxyUsername + */ + public String getOutboundProxyUsername() { + return username; + } + /** + * @param outboundProxyUsername the outboundProxyUsername to set + */ + public void setOutboundProxyUsername(String outboundProxyUsername) { + this.username = outboundProxyUsername; + } + /** + * @return the outboundProxyPassword + */ + public String getOutboundProxyPassword() { + return password; + } + /** + * @param outboundProxyPassword the outboundProxyPassword to set + */ + public void setOutboundProxyPassword(String outboundProxyPassword) { + this.password = outboundProxyPassword; + } + /** + * @return the outboundProxyHeaders + */ + public Map> getOutboundProxyHeaders() { + return outboundProxyHeaders; + } + /** + * @param outboundProxyHeaders the outboundProxyHeaders to set + */ + public void setOutboundProxyHeaders(Map> outboundProxyHeaders) { + this.outboundProxyHeaders = outboundProxyHeaders; + } + public String getFrom() { + return from; + } + + public String getTo() { + return to; + } + + public Sid getAccountId() { + return accountId; + } + + @Override + public boolean isFromApi() { + return isFromApi; + } + + @Override + public boolean isParentCallSidExists() { + return parentCallSid != null; + } + + @Override + public String toString() { + return "From: "+from+", To: "+to+", Type: "+callType.name()+", AccountId: "+accountId+", isFromApi: "+isFromApi+", parentCallSidExists: "+isParentCallSidExists(); + } + + @Override + public CreateCallType getType() { + return callType; + } + + @Override + public String getRequestURI() { + return this.to; + } + + @Override + public String getAccountSid() { + return this.accountId.toString(); + } + + @Override + public boolean isAllowed() { + return this.allowed; + } + + @Override + public void setAllowed(boolean allowed) { + this.allowed = allowed; + } } diff --git a/restcomm/restcomm.telephony/pom.xml b/restcomm/restcomm.telephony/pom.xml index 5f65a86159..fbed976910 100644 --- a/restcomm/restcomm.telephony/pom.xml +++ b/restcomm/restcomm.telephony/pom.xml @@ -80,7 +80,12 @@ ${project.version} provided - + + org.restcomm + restcomm-connect.extension.api + ${project.version} + provided + org.restcomm restcomm-connect.dao diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java index 7f19760557..7250d348a6 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java @@ -28,6 +28,7 @@ import akka.actor.UntypedActorFactory; import akka.event.Logging; import akka.event.LoggingAdapter; + import org.apache.commons.configuration.Configuration; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; @@ -49,6 +50,7 @@ import org.restcomm.connect.commons.patterns.Observe; import org.restcomm.connect.commons.patterns.Observing; import org.restcomm.connect.commons.patterns.StopObserving; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.commons.util.SdpUtils; import org.restcomm.connect.dao.CallDetailRecordsDao; import org.restcomm.connect.dao.DaoManager; @@ -86,7 +88,6 @@ import org.restcomm.connect.telephony.api.ChangeCallDirection; import org.restcomm.connect.telephony.api.ConferenceInfo; import org.restcomm.connect.telephony.api.ConferenceResponse; -import org.restcomm.connect.telephony.api.CreateCall; import org.restcomm.connect.telephony.api.Dial; import org.restcomm.connect.telephony.api.GetCallInfo; import org.restcomm.connect.telephony.api.GetCallObservers; @@ -94,6 +95,7 @@ import org.restcomm.connect.telephony.api.InitializeOutbound; import org.restcomm.connect.telephony.api.Reject; import org.restcomm.connect.telephony.api.RemoveParticipant; + import scala.concurrent.duration.Duration; import javax.sdp.SdpException; @@ -111,6 +113,7 @@ import javax.sip.header.RecordRouteHeader; import javax.sip.header.RouteHeader; import javax.sip.message.Response; + import java.io.IOException; import java.math.BigDecimal; import java.net.InetAddress; @@ -189,10 +192,11 @@ public final class Call extends UntypedActor { private SipURI from; private javax.servlet.sip.URI to; // custom headers for SIP Out https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - private Map headers; + private Map rcmlHeaders; + private Map> headers; private String username; private String password; - private CreateCall.Type type; + private CreateCallType type; private long timeout; private SipServletRequest invite; private SipServletRequest inDialogInvite; @@ -281,7 +285,14 @@ public String toString() { }; public Call(final SipFactory factory, final ActorRef mediaSessionController, final Configuration configuration, - final URI statusCallback, final String statusCallbackMethod, final List statusCallbackEvent) { + final URI statusCallback, final String statusCallbackMethod, final List statusCallbackEvent) { + this(factory, mediaSessionController, configuration, statusCallback, statusCallbackMethod, + statusCallbackEvent, null); + } + + public Call(final SipFactory factory, final ActorRef mediaSessionController, final Configuration configuration, + final URI statusCallback, final String statusCallbackMethod, final List statusCallbackEvent, Map> headers) + { super(); final ActorRef source = self(); this.system = context().system(); @@ -291,6 +302,12 @@ public Call(final SipFactory factory, final ActorRef mediaSessionController, fin if (statusCallback != null) { downloader = downloader(); } + this.rcmlHeaders = new HashMap(); + this.headers = new HashMap>(); + if(headers != null){ + this.headers = headers; + } + // States for the FSM this.uninitialized = new State("uninitialized", null, null); this.initializing = new State("initializing", new Initializing(source), null); @@ -821,7 +838,7 @@ public void execute(Object message) throws Exception { if (toHeaderString.indexOf('?') != -1) { // custom headers parsing for SIP Out // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - headers = new HashMap(); + // we keep only the to URI without the headers to = (SipURI) factory.createURI(toHeaderString.substring(0, toHeaderString.lastIndexOf('?'))); String headersString = toHeaderString.substring(toHeaderString.lastIndexOf('?') + 1); @@ -830,7 +847,7 @@ public void execute(Object message) throws Exception { String headerNameValue = tokenizer.nextToken(); String headerName = headerNameValue.substring(0, headerNameValue.lastIndexOf('=')); String headerValue = headerNameValue.substring(headerNameValue.lastIndexOf('=') + 1); - headers.put(headerName, headerValue); + rcmlHeaders.put(headerName, headerValue); } } timeout = request.timeout(); @@ -945,18 +962,14 @@ public void execute(Object message) throws Exception { invite.setHeader("User-Agent", userAgent); } - if (headers != null) { - // adding custom headers for SIP Out - // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - Set> entrySet = headers.entrySet(); - for (Map.Entry entry : entrySet) { - invite.addHeader("X-" + entry.getKey(), entry.getValue()); - } - } - addCustomHeaders(invite); -// invite.addHeader("X-RestComm-ApiVersion", apiVersion); -// invite.addHeader("X-RestComm-AccountSid", accountId.toString()); -// invite.addHeader("X-RestComm-CallSid", id.toString()); + addCustomHeadersToMap(rcmlHeaders); + // adding custom headers for SIP Out + // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out + addHeadersToMessage(invite, rcmlHeaders, "X-"); + + //the extension headers will override any headers + addHeadersToMessage(invite, headers); + final SipSession session = invite.getSession(); session.setHandler("CallManager"); // Issue: https://telestax.atlassian.net/browse/RESTCOMM-608 @@ -964,7 +977,7 @@ public void execute(Object message) throws Exception { if (logger.isInfoEnabled()) logger.info("bypassLoadBalancer is set to: "+RestcommConfiguration.getInstance().getMain().getBypassLbForClients()); if (RestcommConfiguration.getInstance().getMain().getBypassLbForClients()) { - if (type.equals(CreateCall.Type.CLIENT) || type.equals(CreateCall.Type.SIP)) { + if (type.equals(CreateCallType.CLIENT) || type.equals(CreateCallType.SIP)) { ((SipSessionExt) session).setBypassLoadBalancer(true); ((SipSessionExt) session).setBypassProxy(true); } @@ -986,6 +999,77 @@ public void execute(Object message) throws Exception { context.setReceiveTimeout(Duration.create(timeout, TimeUnit.SECONDS)); executeStatusCallback(CallbackState.INITIATED); } + + //FIXME: duplicate code + private void addHeadersToMessage(SipServletRequest message, Map rcmlHeaders, String keyPrepend) { + + for (Map.Entry entry : rcmlHeaders.entrySet()) { + String headerName = keyPrepend + entry.getKey(); + String headerVal = message.getHeader(headerName); + message.addHeader(headerName , entry.getValue()); + } + } + + /** + * + */ + private void addCustomHeadersToMap(Map headers) { + if (apiVersion != null) + headers.put("RestComm-ApiVersion", apiVersion); + if (accountId != null) + headers.put("RestComm-AccountSid", accountId.toString()); + headers.put("RestComm-CallSid", instanceId+"-"+id.toString()); + } + + /** + * @param keyPrepend TODO + * + */ + private void addHeadersToMessage(SipServletRequest message, Map > headers) { + + if(headers!=null) { + for (Map.Entry> entry : headers.entrySet()) { + //check of header exists + String headerName = entry.getKey(); + String headerVal = message.getHeader(headerName); + + //FIXME: do getValue check first? + StringBuilder sb = new StringBuilder(); + String concatValue; + for(String pair :entry.getValue()){ + logger.debug("pair="+pair); + sb.append(";").append(pair); + } + logger.debug("headerName="+headerName+" headerVal="+headerVal+" concatValue="+sb.toString()); + if(!headerName.equalsIgnoreCase("Request-URI")){ + if(headerVal!=null && !headerVal.isEmpty()) { + message.setHeader(headerName , headerVal+sb.toString()); + }else{ + message.addHeader(headerName , sb.toString()); + } + }else{ + //handle Request-URI + //((SipServletRequest)message).getRequestURI(); + javax.servlet.sip.URI reqURI = message.getRequestURI(); + logger.debug("ReqURI="+reqURI.toString()+" msgReqURI="+message.getRequestURI()); + for(String keyValPair :entry.getValue()){ + String parName = ""; + String parVal = ""; + int equalsPos = keyValPair.indexOf("="); + parName = keyValPair.substring(0, equalsPos); + parVal = keyValPair.substring(equalsPos+1); + reqURI.setParameter(parName, parVal); + logger.debug("ReqURI pars ="+parName+"="+parVal+" equalsPos="+equalsPos+" keyValPair="+keyValPair); + } + + message.setRequestURI(reqURI); + logger.debug("----ReqURI="+reqURI.toString()+" msgReqURI="+message.getRequestURI()); + } + + logger.debug("--headerName="+headerName+" headerVal="+message.getHeader(headerName)); + } + } + } } private final class Ringing extends AbstractAction { diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java index 9eff90b358..61314c977a 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java @@ -42,6 +42,7 @@ import org.restcomm.connect.commons.configuration.RestcommConfiguration; import org.restcomm.connect.commons.dao.Sid; import org.restcomm.connect.commons.patterns.StopObserving; +import org.restcomm.connect.commons.telephony.CreateCallType; import org.restcomm.connect.commons.util.SdpUtils; import org.restcomm.connect.commons.util.UriUtils; import org.restcomm.connect.dao.AccountsDao; @@ -63,6 +64,7 @@ import org.restcomm.connect.extension.api.ExtensionRequest; import org.restcomm.connect.extension.api.ExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; +import org.restcomm.connect.extension.api.IExtensionCreateCallRequest; import org.restcomm.connect.extension.api.RestcommExtensionException; import org.restcomm.connect.extension.api.RestcommExtensionGeneric; import org.restcomm.connect.extension.controller.ExtensionController; @@ -346,7 +348,7 @@ private ActorRef call(final CreateCall request) { @Override public UntypedActor create() throws Exception { return new Call(sipFactory, msControllerFactory.provideCallController(), configuration, - null, null, null); + null, null, null, null); } }); } else { @@ -356,7 +358,7 @@ public UntypedActor create() throws Exception { @Override public UntypedActor create() throws Exception { return new Call(sipFactory, msControllerFactory.provideCallController(), configuration, - request.statusCallback(), request.statusCallbackMethod(), request.statusCallbackEvent()); + request.statusCallback(), request.statusCallbackMethod(), request.statusCallbackEvent(), request.getOutboundProxyHeaders()); } }); } @@ -484,13 +486,19 @@ private void invite(final Object message) throws IOException, NumberParseExcepti logger.info("Client is not null: " + client.getLogin() + " will try to proxy to client: "+ toClient); } - CallRequest callRequest = new CallRequest(fromUser, toUser, CallRequest.Type.CLIENT, - client.getAccountSid(), false, false); +// CallRequest callRequest = new CallRequest(fromUser, toUser, CreateCallType.CLIENT, +// client.getAccountSid(), false, false); ExtensionController ec = ExtensionController.getInstance(); - ExtensionRequest er = new ExtensionRequest(); - er.setObject(callRequest); - ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); - if (extensionResponse.isAllowed()) { + //ExtensionRequest er = new ExtensionRequest(); + IExtensionCreateCallRequest er = new CreateCall(fromUser, toUser, "", "", false, 0, CreateCallType.CLIENT, client.getAccountSid(), null,null, null, null); + +// IExtensionCreateSmsSessionRequest ier = (CreateSmsSession)message; +// ier.setConfiguration(this.configuration); +// ec.executePreOutboundAction(ier, this.extensions); + //ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); + ec.executePreOutboundAction(er, this.extensions); + + if (er.isAllowed()) { if (B2BUAHelper.redirectToB2BUA(request, client, toClient, storage, sipFactory, patchForNatB2BUASessions)) { if(logger.isInfoEnabled()) { logger.info("Call to CLIENT. myHostIp: " + myHostIp + " mediaExternalIp: " + mediaExternalIp + " toHost: " @@ -517,7 +525,7 @@ private void invite(final Object message) throws IOException, NumberParseExcepti final SipServletResponse resp = request.createResponse(SC_FORBIDDEN, "Call not allowed"); resp.send(); } - ec.executePostOutboundAction(callRequest, this.extensions); + ec.executePostOutboundAction(er, this.extensions); return; } else { // toClient is null or we couldn't make the b2bua call to another client. check if this call is for a registered @@ -547,10 +555,10 @@ private void invite(final Object message) throws IOException, NumberParseExcepti // proxy DID or number if the outbound proxy fields are not empty in the restcomm.xml if (proxyURI != null && !proxyURI.isEmpty()) { // String destination = ((SipURI)request.getTo().getURI()).getUser(); - CallRequest callRequest = new CallRequest(fromUser,toUser, CallRequest.Type.PSTN, client.getAccountSid(), false, false); + CallRequest callRequest = new CallRequest(fromUser,toUser, CreateCallType.PSTN, client.getAccountSid(), false, false); ExtensionController ec = ExtensionController.getInstance(); ExtensionRequest er = new ExtensionRequest(); - er.setObject(callRequest); + //er.setObject(callRequest); ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); if (extensionResponse.isAllowed()) { proxyOut(request, client, toUser, toHost, toHostIpAddress, toPort, outboundIntf, proxyURI, proxyUsername, proxyPassword, from, to, callToSipUri); @@ -1507,14 +1515,11 @@ private void update(final Object message) throws Exception { private void outbound(final Object message, final ActorRef sender) throws ServletParseException { final CreateCall request = (CreateCall) message; - CallRequest callRequest = new CallRequest(request.from(), request.to(), CallRequest.Type.valueOf(request.type().name()), request.accountId(), request.isFromApi(), request.parentCallSid() != null); ExtensionController ec = ExtensionController.getInstance(); - ExtensionRequest er = new ExtensionRequest(); - er.setObject(callRequest); - ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); + ec.executePreOutboundAction(request, this.extensions); switch (request.type()) { case CLIENT: { - if (extensionResponse.isAllowed()) { + if (request.isAllowed()) { outboundToClient(request, sender); } else { //Extensions didn't allowed this call @@ -1522,11 +1527,11 @@ private void outbound(final Object message, final ActorRef sender) throws Servle logger.warning(errMsg); sender.tell(new CallManagerResponse(new RestcommExtensionException(errMsg), this.createCallRequest), self()); } - ec.executePostOutboundAction(callRequest, this.extensions); + ec.executePostOutboundAction(request, this.extensions); break; } case PSTN: { - if (extensionResponse.isAllowed()) { + if (request.isAllowed()) { outboundToPstn(request, sender); } else { //Extensions didn't allowed this call @@ -1534,14 +1539,14 @@ private void outbound(final Object message, final ActorRef sender) throws Servle logger.warning(errMsg); sender.tell(new CallManagerResponse(new RestcommExtensionException(errMsg), this.createCallRequest), self()); } - ec.executePostOutboundAction(callRequest, this.extensions); + ec.executePostOutboundAction(request, this.extensions); break; } case SIP: { if (actAsImsUa) { outboundToIms(request, sender); } - else if (extensionResponse.isAllowed()) { + else if (request.isAllowed()) { outboundToSip(request, sender); } else { //Extensions didn't allowed this call @@ -1549,7 +1554,7 @@ else if (extensionResponse.isAllowed()) { logger.warning(errMsg); sender.tell(new CallManagerResponse(new RestcommExtensionException(errMsg), this.createCallRequest), self()); } - ec.executePostOutboundAction(callRequest, this.extensions); + ec.executePostOutboundAction(request, this.extensions); break; } } @@ -1667,7 +1672,7 @@ private void outboundToClient(final CreateCall request, final ActorRef sender) t } private void outboundToPstn(final CreateCall request, final ActorRef sender) throws ServletParseException { - final String uri = activeProxy; + final String uri = (!request.getOutboundProxy().isEmpty()) ? request.getOutboundProxy() : activeProxy; SipURI outboundIntf = null; SipURI from = null; SipURI to = null; From 82b025bfa81f558541faf326899f1472fb112e3d Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 6 Jun 2017 14:58:34 +0800 Subject: [PATCH 05/12] RESTCOMM-884: Voice_2b: Modify SmsService and SmppHandler to use IExtensionRequest --- restcomm/restcomm.sms.api/pom.xml | 7 ++++- .../connect/sms/api/CreateSmsSession.java | 29 +++++++++++++++++-- .../org/restcomm/connect/sms/SmsService.java | 27 +++++++---------- .../connect/sms/smpp/SmppMessageHandler.java | 20 +++++++------ 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/restcomm/restcomm.sms.api/pom.xml b/restcomm/restcomm.sms.api/pom.xml index 10f1e11f94..bd8c60fded 100644 --- a/restcomm/restcomm.sms.api/pom.xml +++ b/restcomm/restcomm.sms.api/pom.xml @@ -17,6 +17,11 @@ restcomm-connect.commons ${project.version} - + + org.restcomm + restcomm-connect.extension.api + ${project.version} + provided + diff --git a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java index e032c03c1f..71217f276f 100644 --- a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java +++ b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java @@ -19,17 +19,20 @@ */ package org.restcomm.connect.sms.api; +import org.apache.commons.configuration.Configuration; import org.restcomm.connect.commons.annotations.concurrency.Immutable; - +import org.restcomm.connect.extension.api.IExtensionCreateSmsSessionRequest; /** * @author quintana.thomas@gmail.com (Thomas Quintana) */ @Immutable -public final class CreateSmsSession { +public final class CreateSmsSession implements IExtensionCreateSmsSessionRequest { private final String from; private final String to; private final String accountSid; private final boolean isFromApi; + private Configuration configuration; + private boolean allowed = true; //This will be used to create SmsSession from @@ -52,10 +55,12 @@ public String getTo() { return to; } + @Override public String getAccountSid() { return accountSid; } + //@Override public boolean isFromApi() { return isFromApi; } @@ -64,4 +69,24 @@ public boolean isFromApi() { public String toString() { return "From: "+from+" , To: "+to+" , AccountSid: "+accountSid+" , isFromApi: "+isFromApi; } + + @Override + public boolean isAllowed() { + return this.allowed; + } + + @Override + public void setAllowed(boolean allowed) { + this.allowed = allowed; + } + + @Override + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + @Override + public Configuration getConfiguration() { + return this.configuration; + } } diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java index 86ff8949a9..4816fd2277 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java @@ -27,8 +27,10 @@ import akka.actor.UntypedActorFactory; import akka.event.Logging; import akka.event.LoggingAdapter; + import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; + import org.apache.commons.configuration.Configuration; import org.joda.time.DateTime; import org.restcomm.connect.commons.dao.Sid; @@ -47,9 +49,10 @@ import org.restcomm.connect.dao.entities.SmsMessage; import org.restcomm.connect.dao.entities.SmsMessage.Direction; import org.restcomm.connect.dao.entities.SmsMessage.Status; -import org.restcomm.connect.extension.api.ExtensionResponse; -import org.restcomm.connect.extension.api.ExtensionRequest; +//import org.restcomm.connect.extension.api.ExtensionResponse; +//import org.restcomm.connect.extension.api.ExtensionRequest; import org.restcomm.connect.extension.api.ExtensionType; +import org.restcomm.connect.extension.api.IExtensionCreateSmsSessionRequest; import org.restcomm.connect.extension.api.RestcommExtensionException; import org.restcomm.connect.extension.api.RestcommExtensionGeneric; import org.restcomm.connect.extension.controller.ExtensionController; @@ -61,11 +64,9 @@ import org.restcomm.connect.sms.api.SmsServiceResponse; import org.restcomm.connect.sms.api.SmsSessionAttribute; import org.restcomm.connect.sms.api.SmsSessionRequest; - import org.restcomm.connect.telephony.api.TextMessage; import org.restcomm.connect.telephony.api.util.B2BUAHelper; import org.restcomm.connect.telephony.api.util.CallControlHelper; - import org.restcomm.smpp.parameter.TlvSet; import javax.servlet.ServletConfig; @@ -340,19 +341,11 @@ public void onReceive(final Object message) throws Exception { final ActorRef sender = sender(); ExtensionController ec = ExtensionController.getInstance(); if (CreateSmsSession.class.equals(klass)) { - //retrieve extension object - //FIXME:we need a real interface here rather than amending a preexisting request interface - ExtensionRequest er = new ExtensionRequest(); - er.setObject(message); - er.setConfiguration(this.configuration); - - ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); - if (extensionResponse.isAllowed()) { - //pass in response object to sms session - Object obj = ec.handleExtensionResponse(extensionResponse, this.configuration); - //FIXME:not all instances of extensions should modify - //a session configuration, we should do checks here - final ActorRef session = session((Configuration)obj); + IExtensionCreateSmsSessionRequest ier = (CreateSmsSession)message; + ier.setConfiguration(this.configuration); + ec.executePreOutboundAction(ier, this.extensions); + if (ier.isAllowed()) { + final ActorRef session = session(ier.getConfiguration()); final SmsServiceResponse response = new SmsServiceResponse(session); sender.tell(response, self); } else { diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppMessageHandler.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppMessageHandler.java index a434af6ad7..32f1a8d7ef 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppMessageHandler.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppMessageHandler.java @@ -8,6 +8,7 @@ import akka.actor.UntypedActorFactory; import akka.event.Logging; import akka.event.LoggingAdapter; + import com.cloudhopper.commons.charset.CharsetUtil; import com.cloudhopper.smpp.pdu.SubmitSm; import com.cloudhopper.smpp.type.Address; @@ -18,6 +19,7 @@ import com.cloudhopper.smpp.type.UnrecoverablePduException; import com.cloudhopper.smpp.tlv.Tlv; import com.google.i18n.phonenumbers.PhoneNumberUtil; + import org.apache.commons.configuration.Configuration; import org.restcomm.connect.commons.dao.Sid; import org.restcomm.connect.commons.util.UriUtils; @@ -27,9 +29,10 @@ import org.restcomm.connect.dao.IncomingPhoneNumbersDao; import org.restcomm.connect.dao.entities.Application; import org.restcomm.connect.dao.entities.IncomingPhoneNumber; -import org.restcomm.connect.extension.api.ExtensionRequest; -import org.restcomm.connect.extension.api.ExtensionResponse; +//import org.restcomm.connect.extension.api.ExtensionRequest; +//import org.restcomm.connect.extension.api.ExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; +import org.restcomm.connect.extension.api.IExtensionCreateSmsSessionRequest; import org.restcomm.connect.extension.api.RestcommExtensionException; import org.restcomm.connect.extension.api.RestcommExtensionGeneric; import org.restcomm.connect.extension.controller.ExtensionController; @@ -45,6 +48,7 @@ import javax.servlet.sip.SipFactory; import javax.servlet.sip.SipServlet; import javax.servlet.sip.SipURI; + import java.io.IOException; import java.net.URI; import java.util.List; @@ -92,13 +96,11 @@ public void onReceive(Object message) throws Exception { } outbound((SmppOutboundMessageEntity) message); } else if (message instanceof CreateSmsSession) { - ExtensionRequest er = new ExtensionRequest(); - er.setObject(message); - er.setConfiguration(this.configuration); - ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); - if (extensionResponse.isAllowed()) { - Object obj = ec.handleExtensionResponse(extensionResponse, this.configuration); - final ActorRef session = session((Configuration)obj); + IExtensionCreateSmsSessionRequest ier = (CreateSmsSession)message; + ier.setConfiguration(this.configuration); + ec.executePreOutboundAction(ier, this.extensions); + if (ier.isAllowed()) { + final ActorRef session = session(ier.getConfiguration()); final SmsServiceResponse response = new SmsServiceResponse(session); sender.tell(response, self); } else { From b41ce41f646a4ff792bdf938a260e75d3036014f Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 6 Jun 2017 16:02:41 +0800 Subject: [PATCH 06/12] RESTCOMM-884: Voice_2b: Cleanup, add pragmas, docs. Check before logging. Reorder methods --- .../commons/telephony/CreateCallType.java | 20 ++++++ .../extension/api/ExtensionRequest.java | 20 +++++- .../api/IExtensionCreateCallRequest.java | 15 +++++ .../IExtensionCreateSmsSessionRequest.java | 31 +++++++++ .../extension/api/IExtensionRequest.java | 34 +++++++++- .../connect/sms/api/CreateSmsSession.java | 31 +++++++-- .../org/restcomm/connect/sms/SmsService.java | 2 - .../connect/telephony/api/CreateCall.java | 66 +++++++++++++++++-- .../org/restcomm/connect/telephony/Call.java | 40 ++++++----- .../connect/telephony/CallManager.java | 8 --- 10 files changed, 229 insertions(+), 38 deletions(-) diff --git a/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java b/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java index 93b8e5314e..31c9b996a7 100755 --- a/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java +++ b/restcomm/restcomm.commons/src/main/java/org/restcomm/connect/commons/telephony/CreateCallType.java @@ -1,3 +1,23 @@ +/* + * TeleStax, Open Source Cloud Communications + * Copyright 2011-2013, Telestax Inc and individual contributors + * by the @authors tag. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ package org.restcomm.connect.commons.telephony; public enum CreateCallType { diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java index 8057d9e33f..fc79185add 100755 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java @@ -23,18 +23,36 @@ public class ExtensionRequest implements IExtensionRequest{ private boolean allowed = true; private String accountSid; - public ExtensionRequest() {} + public ExtensionRequest() { + this("", true); + } + public ExtensionRequest(String accountSid, boolean allowed) { + this.accountSid = accountSid; + this.allowed = allowed; + } + /** + * IExtensionRequest + * @return get accountSid + */ @Override public String getAccountSid() { return this.accountSid; } + /** + * IExtensionRequest + * @return is allowed + */ @Override public boolean isAllowed() { return this.allowed; } + /** + * IExtensionRequest + * @param is allowed + */ @Override public void setAllowed(boolean allowed) { this.allowed = allowed; diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java index 63e52c5af4..f88ea24199 100755 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateCallRequest.java @@ -8,14 +8,29 @@ public interface IExtensionCreateCallRequest extends IExtensionRequest { + /** + * @return the from address + */ String getFrom(); + /** + * @return the to address + */ String getTo(); + /** + * @return the accountId + */ Sid getAccountId(); + /** + * @return boolean if is from EP + */ boolean isFromApi(); + /** + * @return boolean if this is a child call + */ boolean isParentCallSidExists(); /** diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java index 40005cfbd7..ad7dd73008 100755 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionCreateSmsSessionRequest.java @@ -1,8 +1,39 @@ +/* + * TeleStax, Open Source Cloud Communications + * Copyright 2011-2013, Telestax Inc and individual contributors + * by the @authors tag. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ package org.restcomm.connect.extension.api; import org.apache.commons.configuration.Configuration; public interface IExtensionCreateSmsSessionRequest extends IExtensionRequest { + /** + * FIXME: potentially we will change this to be specific properties + * rather than a whole Config object + * @param set Configuration object + */ void setConfiguration(Configuration configuration); + + /** + * FIXME: potentially we will change this to be specific properties + * rather than a whole Config object + * @return the Configuration object + */ Configuration getConfiguration(); } diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java index 3bb4279c97..0211de62d6 100755 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/IExtensionRequest.java @@ -1,8 +1,40 @@ +/* + * TeleStax, Open Source Cloud Communications + * Copyright 2011-2013, Telestax Inc and individual contributors + * by the @authors tag. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ package org.restcomm.connect.extension.api; public interface IExtensionRequest { + + /** + * @return the accountId as String + * FIXME: should this be at this level? + */ String getAccountSid(); + + /** + * @return whether request should proceed + */ boolean isAllowed(); + + /** + * @param set to allow/restrict request + */ void setAllowed(boolean allowed); - //boolean isFromApi(); } diff --git a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java index 71217f276f..726d5ed514 100644 --- a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java +++ b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/CreateSmsSession.java @@ -55,12 +55,6 @@ public String getTo() { return to; } - @Override - public String getAccountSid() { - return accountSid; - } - - //@Override public boolean isFromApi() { return isFromApi; } @@ -70,21 +64,46 @@ public String toString() { return "From: "+from+" , To: "+to+" , AccountSid: "+accountSid+" , isFromApi: "+isFromApi; } + /** + * IExtensionRequest + * @return accountSid + */ + @Override + public String getAccountSid() { + return accountSid; + } + + /** + * IExtensionRequest + * @return if allowed + */ @Override public boolean isAllowed() { return this.allowed; } + /** + * IExtensionRequest + * @param set allowed + */ @Override public void setAllowed(boolean allowed) { this.allowed = allowed; } + /** + * IExtensionCreateSmsSessionRequest + * @param set Configuration object + */ @Override public void setConfiguration(Configuration configuration) { this.configuration = configuration; } + /** + * IExtensionCreateSmsSessionRequest + * @return Configuration object + */ @Override public Configuration getConfiguration() { return this.configuration; diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java index 4816fd2277..49622b5027 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsService.java @@ -49,8 +49,6 @@ import org.restcomm.connect.dao.entities.SmsMessage; import org.restcomm.connect.dao.entities.SmsMessage.Direction; import org.restcomm.connect.dao.entities.SmsMessage.Status; -//import org.restcomm.connect.extension.api.ExtensionResponse; -//import org.restcomm.connect.extension.api.ExtensionRequest; import org.restcomm.connect.extension.api.ExtensionType; import org.restcomm.connect.extension.api.IExtensionCreateSmsSessionRequest; import org.restcomm.connect.extension.api.RestcommExtensionException; diff --git a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java index e649f07673..b3680da8cb 100644 --- a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java +++ b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java @@ -139,102 +139,158 @@ public Sid parentCallSid() { public List statusCallbackEvent() { return statusCallbackEvent; } /** + * IExtensionCreateCallRequest * @return the outboundProxy */ public String getOutboundProxy() { return outboundProxy; } + /** + * IExtensionCreateCallRequest * @param outboundProxy the outboundProxy to set */ public void setOutboundProxy(String outboundProxy) { this.outboundProxy = outboundProxy; } + /** + * IExtensionCreateCallRequest * @return the outboundProxyUsername */ public String getOutboundProxyUsername() { return username; } + /** + * IExtensionCreateCallRequest * @param outboundProxyUsername the outboundProxyUsername to set */ public void setOutboundProxyUsername(String outboundProxyUsername) { this.username = outboundProxyUsername; } + /** + * IExtensionCreateCallRequest * @return the outboundProxyPassword */ public String getOutboundProxyPassword() { return password; } + /** + * IExtensionCreateCallRequest * @param outboundProxyPassword the outboundProxyPassword to set */ public void setOutboundProxyPassword(String outboundProxyPassword) { this.password = outboundProxyPassword; } + /** + * IExtensionCreateCallRequest * @return the outboundProxyHeaders */ public Map> getOutboundProxyHeaders() { return outboundProxyHeaders; } + /** + * IExtensionCreateCallRequest * @param outboundProxyHeaders the outboundProxyHeaders to set */ public void setOutboundProxyHeaders(Map> outboundProxyHeaders) { this.outboundProxyHeaders = outboundProxyHeaders; } + + /** + * IExtensionCreateCallRequest + * @return from address + */ public String getFrom() { return from; } + /** + * IExtensionCreateCallRequest + * @return to address + */ public String getTo() { return to; } + /** + * IExtensionCreateCallRequest + * @return accountId + */ public Sid getAccountId() { return accountId; } + /** + * IExtensionCreateCallRequest + * @return boolean fromApi + */ @Override public boolean isFromApi() { return isFromApi; } + /** + * IExtensionCreateCallRequest + * @return boolean is child call + */ @Override public boolean isParentCallSidExists() { return parentCallSid != null; } - @Override - public String toString() { - return "From: "+from+", To: "+to+", Type: "+callType.name()+", AccountId: "+accountId+", isFromApi: "+isFromApi+", parentCallSidExists: "+isParentCallSidExists(); - } - + /** + * IExtensionCreateCallRequest + * @return the CreateCallType + */ @Override public CreateCallType getType() { return callType; } + /** + * IExtensionCreateCallRequest + * @return the CreateCallType + */ @Override public String getRequestURI() { return this.to; } + /** + * IExtensionRequest + * @return accountSid + */ @Override public String getAccountSid() { return this.accountId.toString(); } + /** + * IExtensionRequest + * @return is allowed + */ @Override public boolean isAllowed() { return this.allowed; } + /** + * IExtensionRequest + * @param set allowed + */ @Override public void setAllowed(boolean allowed) { this.allowed = allowed; } + + @Override + public String toString() { + return "From: "+from+", To: "+to+", Type: "+callType.name()+", AccountId: "+accountId+", isFromApi: "+isFromApi+", parentCallSidExists: "+isParentCallSidExists(); + } } diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java index 7250d348a6..40a3b14483 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java @@ -1011,7 +1011,7 @@ private void addHeadersToMessage(SipServletRequest message, Map } /** - * + * addCustomHeadersToMap */ private void addCustomHeadersToMap(Map headers) { if (apiVersion != null) @@ -1022,25 +1022,29 @@ private void addCustomHeadersToMap(Map headers) { } /** - * @param keyPrepend TODO - * + * Replace headers + * @param SipServletRequest message + * @param Map > headers */ private void addHeadersToMessage(SipServletRequest message, Map > headers) { if(headers!=null) { for (Map.Entry> entry : headers.entrySet()) { - //check of header exists + //check if header exists String headerName = entry.getKey(); String headerVal = message.getHeader(headerName); //FIXME: do getValue check first? StringBuilder sb = new StringBuilder(); - String concatValue; - for(String pair :entry.getValue()){ - logger.debug("pair="+pair); - sb.append(";").append(pair); + //if(entry.getValue() instanceof ArrayList){ + for(String pair : entry.getValue()){ + logger.debug("pair="+pair); + sb.append(";").append(pair); + } + //} + if(logger.isDebugEnabled()) { + logger.debug("headerName="+headerName+" headerVal="+headerVal+" concatValue="+sb.toString()); } - logger.debug("headerName="+headerName+" headerVal="+headerVal+" concatValue="+sb.toString()); if(!headerName.equalsIgnoreCase("Request-URI")){ if(headerVal!=null && !headerVal.isEmpty()) { message.setHeader(headerName , headerVal+sb.toString()); @@ -1049,9 +1053,10 @@ private void addHeadersToMessage(SipServletRequest message, Map Date: Sun, 11 Jun 2017 20:17:34 +0800 Subject: [PATCH 07/12] RESTCOMM-884: Add outboundProxy usage for outboundToSip. Address review comments: Remove CreateCall, unused *Response, change method interfaces. Remove CallManager.handleExtensionResponse. Add extension check for proxyDID scenario. --- .../connect/extension/api/CallRequest.java | 56 -------- .../api/MessageExtensionResponse.java | 27 ---- .../extension/api/NodeExtensionResponse.java | 27 ---- .../api/RestcommExtensionGeneric.java | 2 +- .../api/SessionExtensionResponse.java | 44 ------ .../api/SystemExtensionResponse.java | 27 ---- .../api/TransactionExtensionResponse.java | 28 ---- .../controller/ExtensionController.java | 35 ----- .../connect/telephony/api/CreateCall.java | 12 +- .../org/restcomm/connect/telephony/Call.java | 25 ++-- .../connect/telephony/CallManager.java | 127 +++++++++++++++--- 11 files changed, 129 insertions(+), 281 deletions(-) delete mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java delete mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/MessageExtensionResponse.java delete mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/NodeExtensionResponse.java delete mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SessionExtensionResponse.java delete mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SystemExtensionResponse.java delete mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/TransactionExtensionResponse.java diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java deleted file mode 100644 index c47e2240ba..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallRequest.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.restcomm.connect.extension.api; - - -import org.restcomm.connect.commons.dao.Sid; -import org.restcomm.connect.commons.telephony.CreateCallType; -//TODO: Remove, obsoleted by Interface usage -/** - * Created by gvagenas on 27/09/16. - */ -public class CallRequest extends ExtensionRequest { - - private final String from; - private final String to; - private final CreateCallType type; - private final Sid accountId; - private final boolean isFromApi; - private final boolean parentCallSidExists; - - public CallRequest(String from, String to, CreateCallType type, Sid accountId, boolean isFromApi, boolean parentCallSidExists) { - this.from = from; - this.to = to; - this.type = type; - this.accountId = accountId; - this.isFromApi = isFromApi; - this.parentCallSidExists = parentCallSidExists; - } - - public String getFrom() { - return from; - } - - public String getTo() { - return to; - } - - public CreateCallType getType() { - return type; - } - - public Sid getAccountId() { - return accountId; - } - - public boolean isFromApi() { - return isFromApi; - } - - public boolean isParentCallSidExists() { - return parentCallSidExists; - } - - @Override - public String toString() { - return "From: "+from+", To: "+to+", Type: "+type.name()+", AccountId: "+accountId+", isFromApi: "+isFromApi+", parentCallSidExists: "+parentCallSidExists; - } -} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/MessageExtensionResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/MessageExtensionResponse.java deleted file mode 100644 index de1b637ff5..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/MessageExtensionResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * TeleStax, Open Source Cloud Communications - * Copyright 2011-2013, Telestax Inc and individual contributors - * by the @authors tag. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -/** - * When an Extension returns a MessageReponse, RC will reconfigure the message it will send - */ -package org.restcomm.connect.extension.api; -public class MessageExtensionResponse extends ExtensionResponse { - //TODO: needs discussion, definition -} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/NodeExtensionResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/NodeExtensionResponse.java deleted file mode 100644 index ed3b2f4965..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/NodeExtensionResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * TeleStax, Open Source Cloud Communications - * Copyright 2011-2013, Telestax Inc and individual contributors - * by the @authors tag. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -/** - * When an Extension returns a NodeReponse, RC will reconfigure the specific RC node it is in - */ -package org.restcomm.connect.extension.api; -public class NodeExtensionResponse extends ExtensionResponse { - //TODO: needs discussion, definition -} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java index cc22594066..e2a8a162cd 100644 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/RestcommExtensionGeneric.java @@ -64,7 +64,7 @@ public interface RestcommExtensionGeneric { * and either block or allow or modify the session after Restcomm process it * @return ExtensionResponse see ExtensionResponse */ - ExtensionResponse postOutboundAction(CallRequest callRequest); + ExtensionResponse postOutboundAction(IExtensionRequest extensionRequest); /** * Method that will be executed before the process of an API action, such as DID purchase (but after security checks) diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SessionExtensionResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SessionExtensionResponse.java deleted file mode 100644 index 9d8013a87f..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SessionExtensionResponse.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * TeleStax, Open Source Cloud Communications - * Copyright 2011-2013, Telestax Inc and individual contributors - * by the @authors tag. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -/** - * When an Extension returns a SessionReponse, RC will reconfigure the session it is in - */ -package org.restcomm.connect.extension.api; -import org.apache.commons.configuration.Configuration; -public class SessionExtensionResponse extends ExtensionResponse { - //TODO: needs discussion, definition - /** - * The Extension is expected to populate the session specific - * Configuration - */ - public void setConfiguration(Configuration configuration){ - super.setObject(configuration); - } - - /** - * RC expects an Extension to populate Configuration when it returns - * this SessionResponse - * @return Configuration object - */ - public Configuration getConfiguration(){ - return (Configuration) super.getObject(); - } -} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SystemExtensionResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SystemExtensionResponse.java deleted file mode 100644 index 4df9d6a039..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SystemExtensionResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * TeleStax, Open Source Cloud Communications - * Copyright 2011-2013, Telestax Inc and individual contributors - * by the @authors tag. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -/** - * When an Extension returns a SystemReponse, RC will reconfigure itself systemwide - */ -package org.restcomm.connect.extension.api; -public class SystemExtensionResponse extends ExtensionResponse { - //TODO: needs discussion, definition -} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/TransactionExtensionResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/TransactionExtensionResponse.java deleted file mode 100644 index c3ac493ab2..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/TransactionExtensionResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * TeleStax, Open Source Cloud Communications - * Copyright 2011-2013, Telestax Inc and individual contributors - * by the @authors tag. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -/** - * When an Extension returns a TransactionReponse, RC will reconfigure the transaction it - * is in - */ -package org.restcomm.connect.extension.api; -public class TransactionExtensionResponse extends ExtensionResponse { - //TODO: needs discussion, definition -} \ No newline at end of file diff --git a/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java index ccf4c13e91..0098482e1d 100644 --- a/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java +++ b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/controller/ExtensionController.java @@ -3,14 +3,8 @@ import org.restcomm.connect.extension.api.ExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; import org.restcomm.connect.extension.api.IExtensionRequest; -import org.restcomm.connect.extension.api.MessageExtensionResponse; -import org.restcomm.connect.extension.api.NodeExtensionResponse; import org.restcomm.connect.extension.api.RestcommExtension; import org.restcomm.connect.extension.api.RestcommExtensionGeneric; -import org.restcomm.connect.extension.api.SessionExtensionResponse; -import org.restcomm.connect.extension.api.SystemExtensionResponse; -import org.restcomm.connect.extension.api.TransactionExtensionResponse; -import org.apache.commons.configuration.Configuration; import org.apache.log4j.Logger; import java.util.List; @@ -122,33 +116,4 @@ public ExtensionResponse executePostOutboundAction(final IExtensionRequest er, L //TODO: implement actual calls return response; } - - //FIXME: there must be a fixed contract between the returned extensions object - // and how the system will reconfigure itself with the type of ExtensionResponse - // for now we will just map SessionExtensionResponse to Configuration object - //FIXME: method signature is too restrictive - public Object handleExtensionResponse(ExtensionResponse response, Configuration configuration){ - //check type of extension - //FIXME: hack to default - Object object = configuration; - if(response instanceof SystemExtensionResponse){ - //TODO:return systemwide level customization behaviour - } - if(response instanceof NodeExtensionResponse){ - //TODO:return node level customization behaviour - } - if(response instanceof SessionExtensionResponse){ - SessionExtensionResponse ser = (SessionExtensionResponse) response; - Configuration config = ser.getConfiguration(); - - object = config; - } - if(response instanceof TransactionExtensionResponse){ - //TODO:return transaction level customization behaviour - } - if(response instanceof MessageExtensionResponse){ - //TODO:return message level customization behaviour - } - return object; - } } diff --git a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java index b3680da8cb..4fb83228f7 100644 --- a/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java +++ b/restcomm/restcomm.telephony.api/src/main/java/org/restcomm/connect/telephony/api/CreateCall.java @@ -51,8 +51,6 @@ public final class CreateCall implements IExtensionCreateCallRequest{ private final String statusCallbackMethod; private final List statusCallbackEvent; private String outboundProxy; - private String outboundProxyUsername; - private String outboundProxyPassword; private Map> outboundProxyHeaders; private boolean allowed = true; @@ -60,12 +58,12 @@ public CreateCall(final String from, final String to, final String username, fin final boolean isFromApi, final int timeout, final CreateCallType type, final Sid accountId, final Sid parentCallSid, final URI statusCallbackUrl, final String statusCallbackMethod, final List statusCallbackEvent ) { - this(from, to, username, password, isFromApi, timeout, type, accountId, parentCallSid, statusCallbackUrl, statusCallbackMethod, statusCallbackEvent, "","","",null); + this(from, to, username, password, isFromApi, timeout, type, accountId, parentCallSid, statusCallbackUrl, statusCallbackMethod, statusCallbackEvent, "", null); } public CreateCall(final String from, final String to, final String username, final String password, final boolean isFromApi, final int timeout, final CreateCallType type, final Sid accountId, final Sid parentCallSid, final URI statusCallbackUrl, final String statusCallbackMethod, final List statusCallbackEvent, - final String outboundProxy, final String outboundProxyUsername, final String outboundProxyPassword, final Map> outboundProxyHeaders) { + final String outboundProxy, final Map> outboundProxyHeaders) { super(); this.from = from; this.to = to; @@ -80,8 +78,6 @@ public CreateCall(final String from, final String to, final String username, fin this.statusCallbackMethod = statusCallbackMethod; this.statusCallbackEvent = statusCallbackEvent; this.outboundProxy = outboundProxy; - this.outboundProxyUsername = outboundProxyUsername;//FIXME:unused - this.outboundProxyPassword = outboundProxyPassword;//FIXME:unused this.outboundProxyHeaders = outboundProxyHeaders; } @@ -156,6 +152,7 @@ public void setOutboundProxy(String outboundProxy) { /** * IExtensionCreateCallRequest + * the outboundProxyUsername is a facade to the username field * @return the outboundProxyUsername */ public String getOutboundProxyUsername() { @@ -164,6 +161,7 @@ public String getOutboundProxyUsername() { /** * IExtensionCreateCallRequest + * the outboundProxyUsername is a facade to the username field * @param outboundProxyUsername the outboundProxyUsername to set */ public void setOutboundProxyUsername(String outboundProxyUsername) { @@ -172,6 +170,7 @@ public void setOutboundProxyUsername(String outboundProxyUsername) { /** * IExtensionCreateCallRequest + * the outboundProxyPassword is a facade to the password field * @return the outboundProxyPassword */ public String getOutboundProxyPassword() { @@ -180,6 +179,7 @@ public String getOutboundProxyPassword() { /** * IExtensionCreateCallRequest + * the outboundProxyPassword is a facade to the password field * @param outboundProxyPassword the outboundProxyPassword to set */ public void setOutboundProxyPassword(String outboundProxyPassword) { diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java index 40a3b14483..8e47cf2878 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java @@ -192,8 +192,10 @@ public final class Call extends UntypedActor { private SipURI from; private javax.servlet.sip.URI to; // custom headers for SIP Out https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out + //headers defined in rcml private Map rcmlHeaders; - private Map> headers; + //headers populated by extension to modify existing headers and add new headers + private Map> extensionHeaders; private String username; private String password; private CreateCallType type; @@ -302,10 +304,10 @@ public Call(final SipFactory factory, final ActorRef mediaSessionController, fin if (statusCallback != null) { downloader = downloader(); } - this.rcmlHeaders = new HashMap(); - this.headers = new HashMap>(); + + this.extensionHeaders = new HashMap>(); if(headers != null){ - this.headers = headers; + this.extensionHeaders = headers; } // States for the FSM @@ -838,7 +840,7 @@ public void execute(Object message) throws Exception { if (toHeaderString.indexOf('?') != -1) { // custom headers parsing for SIP Out // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - + rcmlHeaders = new HashMap(); // we keep only the to URI without the headers to = (SipURI) factory.createURI(toHeaderString.substring(0, toHeaderString.lastIndexOf('?'))); String headersString = toHeaderString.substring(toHeaderString.lastIndexOf('?') + 1); @@ -968,7 +970,7 @@ public void execute(Object message) throws Exception { addHeadersToMessage(invite, rcmlHeaders, "X-"); //the extension headers will override any headers - addHeadersToMessage(invite, headers); + addHeadersToMessage(invite, extensionHeaders); final SipSession session = invite.getSession(); session.setHandler("CallManager"); @@ -1005,7 +1007,6 @@ private void addHeadersToMessage(SipServletRequest message, Map for (Map.Entry entry : rcmlHeaders.entrySet()) { String headerName = keyPrepend + entry.getKey(); - String headerVal = message.getHeader(headerName); message.addHeader(headerName , entry.getValue()); } } @@ -1032,20 +1033,18 @@ private void addHeadersToMessage(SipServletRequest message, Map> entry : headers.entrySet()) { //check if header exists String headerName = entry.getKey(); - String headerVal = message.getHeader(headerName); - //FIXME: do getValue check first? StringBuilder sb = new StringBuilder(); - //if(entry.getValue() instanceof ArrayList){ + if(entry.getValue() instanceof ArrayList){ for(String pair : entry.getValue()){ - logger.debug("pair="+pair); sb.append(";").append(pair); } - //} + } if(logger.isDebugEnabled()) { - logger.debug("headerName="+headerName+" headerVal="+headerVal+" concatValue="+sb.toString()); + logger.debug("headerName="+headerName+" headerVal="+message.getHeader(headerName)+" concatValue="+sb.toString()); } if(!headerName.equalsIgnoreCase("Request-URI")){ + String headerVal = message.getHeader(headerName); if(headerVal!=null && !headerVal.isEmpty()) { message.setHeader(headerName , headerVal+sb.toString()); }else{ diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java index b5b566cdf2..073ac77f17 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java @@ -60,9 +60,6 @@ import org.restcomm.connect.dao.entities.IncomingPhoneNumber; import org.restcomm.connect.dao.entities.Notification; import org.restcomm.connect.dao.entities.Registration; -import org.restcomm.connect.extension.api.CallRequest; -import org.restcomm.connect.extension.api.ExtensionRequest; -import org.restcomm.connect.extension.api.ExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; import org.restcomm.connect.extension.api.IExtensionCreateCallRequest; import org.restcomm.connect.extension.api.RestcommExtensionException; @@ -118,6 +115,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -538,30 +536,38 @@ private void invite(final Object message) throws IOException, NumberParseExcepti } // https://telestax.atlassian.net/browse/RESTCOMM-335 - final String proxyURI = activeProxy; - final String proxyUsername = activeProxyUsername; - final String proxyPassword = activeProxyPassword; + String proxyURI = activeProxy; + String proxyUsername = activeProxyUsername; + String proxyPassword = activeProxyPassword; SipURI from = null; SipURI to = null; boolean callToSipUri = false; + ExtensionController ec = ExtensionController.getInstance(); + IExtensionCreateCallRequest er = new CreateCall(fromUser, toUser, "", "", false, 0, CreateCallType.PSTN, client.getAccountSid(), null,null, null, null); + ec.executePreOutboundAction(er, this.extensions); + if(er.getOutboundProxy()!=null && !er.getOutboundProxy().isEmpty()){ + proxyURI = er.getOutboundProxy(); + } + if(er.getOutboundProxyUsername()!=null && !er.getOutboundProxyUsername().isEmpty()){ + proxyUsername = er.getOutboundProxyUsername(); + } + if(er.getOutboundProxyPassword()!=null && !er.getOutboundProxyPassword().isEmpty()){ + proxyUsername = er.getOutboundProxyPassword(); + } // proxy DID or number if the outbound proxy fields are not empty in the restcomm.xml if (proxyURI != null && !proxyURI.isEmpty()) { -// String destination = ((SipURI)request.getTo().getURI()).getUser(); - CallRequest callRequest = new CallRequest(fromUser,toUser, CreateCallType.PSTN, client.getAccountSid(), false, false); - ExtensionController ec = ExtensionController.getInstance(); - ExtensionRequest er = new ExtensionRequest(); - //er.setObject(callRequest); - ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); - if (extensionResponse.isAllowed()) { + if (er.isAllowed()) { + //FIXME: not so nice to just inject headers here + addHeadersToMessage(request, er.getOutboundProxyHeaders()); proxyOut(request, client, toUser, toHost, toHostIpAddress, toPort, outboundIntf, proxyURI, proxyUsername, proxyPassword, from, to, callToSipUri); } else { final SipServletResponse response = request.createResponse(SC_FORBIDDEN, "Call request not allowed"); response.send(); if (logger.isDebugEnabled()) { - logger.debug("Call request now allowed: "+callRequest.toString()); + logger.debug("Call request now allowed: "+er.toString()); } } - ec.executePostOutboundAction(callRequest, this.extensions); + ec.executePostOutboundAction(er, this.extensions); return; } else { String msg = "Restcomm tried to proxy this call to an outbound party but it seems the outbound proxy is not configured."; @@ -589,6 +595,65 @@ private void invite(final Object message) throws IOException, NumberParseExcepti } + /** + * FIXME: duplicated code make into static function or something more optimized + * Replace headers + * @param SipServletRequest message + * @param Map > headers + */ + private void addHeadersToMessage(SipServletRequest message, Map > headers) { + + if(headers!=null) { + for (Map.Entry> entry : headers.entrySet()) { + //check if header exists + String headerName = entry.getKey(); + + StringBuilder sb = new StringBuilder(); + if(entry.getValue() instanceof ArrayList){ + for(String pair : entry.getValue()){ + sb.append(";").append(pair); + } + } + if(logger.isDebugEnabled()) { + logger.debug("headerName="+headerName+" headerVal="+message.getHeader(headerName)+" concatValue="+sb.toString()); + } + if(!headerName.equalsIgnoreCase("Request-URI")){ + String headerVal = message.getHeader(headerName); + if(headerVal!=null && !headerVal.isEmpty()) { + message.setHeader(headerName , headerVal+sb.toString()); + }else{ + message.addHeader(headerName , sb.toString()); + } + }else{ + //handle Request-URI + javax.servlet.sip.URI reqURI = message.getRequestURI(); + if(logger.isDebugEnabled()) { + logger.debug("ReqURI="+reqURI.toString()+" msgReqURI="+message.getRequestURI()); + } + for(String keyValPair :entry.getValue()){ + String parName = ""; + String parVal = ""; + int equalsPos = keyValPair.indexOf("="); + parName = keyValPair.substring(0, equalsPos); + parVal = keyValPair.substring(equalsPos+1); + reqURI.setParameter(parName, parVal); + if(logger.isDebugEnabled()) { + logger.debug("ReqURI pars ="+parName+"="+parVal+" equalsPos="+equalsPos+" keyValPair="+keyValPair); + } + } + + message.setRequestURI(reqURI); + if(logger.isDebugEnabled()) { + logger.debug("ReqURI="+reqURI.toString()+" msgReqURI="+message.getRequestURI()); + } + } + if(logger.isDebugEnabled()) { + logger.debug("headerName="+headerName+" headerVal="+message.getHeader(headerName)); + } + } + } + } + private boolean proxyOut(SipServletRequest request, Client client, String toUser, String toHost, String toHostIpAddress, String toPort, SipURI outboundIntf, String proxyURI, String proxyUsername, String proxyPassword, SipURI from, SipURI to, boolean callToSipUri) throws UnknownHostException { final Configuration runtime = configuration.subset("runtime-settings"); final boolean useLocalAddressAtFromHeader = runtime.getBoolean("use-local-address", false); @@ -1664,7 +1729,7 @@ private void outboundToClient(final CreateCall request, final ActorRef sender) t } private void outboundToPstn(final CreateCall request, final ActorRef sender) throws ServletParseException { - final String uri = (!request.getOutboundProxy().isEmpty()) ? request.getOutboundProxy() : activeProxy; + final String uri = (request.getOutboundProxy()!= null && (!request.getOutboundProxy().isEmpty())) ? request.getOutboundProxy() : activeProxy; SipURI outboundIntf = null; SipURI from = null; SipURI to = null; @@ -1724,11 +1789,39 @@ private void outboundToPstn(final CreateCall request, final ActorRef sender) thr private void outboundToSip(final CreateCall request, final ActorRef sender) throws ServletParseException { + final String uri = (request.getOutboundProxy()!= null && (!request.getOutboundProxy().isEmpty())) ? request.getOutboundProxy() : ""; SipURI outboundIntf = null; SipURI from = null; SipURI to = null; - to = (SipURI) sipFactory.createURI(request.to()); + String toUser = ""; + String toHost = ""; + String scheme = ""; + boolean isSecure = false; + if(request.to().contains("@") && + (request.to().startsWith("sip:") || request.to().startsWith("sips:")) ){ + String [] tokens = request.to().split("[@:]"); + scheme = tokens[0]; + toUser = tokens[1]; + toHost = tokens[2]; + if(scheme.equals("sips")){ + isSecure = true; + } + }else{ + toUser = request.to(); + } + + if(!uri.isEmpty() || toHost.isEmpty()){ + toHost = uri; + }else if(uri.isEmpty() && toHost.isEmpty()){ + if(logger.isDebugEnabled()){ + logger.debug("uri and toHost is empty!"); + } + } + + to = sipFactory.createSipURI(toUser, toHost); + to.setSecure(isSecure); + String transport = (to.getTransportParam() != null) ? to.getTransportParam() : "udp"; outboundIntf = outboundInterface(transport); if (request.from() == null) { From 1eecc8d22acdc67578010e6ac1e71ca3cc37e721 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Mon, 12 Jun 2017 12:32:18 +0800 Subject: [PATCH 08/12] RESTCOMM-884: Move rcmlHeaders instantiation functions --- .../org/restcomm/connect/telephony/Call.java | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java index 8e47cf2878..1a9c816eb9 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java @@ -841,6 +841,9 @@ public void execute(Object message) throws Exception { // custom headers parsing for SIP Out // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out rcmlHeaders = new HashMap(); + addCustomHeadersToMap(rcmlHeaders); + addHeadersToMessage(invite, rcmlHeaders, "X-"); + // we keep only the to URI without the headers to = (SipURI) factory.createURI(toHeaderString.substring(0, toHeaderString.lastIndexOf('?'))); String headersString = toHeaderString.substring(toHeaderString.lastIndexOf('?') + 1); @@ -906,6 +909,24 @@ public void execute(Object message) throws Exception { } } } + + /** + * addCustomHeadersToMap + */ + private void addCustomHeadersToMap(Map headers) { + if (apiVersion != null) + headers.put("RestComm-ApiVersion", apiVersion); + if (accountId != null) + headers.put("RestComm-AccountSid", accountId.toString()); + headers.put("RestComm-CallSid", instanceId+"-"+id.toString()); + } + + private void addHeadersToMessage(SipServletRequest message, Map headers, String keyPrepend) { + for (Map.Entry entry : headers.entrySet()) { + String headerName = keyPrepend + entry.getKey(); + message.addHeader(headerName , entry.getValue()); + } + } } private final class Dialing extends AbstractAction { @@ -964,11 +985,6 @@ public void execute(Object message) throws Exception { invite.setHeader("User-Agent", userAgent); } - addCustomHeadersToMap(rcmlHeaders); - // adding custom headers for SIP Out - // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - addHeadersToMessage(invite, rcmlHeaders, "X-"); - //the extension headers will override any headers addHeadersToMessage(invite, extensionHeaders); @@ -1002,26 +1018,6 @@ public void execute(Object message) throws Exception { executeStatusCallback(CallbackState.INITIATED); } - //FIXME: duplicate code - private void addHeadersToMessage(SipServletRequest message, Map rcmlHeaders, String keyPrepend) { - - for (Map.Entry entry : rcmlHeaders.entrySet()) { - String headerName = keyPrepend + entry.getKey(); - message.addHeader(headerName , entry.getValue()); - } - } - - /** - * addCustomHeadersToMap - */ - private void addCustomHeadersToMap(Map headers) { - if (apiVersion != null) - headers.put("RestComm-ApiVersion", apiVersion); - if (accountId != null) - headers.put("RestComm-AccountSid", accountId.toString()); - headers.put("RestComm-CallSid", instanceId+"-"+id.toString()); - } - /** * Replace headers * @param SipServletRequest message From c6636c3ca02f0a6789f11001a8cd96e85590eb98 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 13 Jun 2017 00:20:38 +0800 Subject: [PATCH 09/12] RESTCOMM-884: Call extensions for WebRTC case. Optimize outboundToSip host replacement --- .../connect/telephony/CallManager.java | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java index 073ac77f17..43a82fb382 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java @@ -531,7 +531,28 @@ private void invite(final Object message) throws IOException, NumberParseExcepti if (isWebRTC(request)) { //This is a WebRTC client that dials out - proxyThroughMediaServer(request, client, toUser); + ExtensionController ec = ExtensionController.getInstance(); + IExtensionCreateCallRequest er = new CreateCall(client.getFriendlyName(), toUser, "", "", false, 0, CreateCallType.CLIENT, client.getAccountSid(), null,null, null, null); + ec.executePreOutboundAction(er, this.extensions); + + if (er.isAllowed()) { + //TODO: should we inject headers for this case? + proxyThroughMediaServer(request, client, toUser); + } else { + //Extensions didn't allow this call + if (logger.isDebugEnabled()) { + //FIXME: proper error message + errMsg = "Client not Allowed to make this WebRTC outbound call"; + logger.debug(errMsg); + } + //FIXME: proper error message + errMsg = "Cannot Connect to Client: " + toClient.getFriendlyName() + + " : Make sure the Client exist or is registered with Restcomm"; + sendNotification(errMsg, 11001, "warning", true); + final SipServletResponse resp = request.createResponse(SC_FORBIDDEN, "Call not allowed"); + resp.send(); + } + ec.executePostOutboundAction(er, this.extensions); return; } @@ -1792,36 +1813,18 @@ private void outboundToSip(final CreateCall request, final ActorRef sender) thro final String uri = (request.getOutboundProxy()!= null && (!request.getOutboundProxy().isEmpty())) ? request.getOutboundProxy() : ""; SipURI outboundIntf = null; SipURI from = null; - SipURI to = null; + SipURI to = (SipURI) sipFactory.createURI(request.to()); - String toUser = ""; - String toHost = ""; - String scheme = ""; - boolean isSecure = false; - if(request.to().contains("@") && - (request.to().startsWith("sip:") || request.to().startsWith("sips:")) ){ + if(!uri.isEmpty()){ + //NB: we expect uri with no scheme for db outboundProxy + //user@host.com:port String [] tokens = request.to().split("[@:]"); - scheme = tokens[0]; - toUser = tokens[1]; - toHost = tokens[2]; - if(scheme.equals("sips")){ - isSecure = true; - } - }else{ - toUser = request.to(); + String toUser = tokens[1]; + boolean isSecure = to.isSecure(); + to = sipFactory.createSipURI(toUser, uri); + to.setSecure(isSecure); } - if(!uri.isEmpty() || toHost.isEmpty()){ - toHost = uri; - }else if(uri.isEmpty() && toHost.isEmpty()){ - if(logger.isDebugEnabled()){ - logger.debug("uri and toHost is empty!"); - } - } - - to = sipFactory.createSipURI(toUser, toHost); - to.setSecure(isSecure); - String transport = (to.getTransportParam() != null) ? to.getTransportParam() : "udp"; outboundIntf = outboundInterface(transport); if (request.from() == null) { From f7d004d2d839a9c7194ef84a6fb91acf874935d8 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 13 Jun 2017 10:09:42 +0800 Subject: [PATCH 10/12] RESTCOMM-884 : Catch exception for SipMessage.setHeader/addHeader --- .../org/restcomm/connect/telephony/Call.java | 18 +++++++++++++----- .../connect/telephony/CallManager.java | 16 +++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java index 1a9c816eb9..0535191c8f 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java @@ -922,6 +922,8 @@ private void addCustomHeadersToMap(Map headers) { } private void addHeadersToMessage(SipServletRequest message, Map headers, String keyPrepend) { + //NB: for the current limited usage of this function, + //we know that no system headers will be modified so we dont need to catch an IAE for (Map.Entry entry : headers.entrySet()) { String headerName = keyPrepend + entry.getKey(); message.addHeader(headerName , entry.getValue()); @@ -1040,11 +1042,17 @@ private void addHeadersToMessage(SipServletRequest message, Map Date: Tue, 13 Jun 2017 15:53:42 +0800 Subject: [PATCH 11/12] RESTCOMM-884 : call SipURI.setHost to set outboundProxy --- .../java/org/restcomm/connect/telephony/CallManager.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java index 2f0f9c254a..7278d1f47e 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java @@ -1822,13 +1822,7 @@ private void outboundToSip(final CreateCall request, final ActorRef sender) thro SipURI to = (SipURI) sipFactory.createURI(request.to()); if(!uri.isEmpty()){ - //NB: we expect uri with no scheme for db outboundProxy - //user@host.com:port - String [] tokens = request.to().split("[@:]"); - String toUser = tokens[1]; - boolean isSecure = to.isSecure(); - to = sipFactory.createSipURI(toUser, uri); - to.setSecure(isSecure); + to.setHost(uri); } String transport = (to.getTransportParam() != null) ? to.getTransportParam() : "udp"; From 3cb348a568c4c8f20b13c592e41b45c5b08f1752 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 13 Jun 2017 22:42:40 +0800 Subject: [PATCH 12/12] RESTCOMM-884 : Simplify extensions check for proxyDID and WebRTC. Revert mistaken rcmlHeaders functions changes, instantiate rcmlHeaders outside of if block --- .../org/restcomm/connect/telephony/Call.java | 53 +++++----- .../connect/telephony/CallManager.java | 97 ++++++++----------- 2 files changed, 70 insertions(+), 80 deletions(-) diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java index 0535191c8f..678a557336 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/Call.java @@ -837,12 +837,10 @@ public void execute(Object message) throws Exception { imsProxyAddress = request.getImsProxyAddress(); imsProxyPort = request.getImsProxyPort(); String toHeaderString = to.toString(); + rcmlHeaders = new HashMap(); if (toHeaderString.indexOf('?') != -1) { // custom headers parsing for SIP Out // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out - rcmlHeaders = new HashMap(); - addCustomHeadersToMap(rcmlHeaders); - addHeadersToMessage(invite, rcmlHeaders, "X-"); // we keep only the to URI without the headers to = (SipURI) factory.createURI(toHeaderString.substring(0, toHeaderString.lastIndexOf('?'))); @@ -909,26 +907,6 @@ public void execute(Object message) throws Exception { } } } - - /** - * addCustomHeadersToMap - */ - private void addCustomHeadersToMap(Map headers) { - if (apiVersion != null) - headers.put("RestComm-ApiVersion", apiVersion); - if (accountId != null) - headers.put("RestComm-AccountSid", accountId.toString()); - headers.put("RestComm-CallSid", instanceId+"-"+id.toString()); - } - - private void addHeadersToMessage(SipServletRequest message, Map headers, String keyPrepend) { - //NB: for the current limited usage of this function, - //we know that no system headers will be modified so we dont need to catch an IAE - for (Map.Entry entry : headers.entrySet()) { - String headerName = keyPrepend + entry.getKey(); - message.addHeader(headerName , entry.getValue()); - } - } } private final class Dialing extends AbstractAction { @@ -986,6 +964,10 @@ public void execute(Object message) throws Exception { if(userAgent!=null){ invite.setHeader("User-Agent", userAgent); } + addCustomHeadersToMap(rcmlHeaders); + // adding custom headers for SIP Out + // https://bitbucket.org/telestax/telscale-restcomm/issue/132/implement-twilio-sip-out + addHeadersToMessage(invite, rcmlHeaders, "X-"); //the extension headers will override any headers addHeadersToMessage(invite, extensionHeaders); @@ -1020,6 +1002,31 @@ public void execute(Object message) throws Exception { executeStatusCallback(CallbackState.INITIATED); } + /** + * addCustomHeadersToMap + */ + private void addCustomHeadersToMap(Map headers) { + if (apiVersion != null) + headers.put("RestComm-ApiVersion", apiVersion); + if (accountId != null) + headers.put("RestComm-AccountSid", accountId.toString()); + headers.put("RestComm-CallSid", instanceId+"-"+id.toString()); + } + + //TODO: put this in a central place + private void addHeadersToMessage(SipServletRequest message, Map headers, String keyPrepend) { + try { + for (Map.Entry entry : headers.entrySet()) { + String headerName = keyPrepend + entry.getKey(); + message.addHeader(headerName , entry.getValue()); + } + } catch (IllegalArgumentException iae) { + if(logger.isErrorEnabled()) { + logger.error("Exception while setting message header: "+iae.getMessage()); + } + } + } + /** * Replace headers * @param SipServletRequest message diff --git a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java index 7278d1f47e..256bb836cb 100644 --- a/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java +++ b/restcomm/restcomm.telephony/src/main/java/org/restcomm/connect/telephony/CallManager.java @@ -524,76 +524,59 @@ private void invite(final Object message) throws IOException, NumberParseExcepti // This is a call to a registered DID (application) return; } + // This call is not a registered DID (application). Try to proxy out this call. // log to console and to notification engine String errMsg = "A Restcomm Client is trying to call a Number/DID that is not registered with Restcomm"; sendNotification(errMsg, 11002, "info", true); - if (isWebRTC(request)) { - //This is a WebRTC client that dials out - ExtensionController ec = ExtensionController.getInstance(); - IExtensionCreateCallRequest er = new CreateCall(client.getFriendlyName(), toUser, "", "", false, 0, CreateCallType.CLIENT, client.getAccountSid(), null,null, null, null); - ec.executePreOutboundAction(er, this.extensions); - - if (er.isAllowed()) { - //TODO: should we inject headers for this case? - proxyThroughMediaServer(request, client, toUser); - } else { - //Extensions didn't allow this call - if (logger.isDebugEnabled()) { - //FIXME: proper error message - errMsg = "Client not Allowed to make this WebRTC outbound call"; - logger.debug(errMsg); - } - //FIXME: proper error message - errMsg = "Cannot Connect to Client: " + toClient.getFriendlyName() - + " : Make sure the Client exist or is registered with Restcomm"; - sendNotification(errMsg, 11001, "warning", true); - final SipServletResponse resp = request.createResponse(SC_FORBIDDEN, "Call not allowed"); - resp.send(); - } - ec.executePostOutboundAction(er, this.extensions); - return; - } - - // https://telestax.atlassian.net/browse/RESTCOMM-335 - String proxyURI = activeProxy; - String proxyUsername = activeProxyUsername; - String proxyPassword = activeProxyPassword; - SipURI from = null; - SipURI to = null; - boolean callToSipUri = false; ExtensionController ec = ExtensionController.getInstance(); IExtensionCreateCallRequest er = new CreateCall(fromUser, toUser, "", "", false, 0, CreateCallType.PSTN, client.getAccountSid(), null,null, null, null); ec.executePreOutboundAction(er, this.extensions); - if(er.getOutboundProxy()!=null && !er.getOutboundProxy().isEmpty()){ - proxyURI = er.getOutboundProxy(); - } - if(er.getOutboundProxyUsername()!=null && !er.getOutboundProxyUsername().isEmpty()){ - proxyUsername = er.getOutboundProxyUsername(); - } - if(er.getOutboundProxyPassword()!=null && !er.getOutboundProxyPassword().isEmpty()){ - proxyUsername = er.getOutboundProxyPassword(); - } - // proxy DID or number if the outbound proxy fields are not empty in the restcomm.xml - if (proxyURI != null && !proxyURI.isEmpty()) { - if (er.isAllowed()) { - //FIXME: not so nice to just inject headers here - addHeadersToMessage(request, er.getOutboundProxyHeaders()); - proxyOut(request, client, toUser, toHost, toHostIpAddress, toPort, outboundIntf, proxyURI, proxyUsername, proxyPassword, from, to, callToSipUri); + if (er.isAllowed()) { + if (isWebRTC(request)) { + //This is a WebRTC client that dials out + //TODO: should we inject headers for this case? + proxyThroughMediaServer(request, client, toUser); + } else { - final SipServletResponse response = request.createResponse(SC_FORBIDDEN, "Call request not allowed"); - response.send(); - if (logger.isDebugEnabled()) { - logger.debug("Call request now allowed: "+er.toString()); + // https://telestax.atlassian.net/browse/RESTCOMM-335 + String proxyURI = activeProxy; + String proxyUsername = activeProxyUsername; + String proxyPassword = activeProxyPassword; + SipURI from = null; + SipURI to = null; + boolean callToSipUri = false; + + if(er.getOutboundProxy()!=null && !er.getOutboundProxy().isEmpty()){ + proxyURI = er.getOutboundProxy(); + } + if(er.getOutboundProxyUsername()!=null && !er.getOutboundProxyUsername().isEmpty()){ + proxyUsername = er.getOutboundProxyUsername(); + } + if(er.getOutboundProxyPassword()!=null && !er.getOutboundProxyPassword().isEmpty()){ + proxyUsername = er.getOutboundProxyPassword(); + } + // proxy DID or number if the outbound proxy fields are not empty in the restcomm.xml + if (proxyURI != null && !proxyURI.isEmpty()) { + //FIXME: not so nice to just inject headers here + addHeadersToMessage(request, er.getOutboundProxyHeaders()); + proxyOut(request, client, toUser, toHost, toHostIpAddress, toPort, outboundIntf, proxyURI, proxyUsername, proxyPassword, from, to, callToSipUri); + } else { + errMsg = "Restcomm tried to proxy this call to an outbound party but it seems the outbound proxy is not configured."; + sendNotification(errMsg, 11004, "warning", true); } } - ec.executePostOutboundAction(er, this.extensions); - return; } else { - String msg = "Restcomm tried to proxy this call to an outbound party but it seems the outbound proxy is not configured."; - sendNotification(errMsg, 11004, "warning", true); + //Extensions didn't allow this call + final SipServletResponse response = request.createResponse(SC_FORBIDDEN, "Call request not allowed"); + response.send(); + if (logger.isDebugEnabled()) { + logger.debug("Call request not allowed: "+er.toString()); + } } + ec.executePostOutboundAction(er, this.extensions); + return; } } else { // Client is null, check if this call is for a registered DID (application)