From 65084be7691c5e12ea70a8afb8f162814625c4c0 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Wed, 29 Mar 2017 15:58:51 +0800 Subject: [PATCH 1/5] Issue #1981: Clean up. Change interface name getExtensionClob to getAccountExtensionConfiguration Issue #1981: Revert ExtensionsBootStrapper xml parsing Issue #1981: modify mysql extensions sql Issue #1981: Fix poms Issue #1981: Add proper tlvs to outbound and sip request Issue #1981: WIP. Fix Accounts Extensions DAO. Fix ExtensionConfig to json to XMLConfig mapping. Add example account mappings Issue #1981: WIP. Dao changes. Table changes. SMSService changes. Issue #1981: Make changes to SmsSession objects Issue #1981: Add ExtensionResponse subclasses. Handle Session specific Extension customization by modifying the SmsSession configuration. --- restcomm/restcomm.application/pom.xml | 6 +- .../main/webapp/WEB-INF/conf/extensions.xml | 10 +-- .../webapp/WEB-INF/data/hsql/restcomm.script | 7 ++ .../webapp/WEB-INF/scripts/mariadb/init.sql | 11 +++ .../mariadb/sql/extensions-configuration.xml | 13 +++ .../WEB-INF/sql/extensions-configuration.xml | 7 +- .../dao/ExtensionsConfigurationDao.java | 3 + .../MybatisExtensionsConfigurationDao.java | 25 ++++++ .../extension/api/ExtensionRequest.java | 27 ++++++ .../extension/api/ExtensionResponse.java | 2 +- .../api/MessageExtensionResponse.java | 3 + .../extension/api/NodeExtensionResponse.java | 3 + .../api/SessionExtensionResponse.java | 11 +++ .../api/SystemExtensionResponse.java | 3 + .../api/TransactionExtensionResponse.java | 4 + restcomm/restcomm.sms.api/pom.xml | 6 +- .../connect/sms/api/SmsSessionRequest.java | 18 +++- restcomm/restcomm.sms/pom.xml | 5 ++ .../org/restcomm/connect/sms/SmsService.java | 85 ++++++++++++++++--- .../org/restcomm/connect/sms/SmsSession.java | 36 ++++++-- .../sms/smpp/SmppInboundMessageEntity.java | 13 ++- .../connect/sms/smpp/SmppMessageHandler.java | 26 ++++-- .../sms/smpp/SmppOutboundMessageEntity.java | 14 +++ 23 files changed, 299 insertions(+), 39 deletions(-) create mode 100755 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java create mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/MessageExtensionResponse.java create mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/NodeExtensionResponse.java create mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SessionExtensionResponse.java create mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SystemExtensionResponse.java create mode 100644 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/TransactionExtensionResponse.java diff --git a/restcomm/restcomm.application/pom.xml b/restcomm/restcomm.application/pom.xml index 61c1fa756f..ba55d17df3 100644 --- a/restcomm/restcomm.application/pom.xml +++ b/restcomm/restcomm.application/pom.xml @@ -272,7 +272,11 @@ org.hsqldb hsqldb - + + org.apache.maven + maven-artifact + 3.1.0 + diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml index 358d6c5b80..c922f3fd71 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml @@ -11,11 +11,9 @@ MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> - + \ No newline at end of file diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script b/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script index fa4718a037..2873a3b004 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script @@ -21,12 +21,15 @@ CREATE MEMORY TABLE "restcomm_gateways"("sid" VARCHAR(34) NOT NULL PRIMARY KEY," CREATE MEMORY TABLE "restcomm_media_servers" ( "ms_id" INT GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL, "local_ip" VARCHAR(34) NOT NULL, "local_port" INT NOT NULL, "remote_ip" VARCHAR(34) NOT NULL UNIQUE, "remote_port" INT NOT NULL, "compatibility" VARCHAR(34) DEFAULT 'rms', "response_timeout" VARCHAR(34), "external_address" VARCHAR(34)) CREATE MEMORY TABLE "restcomm_media_resource_broker_entity" ("conference_sid" VARCHAR(34) NOT NULL, "slave_ms_id" VARCHAR(34) NOT NULL, "slave_ms_bridge_ep_id" VARCHAR(34),"slave_ms_cnf_ep_id" VARCHAR(34),"is_bridged_together" BOOLEAN DEFAULT FALSE,PRIMARY KEY ("conference_sid" , "slave_ms_id")) CREATE MEMORY TABLE PUBLIC."restcomm_extensions_configuration"("sid" VARCHAR(34) NOT NULL PRIMARY KEY,"extension" VARCHAR(255) NOT NULL,"configuration_data" VARCHAR(16777216),"configuration_type" VARCHAR(255) NOT NULL,"date_created" TIMESTAMP NOT NULL,"date_updated" TIMESTAMP, "enabled" BOOLEAN DEFAULT TRUE NOT NULL) +CREATE MEMORY TABLE PUBLIC."restcomm_accounts_extensions" ("account_sid" VARCHAR(34) NOT NULL, "extension_sid" VARCHAR(34) NOT NULL, PRIMARY KEY("account_sid", "extension_sid"), "configuration_data" VARCHAR(16777216)) CREATE MEMORY TABLE "restcomm_geolocation"("sid" VARCHAR(34) NOT NULL PRIMARY KEY, "date_created" DATETIME NOT NULL, "date_updated" DATETIME NOT NULL, "date_executed" DATETIME NOT NULL, "account_sid" VARCHAR(34) NOT NULL, "source" VARCHAR(30), "device_identifier" VARCHAR(30) NOT NULL, "geolocation_type" VARCHAR(15) NOT NULL, "response_status" VARCHAR(30), "cell_id" VARCHAR(10), "location_area_code" VARCHAR(10), "mobile_country_code" INTEGER, "mobile_network_code" VARCHAR(3), "network_entity_address" BIGINT, "age_of_location_info" INTEGER, "device_latitude" VARCHAR(15), "device_longitude" VARCHAR(15), "accuracy" BIGINT, "physical_address" VARCHAR(50), "internet_address" VARCHAR(50), "formatted_address" VARCHAR(200), "location_timestamp" DATETIME, "event_geofence_latitude" VARCHAR(15), "event_geofence_longitude" VARCHAR(15), "radius" BIGINT, "geolocation_positioning_type" VARCHAR(15), "last_geolocation_response" VARCHAR(10), "cause" VARCHAR(150), "api_version" VARCHAR(10) NOT NULL, "uri" LONGVARCHAR NOT NULL) CREATE USER SA PASSWORD "" GRANT DBA TO SA SET WRITE_DELAY 10 SET SCHEMA PUBLIC INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2acf','2012-04-24 00:00:00.000000000','2012-04-24 00:00:00.000000000','administrator@company.com','Default Administrator Account',NULL,'Full','uninitialized','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf') +INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2acg','2012-04-24 00:00:00.000000000','2012-04-24 00:00:00.000000000','second@company.com','Second Administrator Account',NULL,'Full','uninitialized','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acg') +INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2ach','2012-04-24 00:00:00.000000000','2012-04-24 00:00:00.000000000','third@company.com','Third Administrator Account',NULL,'Full','uninitialized','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2ach') INSERT INTO "restcomm_applications" VALUES('AP73926e7113fa4d95981aa96b76eca854','2015-09-23 06:56:04.108000','2015-09-23 06:56:04.108000','rvdCollectVerbDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP73926e7113fa4d95981aa96b76eca854','/restcomm-rvd/services/apps/AP73926e7113fa4d95981aa96b76eca854/controller','voice') INSERT INTO "restcomm_applications" VALUES('AP81cf45088cba4abcac1261385916d582','2015-09-23 06:56:17.977000','2015-09-23 06:56:17.977000','rvdESDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP81cf45088cba4abcac1261385916d582','/restcomm-rvd/services/apps/AP81cf45088cba4abcac1261385916d582/controller','voice') INSERT INTO "restcomm_applications" VALUES('APb70c33bf0b6748f09eaec97030af36f3','2015-09-23 06:56:26.120000','2015-09-23 06:56:26.120000','rvdSayVerbDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/APb70c33bf0b6748f09eaec97030af36f3','/restcomm-rvd/services/apps/APb70c33bf0b6748f09eaec97030af36f3/controller','voice') @@ -42,3 +45,7 @@ INSERT INTO "restcomm_incoming_phone_numbers" VALUES('PN46678e5b01d44973bf184f65 INSERT INTO "restcomm_incoming_phone_numbers" VALUES('PNb43ed9e641364277b6432547ff1109e9','2014-02-17 22:37:19.392000000','2014-02-17 22:37:19.392000000','RVD external services app, customer ID 1 or 2 ','ACae6e420f425248d6a26948c17a9e2acf','+1241','2012-04-24',FALSE,NULL,'POST',NULL,'POST',NULL,'POST','AP81cf45088cba4abcac1261385916d582',NULL,'POST',NULL,'POST',NULL,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/IncomingPhoneNumbers/PNb43ed9e641364277b6432547ff1109e9',NULL,NULL,NULL,NULL, TRUE,'0.0', NULL, NULL) INSERT INTO "restcomm_clients" VALUES('CLa2b99142e111427fbb489c3de357f60a','2013-11-04 12:52:44.144000000','2013-11-04 12:52:44.144000000','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24','alice','alice','1234',1,NULL,'POST',NULL,'POST',NULL,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Clients/CLa2b99142e111427fbb489c3de357f60a') INSERT INTO "restcomm_clients" VALUES('CL3003328d0de04ba68f38de85b732ed56','2013-11-04 16:33:39.248000000','2013-11-04 16:33:39.248000000','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24','bob','bob','1234',1,NULL,'POST',NULL,'POST',NULL,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Clients/CL3003328d0de04ba68f38de85b732ed56') +INSERT INTO "restcomm_accounts_extensions" VALUES('ACae6e420f425248d6a26948c17a9e2acf','EX00000000000000000000000000000005','{"outbound-sms": [{"destination_network_id": "1000"}]}') +INSERT INTO "restcomm_accounts_extensions" VALUES('ACae6e420f425248d6a26948c17a9e2acg','EX00000000000000000000000000000005','{"outbound-sms": [{"destination_network_id": "2000"}]}') +INSERT INTO "restcomm_accounts_extensions" VALUES('ACae6e420f425248d6a26948c17a9e2ach','EX00000000000000000000000000000005','{"outbound-sms": [{"destination_network_id": "3000"}]}') +INSERT INTO "restcomm_extensions_configuration" VALUES('EX00000000000000000000000000000005','multi_provider','{"outbound-sms": [{"destination_network_id": "1"}]}','JSON','2012-04-24 00:00:00.000000','2012-04-24 00:00:00.000000',TRUE) diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql index c3cd1c4ce2..a092a2c3de 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql @@ -381,6 +381,13 @@ date_updated DATETIME, enabled BOOLEAN NOT NULL DEFAULT TRUE ); +CREATE TABLE restcomm_accounts_extensions ( +account_sid VARCHAR(34) NOT NULL, +extension_sid VARCHAR(34) NOT NULL, +configuration_data LONGTEXT NOT NULL, +PRIMARY KEY (account_sid, extension_sid) +); + INSERT INTO restcomm_accounts VALUES ( "ACae6e420f425248d6a26948c17a9e2acf", Date("2012-04-24"), @@ -394,6 +401,10 @@ null, "Administrator", "/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf"); +INSERT INTO restcomm_accounts_extensions VALUES("ACae6e420f425248d6a26948c17a9e2acf","EX00000000000000000000000000000005","{\"outbound-sms\": [{\"destination_network_id\": \"1000\"}]}") +INSERT INTO restcomm_accounts_extensions VALUES("ACae6e420f425248d6a26948c17a9e2acg","EX00000000000000000000000000000005","{\"outbound-sms\": [{\"destination_network_id\": \"2000\"}]}") +INSERT INTO restcomm_accounts_extensions VALUES("ACae6e420f425248d6a26948c17a9e2ach","EX00000000000000000000000000000005","{\"outbound-sms\": [{\"destination_network_id\": \"3000\"}]}") +INSERT INTO restcomm_extensions_configuration VALUES("EX00000000000000000000000000000005","multi_provider","{\"outbound-sms\": [{\"destination_network_id\": \"1\"}]}","JSON","2012-04-24 00:00:00.000000","2012-04-24 00:00:00.000000",TRUE, TRUE); /* Create demo Applications */ INSERT INTO restcomm_applications VALUES('AP73926e7113fa4d95981aa96b76eca854','2015-09-23 06:56:04.108000','2015-09-23 06:56:04.108000','rvdCollectVerbDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP73926e7113fa4d95981aa96b76eca854','/restcomm-rvd/services/apps/AP73926e7113fa4d95981aa96b76eca854/controller','voice'); INSERT INTO restcomm_applications VALUES('AP81cf45088cba4abcac1261385916d582','2015-09-23 06:56:17.977000','2015-09-23 06:56:17.977000','rvdESDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP81cf45088cba4abcac1261385916d582','/restcomm-rvd/services/apps/AP81cf45088cba4abcac1261385916d582/controller','voice'); diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml index cf1ed3a48f..ccd2cc18a5 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml @@ -61,4 +61,17 @@ + + + + diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml index 552915e6db..5618d516ee 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml @@ -67,4 +67,9 @@ - \ No newline at end of file + + + diff --git a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java index 4c5ea677bb..ddad232753 100644 --- a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java +++ b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java @@ -97,4 +97,7 @@ public interface ExtensionsConfigurationDao { * @return */ boolean validate(ExtensionConfiguration extensionConfiguration); + + /**/ + ExtensionConfiguration getAccountExtensionConfiguration(String accountSid, String extensionSid); } diff --git a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java index 4e3a58918d..867cf70cb1 100644 --- a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java +++ b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java @@ -259,6 +259,13 @@ private ExtensionConfiguration toExtensionConfiguration(final Map map) { + final Sid sid = new Sid((String)map.get("extension")); + final String extension = (String) map.get("extension"); + final Object confData = map.get("configuration_data"); + return new ExtensionConfiguration(sid, extension, true, confData, null, null, null); + } + private Map toMap(final ExtensionConfiguration extensionConfiguration) { final Map map = new HashMap(); map.put("sid", DaoUtils.writeSid(extensionConfiguration.getSid())); @@ -276,4 +283,22 @@ private Map toMap(final ExtensionConfiguration extensionConfigur map.put("enabled", extensionConfiguration.isEnabled()); return map; } + + @Override + public ExtensionConfiguration getAccountExtensionConfiguration(String accountSid, String extensionSid) { + final SqlSession session = sessions.openSession(); + ExtensionConfiguration extensionConfiguration = null; + try { + Map params = new HashMap(); + params.put("account_sid", accountSid.toString()); + params.put("extension_sid", extensionSid.toString()); + final Map result = session.selectOne(namespace + "getAccountExtensionConfiguration", params); + if (result != null) { + extensionConfiguration = toAccountsExtensionConfiguration(result); + } + return extensionConfiguration; + } finally { + session.close(); + } + } } 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 new file mode 100755 index 0000000000..ce2f08a46d --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionRequest.java @@ -0,0 +1,27 @@ +package org.restcomm.connect.extension.api; +import org.apache.commons.configuration.Configuration; + +public class ExtensionRequest { + private Object payload; + private Configuration configuration; + + public ExtensionRequest() {} + + public Object getObject() { + return payload; + } + + public void setObject(Object object) { + this.payload = object; + } + + public void setConfiguration(Configuration configuration) { + // TODO Auto-generated method stub + this.configuration = configuration; + } + public Configuration getConfiguration() { + // TODO Auto-generated method stub + return this.configuration; + } + +} diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionResponse.java index 065e2aff1f..2bbf8c71b6 100644 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionResponse.java +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/ExtensionResponse.java @@ -26,7 +26,7 @@ */ public class ExtensionResponse { private Object object; - private boolean allowed; + private boolean allowed = true; public ExtensionResponse() {} 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 new file mode 100644 index 0000000000..da18075e3d --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/MessageExtensionResponse.java @@ -0,0 +1,3 @@ +package org.restcomm.connect.extension.api; +public class MessageExtensionResponse extends ExtensionResponse { +} 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 new file mode 100644 index 0000000000..0b883aebc2 --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/NodeExtensionResponse.java @@ -0,0 +1,3 @@ +package org.restcomm.connect.extension.api; +public class NodeExtensionResponse extends ExtensionResponse { +} 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 new file mode 100644 index 0000000000..45aa2f963a --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SessionExtensionResponse.java @@ -0,0 +1,11 @@ +package org.restcomm.connect.extension.api; +import org.apache.commons.configuration.Configuration; +public class SessionExtensionResponse extends ExtensionResponse { + + public void setConfiguration(Configuration configuration){ + super.setObject(configuration); + } + 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 new file mode 100644 index 0000000000..2784746659 --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/SystemExtensionResponse.java @@ -0,0 +1,3 @@ +package org.restcomm.connect.extension.api; +public class SystemExtensionResponse extends ExtensionResponse { +} 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 new file mode 100644 index 0000000000..f073f5032b --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/TransactionExtensionResponse.java @@ -0,0 +1,4 @@ +package org.restcomm.connect.extension.api; +public class TransactionExtensionResponse extends ExtensionResponse { + +} \ No newline at end of file diff --git a/restcomm/restcomm.sms.api/pom.xml b/restcomm/restcomm.sms.api/pom.xml index d086288090..b4c4d6f120 100644 --- a/restcomm/restcomm.sms.api/pom.xml +++ b/restcomm/restcomm.sms.api/pom.xml @@ -8,7 +8,11 @@ restcomm-connect.sms.api - + + org.restcomm.smpp + smpp-extensions + 1.0.13 + org.restcomm restcomm-connect.commons diff --git a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java index e6d722a914..aeca0196a3 100644 --- a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java +++ b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java @@ -22,7 +22,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.servlet.sip.SipServletRequest; - +import org.restcomm.smpp.parameter.TlvSet; import org.restcomm.connect.commons.annotations.concurrency.Immutable; /** @@ -36,6 +36,7 @@ public final class SmsSessionRequest { private final Encoding encoding; private final SipServletRequest origRequest; private final ConcurrentHashMap customHeaders; + private final TlvSet tlvSet; public enum Encoding { UCS_2("UCS-2"), @@ -55,6 +56,9 @@ public String toString() { //TODO need to check which is using the SmsSessionRequest and modify accordingly to include or not the custom headers public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders) { + this(from, to, body, encoding, origRequest, customHeaders, null); + } + public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders, TlvSet tlvSet) { super(); this.from = from; this.to = to; @@ -62,14 +66,20 @@ public SmsSessionRequest(final String from, final String to, final String body, this.body = body; this.customHeaders = customHeaders; this.encoding = encoding; + this.tlvSet = tlvSet; + } public SmsSessionRequest(final String from, final String to, final String body, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders) { this(from, to, body, Encoding.GSM, origRequest, customHeaders); } + public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final ConcurrentHashMap customHeaders, TlvSet tlvSet) { + this(from, to, body, encoding, null, customHeaders, tlvSet); + } + public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final ConcurrentHashMap customHeaders) { - this(from, to, body, encoding, null, customHeaders); + this(from, to, body, encoding, null, customHeaders, null); } public SmsSessionRequest(final String from, final String to, final String body, final ConcurrentHashMap customHeaders) { @@ -92,6 +102,10 @@ public Encoding encoding() { return encoding; } + public TlvSet getTlvSet() { + return tlvSet; + } + public SipServletRequest getOrigRequest() { return origRequest; } diff --git a/restcomm/restcomm.sms/pom.xml b/restcomm/restcomm.sms/pom.xml index b4778f7ce3..709d8ced9d 100644 --- a/restcomm/restcomm.sms/pom.xml +++ b/restcomm/restcomm.sms/pom.xml @@ -17,6 +17,11 @@ + + org.restcomm.smpp + smpp-extensions + 1.0.13 + log4j log4j 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 dc6dc33088..ae086b4bfe 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 @@ -48,6 +48,12 @@ 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.SystemExtensionResponse; +import org.restcomm.connect.extension.api.NodeExtensionResponse; +import org.restcomm.connect.extension.api.TransactionExtensionResponse; +import org.restcomm.connect.extension.api.SessionExtensionResponse; +import org.restcomm.connect.extension.api.MessageExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; import org.restcomm.connect.extension.api.RestcommExtensionException; import org.restcomm.connect.extension.api.RestcommExtensionGeneric; @@ -60,10 +66,13 @@ 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.sms.api.SmsSessionRequest.Encoding; 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; import javax.servlet.ServletContext; import javax.servlet.sip.SipApplicationSession; @@ -72,6 +81,7 @@ import javax.servlet.sip.SipServletRequest; import javax.servlet.sip.SipServletResponse; import javax.servlet.sip.SipURI; + import java.io.IOException; import java.math.BigDecimal; import java.net.URI; @@ -208,8 +218,8 @@ private void message(final Object message) throws IOException { final SipServletResponse trying = request.createResponse(SipServletResponse.SC_TRYING); trying.send(); - - ActorRef session = session(); + //TODO:do extensions check here too? + ActorRef session = session(this.configuration); // Create an SMS detail record. final Sid sid = Sid.generate(Sid.Type.SMS_MESSAGE); final SmsMessage.Builder builder = SmsMessage.builder(); @@ -236,7 +246,8 @@ private void message(final Object message) throws IOException { // Store the sms record in the sms session. session.tell(new SmsSessionAttribute("record", record), self()); // Send the SMS. - final SmsSessionRequest sms = new SmsSessionRequest(client.getLogin(), toUser, new String(request.getRawContent()),request, null); + TlvSet tlvSet = new TlvSet(); + final SmsSessionRequest sms = new SmsSessionRequest(client.getLogin(), toUser, new String(request.getRawContent()), Encoding.GSM, request, null, tlvSet); monitoringService.tell(new TextMessage(((SipURI)request.getFrom().getURI()).getUser(), ((SipURI)request.getTo().getURI()).getUser(), TextMessage.SmsState.INBOUND_TO_PROXY_OUT), self); session.tell(sms, self()); } @@ -312,7 +323,8 @@ private boolean redirectToHostedSmsApp(final ActorRef self, final SipServletRequ } interpreter = builder.build(); } - final ActorRef session = session(); + //TODO:do extensions check here too? + final ActorRef session = session(this.configuration); session.tell(request, self); final StartInterpreter start = new StartInterpreter(session); interpreter.tell(start, self); @@ -325,23 +337,59 @@ private boolean redirectToHostedSmsApp(final ActorRef self, final SipServletRequ return isFoundHostedApp; } - private boolean executePreOutboundAction(final Object message) { + private ExtensionResponse executePreOutboundAction(final Object er) { + //TODO: should allow multiple types of responses perhaps + ExtensionResponse response = new ExtensionResponse(); if (extensions != null && extensions.size() > 0) { + for (RestcommExtensionGeneric extension : extensions) { + logger.info( "isEnabled="+extension.isEnabled()); if (extension.isEnabled()) { - ExtensionResponse response = extension.preOutboundAction(message); - if (!response.isAllowed()) - return false; + response = extension.preOutboundAction(er); + //fail fast + if (!response.isAllowed()){ + break; + } } } } - return true; + //return object + return response; } private boolean executePostOutboundAction(final Object message) { return true; } + //FIXME: make into static util? + //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 + private Object handleExtensionResponse(ExtensionResponse response){ + //check type of extension + //FIXME: hack to default + Object object = this.configuration;//new Object(); + 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; + } + @Override public void onReceive(final Object message) throws Exception { final UntypedActorContext context = getContext(); @@ -349,8 +397,19 @@ public void onReceive(final Object message) throws Exception { final ActorRef self = self(); final ActorRef sender = sender(); if (CreateSmsSession.class.equals(klass)) { - if (executePreOutboundAction(message)) { - final ActorRef session = session(); + //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 = executePreOutboundAction(er); + if (extensionResponse.isAllowed()) { + //pass in response object to sms session + Object obj = handleExtensionResponse(extensionResponse); + //FIXME:not all instances of extensions should modify + //a session configuration, we should do checks here + final ActorRef session = session((Configuration)obj); final SmsServiceResponse response = new SmsServiceResponse(session); sender.tell(response, self); } else { @@ -418,13 +477,13 @@ private SipURI outboundInterface() { return result; } - private ActorRef session() { + private ActorRef session(final Configuration p_configuration) { final Props props = new Props(new UntypedActorFactory() { private static final long serialVersionUID = 1L; @Override public UntypedActor create() throws Exception { - return new SmsSession(configuration, sipFactory, outboundInterface(), storage, monitoringService, servletContext); + return new SmsSession(p_configuration, sipFactory, outboundInterface(), storage, monitoringService, servletContext); } }); return system.actorOf(props); diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java index dc1a9847b2..4f0b90c0f0 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java @@ -25,6 +25,9 @@ import akka.event.LoggingAdapter; import com.cloudhopper.commons.charset.Charset; import com.cloudhopper.commons.charset.CharsetUtil; +import com.cloudhopper.commons.util.ByteArrayUtil; +import com.cloudhopper.smpp.tlv.Tlv; +import com.cloudhopper.smpp.SmppConstants; import com.google.common.collect.ImmutableMap; import org.apache.commons.configuration.Configuration; import org.restcomm.connect.sms.api.GetLastSmsRequest; @@ -32,6 +35,7 @@ import org.restcomm.connect.sms.api.SmsSessionInfo; import org.restcomm.connect.sms.api.SmsSessionRequest; import org.restcomm.connect.sms.api.SmsSessionResponse; +import org.restcomm.connect.sms.api.SmsSessionRequest.Encoding; import org.restcomm.connect.dao.ClientsDao; import org.restcomm.connect.dao.DaoManager; import org.restcomm.connect.dao.RegistrationsDao; @@ -45,6 +49,7 @@ import org.restcomm.connect.sms.smpp.SmppMessageHandler; import org.restcomm.connect.sms.smpp.SmppOutboundMessageEntity; import org.restcomm.connect.telephony.api.TextMessage; +import org.restcomm.smpp.parameter.TlvSet; import javax.servlet.ServletContext; import javax.servlet.sip.SipApplicationSession; @@ -61,6 +66,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; + /** * @author quintana.thomas@gmail.com (Thomas Quintana) */ @@ -78,6 +84,7 @@ public final class SmsSession extends UntypedActor { private ConcurrentHashMap customRequestHeaderMap = new ConcurrentHashMap(); // Map for custom headers from HTTP App Server (when creating outbound SIP MESSAGE) private ConcurrentHashMap customHttpHeaderMap; + private TlvSet tlvSet; private final DaoManager storage; @@ -113,6 +120,18 @@ public SmsSession(final Configuration configuration, final SipFactory factory, f this.externalIP = this.configuration.subset("runtime-settings").getString("external-ip"); if (externalIP == null || externalIP.isEmpty() || externalIP.equals("")) externalIP = defaultHost; + + this.tlvSet = new TlvSet(); + if(!this.configuration.subset("outbound-sms").isEmpty()) { + //FIXME: hardcoded to TAG_DEST_NETWORK_ID + try { + String valStr = this.configuration.subset("outbound-sms").getString("destination_network_id"); + //FIXME:fetch the tag value from the arbitrary key + this.tlvSet.addOptionalParameter(new Tlv(SmppConstants.TAG_DEST_NETWORK_ID,ByteArrayUtil.toByteArray(Integer.parseInt(valStr)))); + } catch (Exception e) { + // TODO: handle exception + } + } } private void inbound(final Object message) throws IOException { @@ -135,7 +154,8 @@ private void inbound(final Object message) throws IOException { } } // Store the last sms event. - last = new SmsSessionRequest(from, to, body, customRequestHeaderMap); + + last = new SmsSessionRequest(from, to, body, Encoding.GSM, customRequestHeaderMap, this.tlvSet); if (initial == null) { initial = last; } @@ -154,7 +174,8 @@ private void inbound(final Object message) throws IOException { encoding = SmsSessionRequest.Encoding.GSM; } // Store the last sms event. - last = new SmsSessionRequest (request.getSmppFrom(), request.getSmppTo(), request.getSmppContent(), encoding, null); + + last = new SmsSessionRequest (request.getSmppFrom(), request.getSmppTo(), request.getSmppContent(), encoding, null, request.getTlvSet()); if (initial == null) { initial = last; } @@ -275,7 +296,7 @@ private void outbound(final Object message) { if(logger.isInfoEnabled()) { logger.info("Destination is not a local registered client, therefore, sending through SMPP to: " + last.to() ); } - if (sendUsingSmpp(last.from(), last.to(), last.body(), charset)) + if (sendUsingSmpp(last.from(), last.to(), last.body(), tlvSet, charset)) return; } @@ -332,16 +353,19 @@ private void outbound(final Object message) { } // Log the exception. logger.error(exception.getMessage(), exception); - }} - + } + } private boolean sendUsingSmpp(String from, String to, String body, Charset encoding) { + return sendUsingSmpp(from, to, body, null, encoding); + } + private boolean sendUsingSmpp(String from, String to, String body, TlvSet tlvSet, Charset encoding) { if ((SmppClientOpsThread.getSmppSession() != null && SmppClientOpsThread.getSmppSession().isBound()) && smppMessageHandler != null) { if(logger.isInfoEnabled()) { logger.info("SMPP session is available and connected, outbound message will be forwarded to : " + to ); logger.info("Encoding: " + encoding ); } try { - final SmppOutboundMessageEntity sms = new SmppOutboundMessageEntity(to, from, body, encoding); + final SmppOutboundMessageEntity sms = new SmppOutboundMessageEntity(to, from, body, encoding, tlvSet); smppMessageHandler.tell(sms, null); }catch (final Exception exception) { // Log the exception. diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppInboundMessageEntity.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppInboundMessageEntity.java index af640df549..00efb68030 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppInboundMessageEntity.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppInboundMessageEntity.java @@ -1,5 +1,7 @@ package org.restcomm.connect.sms.smpp; +import org.restcomm.smpp.parameter.TlvSet; + import com.cloudhopper.commons.charset.Charset; public class SmppInboundMessageEntity { @@ -9,19 +11,24 @@ public class SmppInboundMessageEntity { private final String smppFrom; private final String smppContent; private final Charset smppEncoding; - - + private final TlvSet tlvSet; public SmppInboundMessageEntity(String smppTo, String smppFrom, String smppContent, Charset smppEncoding){ + this(smppTo, smppFrom, smppContent, smppEncoding, null); + } + public SmppInboundMessageEntity(String smppTo, String smppFrom, String smppContent, Charset smppEncoding, TlvSet tlvSet){ this.smppTo = smppTo; this.smppFrom = smppFrom; this.smppContent = smppContent; this.smppEncoding = smppEncoding; + this.tlvSet = tlvSet; } - + public final TlvSet getTlvSet(){ + return tlvSet; + } public final String getSmppTo(){ return smppTo; 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 09a775ce98..a91116faf8 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 @@ -16,6 +16,7 @@ import com.cloudhopper.smpp.type.SmppInvalidArgumentException; import com.cloudhopper.smpp.type.SmppTimeoutException; 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; @@ -32,6 +33,7 @@ import org.restcomm.connect.sms.api.CreateSmsSession; import org.restcomm.connect.sms.api.DestroySmsSession; import org.restcomm.connect.sms.api.SmsServiceResponse; +import org.restcomm.smpp.parameter.TlvSet; import javax.servlet.ServletContext; import javax.servlet.sip.SipFactory; @@ -40,6 +42,7 @@ import java.io.IOException; import java.net.URI; import java.util.List; +import java.util.Collection; public class SmppMessageHandler extends UntypedActor { @@ -75,7 +78,9 @@ public void onReceive(Object message) throws Exception { } outbound((SmppOutboundMessageEntity) message); } else if (message instanceof CreateSmsSession) { - final ActorRef session = session(); + //Extension + Configuration cfg = this.configuration; + final ActorRef session = session(cfg); final SmsServiceResponse response = new SmsServiceResponse(session); sender.tell(response, self); }else if (message instanceof DestroySmsSession) { @@ -153,8 +158,9 @@ private boolean redirectToHostedSmsApp(final ActorRef self, final SmppInboundMes builder.setFallbackMethod(number.getSmsFallbackMethod()); } interpreter = builder.build(); - - final ActorRef session = session(); + Configuration cfg = this.configuration; + //Extension + final ActorRef session = session(cfg); session.tell(request, self); final StartInterpreter start = new StartInterpreter(session); interpreter.tell(start, self); @@ -181,13 +187,13 @@ private SipURI outboundInterface() { return result; } - private ActorRef session() { + private ActorRef session(final Configuration p_configuration) { final Props props = new Props(new UntypedActorFactory() { private static final long serialVersionUID = 1L; @Override public UntypedActor create() throws Exception { - return new SmsSession(configuration, sipFactory, outboundInterface(), storage, monitoringService, servletContext); + return new SmsSession(p_configuration, sipFactory, outboundInterface(), storage, monitoringService, servletContext); } }); return system.actorOf(props); @@ -214,6 +220,16 @@ public void outbound(SmppOutboundMessageEntity request) throws SmppInvalidArgume } submit0.setShortMessage(textBytes); + + TlvSet tlvSet = request.getTlvSet(); + + if(tlvSet!=null) { + for (Tlv tlv : (Collection)tlvSet.getOptionalParameters()) { + submit0.setOptionalParameter(tlv); + } + }else{ + logger.info("tlvSet is null"); + } try { if(logger.isInfoEnabled()) { logger.info("Sending SubmitSM for " + request); diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppOutboundMessageEntity.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppOutboundMessageEntity.java index 3c2f4942b0..e70d1fdff6 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppOutboundMessageEntity.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/smpp/SmppOutboundMessageEntity.java @@ -1,5 +1,7 @@ package org.restcomm.connect.sms.smpp; +import org.restcomm.smpp.parameter.TlvSet; + import com.cloudhopper.commons.charset.Charset; public class SmppOutboundMessageEntity { @@ -9,15 +11,23 @@ public class SmppOutboundMessageEntity { private final String smppFrom; private final String smppContent; private final Charset smppEncoding; + private final TlvSet tlvSet; public SmppOutboundMessageEntity(String smppTo, String smppFrom, String smppContent, Charset smppEncoding){ + this(smppTo, smppFrom, smppContent, smppEncoding, null); + } + public SmppOutboundMessageEntity(String smppTo, String smppFrom, String smppContent, Charset smppEncoding, TlvSet tlvSet){ this.smppTo = smppTo; this.smppFrom = smppFrom; this.smppContent = smppContent; this.smppEncoding = smppEncoding; + this.tlvSet = tlvSet; + } + public final TlvSet getTlvSet(){ + return tlvSet; } @@ -48,6 +58,10 @@ public String toString() { .append(smppContent) .append(",Encoding=") .append(smppEncoding); + if(tlvSet!=null){ + builder.append(",TlvSet=") + .append(tlvSet.toString()); + } return super.toString(); } From a023fc50bccf2e6132e45ba26e1287a61202e0d6 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Mon, 24 Apr 2017 04:55:46 +0800 Subject: [PATCH 2/5] Issue #1981: Add extensions check to SMS inbound hosted app --- .../connect/sms/smpp/SmppMessageHandler.java | 85 ++++++++++++++++++- 1 file changed, 81 insertions(+), 4 deletions(-) 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 a91116faf8..c888747aea 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 @@ -27,6 +27,17 @@ 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.ExtensionType; +import org.restcomm.connect.extension.api.MessageExtensionResponse; +import org.restcomm.connect.extension.api.NodeExtensionResponse; +import org.restcomm.connect.extension.api.RestcommExtensionException; +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.restcomm.connect.extension.controller.ExtensionController; import org.restcomm.connect.interpreter.StartInterpreter; import org.restcomm.connect.monitoringservice.MonitoringService; import org.restcomm.connect.sms.SmsSession; @@ -53,6 +64,8 @@ public class SmppMessageHandler extends UntypedActor { private final Configuration configuration; private final SipFactory sipFactory; private final ActorRef monitoringService; + //List of extensions for SmsService + List extensions; public SmppMessageHandler(final ServletContext servletContext) { this.servletContext = servletContext; @@ -60,6 +73,11 @@ public SmppMessageHandler(final ServletContext servletContext) { this.configuration = (Configuration) servletContext.getAttribute(Configuration.class.getName()); this.sipFactory = (SipFactory) servletContext.getAttribute(SipFactory.class.getName()); this.monitoringService = (ActorRef) servletContext.getAttribute(MonitoringService.class.getName()); + //FIXME:SmsService or SmppMessageHandler + extensions = ExtensionController.getInstance().getExtensions(ExtensionType.SmsService); + if (logger.isInfoEnabled()) { + logger.info("SmsService extensions: "+(extensions != null ? extensions.size() : "0")); + } } @Override @@ -79,10 +97,21 @@ public void onReceive(Object message) throws Exception { outbound((SmppOutboundMessageEntity) message); } else if (message instanceof CreateSmsSession) { //Extension - Configuration cfg = this.configuration; - final ActorRef session = session(cfg); - final SmsServiceResponse response = new SmsServiceResponse(session); - sender.tell(response, self); + ExtensionRequest er = new ExtensionRequest(); + er.setObject(message); + er.setConfiguration(this.configuration); + ExtensionResponse extensionResponse = executePreOutboundAction(er); + if (extensionResponse.isAllowed()) { + Object obj = handleExtensionResponse(extensionResponse); + //Configuration cfg = this.configuration; + final ActorRef session = session((Configuration)obj); + final SmsServiceResponse response = new SmsServiceResponse(session); + sender.tell(response, self); + } else { + final SmsServiceResponse response = new SmsServiceResponse(new RestcommExtensionException("Now allowed to create SmsSession")); + sender.tell(response, self()); + } + executePostOutboundAction(message); }else if (message instanceof DestroySmsSession) { final DestroySmsSession destroySmsSession = (DestroySmsSession) message; final ActorRef session = destroySmsSession.session(); @@ -90,6 +119,54 @@ public void onReceive(Object message) throws Exception { } } + private Object handleExtensionResponse(ExtensionResponse response) { + // TODO Auto-generated method stub + Object object = this.configuration;//new Object(); + 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; + } + + private ExtensionResponse executePreOutboundAction(final Object er) { + //TODO: should allow multiple types of responses perhaps + ExtensionResponse response = new ExtensionResponse(); + if (extensions != null && extensions.size() > 0) { + + for (RestcommExtensionGeneric extension : extensions) { + logger.info( "isEnabled="+extension.isEnabled()); + if (extension.isEnabled()) { + response = extension.preOutboundAction(er); + //fail fast + if (!response.isAllowed()){ + break; + } + } + } + } + //return object + return response; + } + + private boolean executePostOutboundAction(final Object message) { + return true; + } + private void inbound(final SmppInboundMessageEntity request ) throws IOException { final ActorRef self = self(); From bbef17c7a26ee9d4e8a4f78635ddea69c6d9c6b2 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 25 Apr 2017 20:54:24 +0800 Subject: [PATCH 3/5] Issue #1981: Modify Extensions REST API for acount specific configuration --- .../mariadb/sql/extensions-configuration.xml | 17 ++-- .../WEB-INF/sql/extensions-configuration.xml | 17 +++- .../dao/ExtensionsConfigurationDao.java | 9 +++ .../MybatisExtensionsConfigurationDao.java | 64 +++++++++++++++ .../http/ExtensionsConfigurationEndpoint.java | 81 +++++++++++++++---- .../ExtensionsConfigurationJsonEndpoint.java | 7 +- .../ExtensionsConfigurationXmlEndpoint.java | 7 +- 7 files changed, 178 insertions(+), 24 deletions(-) diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml index ccd2cc18a5..261c3e385b 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/sql/extensions-configuration.xml @@ -66,12 +66,19 @@ SELECT configuration_data, account_sid AS "sid", extension_sid AS "extension" FROM restcomm_accounts_extensions WHERE account_sid=#{account_sid} AND extension_sid=#{extension_sid}; - - + + + + DELETE FROM restcomm_accounts_extensions + WHERE account_sid=#{account_sid} AND extension_sid=#{extension_sid}; + diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml index 5618d516ee..b20ac5233b 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/sql/extensions-configuration.xml @@ -69,7 +69,22 @@ + + + INSERT INTO "restcomm_accounts_extensions" ("account_sid", "extension_sid", "configuration_data") + VALUES (#{account_sid}, #{extension_sid}, #{configuration_data}); + + + + UPDATE "restcomm_accounts_extensions" SET "configuration_data"=#{configuration_data} + WHERE "account_sid"=#{account_sid} AND "extension_sid"=#{extension_sid}; + + + + DELETE FROM "restcomm_accounts_extensions" + WHERE "account_sid"=#{account_sid} AND "extension_sid"=#{extension_sid}; + diff --git a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java index ddad232753..b6d9803063 100644 --- a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java +++ b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java @@ -100,4 +100,13 @@ public interface ExtensionsConfigurationDao { /**/ ExtensionConfiguration getAccountExtensionConfiguration(String accountSid, String extensionSid); + + /**/ + void addAccountExtensionConfiguration(ExtensionConfiguration extensionConfiguration, Sid accountSid) throws ConfigurationException; + + /**/ + void updateAccountExtensionConfiguration(ExtensionConfiguration extensionConfiguration, Sid accountSid) throws ConfigurationException; + + /**/ + void deleteAccountExtensionConfiguration(String accountSid, String extensionSid); } diff --git a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java index 867cf70cb1..e5dfb2f6ee 100644 --- a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java +++ b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/mybatis/MybatisExtensionsConfigurationDao.java @@ -301,4 +301,68 @@ public ExtensionConfiguration getAccountExtensionConfiguration(String accountSid session.close(); } } + + @Override + public void addAccountExtensionConfiguration(ExtensionConfiguration extensionConfiguration, Sid accountSid) throws ConfigurationException { + final SqlSession session = sessions.openSession(); + try { + if (extensionConfiguration != null && extensionConfiguration.getConfigurationData() != null) { + if (validate(extensionConfiguration)) { + final Map map = new HashMap(); + map.put("account_sid", DaoUtils.writeSid(accountSid)); + map.put("extension_sid", DaoUtils.writeSid(extensionConfiguration.getSid())); + + if (extensionConfiguration.getConfigurationData() != null) + map.put("configuration_data", extensionConfiguration.getConfigurationData()); + + session.insert(namespace + "addAccountExtensionConfiguration", map); + session.commit(); + } else { + throw new ConfigurationException("Exception trying to add new configuration, validation failed. configuration type: " + + extensionConfiguration.getConfigurationType()); + } + } + } finally { + session.close(); + } + } + + @Override + public void updateAccountExtensionConfiguration(ExtensionConfiguration extensionConfiguration, Sid accountSid) + throws ConfigurationException { + final SqlSession session = sessions.openSession(); + try { + if (extensionConfiguration != null && extensionConfiguration.getConfigurationData() != null) { + if (validate(extensionConfiguration)) { + final Map map = new HashMap(); + map.put("account_sid", DaoUtils.writeSid(accountSid)); + map.put("extension_sid", DaoUtils.writeSid(extensionConfiguration.getSid())); + + if (extensionConfiguration.getConfigurationData() != null) + map.put("configuration_data", extensionConfiguration.getConfigurationData()); + session.update(namespace + "updateAccountExtensionConfiguration", map); + } else { + throw new ConfigurationException("Exception trying to update configuration, validation failed. configuration type: " + + extensionConfiguration.getConfigurationType()); + } + } + session.commit(); + } finally { + session.close(); + } + } + + @Override + public void deleteAccountExtensionConfiguration(String accountSid, String extensionSid) { + final SqlSession session = sessions.openSession(); + try { + Map params = new HashMap(); + params.put("account_sid", accountSid.toString()); + params.put("extension_sid", extensionSid.toString()); + session.delete(namespace + "deleteAccountExtensionConfiguration", params); + session.commit(); + } finally { + session.close(); + } + } } diff --git a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java index ba54e6713b..856877f42e 100644 --- a/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java +++ b/restcomm/restcomm.http/src/main/java/org/restcomm/connect/http/ExtensionsConfigurationEndpoint.java @@ -22,6 +22,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.thoughtworks.xstream.XStream; + import org.apache.commons.configuration.Configuration; import org.joda.time.DateTime; import org.restcomm.connect.commons.dao.Sid; @@ -87,23 +88,44 @@ void init() { * @param responseType * @return */ - protected Response getConfiguration(final String extensionId, final MediaType responseType) { + protected Response getConfiguration(final String extensionId, final Sid accountSid, final MediaType responseType) { //Parameter "extensionId" could be the extension Sid or extension name. if (!isSuperAdmin()) { throw new InsufficientPermission(); } ExtensionConfiguration extensionConfiguration = null; + ExtensionConfiguration extensionAccountConfiguration = null; + Sid extensionSid = null; + String extensionName = null; + + if(Sid.pattern.matcher(extensionId).matches()){ + extensionSid = new Sid(extensionId); + } else { + extensionName = extensionId; + } if (Sid.pattern.matcher(extensionId).matches()) { try { - extensionConfiguration = extensionsConfigurationDao.getConfigurationBySid(new Sid(extensionId)); + extensionConfiguration = extensionsConfigurationDao.getConfigurationBySid(extensionSid); } catch (Exception e) { return status(NOT_FOUND).build(); } } else { try { - extensionConfiguration = extensionsConfigurationDao.getConfigurationByName(extensionId); + extensionConfiguration = extensionsConfigurationDao.getConfigurationByName(extensionName); + } catch (Exception e) { + return status(NOT_FOUND).build(); + } + } + + if (accountSid!=null) { + if(extensionSid == null ){ + extensionSid = extensionConfiguration.getSid(); + } + try { + extensionAccountConfiguration = extensionsConfigurationDao.getAccountExtensionConfiguration(accountSid.toString(), extensionSid.toString()); + extensionConfiguration.setConfigurationData(extensionAccountConfiguration.getConfigurationData(), extensionAccountConfiguration.getConfigurationType()); } catch (Exception e) { return status(NOT_FOUND).build(); } @@ -116,7 +138,7 @@ protected Response getConfiguration(final String extensionId, final MediaType re final RestCommResponse response = new RestCommResponse(extensionConfiguration); return ok(xstream.toXML(response), APPLICATION_XML).build(); } else if (APPLICATION_JSON_TYPE == responseType) { - return ok(gson.toJson(extensionConfiguration), APPLICATION_JSON).build(); + return ok(gson.toJson(extensionConfiguration.getConfigurationData()), APPLICATION_JSON).build(); } else { return null; } @@ -146,6 +168,7 @@ private ExtensionConfiguration createFrom(final MultivaluedMap d DateTime dateCreated = DateTime.now(); DateTime dateUpdated = DateTime.now(); ExtensionConfiguration extensionConfiguration = new ExtensionConfiguration(sid, extension, enabled, configurationData, configurationType, dateCreated, dateUpdated); + return extensionConfiguration; } @@ -154,17 +177,37 @@ protected Response postConfiguration(final MultivaluedMap data, throw new InsufficientPermission(); } - ExtensionConfiguration extensionConfiguration = null; - try { - extensionConfiguration = createFrom(data, responseType); - } catch (final NullPointerException exception) { - return status(BAD_REQUEST).entity(exception.getMessage()).build(); + Sid accountSid = null; + + String accountSidQuery = data.getFirst("AccountSid"); + if(accountSidQuery != null && !accountSidQuery.isEmpty()){ + accountSid = new Sid(accountSidQuery); } + //if extension doesnt exist, add new extension + String extensionName = data.getFirst("ExtensionName"); + ExtensionConfiguration extensionConfiguration = extensionsConfigurationDao.getConfigurationByName(extensionName); - try { - extensionsConfigurationDao.addConfiguration(extensionConfiguration); - } catch (ConfigurationException exception) { - return status(NOT_ACCEPTABLE).entity(exception.getMessage()).build(); + if(extensionConfiguration==null){ + try { + extensionConfiguration = createFrom(data, responseType); + } catch (final NullPointerException exception) { + return status(BAD_REQUEST).entity(exception.getMessage()).build(); + } + try { + extensionsConfigurationDao.addConfiguration(extensionConfiguration); + } catch (ConfigurationException exception) { + return status(NOT_ACCEPTABLE).entity(exception.getMessage()).build(); + } + } + if (accountSid!=null) { + try { + Object configurationData = data.getFirst("ConfigurationData"); + // if accountSid exists, then this configuration is account specific, if it doesnt then its global config + extensionConfiguration.setConfigurationData(configurationData, extensionConfiguration.getConfigurationType()); + extensionsConfigurationDao.addAccountExtensionConfiguration(extensionConfiguration, accountSid); + } catch (ConfigurationException exception) { + return status(NOT_ACCEPTABLE).entity(exception.getMessage()).build(); + } } if (APPLICATION_JSON_TYPE == responseType) { @@ -192,6 +235,12 @@ protected Response updateConfiguration(String extensionSid, MultivaluedMap Date: Sat, 6 May 2017 19:50:44 +0800 Subject: [PATCH 4/5] Issue#1981: Address PR comments --- restcomm/restcomm.application/pom.xml | 6 +- .../main/webapp/WEB-INF/conf/extensions.xml | 14 +- .../webapp/WEB-INF/data/hsql/restcomm.script | 6 - .../webapp/WEB-INF/scripts/mariadb/init.sql | 4 - .../dao/ExtensionsConfigurationDao.java | 25 +- .../connect/extension/api/CallResponse.java | 36 +++ .../extension/api/ExtensionRequest.java | 73 +++-- .../api/MessageExtensionResponse.java | 30 +- .../extension/api/NodeExtensionResponse.java | 30 +- .../api/RestcommExtensionGeneric.java | 11 + .../api/SessionExtensionResponse.java | 55 +++- .../api/SystemExtensionResponse.java | 30 +- .../api/TransactionExtensionResponse.java | 30 +- .../DefaultExtensionConfiguration.java | 262 ++++++++++++++++++ .../controller/ExtensionController.java | 65 +++++ .../connect/sms/api/SmsSessionRequest.java | 46 ++- .../org/restcomm/connect/sms/SmsService.java | 62 +---- .../org/restcomm/connect/sms/SmsSession.java | 9 +- .../connect/sms/smpp/SmppMessageHandler.java | 63 +---- 19 files changed, 654 insertions(+), 203 deletions(-) create mode 100755 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java create mode 100755 restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java diff --git a/restcomm/restcomm.application/pom.xml b/restcomm/restcomm.application/pom.xml index ba55d17df3..61c1fa756f 100644 --- a/restcomm/restcomm.application/pom.xml +++ b/restcomm/restcomm.application/pom.xml @@ -272,11 +272,7 @@ org.hsqldb hsqldb - - org.apache.maven - maven-artifact - 3.1.0 - + diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml b/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml index c922f3fd71..3fb0ce7ea0 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/conf/extensions.xml @@ -10,10 +10,14 @@ the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> + - - \ No newline at end of file + + --> + + \ No newline at end of file diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script b/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script index 2873a3b004..44bbe2d31f 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/data/hsql/restcomm.script @@ -28,8 +28,6 @@ GRANT DBA TO SA SET WRITE_DELAY 10 SET SCHEMA PUBLIC INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2acf','2012-04-24 00:00:00.000000000','2012-04-24 00:00:00.000000000','administrator@company.com','Default Administrator Account',NULL,'Full','uninitialized','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf') -INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2acg','2012-04-24 00:00:00.000000000','2012-04-24 00:00:00.000000000','second@company.com','Second Administrator Account',NULL,'Full','uninitialized','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acg') -INSERT INTO "restcomm_accounts" VALUES('ACae6e420f425248d6a26948c17a9e2ach','2012-04-24 00:00:00.000000000','2012-04-24 00:00:00.000000000','third@company.com','Third Administrator Account',NULL,'Full','uninitialized','77f8c12cc7b8f8423e5c38b035249166','Administrator','/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2ach') INSERT INTO "restcomm_applications" VALUES('AP73926e7113fa4d95981aa96b76eca854','2015-09-23 06:56:04.108000','2015-09-23 06:56:04.108000','rvdCollectVerbDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP73926e7113fa4d95981aa96b76eca854','/restcomm-rvd/services/apps/AP73926e7113fa4d95981aa96b76eca854/controller','voice') INSERT INTO "restcomm_applications" VALUES('AP81cf45088cba4abcac1261385916d582','2015-09-23 06:56:17.977000','2015-09-23 06:56:17.977000','rvdESDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP81cf45088cba4abcac1261385916d582','/restcomm-rvd/services/apps/AP81cf45088cba4abcac1261385916d582/controller','voice') INSERT INTO "restcomm_applications" VALUES('APb70c33bf0b6748f09eaec97030af36f3','2015-09-23 06:56:26.120000','2015-09-23 06:56:26.120000','rvdSayVerbDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/APb70c33bf0b6748f09eaec97030af36f3','/restcomm-rvd/services/apps/APb70c33bf0b6748f09eaec97030af36f3/controller','voice') @@ -45,7 +43,3 @@ INSERT INTO "restcomm_incoming_phone_numbers" VALUES('PN46678e5b01d44973bf184f65 INSERT INTO "restcomm_incoming_phone_numbers" VALUES('PNb43ed9e641364277b6432547ff1109e9','2014-02-17 22:37:19.392000000','2014-02-17 22:37:19.392000000','RVD external services app, customer ID 1 or 2 ','ACae6e420f425248d6a26948c17a9e2acf','+1241','2012-04-24',FALSE,NULL,'POST',NULL,'POST',NULL,'POST','AP81cf45088cba4abcac1261385916d582',NULL,'POST',NULL,'POST',NULL,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/IncomingPhoneNumbers/PNb43ed9e641364277b6432547ff1109e9',NULL,NULL,NULL,NULL, TRUE,'0.0', NULL, NULL) INSERT INTO "restcomm_clients" VALUES('CLa2b99142e111427fbb489c3de357f60a','2013-11-04 12:52:44.144000000','2013-11-04 12:52:44.144000000','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24','alice','alice','1234',1,NULL,'POST',NULL,'POST',NULL,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Clients/CLa2b99142e111427fbb489c3de357f60a') INSERT INTO "restcomm_clients" VALUES('CL3003328d0de04ba68f38de85b732ed56','2013-11-04 16:33:39.248000000','2013-11-04 16:33:39.248000000','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24','bob','bob','1234',1,NULL,'POST',NULL,'POST',NULL,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Clients/CL3003328d0de04ba68f38de85b732ed56') -INSERT INTO "restcomm_accounts_extensions" VALUES('ACae6e420f425248d6a26948c17a9e2acf','EX00000000000000000000000000000005','{"outbound-sms": [{"destination_network_id": "1000"}]}') -INSERT INTO "restcomm_accounts_extensions" VALUES('ACae6e420f425248d6a26948c17a9e2acg','EX00000000000000000000000000000005','{"outbound-sms": [{"destination_network_id": "2000"}]}') -INSERT INTO "restcomm_accounts_extensions" VALUES('ACae6e420f425248d6a26948c17a9e2ach','EX00000000000000000000000000000005','{"outbound-sms": [{"destination_network_id": "3000"}]}') -INSERT INTO "restcomm_extensions_configuration" VALUES('EX00000000000000000000000000000005','multi_provider','{"outbound-sms": [{"destination_network_id": "1"}]}','JSON','2012-04-24 00:00:00.000000','2012-04-24 00:00:00.000000',TRUE) diff --git a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql index a092a2c3de..1edcae09a4 100644 --- a/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql +++ b/restcomm/restcomm.application/src/main/webapp/WEB-INF/scripts/mariadb/init.sql @@ -401,10 +401,6 @@ null, "Administrator", "/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf"); -INSERT INTO restcomm_accounts_extensions VALUES("ACae6e420f425248d6a26948c17a9e2acf","EX00000000000000000000000000000005","{\"outbound-sms\": [{\"destination_network_id\": \"1000\"}]}") -INSERT INTO restcomm_accounts_extensions VALUES("ACae6e420f425248d6a26948c17a9e2acg","EX00000000000000000000000000000005","{\"outbound-sms\": [{\"destination_network_id\": \"2000\"}]}") -INSERT INTO restcomm_accounts_extensions VALUES("ACae6e420f425248d6a26948c17a9e2ach","EX00000000000000000000000000000005","{\"outbound-sms\": [{\"destination_network_id\": \"3000\"}]}") -INSERT INTO restcomm_extensions_configuration VALUES("EX00000000000000000000000000000005","multi_provider","{\"outbound-sms\": [{\"destination_network_id\": \"1\"}]}","JSON","2012-04-24 00:00:00.000000","2012-04-24 00:00:00.000000",TRUE, TRUE); /* Create demo Applications */ INSERT INTO restcomm_applications VALUES('AP73926e7113fa4d95981aa96b76eca854','2015-09-23 06:56:04.108000','2015-09-23 06:56:04.108000','rvdCollectVerbDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP73926e7113fa4d95981aa96b76eca854','/restcomm-rvd/services/apps/AP73926e7113fa4d95981aa96b76eca854/controller','voice'); INSERT INTO restcomm_applications VALUES('AP81cf45088cba4abcac1261385916d582','2015-09-23 06:56:17.977000','2015-09-23 06:56:17.977000','rvdESDemo','ACae6e420f425248d6a26948c17a9e2acf','2012-04-24',FALSE,'/2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Applications/AP81cf45088cba4abcac1261385916d582','/restcomm-rvd/services/apps/AP81cf45088cba4abcac1261385916d582/controller','voice'); diff --git a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java index b6d9803063..a66a4484dc 100644 --- a/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java +++ b/restcomm/restcomm.dao/src/main/java/org/restcomm/connect/dao/ExtensionsConfigurationDao.java @@ -98,15 +98,32 @@ public interface ExtensionsConfigurationDao { */ boolean validate(ExtensionConfiguration extensionConfiguration); - /**/ + /** + * Get account specific ExtensionConfiguration + * @param accountSid + * @param extensionSid + * @return ExtensionConfiguration + */ ExtensionConfiguration getAccountExtensionConfiguration(String accountSid, String extensionSid); - /**/ + /** + * Add a new account specific ExtensionConfiguration + * @param extensionConfiguration + * @param accountSid + */ void addAccountExtensionConfiguration(ExtensionConfiguration extensionConfiguration, Sid accountSid) throws ConfigurationException; - /**/ + /** + * Update an existing account specific ExtensionConfiguration + * @param extensionConfiguration + * @param accountSid + */ void updateAccountExtensionConfiguration(ExtensionConfiguration extensionConfiguration, Sid accountSid) throws ConfigurationException; - /**/ + /** + * Delete account specific ExtensionConfiguration + * @param accountSid + * @param extensionSid + */ void deleteAccountExtensionConfiguration(String accountSid, String extensionSid); } diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java new file mode 100755 index 0000000000..1a63381898 --- /dev/null +++ b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java @@ -0,0 +1,36 @@ +package org.restcomm.connect.extension.api; + +import java.util.Map; + +public class CallResponse extends ExtensionResponse{ + //expose all expected properties +// "outbound-proxy": [ +// { +// "outbound-proxy": "outbound.proxy.com:5060", +// "username": "myusername", +// "password": "mypassword", +// "additional-headers": [ +// { +// "header-name": "Route", +// "header-value": "sip:10.10.10.10:5080;transport=UDP;lr" +// }, +// { +// "header-name": "X-Custom-Header1", +// "header-value": "ID-X-12345" +// } +// ] +// } +// ], +// username:{ +// }, +// password:{ +// }, +// proxy:{ +// //proxy info here +// }, + + Map additionalHeaders; + String outboundProxy; + String outboundProxyUsername; + String outboundProxyPassword; +} 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 ce2f08a46d..76231eba0d 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 @@ -1,27 +1,46 @@ -package org.restcomm.connect.extension.api; -import org.apache.commons.configuration.Configuration; - -public class ExtensionRequest { - private Object payload; - private Configuration configuration; - - public ExtensionRequest() {} - - public Object getObject() { - return payload; - } - - public void setObject(Object object) { - this.payload = object; - } - - public void setConfiguration(Configuration configuration) { - // TODO Auto-generated method stub - this.configuration = configuration; - } - public Configuration getConfiguration() { - // TODO Auto-generated method stub - return this.configuration; - } - -} +/* + * 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 class ExtensionRequest { + private Object payload; + private Configuration configuration; + + public ExtensionRequest() {} + + public Object getObject() { + return payload; + } + + public void setObject(Object object) { + this.payload = object; + } + + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + public Configuration getConfiguration() { + return this.configuration; + } + +} 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 index da18075e3d..de1b637ff5 100644 --- 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 @@ -1,3 +1,27 @@ -package org.restcomm.connect.extension.api; -public class MessageExtensionResponse extends ExtensionResponse { -} +/* + * 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 index 0b883aebc2..ed3b2f4965 100644 --- 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 @@ -1,3 +1,27 @@ -package org.restcomm.connect.extension.api; -public class NodeExtensionResponse extends ExtensionResponse { -} +/* + * 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 1fd04ff3a2..ae3fdb1e14 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 @@ -78,4 +78,15 @@ public interface RestcommExtensionGeneric { */ ExtensionResponse postApiAction(ApiRequest apiRequest); + /** + * Extension name getter + * @return String name of Extension + */ + String getName(); + + /** + * Extension version getter + * @return String version of Extension + */ + String getVersion(); } 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 index 45aa2f963a..9d8013a87f 100644 --- 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 @@ -1,11 +1,44 @@ -package org.restcomm.connect.extension.api; -import org.apache.commons.configuration.Configuration; -public class SessionExtensionResponse extends ExtensionResponse { - - public void setConfiguration(Configuration configuration){ - super.setObject(configuration); - } - public Configuration getConfiguration(){ - return (Configuration) super.getObject(); - } -} +/* + * 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 index 2784746659..4df9d6a039 100644 --- 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 @@ -1,3 +1,27 @@ -package org.restcomm.connect.extension.api; -public class SystemExtensionResponse extends ExtensionResponse { -} +/* + * 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 index f073f5032b..c3ac493ab2 100644 --- 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 @@ -1,4 +1,28 @@ -package org.restcomm.connect.extension.api; -public class TransactionExtensionResponse extends ExtensionResponse { - +/* + * 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/configuration/DefaultExtensionConfiguration.java b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java new file mode 100755 index 0000000000..a23f22b44e --- /dev/null +++ b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java @@ -0,0 +1,262 @@ +/* + * TeleStax, Open Source Cloud Communications + * Copyright 2011-2016, Telestax Inc and individual contributors + * by the @authors tag. + * + * This program is free software: you can redistribute it and/or modify + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + */ +package org.restcomm.connect.extension.configuration; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.util.HashMap; + +import java.util.Map; + +import org.apache.ibatis.exceptions.PersistenceException; +import org.apache.log4j.Logger; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.joda.time.DateTime; +import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.dao.DaoManager; +import org.restcomm.connect.dao.ExtensionsConfigurationDao; +import org.restcomm.connect.extension.api.ConfigurationException; +import org.restcomm.connect.extension.api.ExtensionConfiguration; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; + +public class DefaultExtensionConfiguration { + public enum PropertyType { + VERSION("version"); + private String value; + + private PropertyType(String value) { + this.value = value; + } + }; + + private static final Logger logger = Logger.getLogger(DefaultExtensionConfiguration.class); + private boolean workingWithLocalConf; + private ExtensionsConfigurationDao extensionConfigurationDao; + private ExtensionConfiguration extensionConfiguration; + private JsonObject configurationJsonObj; + private JsonParser jsonParser; + private DaoManager daoManager; + private Gson gson; + private JsonObject defaultConfigurationJsonObj; + private String extensionName; + private DefaultArtifactVersion defVersion; + private HashMap specificConfigurationMap; + private Sid sid; + private String localConfigPath; + + public DefaultExtensionConfiguration() { + this.sid = new Sid("EX00000000000000000000000000000001"); + this.localConfigPath = ""; + } + + public DefaultExtensionConfiguration(final DaoManager daoManager, String extensionName, String localConfigPath) { + try { + init(daoManager, extensionName, localConfigPath); + } catch (Exception e) { + logger.error("Exception initializing"); + } + } + + public void init(final DaoManager daoManager, String extensionName, String localConfigPath) throws ConfigurationException { + try { + this.setDaoManager(daoManager); + this.extensionConfigurationDao = daoManager.getExtensionsConfigurationDao(); + + if (extensionName.isEmpty() && localConfigPath.isEmpty()) { + throw new ConfigurationException("extensionName or local config cant be empty"); + } + if (!extensionName.isEmpty()) { + this.extensionName = extensionName; + } + if (!localConfigPath.isEmpty()) { + // Load the default extensionConfiguration from file + this.defaultConfigurationJsonObj = loadDefaultConfiguration(localConfigPath); + + configurationJsonObj = this.defaultConfigurationJsonObj; + + // Get the extension name from default extensionConfiguration + String temp = defaultConfigurationJsonObj.get("extension_name").getAsString(); + if (!temp.isEmpty()) { + extensionName = temp; + } + defVersion = new DefaultArtifactVersion(defaultConfigurationJsonObj.get("version").getAsString()); + } + // Load extensionConfiguration from DB + extensionConfiguration = extensionConfigurationDao.getConfigurationByName(extensionName); + + // try fetch sid from name + if (extensionConfiguration == null) { + // If extensionConfiguration from DB is null then add the default values to DB + this.sid = Sid.generate(Sid.Type.EXTENSION_CONFIGURATION); + extensionConfiguration = new ExtensionConfiguration(sid, this.extensionName, true, + defaultConfigurationJsonObj.toString(), ExtensionConfiguration.configurationType.JSON, DateTime.now()); + extensionConfigurationDao.addConfiguration(extensionConfiguration); + + } else { + // Get configuration object + this.sid = extensionConfiguration.getSid(); + // try get default config data + JsonObject dbConfiguration = null; + + DefaultArtifactVersion currentVersion = null; + try { + dbConfiguration = (JsonObject) jsonParser.parse((String) extensionConfiguration.getConfigurationData()); + if (dbConfiguration.get("version") != null) { + currentVersion = new DefaultArtifactVersion(dbConfiguration.get("version").getAsString()); + } + + if (dbConfiguration != null && (currentVersion == null || currentVersion.compareTo(defVersion) < 0)) { + if (logger.isInfoEnabled()) { + logger.info("Configuration found in the DB is older version than the default one: " + + defVersion.toString()); + } + + for (Map.Entry jsonElementEntry : defaultConfigurationJsonObj.entrySet()) { + if (!jsonElementEntry.getKey().equalsIgnoreCase("specifics_configuration") + && dbConfiguration.get(jsonElementEntry.getKey()) == null) { + dbConfiguration.add(jsonElementEntry.getKey(), jsonElementEntry.getValue()); + } + } + if (dbConfiguration.get("version") != null) { + dbConfiguration.remove("version"); + } + dbConfiguration.addProperty("version", defaultConfigurationJsonObj.get("version").getAsString()); + + extensionConfiguration = new ExtensionConfiguration(extensionConfiguration.getSid(), extensionName, + extensionConfiguration.isEnabled(), dbConfiguration.toString(), + ExtensionConfiguration.configurationType.JSON, DateTime.now()); + extensionConfigurationDao.updateConfiguration(extensionConfiguration); + } + configurationJsonObj = dbConfiguration; + // Load Specific Configuration Map + // loadSpecificConfigurationMap(configurationJsonObj); + } catch (Exception e) { + } + + } + if (logger.isInfoEnabled()) { + logger.info("Finished loading configuration for extension: " + extensionName); + } + } catch (ConfigurationException configurationException) { + String errorMessage = "Exception during " + this.getClass() + " Configuration constructor "; + if (logger.isDebugEnabled()) { + logger.debug(errorMessage + configurationException); + } + throw new ConfigurationException(errorMessage); + } catch (PersistenceException persistenceException) { + if (logger.isDebugEnabled()) { + logger.debug("PersistenceException during " + this.getClass() + " init, will fallback to default configuration"); + } + workingWithLocalConf = true; + } catch (IOException e) { + logger.debug("IOException during " + this.getClass()); + } + } + + public JsonObject loadDefaultConfiguration(String localConfigFilePath) throws IOException { + JsonObject jsonObj = null; + jsonParser = new JsonParser(); + InputStream in = (InputStream) getClass().getResourceAsStream(localConfigFilePath); + BufferedReader inReader = new BufferedReader(new InputStreamReader(in)); + JsonReader reader = new JsonReader(inReader); + JsonElement jsonElement = jsonParser.parse(reader); + jsonObj = (JsonObject) jsonElement; + in.close(); + inReader.close(); + reader.close(); + return jsonObj; + } + + public void reloadConfiguration() { + if (!workingWithLocalConf) { + if (extensionConfigurationDao.isLatestVersionByName(extensionName, extensionConfiguration.getDateUpdated())) { + extensionConfiguration = extensionConfigurationDao.getConfigurationByName(extensionName); + String updatedConf = (String) extensionConfiguration.getConfigurationData(); + configurationJsonObj = (JsonObject) jsonParser.parse(updatedConf); + // loadSpecificConfigurationMap(configurationJsonObj); + if (logger.isInfoEnabled()) { + logger.info(this.extensionName + " extension configuration reloaded"); + } + } + } + } + + public boolean isEnabled() { + reloadConfiguration(); + if (extensionConfiguration != null) { + return extensionConfiguration.isEnabled(); + } else { + return true; + } + } + + public String getVersion() { + reloadConfiguration(); + String ver = configurationJsonObj.get(PropertyType.VERSION.value).getAsString(); + return ver; + } + + public Sid getSid() { + return this.sid; + } + + public void loadSpecificConfigurationMap(final JsonObject json) { + JsonArray specificConfJsonArray = json.getAsJsonArray(); + // JsonArray specificConfJsonArray = json.getAsJsonArray("specifics_configuration"); + // if (specificConfJsonArray != null) { + // specificConfigurationMap = new HashMap(); + // Iterator iter = specificConfJsonArray.iterator(); + // while (iter.hasNext()) { + // JsonElement elem = iter.next(); + // if (elem.getAsJsonObject().get("sid") != null) { + // specificConfigurationMap.put(sid, value); + // } + // } + // } + // return map + } + + // getConfigAsJson + // getConfigAsConfiguration + // getConfigAsHashMap + /*public void getSpecificConfigurationMapAsXml() { + }*/ + + /** + * @return the daoManager + */ + public DaoManager getDaoManager() { + return daoManager; + } + + /** + * @param daoManager the daoManager to set + */ + public void setDaoManager(DaoManager daoManager) { + this.daoManager = daoManager; + } +} 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 d3912c76ac..3e253823c4 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,15 @@ package org.restcomm.connect.extension.controller; +import org.restcomm.connect.extension.api.ExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; +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; @@ -80,4 +87,62 @@ public void registerExtension(final RestcommExtensionGeneric extension) { } } } + + public ExtensionResponse executePreOutboundAction(final Object er, List extensions) { + //FIXME: if we have more than one extension in chain + // and all of them are successful, we only receive the last + // extensionResponse + ExtensionResponse response = new ExtensionResponse(); + if (extensions != null && extensions.size() > 0) { + + for (RestcommExtensionGeneric extension : extensions) { + if(logger.isInfoEnabled()) { + logger.info( extension.getName()+" is enabled="+extension.isEnabled()); + } + if (extension.isEnabled()) { + response = extension.preOutboundAction(er); + //fail fast + if (!response.isAllowed()){ + break; + } + } + } + } + return response; + } + + public ExtensionResponse executePostOutboundAction(final Object er, List extensions) { + ExtensionResponse response = new ExtensionResponse(); + //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.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java index aeca0196a3..0665fdb146 100644 --- a/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java +++ b/restcomm/restcomm.sms.api/src/main/java/org/restcomm/connect/sms/api/SmsSessionRequest.java @@ -53,12 +53,17 @@ public String toString() { return name; } } - - //TODO need to check which is using the SmsSessionRequest and modify accordingly to include or not the custom headers - public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders) { - this(from, to, body, encoding, origRequest, customHeaders, null); - } - public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders, TlvSet tlvSet) { + //FIXME: all signatures should be changed, encoding, sipReq, tlvSet are optional and should come after headers + //(from, to, body, headers, encoding, sipReq, tlvSet) + //(from, to, body, headers, encoding, sipReq) + //(from, to, body, headers, encoding, tlvSet) + //(from, to, body, headers, sipReq, tlvSet) + //(from, to, body, headers, encoding) + //(from, to, body, headers, sipReq) + //(from, to, body, headers, tlvSet) + //(from, to, body) + + public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final SipServletRequest origRequest, TlvSet tlvSet, final ConcurrentHashMap customHeaders) { super(); this.from = from; this.to = to; @@ -70,20 +75,37 @@ public SmsSessionRequest(final String from, final String to, final String body, } - public SmsSessionRequest(final String from, final String to, final String body, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders) { - this(from, to, body, Encoding.GSM, origRequest, customHeaders); + //TODO need to check which is using the SmsSessionRequest and modify accordingly to include or not the custom headers + public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders) { + this(from, to, body, encoding, origRequest, null, customHeaders); + } + + public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final TlvSet tlvSet, final ConcurrentHashMap customHeaders) { + this(from, to, body, encoding, null, tlvSet, customHeaders); + } + + public SmsSessionRequest(final String from, final String to, final String body, final SipServletRequest origRequest, final TlvSet tlvSet, final ConcurrentHashMap customHeaders) { + this(from, to, body, Encoding.GSM, null, tlvSet, customHeaders); } - public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final ConcurrentHashMap customHeaders, TlvSet tlvSet) { - this(from, to, body, encoding, null, customHeaders, tlvSet); + public SmsSessionRequest(final String from, final String to, final String body, final SipServletRequest origRequest, final ConcurrentHashMap customHeaders) { + this(from, to, body, Encoding.GSM, origRequest, null, customHeaders); } public SmsSessionRequest(final String from, final String to, final String body, final Encoding encoding, final ConcurrentHashMap customHeaders) { - this(from, to, body, encoding, null, customHeaders, null); + this(from, to, body, encoding, null, null, customHeaders); + } + + public SmsSessionRequest(final String from, final String to, final String body, final TlvSet tlvSet, final ConcurrentHashMap customHeaders) { + this(from, to, body, Encoding.GSM, null, null, customHeaders); } public SmsSessionRequest(final String from, final String to, final String body, final ConcurrentHashMap customHeaders) { - this(from, to, body, Encoding.GSM, null, customHeaders); + this(from, to, body, Encoding.GSM, null, null, customHeaders); + } + + public SmsSessionRequest(final String from, final String to, final String body) { + this(from, to, body, Encoding.GSM, null, null, null); } public String from() { 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 ae086b4bfe..80985507a9 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 @@ -247,7 +247,7 @@ private void message(final Object message) throws IOException { session.tell(new SmsSessionAttribute("record", record), self()); // Send the SMS. TlvSet tlvSet = new TlvSet(); - final SmsSessionRequest sms = new SmsSessionRequest(client.getLogin(), toUser, new String(request.getRawContent()), Encoding.GSM, request, null, tlvSet); + final SmsSessionRequest sms = new SmsSessionRequest(client.getLogin(), toUser, new String(request.getRawContent()), request, tlvSet, null); monitoringService.tell(new TextMessage(((SipURI)request.getFrom().getURI()).getUser(), ((SipURI)request.getTo().getURI()).getUser(), TextMessage.SmsState.INBOUND_TO_PROXY_OUT), self); session.tell(sms, self()); } @@ -337,65 +337,13 @@ private boolean redirectToHostedSmsApp(final ActorRef self, final SipServletRequ return isFoundHostedApp; } - private ExtensionResponse executePreOutboundAction(final Object er) { - //TODO: should allow multiple types of responses perhaps - ExtensionResponse response = new ExtensionResponse(); - if (extensions != null && extensions.size() > 0) { - - for (RestcommExtensionGeneric extension : extensions) { - logger.info( "isEnabled="+extension.isEnabled()); - if (extension.isEnabled()) { - response = extension.preOutboundAction(er); - //fail fast - if (!response.isAllowed()){ - break; - } - } - } - } - //return object - return response; - } - - private boolean executePostOutboundAction(final Object message) { - return true; - } - - //FIXME: make into static util? - //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 - private Object handleExtensionResponse(ExtensionResponse response){ - //check type of extension - //FIXME: hack to default - Object object = this.configuration;//new Object(); - 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; - } - @Override public void onReceive(final Object message) throws Exception { final UntypedActorContext context = getContext(); final Class klass = message.getClass(); final ActorRef self = self(); 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 @@ -403,10 +351,10 @@ public void onReceive(final Object message) throws Exception { er.setObject(message); er.setConfiguration(this.configuration); - ExtensionResponse extensionResponse = executePreOutboundAction(er); + ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); if (extensionResponse.isAllowed()) { //pass in response object to sms session - Object obj = handleExtensionResponse(extensionResponse); + 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); @@ -416,7 +364,7 @@ public void onReceive(final Object message) throws Exception { final SmsServiceResponse response = new SmsServiceResponse(new RestcommExtensionException("Now allowed to create SmsSession")); sender.tell(response, self()); } - executePostOutboundAction(message); + ec.executePostOutboundAction(message, this.extensions); } else if (DestroySmsSession.class.equals(klass)) { final DestroySmsSession request = (DestroySmsSession) message; final ActorRef session = request.session(); diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java index 4f0b90c0f0..6f78ed20b7 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java @@ -123,13 +123,12 @@ public SmsSession(final Configuration configuration, final SipFactory factory, f this.tlvSet = new TlvSet(); if(!this.configuration.subset("outbound-sms").isEmpty()) { - //FIXME: hardcoded to TAG_DEST_NETWORK_ID + //TODO: handle arbitrary keys instead of just TAG_DEST_NETWORK_ID try { String valStr = this.configuration.subset("outbound-sms").getString("destination_network_id"); - //FIXME:fetch the tag value from the arbitrary key this.tlvSet.addOptionalParameter(new Tlv(SmppConstants.TAG_DEST_NETWORK_ID,ByteArrayUtil.toByteArray(Integer.parseInt(valStr)))); } catch (Exception e) { - // TODO: handle exception + logger.error("Error while parsing tlv configuration " + e); } } } @@ -155,7 +154,7 @@ private void inbound(final Object message) throws IOException { } // Store the last sms event. - last = new SmsSessionRequest(from, to, body, Encoding.GSM, customRequestHeaderMap, this.tlvSet); + last = new SmsSessionRequest(from, to, body, this.tlvSet, customRequestHeaderMap); if (initial == null) { initial = last; } @@ -175,7 +174,7 @@ private void inbound(final Object message) throws IOException { } // Store the last sms event. - last = new SmsSessionRequest (request.getSmppFrom(), request.getSmppTo(), request.getSmppContent(), encoding, null, request.getTlvSet()); + last = new SmsSessionRequest (request.getSmppFrom(), request.getSmppTo(), request.getSmppContent(), encoding, request.getTlvSet(), null); if (initial == null) { initial = last; } 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 c888747aea..797a415279 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 @@ -73,7 +73,7 @@ public SmppMessageHandler(final ServletContext servletContext) { this.configuration = (Configuration) servletContext.getAttribute(Configuration.class.getName()); this.sipFactory = (SipFactory) servletContext.getAttribute(SipFactory.class.getName()); this.monitoringService = (ActorRef) servletContext.getAttribute(MonitoringService.class.getName()); - //FIXME:SmsService or SmppMessageHandler + //FIXME:Should new ExtensionType.SmppMessageHandler be defined? extensions = ExtensionController.getInstance().getExtensions(ExtensionType.SmsService); if (logger.isInfoEnabled()) { logger.info("SmsService extensions: "+(extensions != null ? extensions.size() : "0")); @@ -85,6 +85,7 @@ public void onReceive(Object message) throws Exception { final UntypedActorContext context = getContext(); final ActorRef sender = sender(); final ActorRef self = self(); + ExtensionController ec = ExtensionController.getInstance(); if (message instanceof SmppInboundMessageEntity){ if(logger.isInfoEnabled()) { logger.info("SmppMessageHandler processing Inbound Message " + message.toString()); @@ -96,14 +97,12 @@ public void onReceive(Object message) throws Exception { } outbound((SmppOutboundMessageEntity) message); } else if (message instanceof CreateSmsSession) { - //Extension ExtensionRequest er = new ExtensionRequest(); er.setObject(message); er.setConfiguration(this.configuration); - ExtensionResponse extensionResponse = executePreOutboundAction(er); + ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); if (extensionResponse.isAllowed()) { - Object obj = handleExtensionResponse(extensionResponse); - //Configuration cfg = this.configuration; + Object obj = ec.handleExtensionResponse(extensionResponse, this.configuration); final ActorRef session = session((Configuration)obj); final SmsServiceResponse response = new SmsServiceResponse(session); sender.tell(response, self); @@ -111,7 +110,7 @@ public void onReceive(Object message) throws Exception { final SmsServiceResponse response = new SmsServiceResponse(new RestcommExtensionException("Now allowed to create SmsSession")); sender.tell(response, self()); } - executePostOutboundAction(message); + ec.executePostOutboundAction(message, this.extensions); }else if (message instanceof DestroySmsSession) { final DestroySmsSession destroySmsSession = (DestroySmsSession) message; final ActorRef session = destroySmsSession.session(); @@ -119,54 +118,6 @@ public void onReceive(Object message) throws Exception { } } - private Object handleExtensionResponse(ExtensionResponse response) { - // TODO Auto-generated method stub - Object object = this.configuration;//new Object(); - 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; - } - - private ExtensionResponse executePreOutboundAction(final Object er) { - //TODO: should allow multiple types of responses perhaps - ExtensionResponse response = new ExtensionResponse(); - if (extensions != null && extensions.size() > 0) { - - for (RestcommExtensionGeneric extension : extensions) { - logger.info( "isEnabled="+extension.isEnabled()); - if (extension.isEnabled()) { - response = extension.preOutboundAction(er); - //fail fast - if (!response.isAllowed()){ - break; - } - } - } - } - //return object - return response; - } - - private boolean executePostOutboundAction(final Object message) { - return true; - } - private void inbound(final SmppInboundMessageEntity request ) throws IOException { final ActorRef self = self(); @@ -305,7 +256,9 @@ public void outbound(SmppOutboundMessageEntity request) throws SmppInvalidArgume submit0.setOptionalParameter(tlv); } }else{ - logger.info("tlvSet is null"); + if(logger.isInfoEnabled()) { + logger.info("TlvSet is null"); + } } try { if(logger.isInfoEnabled()) { From 771d389cca3590ecc6a514cd738428a815501359 Mon Sep 17 00:00:00 2001 From: abdulazizali77 Date: Tue, 9 May 2017 23:46:29 +0800 Subject: [PATCH 5/5] Issue#1981: Address PR comments: Move DefaultExtensionConfiguration. Change RestcommExtensionGeneric preOutboundAction method signature. Add getName,getVersion. Fix dependencies. Fix checkstyle. Remove mistaken CallResponse add. --- .../connect/extension/api/CallResponse.java | 36 -- .../api/RestcommExtensionGeneric.java | 2 +- .../restcomm.extension.controller/pom.xml | 16 + .../DefaultExtensionConfiguration.java | 524 +++++++++--------- .../controller/ExtensionController.java | 3 +- .../org/restcomm/connect/sms/SmsService.java | 7 +- .../org/restcomm/connect/sms/SmsSession.java | 1 - .../connect/sms/smpp/SmppMessageHandler.java | 5 - .../connect/telephony/CallManager.java | 56 +- 9 files changed, 311 insertions(+), 339 deletions(-) delete mode 100755 restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java diff --git a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java b/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java deleted file mode 100755 index 1a63381898..0000000000 --- a/restcomm/restcomm.extension.api/src/main/java/org/restcomm/connect/extension/api/CallResponse.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.restcomm.connect.extension.api; - -import java.util.Map; - -public class CallResponse extends ExtensionResponse{ - //expose all expected properties -// "outbound-proxy": [ -// { -// "outbound-proxy": "outbound.proxy.com:5060", -// "username": "myusername", -// "password": "mypassword", -// "additional-headers": [ -// { -// "header-name": "Route", -// "header-value": "sip:10.10.10.10:5080;transport=UDP;lr" -// }, -// { -// "header-name": "X-Custom-Header1", -// "header-value": "ID-X-12345" -// } -// ] -// } -// ], -// username:{ -// }, -// password:{ -// }, -// proxy:{ -// //proxy info here -// }, - - Map additionalHeaders; - String outboundProxy; - String outboundProxyUsername; - String outboundProxyPassword; -} 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 ae3fdb1e14..96116be9c6 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(Object message); + ExtensionResponse preOutboundAction(ExtensionRequest 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/pom.xml b/restcomm/restcomm.extension.controller/pom.xml index 3b982e8935..94e5d2fe42 100644 --- a/restcomm/restcomm.extension.controller/pom.xml +++ b/restcomm/restcomm.extension.controller/pom.xml @@ -46,6 +46,22 @@ ${sipservletapi.version} provided + + org.restcomm + restcomm-connect.dao + ${project.version} + + + org.restcomm + restcomm-connect.commons + ${project.version} + + + org.apache.maven + maven-artifact + 3.1.0 + + \ No newline at end of file diff --git a/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java index a23f22b44e..fa5690730a 100755 --- a/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java +++ b/restcomm/restcomm.extension.controller/src/main/java/org/restcomm/connect/extension/configuration/DefaultExtensionConfiguration.java @@ -1,262 +1,262 @@ -/* - * TeleStax, Open Source Cloud Communications - * Copyright 2011-2016, Telestax Inc and individual contributors - * by the @authors tag. - * - * This program is free software: you can redistribute it and/or modify - * under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - */ -package org.restcomm.connect.extension.configuration; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.InputStream; -import java.util.HashMap; - -import java.util.Map; - -import org.apache.ibatis.exceptions.PersistenceException; -import org.apache.log4j.Logger; -import org.apache.maven.artifact.versioning.DefaultArtifactVersion; -import org.joda.time.DateTime; -import org.restcomm.connect.commons.dao.Sid; -import org.restcomm.connect.dao.DaoManager; -import org.restcomm.connect.dao.ExtensionsConfigurationDao; -import org.restcomm.connect.extension.api.ConfigurationException; -import org.restcomm.connect.extension.api.ExtensionConfiguration; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.stream.JsonReader; - -public class DefaultExtensionConfiguration { - public enum PropertyType { - VERSION("version"); - private String value; - - private PropertyType(String value) { - this.value = value; - } - }; - - private static final Logger logger = Logger.getLogger(DefaultExtensionConfiguration.class); - private boolean workingWithLocalConf; - private ExtensionsConfigurationDao extensionConfigurationDao; - private ExtensionConfiguration extensionConfiguration; - private JsonObject configurationJsonObj; - private JsonParser jsonParser; - private DaoManager daoManager; - private Gson gson; - private JsonObject defaultConfigurationJsonObj; - private String extensionName; - private DefaultArtifactVersion defVersion; - private HashMap specificConfigurationMap; - private Sid sid; - private String localConfigPath; - - public DefaultExtensionConfiguration() { - this.sid = new Sid("EX00000000000000000000000000000001"); - this.localConfigPath = ""; - } - - public DefaultExtensionConfiguration(final DaoManager daoManager, String extensionName, String localConfigPath) { - try { - init(daoManager, extensionName, localConfigPath); - } catch (Exception e) { - logger.error("Exception initializing"); - } - } - - public void init(final DaoManager daoManager, String extensionName, String localConfigPath) throws ConfigurationException { - try { - this.setDaoManager(daoManager); - this.extensionConfigurationDao = daoManager.getExtensionsConfigurationDao(); - - if (extensionName.isEmpty() && localConfigPath.isEmpty()) { - throw new ConfigurationException("extensionName or local config cant be empty"); - } - if (!extensionName.isEmpty()) { - this.extensionName = extensionName; - } - if (!localConfigPath.isEmpty()) { - // Load the default extensionConfiguration from file - this.defaultConfigurationJsonObj = loadDefaultConfiguration(localConfigPath); - - configurationJsonObj = this.defaultConfigurationJsonObj; - - // Get the extension name from default extensionConfiguration - String temp = defaultConfigurationJsonObj.get("extension_name").getAsString(); - if (!temp.isEmpty()) { - extensionName = temp; - } - defVersion = new DefaultArtifactVersion(defaultConfigurationJsonObj.get("version").getAsString()); - } - // Load extensionConfiguration from DB - extensionConfiguration = extensionConfigurationDao.getConfigurationByName(extensionName); - - // try fetch sid from name - if (extensionConfiguration == null) { - // If extensionConfiguration from DB is null then add the default values to DB - this.sid = Sid.generate(Sid.Type.EXTENSION_CONFIGURATION); - extensionConfiguration = new ExtensionConfiguration(sid, this.extensionName, true, - defaultConfigurationJsonObj.toString(), ExtensionConfiguration.configurationType.JSON, DateTime.now()); - extensionConfigurationDao.addConfiguration(extensionConfiguration); - - } else { - // Get configuration object - this.sid = extensionConfiguration.getSid(); - // try get default config data - JsonObject dbConfiguration = null; - - DefaultArtifactVersion currentVersion = null; - try { - dbConfiguration = (JsonObject) jsonParser.parse((String) extensionConfiguration.getConfigurationData()); - if (dbConfiguration.get("version") != null) { - currentVersion = new DefaultArtifactVersion(dbConfiguration.get("version").getAsString()); - } - - if (dbConfiguration != null && (currentVersion == null || currentVersion.compareTo(defVersion) < 0)) { - if (logger.isInfoEnabled()) { - logger.info("Configuration found in the DB is older version than the default one: " - + defVersion.toString()); - } - - for (Map.Entry jsonElementEntry : defaultConfigurationJsonObj.entrySet()) { - if (!jsonElementEntry.getKey().equalsIgnoreCase("specifics_configuration") - && dbConfiguration.get(jsonElementEntry.getKey()) == null) { - dbConfiguration.add(jsonElementEntry.getKey(), jsonElementEntry.getValue()); - } - } - if (dbConfiguration.get("version") != null) { - dbConfiguration.remove("version"); - } - dbConfiguration.addProperty("version", defaultConfigurationJsonObj.get("version").getAsString()); - - extensionConfiguration = new ExtensionConfiguration(extensionConfiguration.getSid(), extensionName, - extensionConfiguration.isEnabled(), dbConfiguration.toString(), - ExtensionConfiguration.configurationType.JSON, DateTime.now()); - extensionConfigurationDao.updateConfiguration(extensionConfiguration); - } - configurationJsonObj = dbConfiguration; - // Load Specific Configuration Map - // loadSpecificConfigurationMap(configurationJsonObj); - } catch (Exception e) { - } - - } - if (logger.isInfoEnabled()) { - logger.info("Finished loading configuration for extension: " + extensionName); - } - } catch (ConfigurationException configurationException) { - String errorMessage = "Exception during " + this.getClass() + " Configuration constructor "; - if (logger.isDebugEnabled()) { - logger.debug(errorMessage + configurationException); - } - throw new ConfigurationException(errorMessage); - } catch (PersistenceException persistenceException) { - if (logger.isDebugEnabled()) { - logger.debug("PersistenceException during " + this.getClass() + " init, will fallback to default configuration"); - } - workingWithLocalConf = true; - } catch (IOException e) { - logger.debug("IOException during " + this.getClass()); - } - } - - public JsonObject loadDefaultConfiguration(String localConfigFilePath) throws IOException { - JsonObject jsonObj = null; - jsonParser = new JsonParser(); - InputStream in = (InputStream) getClass().getResourceAsStream(localConfigFilePath); - BufferedReader inReader = new BufferedReader(new InputStreamReader(in)); - JsonReader reader = new JsonReader(inReader); - JsonElement jsonElement = jsonParser.parse(reader); - jsonObj = (JsonObject) jsonElement; - in.close(); - inReader.close(); - reader.close(); - return jsonObj; - } - - public void reloadConfiguration() { - if (!workingWithLocalConf) { - if (extensionConfigurationDao.isLatestVersionByName(extensionName, extensionConfiguration.getDateUpdated())) { - extensionConfiguration = extensionConfigurationDao.getConfigurationByName(extensionName); - String updatedConf = (String) extensionConfiguration.getConfigurationData(); - configurationJsonObj = (JsonObject) jsonParser.parse(updatedConf); - // loadSpecificConfigurationMap(configurationJsonObj); - if (logger.isInfoEnabled()) { - logger.info(this.extensionName + " extension configuration reloaded"); - } - } - } - } - - public boolean isEnabled() { - reloadConfiguration(); - if (extensionConfiguration != null) { - return extensionConfiguration.isEnabled(); - } else { - return true; - } - } - - public String getVersion() { - reloadConfiguration(); - String ver = configurationJsonObj.get(PropertyType.VERSION.value).getAsString(); - return ver; - } - - public Sid getSid() { - return this.sid; - } - - public void loadSpecificConfigurationMap(final JsonObject json) { - JsonArray specificConfJsonArray = json.getAsJsonArray(); - // JsonArray specificConfJsonArray = json.getAsJsonArray("specifics_configuration"); - // if (specificConfJsonArray != null) { - // specificConfigurationMap = new HashMap(); - // Iterator iter = specificConfJsonArray.iterator(); - // while (iter.hasNext()) { - // JsonElement elem = iter.next(); - // if (elem.getAsJsonObject().get("sid") != null) { - // specificConfigurationMap.put(sid, value); - // } - // } - // } - // return map - } - - // getConfigAsJson - // getConfigAsConfiguration - // getConfigAsHashMap - /*public void getSpecificConfigurationMapAsXml() { - }*/ - - /** - * @return the daoManager - */ - public DaoManager getDaoManager() { - return daoManager; - } - - /** - * @param daoManager the daoManager to set - */ - public void setDaoManager(DaoManager daoManager) { - this.daoManager = daoManager; - } -} +/* + * TeleStax, Open Source Cloud Communications + * Copyright 2011-2016, Telestax Inc and individual contributors + * by the @authors tag. + * + * This program is free software: you can redistribute it and/or modify + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + */ +package org.restcomm.connect.extension.configuration; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.util.HashMap; + +import java.util.Map; + +import org.apache.ibatis.exceptions.PersistenceException; +import org.apache.log4j.Logger; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.joda.time.DateTime; +import org.restcomm.connect.commons.dao.Sid; +import org.restcomm.connect.dao.DaoManager; +import org.restcomm.connect.dao.ExtensionsConfigurationDao; +import org.restcomm.connect.extension.api.ConfigurationException; +import org.restcomm.connect.extension.api.ExtensionConfiguration; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; + +public class DefaultExtensionConfiguration { + public enum PropertyType { + VERSION("version"); + private String value; + + private PropertyType(String value) { + this.value = value; + } + }; + + private static final Logger logger = Logger.getLogger(DefaultExtensionConfiguration.class); + private boolean workingWithLocalConf; + private ExtensionsConfigurationDao extensionConfigurationDao; + private ExtensionConfiguration extensionConfiguration; + private JsonObject configurationJsonObj; + private JsonParser jsonParser; + private DaoManager daoManager; + private Gson gson; + private JsonObject defaultConfigurationJsonObj; + private String extensionName; + private DefaultArtifactVersion defVersion; + private HashMap specificConfigurationMap; + private Sid sid; + private String localConfigPath; + + public DefaultExtensionConfiguration() { + this.sid = new Sid("EX00000000000000000000000000000001"); + this.localConfigPath = ""; + } + + public DefaultExtensionConfiguration(final DaoManager daoManager, String extensionName, String localConfigPath) { + try { + init(daoManager, extensionName, localConfigPath); + } catch (Exception e) { + logger.error("Exception initializing"); + } + } + + public void init(final DaoManager daoManager, String extensionName, String localConfigPath) throws ConfigurationException { + try { + this.setDaoManager(daoManager); + this.extensionConfigurationDao = daoManager.getExtensionsConfigurationDao(); + + if (extensionName.isEmpty() && localConfigPath.isEmpty()) { + throw new ConfigurationException("extensionName or local config cant be empty"); + } + if (!extensionName.isEmpty()) { + this.extensionName = extensionName; + } + if (!localConfigPath.isEmpty()) { + // Load the default extensionConfiguration from file + this.defaultConfigurationJsonObj = loadDefaultConfiguration(localConfigPath); + + configurationJsonObj = this.defaultConfigurationJsonObj; + + // Get the extension name from default extensionConfiguration + String temp = defaultConfigurationJsonObj.get("extension_name").getAsString(); + if (!temp.isEmpty()) { + extensionName = temp; + } + defVersion = new DefaultArtifactVersion(defaultConfigurationJsonObj.get("version").getAsString()); + } + // Load extensionConfiguration from DB + extensionConfiguration = extensionConfigurationDao.getConfigurationByName(extensionName); + + // try fetch sid from name + if (extensionConfiguration == null) { + // If extensionConfiguration from DB is null then add the default values to DB + this.sid = Sid.generate(Sid.Type.EXTENSION_CONFIGURATION); + extensionConfiguration = new ExtensionConfiguration(sid, this.extensionName, true, + defaultConfigurationJsonObj.toString(), ExtensionConfiguration.configurationType.JSON, DateTime.now()); + extensionConfigurationDao.addConfiguration(extensionConfiguration); + + } else { + // Get configuration object + this.sid = extensionConfiguration.getSid(); + // try get default config data + JsonObject dbConfiguration = null; + + DefaultArtifactVersion currentVersion = null; + try { + dbConfiguration = (JsonObject) jsonParser.parse((String) extensionConfiguration.getConfigurationData()); + if (dbConfiguration.get("version") != null) { + currentVersion = new DefaultArtifactVersion(dbConfiguration.get("version").getAsString()); + } + + if (dbConfiguration != null && (currentVersion == null || currentVersion.compareTo(defVersion) < 0)) { + if (logger.isInfoEnabled()) { + logger.info("Configuration found in the DB is older version than the default one: " + + defVersion.toString()); + } + + for (Map.Entry jsonElementEntry : defaultConfigurationJsonObj.entrySet()) { + if (!jsonElementEntry.getKey().equalsIgnoreCase("specifics_configuration") + && dbConfiguration.get(jsonElementEntry.getKey()) == null) { + dbConfiguration.add(jsonElementEntry.getKey(), jsonElementEntry.getValue()); + } + } + if (dbConfiguration.get("version") != null) { + dbConfiguration.remove("version"); + } + dbConfiguration.addProperty("version", defaultConfigurationJsonObj.get("version").getAsString()); + + extensionConfiguration = new ExtensionConfiguration(extensionConfiguration.getSid(), extensionName, + extensionConfiguration.isEnabled(), dbConfiguration.toString(), + ExtensionConfiguration.configurationType.JSON, DateTime.now()); + extensionConfigurationDao.updateConfiguration(extensionConfiguration); + } + configurationJsonObj = dbConfiguration; + // Load Specific Configuration Map + // loadSpecificConfigurationMap(configurationJsonObj); + } catch (Exception e) { + } + + } + if (logger.isInfoEnabled()) { + logger.info("Finished loading configuration for extension: " + extensionName); + } + } catch (ConfigurationException configurationException) { + String errorMessage = "Exception during " + this.getClass() + " Configuration constructor "; + if (logger.isDebugEnabled()) { + logger.debug(errorMessage + configurationException); + } + throw new ConfigurationException(errorMessage); + } catch (PersistenceException persistenceException) { + if (logger.isDebugEnabled()) { + logger.debug("PersistenceException during " + this.getClass() + " init, will fallback to default configuration"); + } + workingWithLocalConf = true; + } catch (IOException e) { + logger.debug("IOException during " + this.getClass()); + } + } + + public JsonObject loadDefaultConfiguration(String localConfigFilePath) throws IOException { + JsonObject jsonObj = null; + jsonParser = new JsonParser(); + InputStream in = (InputStream) getClass().getResourceAsStream(localConfigFilePath); + BufferedReader inReader = new BufferedReader(new InputStreamReader(in)); + JsonReader reader = new JsonReader(inReader); + JsonElement jsonElement = jsonParser.parse(reader); + jsonObj = (JsonObject) jsonElement; + in.close(); + inReader.close(); + reader.close(); + return jsonObj; + } + + public void reloadConfiguration() { + if (!workingWithLocalConf) { + if (extensionConfigurationDao.isLatestVersionByName(extensionName, extensionConfiguration.getDateUpdated())) { + extensionConfiguration = extensionConfigurationDao.getConfigurationByName(extensionName); + String updatedConf = (String) extensionConfiguration.getConfigurationData(); + configurationJsonObj = (JsonObject) jsonParser.parse(updatedConf); + // loadSpecificConfigurationMap(configurationJsonObj); + if (logger.isInfoEnabled()) { + logger.info(this.extensionName + " extension configuration reloaded"); + } + } + } + } + + public boolean isEnabled() { + reloadConfiguration(); + if (extensionConfiguration != null) { + return extensionConfiguration.isEnabled(); + } else { + return true; + } + } + + public String getVersion() { + reloadConfiguration(); + String ver = configurationJsonObj.get(PropertyType.VERSION.value).getAsString(); + return ver; + } + + public Sid getSid() { + return this.sid; + } + + public void loadSpecificConfigurationMap(final JsonObject json) { + JsonArray specificConfJsonArray = json.getAsJsonArray(); + // JsonArray specificConfJsonArray = json.getAsJsonArray("specifics_configuration"); + // if (specificConfJsonArray != null) { + // specificConfigurationMap = new HashMap(); + // Iterator iter = specificConfJsonArray.iterator(); + // while (iter.hasNext()) { + // JsonElement elem = iter.next(); + // if (elem.getAsJsonObject().get("sid") != null) { + // specificConfigurationMap.put(sid, value); + // } + // } + // } + // return map + } + + // getConfigAsJson + // getConfigAsConfiguration + // getConfigAsHashMap + /*public void getSpecificConfigurationMapAsXml() { + }*/ + + /** + * @return the daoManager + */ + public DaoManager getDaoManager() { + return daoManager; + } + + /** + * @param daoManager the daoManager to set + */ + public void setDaoManager(DaoManager daoManager) { + this.daoManager = daoManager; + } +} 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 3e253823c4..0668660738 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,5 +1,6 @@ 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.MessageExtensionResponse; @@ -88,7 +89,7 @@ public void registerExtension(final RestcommExtensionGeneric extension) { } } - public ExtensionResponse executePreOutboundAction(final Object er, List extensions) { + public ExtensionResponse executePreOutboundAction(final ExtensionRequest er, List extensions) { //FIXME: if we have more than one extension in chain // and all of them are successful, we only receive the last // extensionResponse 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 80985507a9..86ff8949a9 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,11 +49,6 @@ 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.SystemExtensionResponse; -import org.restcomm.connect.extension.api.NodeExtensionResponse; -import org.restcomm.connect.extension.api.TransactionExtensionResponse; -import org.restcomm.connect.extension.api.SessionExtensionResponse; -import org.restcomm.connect.extension.api.MessageExtensionResponse; import org.restcomm.connect.extension.api.ExtensionType; import org.restcomm.connect.extension.api.RestcommExtensionException; import org.restcomm.connect.extension.api.RestcommExtensionGeneric; @@ -66,7 +61,7 @@ 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.sms.api.SmsSessionRequest.Encoding; + import org.restcomm.connect.telephony.api.TextMessage; import org.restcomm.connect.telephony.api.util.B2BUAHelper; import org.restcomm.connect.telephony.api.util.CallControlHelper; diff --git a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java index 6f78ed20b7..4b4cc4f3b2 100644 --- a/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java +++ b/restcomm/restcomm.sms/src/main/java/org/restcomm/connect/sms/SmsSession.java @@ -35,7 +35,6 @@ import org.restcomm.connect.sms.api.SmsSessionInfo; import org.restcomm.connect.sms.api.SmsSessionRequest; import org.restcomm.connect.sms.api.SmsSessionResponse; -import org.restcomm.connect.sms.api.SmsSessionRequest.Encoding; import org.restcomm.connect.dao.ClientsDao; import org.restcomm.connect.dao.DaoManager; import org.restcomm.connect.dao.RegistrationsDao; 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 797a415279..a434af6ad7 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 @@ -30,13 +30,8 @@ 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.MessageExtensionResponse; -import org.restcomm.connect.extension.api.NodeExtensionResponse; import org.restcomm.connect.extension.api.RestcommExtensionException; 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.restcomm.connect.extension.controller.ExtensionController; import org.restcomm.connect.interpreter.StartInterpreter; import org.restcomm.connect.monitoringservice.MonitoringService; 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 da76d16b7b..bc9bc7eda5 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 @@ -30,10 +30,13 @@ import akka.event.Logging; import akka.event.LoggingAdapter; import akka.util.Timeout; + import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; + import gov.nist.javax.sip.header.UserAgent; + import org.apache.commons.configuration.Configuration; import org.joda.time.DateTime; import org.restcomm.connect.commons.configuration.RestcommConfiguration; @@ -57,6 +60,7 @@ 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.RestcommExtensionException; @@ -86,6 +90,7 @@ import org.restcomm.connect.telephony.api.UpdateCallScript; import org.restcomm.connect.telephony.api.util.B2BUAHelper; import org.restcomm.connect.telephony.api.util.CallControlHelper; + import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; @@ -105,6 +110,7 @@ import javax.servlet.sip.TelURL; import javax.sip.header.RouteHeader; import javax.sip.message.Response; + import java.io.IOException; import java.net.InetAddress; import java.net.URI; @@ -476,9 +482,14 @@ private void invite(final Object message) throws IOException, NumberParseExcepti if(logger.isInfoEnabled()) { 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); - if (executePreOutboundAction(callRequest)) { + ExtensionController ec = ExtensionController.getInstance(); + ExtensionRequest er = new ExtensionRequest(); + er.setObject(callRequest); + ExtensionResponse extensionResponse = ec.executePreOutboundAction(er, this.extensions); + if (extensionResponse.isAllowed()) { if (B2BUAHelper.redirectToB2BUA(request, client, toClient, storage, sipFactory, patchForNatB2BUASessions)) { if(logger.isInfoEnabled()) { logger.info("Call to CLIENT. myHostIp: " + myHostIp + " mediaExternalIp: " + mediaExternalIp + " toHost: " @@ -505,7 +516,7 @@ private void invite(final Object message) throws IOException, NumberParseExcepti final SipServletResponse resp = request.createResponse(SC_FORBIDDEN, "Call not allowed"); resp.send(); } - executePostOutboundAction(callRequest); + ec.executePostOutboundAction(callRequest, 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 @@ -536,7 +547,11 @@ private void invite(final Object message) throws IOException, NumberParseExcepti 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); - if (executePreOutboundAction(callRequest)) { + ExtensionController ec = ExtensionController.getInstance(); + ExtensionRequest er = new ExtensionRequest(); + 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); } else { final SipServletResponse response = request.createResponse(SC_FORBIDDEN, "Call request not allowed"); @@ -545,7 +560,7 @@ private void invite(final Object message) throws IOException, NumberParseExcepti logger.debug("Call request now allowed: "+callRequest.toString()); } } - executePostOutboundAction(callRequest); + ec.executePostOutboundAction(callRequest, 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."; @@ -1484,9 +1499,13 @@ 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); switch (request.type()) { case CLIENT: { - if (executePreOutboundAction(callRequest)) { + if (extensionResponse.isAllowed()) { outboundToClient(request, sender); } else { //Extensions didn't allowed this call @@ -1494,11 +1513,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()); } - executePostOutboundAction(callRequest); + ec.executePostOutboundAction(callRequest, this.extensions); break; } case PSTN: { - if (executePreOutboundAction(callRequest)) { + if (extensionResponse.isAllowed()) { outboundToPstn(request, sender); } else { //Extensions didn't allowed this call @@ -1506,14 +1525,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()); } - executePostOutboundAction(callRequest); + ec.executePostOutboundAction(callRequest, this.extensions); break; } case SIP: { if (actAsImsUa) { outboundToIms(request, sender); } - else if (executePreOutboundAction(callRequest)) { + else if (extensionResponse.isAllowed()) { outboundToSip(request, sender); } else { //Extensions didn't allowed this call @@ -1521,29 +1540,12 @@ else if (executePreOutboundAction(callRequest)) { logger.warning(errMsg); sender.tell(new CallManagerResponse(new RestcommExtensionException(errMsg), this.createCallRequest), self()); } - executePostOutboundAction(callRequest); + ec.executePostOutboundAction(callRequest, this.extensions); break; } } } - private boolean executePreOutboundAction(final Object message) { - if (extensions != null && extensions.size() > 0) { - for (RestcommExtensionGeneric extension : extensions) { - if (extension.isEnabled()) { - ExtensionResponse response = extension.preOutboundAction(message); - if (!response.isAllowed()) - return false; - } - } - } - return true; - } - - private boolean executePostOutboundAction(final CallRequest callRequest) { - return false; - } - private void outboundToClient(final CreateCall request, final ActorRef sender) throws ServletParseException { SipURI outboundIntf = null; SipURI from = null;