├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── freeswitch-cdr-example └── pom.xml ├── freeswitch-cdr-spring-boot-starter-example └── pom.xml ├── freeswitch-cdr-spring-boot-starter └── pom.xml ├── freeswitch-cdr └── pom.xml ├── freeswitch-esl-example ├── pom.xml └── src │ └── main │ └── java │ └── link │ └── thingscloud │ └── freeswitch │ └── esl │ └── example │ └── EslInboundClientExample.java ├── freeswitch-esl-spring-boot-starter-example ├── pom.xml └── src │ ├── main │ ├── java │ │ └── link │ │ │ └── thingscloud │ │ │ └── freeswitch │ │ │ └── esl │ │ │ └── spring │ │ │ └── boot │ │ │ └── starter │ │ │ └── example │ │ │ ├── ExampleApplication.java │ │ │ ├── ExampleInboundClient.java │ │ │ ├── ExampleInboundClientOptionHandler.java │ │ │ ├── HeartbeatEslEventHandler.java │ │ │ ├── ReScheduleEslEventHandler.java │ │ │ ├── ServerConnectionListenerImpl.java │ │ │ └── controller │ │ │ └── DemoController.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── link │ └── thingscloud │ └── freeswitch │ └── esl │ └── spring │ └── boot │ └── starter │ └── example │ └── ExampleApplicationTests.java ├── freeswitch-esl-spring-boot-starter ├── pom.xml └── src │ └── main │ ├── java │ └── link │ │ └── thingscloud │ │ └── freeswitch │ │ └── esl │ │ └── spring │ │ └── boot │ │ └── starter │ │ ├── EnableFreeswitchEslAutoConfiguration.java │ │ ├── annotation │ │ └── EslEventName.java │ │ ├── config │ │ └── FreeswitchEslAutoConfiguration.java │ │ ├── handler │ │ ├── AbstractEslEventHandler.java │ │ ├── AbstractInboundClientOptionHandler.java │ │ ├── DefaultEslEventHandler.java │ │ ├── EslEventHandler.java │ │ └── InboundClientOptionHandler.java │ │ ├── properties │ │ ├── InboundClientProperties.java │ │ └── ServerProperties.java │ │ └── template │ │ ├── DefaultInboundClientOptionHandlerTemplate.java │ │ ├── IEslEventListenerTemplate.java │ │ └── ServerConnectionListenerTemplate.java │ └── resources │ └── META-INF │ ├── spring.factories │ └── spring │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports ├── freeswitch-esl ├── pom.xml └── src │ ├── main │ └── java │ │ └── link │ │ └── thingscloud │ │ └── freeswitch │ │ └── esl │ │ ├── IEslEventListener.java │ │ ├── InboundClient.java │ │ ├── InboundClientBootstrap.java │ │ ├── InboundClientFactory.java │ │ ├── InboundClientService.java │ │ ├── ServerConnectionListener.java │ │ ├── constant │ │ ├── Constants.java │ │ ├── EventNames.java │ │ └── VariableConstant.java │ │ ├── exception │ │ ├── EslDecoderException.java │ │ ├── InboundClientException.java │ │ └── InboundTimeoutExcetion.java │ │ ├── helper │ │ ├── CommandHelper.java │ │ └── EslHelper.java │ │ ├── inbound │ │ ├── AbstractInboundClient.java │ │ ├── AbstractNettyInboundClient.java │ │ ├── NettyInboundClient.java │ │ ├── handler │ │ │ └── InboundChannelHandler.java │ │ ├── listener │ │ │ ├── ChannelEventListener.java │ │ │ ├── EventListener.java │ │ │ └── ServerOptionListener.java │ │ └── option │ │ │ ├── ConnectState.java │ │ │ ├── InboundClientOption.java │ │ │ ├── ServerAddrOption.java │ │ │ └── ServerOption.java │ │ ├── transport │ │ ├── CommandResponse.java │ │ ├── SendEvent.java │ │ ├── SendMsg.java │ │ ├── event │ │ │ ├── EslEvent.java │ │ │ └── EslEventHeaderNames.java │ │ ├── message │ │ │ ├── EslFrameDecoder.java │ │ │ ├── EslHeaders.java │ │ │ └── EslMessage.java │ │ └── util │ │ │ ├── ByteBuilder.java │ │ │ └── HeaderParser.java │ │ └── util │ │ ├── ArrayUtils.java │ │ ├── EslEventUtil.java │ │ ├── RandomUtils.java │ │ ├── RemotingUtil.java │ │ ├── StringUtils.java │ │ ├── Validate.java │ │ └── VariableUtil.java │ └── test │ └── java │ └── link │ └── thingscloud │ └── freeswitch │ └── esl │ ├── helper │ └── CommandHelperTest.java │ └── transport │ └── util │ └── ByteBuilderTest.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | 20 | ### NetBeans ### 21 | /nbproject/private/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ 26 | /build/ 27 | 28 | ### VS Code ### 29 | .vscode/ 30 | 31 | pom.xml.versionsBackup -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreeSWITCH ESL ALL 2 | 3 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/23fb13f7487f4ccd985f09c96341dfab)](https://app.codacy.com/gh/zhouhailin/freeswitch-esl-all?utm_source=github.com&utm_medium=referral&utm_content=zhouhailin/freeswitch-esl-all&utm_campaign=Badge_Grade_Settings) 4 | [![Jdk Version](https://img.shields.io/badge/JDK-8-green.svg)](https://img.shields.io/badge/JDK-8-green.svg) 5 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0) 6 | [![Maven Central](https://img.shields.io/maven-central/v/link.thingscloud/freeswitch-esl-all)](https://mvnrepository.com/artifact/link.thingscloud/freeswitch-esl-all) 7 | [![Gitter](https://badges.gitter.im/freeswitch-esl-all/community.svg)](https://gitter.im/freeswitch-esl-all/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 8 | 9 | ## Summary 10 | 11 | JDK 1.8 + 12 | 13 | Netty used 4.1.x, 5.x is not supported 14 | 15 | ## Features 16 | 17 | 1. Support to connect FreeSWITCH Cluster 18 | 2. Easy to integrate with FreeSWITCH ESL 19 | 3. Support spring boot starter 20 | 4. Support to dynamic add or remove remote server 21 | 22 | ## Maven 23 | 24 | 25 | link.thingscloud 26 | freeswitch-esl 27 | ${freeswitch-esl.version} 28 | 29 | 30 | ## Quick Start 31 | 32 | ### freeswitch-esl-spring-boot-starter 33 | 34 | [Maven Central](https://mvnrepository.com/artifact/link.thingscloud/freeswitch-esl-spring-boot-starter) 35 | 36 | ```xml 37 | 38 | 39 | link.thingscloud 40 | freeswitch-esl-spring-boot-starter 41 | ${freeswitch-esl.version} 42 | 43 | ``` 44 | 45 | application.properties 46 | 47 | ```properties 48 | link.thingscloud.freeswitch.esl.inbound.servers[0].host=127.0.0.1 49 | link.thingscloud.freeswitch.esl.inbound.servers[0].port=8021 50 | link.thingscloud.freeswitch.esl.inbound.servers[0].timeout-seconds=5 51 | link.thingscloud.freeswitch.esl.inbound.servers[0].password=ClueCon 52 | link.thingscloud.freeswitch.esl.inbound.servers[2].host=127.0.0.2 53 | link.thingscloud.freeswitch.esl.inbound.servers[2].port=8021 54 | link.thingscloud.freeswitch.esl.inbound.servers[2].timeout-seconds=5 55 | link.thingscloud.freeswitch.esl.inbound.events=CHANNEL_CREATE CHANNEL_DESTORY 56 | # performance monitor - event driven - business logic processing time 57 | link.thingscloud.freeswitch.esl.inbound.performance=true 58 | link.thingscloud.freeswitch.esl.inbound.performanceCostTime=200 59 | # event performance monitor - event driven - event generate time and event receive time 60 | link.thingscloud.freeswitch.esl.inbound.eventPerformance=false 61 | link.thingscloud.freeswitch.esl.inbound.eventPerformanceCostTime=200 62 | ``` 63 | 64 | application.yml 65 | 66 | ```yaml 67 | link: 68 | thingscloud: 69 | freeswitch: 70 | esl: 71 | inbound: 72 | defaultPassword: ClueCon 73 | performance: false 74 | performanceCostTime: 200 75 | #read-timeout-seconds: 0 76 | servers: 77 | - host: 127.0.0.1 78 | port: 8021 79 | timeoutSeconds: 5 80 | - host: 127.0.0.2 81 | - host: 127.0.0.3 82 | events: 83 | - CHANNEL_CREATE 84 | - CHANNEL_DESTORY 85 | ``` 86 | 87 | ```java 88 | 89 | @Slf4j 90 | @Component 91 | public class ExampleInboundClient { 92 | @Autowired 93 | private InboundClient inboundClient; 94 | 95 | @Autowired 96 | private InboundClientBootstrap inboundClientBootstrap; 97 | 98 | @PostConstruct 99 | public void startup() { 100 | System.out.println(inboundClientBootstrap); 101 | } 102 | 103 | } 104 | ``` 105 | 106 | ```java 107 | 108 | @Slf4j 109 | @Component 110 | public class InboundClientOptionHandlerExample extends AbstractInboundClientOptionHandler { 111 | 112 | /** 113 | * {@inheritDoc} 114 | */ 115 | @Override 116 | protected void intercept(InboundClientOption inboundClientOption) { 117 | List serverOptions = inboundClientOption.serverOptions(); 118 | log.info("serverOptions before : {}", serverOptions); 119 | serverOptions.clear(); 120 | serverOptions.add(new ServerOption("127.0.0.8", 8021)); 121 | log.info("serverOptions after : {}", serverOptions); 122 | } 123 | } 124 | ``` 125 | 126 | ```java 127 | 128 | @Slf4j 129 | @Component 130 | @EslEventName(EventNames.HEARTBEAT) 131 | public class HeartbeatEslEventHandler implements EslEventHandler { 132 | /** 133 | * {@inheritDoc} 134 | */ 135 | @Override 136 | public void handle(String addr, EslEvent event) { 137 | log.info("HeartbeatEslEventHandler handle addr[{}] EslEvent[{}].", addr, event); 138 | } 139 | } 140 | ``` 141 | 142 | ```java 143 | 144 | @Slf4j 145 | @Service 146 | public class ServerConnectionListenerImpl implements ServerConnectionListener { 147 | /** 148 | * {@inheritDoc} 149 | */ 150 | @Override 151 | public void onOpened(ServerOption serverOption) { 152 | log.info("onOpened serverOption : {}", serverOption); 153 | } 154 | 155 | /** 156 | * {@inheritDoc} 157 | */ 158 | @Override 159 | public void onClosed(ServerOption serverOption) { 160 | log.info("onClosed serverOption : {}", serverOption); 161 | } 162 | } 163 | ``` 164 | 165 | ### freeswitch-esl 166 | 167 | [Maven Central](https://mvnrepository.com/artifact/link.thingscloud/freeswitch-esl) 168 | 169 | ```xml 170 | 171 | 172 | link.thingscloud 173 | freeswitch-esl 174 | ${freeswitch-esl.version} 175 | 176 | ``` 177 | 178 | ``` 179 | InboundClientOption option = new InboundClientOption(); 180 | 181 | // set default esl password, if ServerOption not set password, use this default value 182 | option.defaultPassword("ClueCon") 183 | .addServerOption(new ServerOption("127.0.0.1", 8021)); 184 | 185 | // set esl subscribe events 186 | option.addEvents("all"); 187 | 188 | // ESL event listener 189 | option.addListener(new IEslEventListener() { 190 | @Override 191 | public void eventReceived(String addr, EslEvent event) { 192 | System.out.println(addr); 193 | System.out.println(event); 194 | } 195 | 196 | @Override 197 | public void backgroundJobResultReceived(String addr, EslEvent event) { 198 | System.out.println(addr); 199 | System.out.println(event); 200 | } 201 | }); 202 | 203 | option.serverConnectionListener(new ServerConnectionListener() { 204 | @Override 205 | public void onOpened(ServerOption serverOption) { 206 | System.out.println("---onOpened--"); 207 | } 208 | 209 | @Override 210 | public void onClosed(ServerOption serverOption) { 211 | System.out.println("---onClosed--"); 212 | } 213 | }); 214 | 215 | InboundClient inboundClient = InboundClient.newInstance(option); 216 | 217 | // start client 218 | inboundClient.start(); 219 | 220 | // shutdown client, after shutdown, can't start again, shutdown with JVM 221 | inboundClient.shutdown(); 222 | ``` 223 | 224 | ``` 225 | // Get InboundClient Instance 226 | InboundClient inboundClient = InboundClient.getInstance(); 227 | 228 | // Get InboundClient FreeSWITCH API 229 | InboundClient.getBootstrap() 230 | ``` 231 | 232 | ``` 233 | // add server option 234 | inboundClient.option().addServerOption(new ServerOption(host, port)); 235 | // InboundClient.getInstance().option().addServerOption(new ServerOption(host, port)); 236 | 237 | // remove server option 238 | ServerOption serverOption = inboundClient.option().serverOptions().get(0); 239 | inboundClient.option().removeServerOption(serverOption); 240 | // InboundClient.getInstance().option().removeServerOption(serverOption); 241 | 242 | ``` 243 | 244 | ## Star history 245 | 246 | [![Star History Chart](https://api.star-history.com/svg?repos=zhouhailin/freeswitch-externals&type=Date)](https://star-history.com/#zhouhailin/freeswitch-externals&Date) 247 | 248 | ## Notice 249 | 250 | 1. Send api is recommended to use asynchronous operation, especially the originate command 251 | 2. There is a message timeout mechanism at present to deal with the false death of the connection caused by the direct shutdown of the server. Set the value of readTimeoutSeconds parameter to 0 to turn off this feature 252 | 3. In order to improve performance, when processing EslEvent, use Netty's worker thread. If the processing logic involves IO or time-consuming operation, the processing logic must be put in a new thread to process, and the disablePublicExecutor parameter is set 253 | 254 | ## WeChat User Groups - Please note the source 255 | 256 | ![WeChat](https://gitee.com/zhouhailin/images/raw/master/a0eb627b9b6bc1c6da8f19d3292ebce.jpg) 257 | 258 | ## LICENSE 259 | 260 | [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) Copyright (C) Apache Software Foundation 261 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /freeswitch-cdr-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | link.thingscloud 8 | freeswitch-externals 9 | 2.3.0-SNAPSHOT 10 | 11 | 12 | freeswitch-cdr-example 13 | freeswitch-cdr-example-${project.version} 14 | Example project for Freeswitch Cdr 15 | 16 | 17 | 18 | ${project.groupId} 19 | freeswitch-cdr 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /freeswitch-cdr-spring-boot-starter-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | link.thingscloud 8 | freeswitch-externals 9 | 2.3.0-SNAPSHOT 10 | 11 | 12 | freeswitch-cdr-spring-boot-starter-example 13 | freeswitch-cdr-spring-boot-starter-example-${project.version} 14 | 15 | Example project for Freeswitch Cdr Spring Boot Starter 16 | 17 | 18 | 19 | ${project.groupId} 20 | freeswitch-cdr-spring-boot-starter 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-devtools 30 | runtime 31 | true 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /freeswitch-cdr-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | link.thingscloud 8 | freeswitch-externals 9 | 2.3.0-SNAPSHOT 10 | 11 | 12 | freeswitch-cdr-spring-boot-starter 13 | freeswitch-cdr-spring-boot-starter-${project.version} 14 | Freeswitch Cdr Spring Boot Starter 15 | 16 | 17 | 18 | ${project.groupId} 19 | freeswitch-cdr 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-configuration-processor 24 | true 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-autoconfigure 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /freeswitch-cdr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | link.thingscloud 8 | freeswitch-externals 9 | 2.3.0-SNAPSHOT 10 | 11 | 12 | freeswitch-cdr 13 | freeswitch-cdr-${project.version} 14 | freeswitch Call Detail Record 15 | 16 | 17 | 18 | org.dom4j 19 | dom4j 20 | 21 | 22 | 23 | org.slf4j 24 | slf4j-api 25 | 26 | 27 | ch.qos.logback 28 | logback-core 29 | 30 | 31 | ch.qos.logback 32 | logback-classic 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /freeswitch-esl-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 21 | link.thingscloud 22 | freeswitch-externals 23 | 2.3.0-SNAPSHOT 24 | 25 | 4.0.0 26 | 27 | freeswitch-esl-example 28 | freeswitch-esl-example-${project.version} 29 | Example project for Freeswitch Esl 30 | 31 | 32 | 33 | ${project.groupId} 34 | freeswitch-esl 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /freeswitch-esl-example/src/main/java/link/thingscloud/freeswitch/esl/example/EslInboundClientExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.example; 17 | 18 | import link.thingscloud.freeswitch.esl.IEslEventListener; 19 | import link.thingscloud.freeswitch.esl.InboundClient; 20 | import link.thingscloud.freeswitch.esl.ServerConnectionListener; 21 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 22 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 23 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 24 | 25 | /** 26 | *

EslInboundClientExample class.

27 | * 28 | * @author : zhouhailin 29 | * @version 1.0.0 30 | */ 31 | public class EslInboundClientExample { 32 | 33 | /** 34 | *

main.

35 | * 36 | * @param args an array of {@link java.lang.String} objects. 37 | */ 38 | public static void main(String[] args) { 39 | InboundClientOption option = new InboundClientOption(); 40 | 41 | option.defaultPassword("ClueCon") 42 | .addServerOption(new ServerOption("172.16.44.246", 8021)); 43 | option.addEvents("all"); 44 | 45 | option.addListener(new IEslEventListener() { 46 | @Override 47 | public void eventReceived(String addr, EslEvent event) { 48 | System.out.println(addr); 49 | System.out.println(event); 50 | } 51 | 52 | @Override 53 | public void backgroundJobResultReceived(String addr, EslEvent event) { 54 | System.out.println(addr); 55 | System.out.println(event); 56 | } 57 | }); 58 | 59 | option.serverConnectionListener(new ServerConnectionListener() { 60 | @Override 61 | public void onOpened(ServerOption serverOption) { 62 | System.out.println("---onOpened--"); 63 | } 64 | 65 | @Override 66 | public void onClosed(ServerOption serverOption) { 67 | System.out.println("---onClosed--"); 68 | } 69 | }); 70 | 71 | InboundClient inboundClient = InboundClient.newInstance(option); 72 | 73 | inboundClient.start(); 74 | 75 | 76 | System.out.println(option.serverAddrOption().first()); 77 | System.out.println(option.serverAddrOption().last()); 78 | System.out.println(option.serverAddrOption().random()); 79 | 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 19 | 4.0.0 20 | 21 | link.thingscloud 22 | freeswitch-externals 23 | 2.3.0-SNAPSHOT 24 | 25 | 26 | freeswitch-esl-spring-boot-starter-example 27 | freeswitch-esl-spring-boot-starter-example-${project.version} 28 | 29 | Example project for Freeswitch Esl Spring Boot Starter 30 | 31 | 32 | 33 | ${project.groupId} 34 | freeswitch-esl-spring-boot-starter 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-devtools 44 | runtime 45 | true 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/ExampleApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | 21 | //@EnableFreeswitchEslAutoConfiguration 22 | 23 | /** 24 | *

FreeswitchEslSpringBootStarterExampleApplication class.

25 | * 26 | * @author zhouhl 27 | * @version 1.0.0 28 | */ 29 | @SpringBootApplication 30 | public class ExampleApplication { 31 | 32 | /** 33 | *

main.

34 | * 35 | * @param args an array of {@link java.lang.String} objects. 36 | */ 37 | public static void main(String[] args) { 38 | SpringApplication.run(ExampleApplication.class, args); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/ExampleInboundClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import link.thingscloud.freeswitch.esl.InboundClient; 19 | import link.thingscloud.freeswitch.esl.InboundClientBootstrap; 20 | import lombok.extern.slf4j.Slf4j; 21 | import org.springframework.beans.factory.InitializingBean; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.stereotype.Component; 24 | 25 | /** 26 | * @author zhouhailin 27 | */ 28 | @Slf4j 29 | @Component 30 | public class ExampleInboundClient implements InitializingBean { 31 | @Autowired 32 | private InboundClient inboundClient; 33 | 34 | @Autowired 35 | private InboundClientBootstrap inboundClientBootstrap; 36 | 37 | @Override 38 | public void afterPropertiesSet() throws Exception { 39 | System.out.println(inboundClientBootstrap); 40 | } 41 | 42 | // public void hold() { 43 | // inboundClient.hold("", ""); 44 | // } 45 | // 46 | // public void record() { 47 | // inboundClient.record("", "", "", "", 1); 48 | // } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/ExampleInboundClientOptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 19 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 20 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.AbstractInboundClientOptionHandler; 21 | import lombok.extern.slf4j.Slf4j; 22 | import org.springframework.stereotype.Component; 23 | 24 | import java.util.List; 25 | 26 | /** 27 | *

ExampleInboundClientOptionHandler class.

28 | * 29 | * @author zhouhailin 30 | * @version 1.0.0 31 | */ 32 | @Slf4j 33 | @Component 34 | public class ExampleInboundClientOptionHandler extends AbstractInboundClientOptionHandler { 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | protected void intercept(InboundClientOption inboundClientOption) { 41 | List serverOptions = inboundClientOption.serverOptions(); 42 | log.info("serverOptions before : {}", serverOptions); 43 | // serverOptions.clear(); 44 | // serverOptions.add(new ServerOption("127.0.0.8", 8021)); 45 | // log.info("serverOptions after : {}", serverOptions); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/HeartbeatEslEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import link.thingscloud.freeswitch.esl.constant.EventNames; 19 | import link.thingscloud.freeswitch.esl.spring.boot.starter.annotation.EslEventName; 20 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.EslEventHandler; 21 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 22 | import lombok.extern.slf4j.Slf4j; 23 | import org.springframework.stereotype.Component; 24 | 25 | /** 26 | *

HeartbeatEslEventHandler class.

27 | * 28 | * @author : zhouhailin 29 | * @version 1.0.0 30 | */ 31 | @Slf4j 32 | @Component 33 | @EslEventName(EventNames.HEARTBEAT) 34 | public class HeartbeatEslEventHandler implements EslEventHandler { 35 | /** 36 | * {@inheritDoc} 37 | */ 38 | @Override 39 | public void handle(String addr, EslEvent event) { 40 | log.info("HeartbeatEslEventHandler handle addr[{}] EslEvent[{}].", addr, event); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/ReScheduleEslEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import link.thingscloud.freeswitch.esl.InboundClient; 19 | import link.thingscloud.freeswitch.esl.constant.EventNames; 20 | import link.thingscloud.freeswitch.esl.helper.EslHelper; 21 | import link.thingscloud.freeswitch.esl.spring.boot.starter.annotation.EslEventName; 22 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.AbstractEslEventHandler; 23 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 24 | import link.thingscloud.freeswitch.esl.transport.message.EslMessage; 25 | import lombok.extern.slf4j.Slf4j; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Component; 28 | 29 | /** 30 | *

ReScheduleEslEventHandler class.

31 | * 32 | * @author : zhouhailin 33 | * @version 1.0.0 34 | */ 35 | @Slf4j 36 | @EslEventName(EventNames.RE_SCHEDULE) 37 | @Component 38 | public class ReScheduleEslEventHandler extends AbstractEslEventHandler { 39 | 40 | @Autowired 41 | private InboundClient inboundClient; 42 | 43 | /** 44 | * {@inheritDoc} 45 | */ 46 | @Override 47 | public void handle(String addr, EslEvent event) { 48 | log.info("ReScheduleEslEventHandler handle addr[{}] EslEvent[{}].", addr, event); 49 | log.info("{}", inboundClient); 50 | EslMessage eslMessage = inboundClient.sendSyncApiCommand(addr, "version", null); 51 | log.info("{}", EslHelper.formatEslMessage(eslMessage)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/ServerConnectionListenerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import link.thingscloud.freeswitch.esl.ServerConnectionListener; 19 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 20 | import lombok.extern.slf4j.Slf4j; 21 | import org.springframework.stereotype.Service; 22 | 23 | /** 24 | *

ServerConnectionListenerImpl class.

25 | * 26 | * @author : zhouhailin 27 | * @version 1.0.0 28 | */ 29 | @Slf4j 30 | @Service 31 | public class ServerConnectionListenerImpl implements ServerConnectionListener { 32 | /** 33 | * {@inheritDoc} 34 | */ 35 | @Override 36 | public void onOpened(ServerOption serverOption) { 37 | log.info("onOpened serverOption : {}", serverOption); 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | */ 43 | @Override 44 | public void onClosed(ServerOption serverOption) { 45 | log.info("onClosed serverOption : {}", serverOption); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/controller/DemoController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example.controller; 17 | 18 | import link.thingscloud.freeswitch.esl.InboundClient; 19 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.web.bind.annotation.GetMapping; 22 | import org.springframework.web.bind.annotation.RequestMapping; 23 | import org.springframework.web.bind.annotation.RestController; 24 | 25 | /** 26 | *

DemoController class.

27 | * 28 | * @author : zhouhailin 29 | * @version 1.0.0 30 | */ 31 | @RestController 32 | @RequestMapping("/demo") 33 | public class DemoController { 34 | 35 | @Autowired 36 | private InboundClient inboundClient; 37 | 38 | /** 39 | *

demo.

40 | * 41 | * @return a {@link java.lang.String} object. 42 | */ 43 | @GetMapping("/demo") 44 | public String demo() { 45 | return "demo"; 46 | } 47 | 48 | /** 49 | *

addServer1.

50 | * 51 | * @param host a {@link java.lang.String} object. 52 | * @param port a int. 53 | */ 54 | @GetMapping("/addServer1") 55 | public void addServer1(String host, int port) { 56 | InboundClient.getInstance().option().addServerOption(new ServerOption(host, port)); 57 | } 58 | 59 | /** 60 | *

addServer2.

61 | * 62 | * @param host a {@link java.lang.String} object. 63 | * @param port a int. 64 | */ 65 | @GetMapping("/addServer2") 66 | public void addServer2(String host, int port) { 67 | inboundClient.option().addServerOption(new ServerOption(host, port)); 68 | } 69 | 70 | /** 71 | *

removeServer1.

72 | */ 73 | @GetMapping("/removeServer1") 74 | public void removeServer1() { 75 | ServerOption serverOption = inboundClient.option().serverOptions().get(0); 76 | inboundClient.option().removeServerOption(serverOption); 77 | } 78 | 79 | /** 80 | *

serverOptions.

81 | * 82 | * @return a {@link java.lang.String} object. 83 | */ 84 | @GetMapping("/serverOptions") 85 | public String serverOptions() { 86 | return inboundClient.option().serverOptions().toString(); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | link: 2 | thingscloud: 3 | freeswitch: 4 | esl: 5 | inbound: 6 | defaultPassword: ClueCon 7 | performance: false 8 | performanceCostTime: 200 9 | servers: 10 | - host: 172.16.44.246 11 | port: 8021 12 | timeoutSeconds: 5 13 | - host: 127.0.0.1 14 | port: 8021 15 | events: 16 | - all 17 | #logging: 18 | # level: 19 | # link: DEBUG 20 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter-example/src/test/java/link/thingscloud/freeswitch/esl/spring/boot/starter/example/ExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.example; 17 | 18 | import org.junit.Test; 19 | import org.junit.runner.RunWith; 20 | import org.springframework.boot.test.context.SpringBootTest; 21 | import org.springframework.test.context.junit4.SpringRunner; 22 | 23 | /** 24 | *

ExampleApplicationTests class.

25 | * 26 | * @author zhouhailin 27 | * @version 1.0.0 28 | * @since 1.4.0.SNAPSHOT 29 | */ 30 | @RunWith(SpringRunner.class) 31 | @SpringBootTest 32 | public class ExampleApplicationTests { 33 | 34 | /** 35 | *

contextLoads.

36 | */ 37 | @Test 38 | public void contextLoads() { 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 21 | link.thingscloud 22 | freeswitch-externals 23 | 2.3.0-SNAPSHOT 24 | 25 | 4.0.0 26 | 27 | freeswitch-esl-spring-boot-starter 28 | freeswitch-esl-spring-boot-starter-${project.version} 29 | Freeswitch Esl Spring Boot Starter 30 | 31 | 32 | 33 | ${project.groupId} 34 | freeswitch-esl 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-configuration-processor 39 | true 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-autoconfigure 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/EnableFreeswitchEslAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter; 17 | 18 | import link.thingscloud.freeswitch.esl.spring.boot.starter.config.FreeswitchEslAutoConfiguration; 19 | import org.springframework.context.annotation.Import; 20 | 21 | import java.lang.annotation.*; 22 | 23 | /** 24 | *

EnableFreeswitchEslAutoConfiguration class.

25 | * 26 | * @author : zhouhailin 27 | * @version 1.0.0 28 | */ 29 | @Target({ElementType.TYPE}) 30 | @Retention(RetentionPolicy.RUNTIME) 31 | @Documented 32 | @Inherited 33 | @Import(FreeswitchEslAutoConfiguration.class) 34 | public @interface EnableFreeswitchEslAutoConfiguration { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/annotation/EslEventName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.annotation; 17 | 18 | import java.lang.annotation.*; 19 | 20 | /** 21 | *

EslEventName class.

22 | * 23 | * @author : zhouhailin 24 | * @version 1.0.0 25 | */ 26 | @Target({ElementType.TYPE}) 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Documented 29 | public @interface EslEventName { 30 | 31 | String[] value(); 32 | } 33 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/config/FreeswitchEslAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.config; 17 | 18 | import link.thingscloud.freeswitch.esl.IEslEventListener; 19 | import link.thingscloud.freeswitch.esl.InboundClient; 20 | import link.thingscloud.freeswitch.esl.InboundClientBootstrap; 21 | import link.thingscloud.freeswitch.esl.ServerConnectionListener; 22 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 23 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.InboundClientOptionHandler; 24 | import link.thingscloud.freeswitch.esl.spring.boot.starter.properties.InboundClientProperties; 25 | import link.thingscloud.freeswitch.esl.spring.boot.starter.template.DefaultInboundClientOptionHandlerTemplate; 26 | import link.thingscloud.freeswitch.esl.spring.boot.starter.template.IEslEventListenerTemplate; 27 | import link.thingscloud.freeswitch.esl.spring.boot.starter.template.ServerConnectionListenerTemplate; 28 | import lombok.extern.slf4j.Slf4j; 29 | import org.springframework.beans.factory.annotation.Autowired; 30 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 31 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 32 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 33 | import org.springframework.context.annotation.Bean; 34 | import org.springframework.context.annotation.Configuration; 35 | 36 | 37 | /** 38 | *

FreeswitchEslAutoConfiguration class.

39 | * 40 | * @author : zhouhailin 41 | * @version 1.0.0 42 | */ 43 | @Slf4j 44 | @Configuration 45 | @EnableConfigurationProperties({InboundClientProperties.class}) 46 | @ConditionalOnClass(InboundClient.class) 47 | public class FreeswitchEslAutoConfiguration { 48 | 49 | /** 50 | *

inboundClientPropertiesHandler.

51 | * 52 | * @return a {@link link.thingscloud.freeswitch.esl.spring.boot.starter.handler.InboundClientOptionHandler} object. 53 | */ 54 | @Bean 55 | @ConditionalOnMissingBean(InboundClientOptionHandler.class) 56 | public InboundClientOptionHandler inboundClientOptionHandler() { 57 | return new DefaultInboundClientOptionHandlerTemplate(); 58 | } 59 | 60 | /** 61 | *

listener.

62 | * 63 | * @return a {@link link.thingscloud.freeswitch.esl.IEslEventListener} object. 64 | */ 65 | @Bean 66 | @ConditionalOnMissingBean(IEslEventListener.class) 67 | public IEslEventListener listener() { 68 | return new IEslEventListenerTemplate(); 69 | } 70 | 71 | /** 72 | *

serverConnectionListener.

73 | * 74 | * @return a {@link link.thingscloud.freeswitch.esl.ServerConnectionListener} object. 75 | */ 76 | @Bean 77 | @ConditionalOnMissingBean(ServerConnectionListener.class) 78 | public ServerConnectionListener serverConnectionListener() { 79 | return new ServerConnectionListenerTemplate(); 80 | } 81 | 82 | /** 83 | *

inboundClient.

84 | * 85 | * @param serverConnectionListener a {@link link.thingscloud.freeswitch.esl.ServerConnectionListener} object. 86 | * @param inboundClientOptionHandler a {@link link.thingscloud.freeswitch.esl.spring.boot.starter.handler.InboundClientOptionHandler} object. 87 | * @return a {@link link.thingscloud.freeswitch.esl.InboundClient} object. 88 | */ 89 | @Bean(initMethod = "start", destroyMethod = "shutdown") 90 | @ConditionalOnMissingBean(InboundClient.class) 91 | public InboundClient inboundClient(@Autowired ServerConnectionListener serverConnectionListener, @Autowired InboundClientOptionHandler inboundClientOptionHandler) { 92 | InboundClientOption option = inboundClientOptionHandler.getOption(); 93 | option.serverConnectionListener(serverConnectionListener); 94 | log.info("inboundClient properties : [{}]", option); 95 | log.info("inboundClient option : [{}]", option); 96 | return InboundClient.newInstance(option); 97 | } 98 | 99 | /** 100 | * InboundClient Bootstrap 101 | * 102 | * @param inboundClient a {@link link.thingscloud.freeswitch.esl.InboundClient} object. 103 | * @return a {@link link.thingscloud.freeswitch.esl.InboundClientBootstrap} object. 104 | */ 105 | @Bean 106 | @ConditionalOnMissingBean(InboundClientBootstrap.class) 107 | public InboundClientBootstrap inboundClientBootstrap(@Autowired InboundClient inboundClient) { 108 | return new InboundClientBootstrap(inboundClient); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/handler/AbstractEslEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.handler; 17 | 18 | import link.thingscloud.freeswitch.esl.InboundClient; 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | 23 | /** 24 | *

Abstract AbstractEslEventHandler class.

25 | * 26 | * @author : zhouhailin 27 | * @version 1.0.0 28 | */ 29 | public abstract class AbstractEslEventHandler implements EslEventHandler { 30 | 31 | @Autowired 32 | protected InboundClient inboundClient; 33 | 34 | protected final Logger log = LoggerFactory.getLogger(getClass()); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/handler/AbstractInboundClientOptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.handler; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 19 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 20 | import link.thingscloud.freeswitch.esl.spring.boot.starter.properties.InboundClientProperties; 21 | import link.thingscloud.freeswitch.esl.util.StringUtils; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | 24 | /** 25 | *

Abstract AbstractInboundClientOptionHandler class.

26 | * 27 | * @author zhouhailin 28 | * @version 1.0.0 29 | */ 30 | public abstract class AbstractInboundClientOptionHandler implements InboundClientOptionHandler { 31 | 32 | @Autowired 33 | protected InboundClientProperties properties; 34 | 35 | /** 36 | *

intercept.

37 | * 38 | * @param inboundClientOption a {@link link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption} object. 39 | */ 40 | protected abstract void intercept(InboundClientOption inboundClientOption); 41 | 42 | /** 43 | * {@inheritDoc} 44 | */ 45 | @Override 46 | public InboundClientOption getOption() { 47 | InboundClientOption option = newInboundClientOption(); 48 | properties.getServers().forEach(server -> { 49 | if (StringUtils.isNotBlank(server.getHost()) && server.getPort() > 1) { 50 | option.addServerOption(new ServerOption(server.getHost(), server.getPort()) 51 | .timeoutSeconds(server.getTimeoutSeconds()) 52 | .password(server.getPassword())); 53 | } 54 | }); 55 | properties.getEvents().forEach(event -> { 56 | if (StringUtils.isNotBlank(event)) { 57 | option.addEvents(event); 58 | } 59 | }); 60 | intercept(option); 61 | return option; 62 | } 63 | 64 | /** 65 | *

newInboundClientOption.

66 | * 67 | * @return a {@link link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption} object. 68 | */ 69 | protected InboundClientOption newInboundClientOption() { 70 | return new InboundClientOption().sndBufSize(properties.getSndBufSize()) 71 | .rcvBufSize(properties.getRcvBufSize()) 72 | .workerGroupThread(properties.getWorkerGroupThread()) 73 | .publicExecutorThread(properties.getPublicExecutorThread()) 74 | .privateExecutorThread(properties.getPrivateExecutorThread()) 75 | .callbackExecutorThread(properties.getCallbackExecutorThread()) 76 | .defaultTimeoutSeconds(properties.getDefaultTimeoutSeconds()) 77 | .readTimeoutSeconds(properties.getReadTimeoutSeconds()) 78 | .readerIdleTimeSeconds(properties.getReaderIdleTimeSeconds()) 79 | .defaultPassword(properties.getDefaultPassword()) 80 | .disablePublicExecutor(properties.isDisablePublicExecutor()) 81 | .performance(properties.isPerformance()) 82 | .performanceCostTime(properties.getPerformanceCostTime()) 83 | .eventPerformance(properties.isEventPerformance()) 84 | .eventPerformanceCostTime(properties.getEventPerformanceCostTime()); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/handler/DefaultEslEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.handler; 17 | 18 | import link.thingscloud.freeswitch.esl.helper.EslHelper; 19 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 20 | 21 | /** 22 | *

DefaultEslEventHandler class.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public class DefaultEslEventHandler extends AbstractEslEventHandler { 28 | /** 29 | * {@inheritDoc} 30 | */ 31 | @Override 32 | public void handle(String addr, EslEvent event) { 33 | log.warn("Default esl event handler handle addr[{}], event[{}]", addr, EslHelper.formatEslEvent(event)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/handler/EslEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.handler; 17 | 18 | 19 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 20 | 21 | /** 22 | *

EslEventHandler interface.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public interface EslEventHandler { 28 | 29 | /** 30 | * Constant DEFAULT_ESL_EVENT_HANDLER="DEFAULT_ESL_EVENT_HANDLER" 31 | */ 32 | String DEFAULT_ESL_EVENT_HANDLER = "DEFAULT_ESL_EVENT_HANDLER"; 33 | 34 | /** 35 | * sub event key 36 | */ 37 | String SUB_EVENT_HEADER_KEY = "Event-Subclass"; 38 | 39 | /** 40 | *

handle.

41 | * 42 | * @param addr a {@link java.lang.String} object. 43 | * @param event a {@link link.thingscloud.freeswitch.esl.transport.event.EslEvent} object. 44 | */ 45 | void handle(String addr, EslEvent event); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/handler/InboundClientOptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.handler; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 19 | 20 | /** 21 | *

InboundClientOptionHandler interface.

22 | * 23 | * @author zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public interface InboundClientOptionHandler { 27 | 28 | /** 29 | *

getOption.

30 | * 31 | * @return a {@link link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption} object. 32 | */ 33 | InboundClientOption getOption(); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/properties/InboundClientProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.properties; 17 | 18 | import lombok.Data; 19 | import org.springframework.boot.context.properties.ConfigurationProperties; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | *

InboundClientProperties class.

26 | * 27 | * @author : zhouhailin 28 | * @version 1.0.0 29 | */ 30 | @Data 31 | @ConfigurationProperties(prefix = "link.thingscloud.freeswitch.esl.inbound") 32 | public class InboundClientProperties { 33 | 34 | private int sndBufSize = 65535; 35 | private int rcvBufSize = 65535; 36 | private int workerGroupThread = Runtime.getRuntime().availableProcessors() * 2; 37 | private int publicExecutorThread = Runtime.getRuntime().availableProcessors() * 2; 38 | private int privateExecutorThread = Runtime.getRuntime().availableProcessors() * 2; 39 | private int callbackExecutorThread = Runtime.getRuntime().availableProcessors() * 2; 40 | private int defaultTimeoutSeconds = 5; 41 | private int readTimeoutSeconds = 30; 42 | private int readerIdleTimeSeconds = 25; 43 | private String defaultPassword = "ClueCon"; 44 | private boolean disablePublicExecutor = false; 45 | private boolean performance = false; 46 | private long performanceCostTime = 200; 47 | private boolean eventPerformance = false; 48 | private long eventPerformanceCostTime = 200; 49 | private List events = new ArrayList<>(); 50 | private List servers = new ArrayList<>(); 51 | 52 | } 53 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/properties/ServerProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.properties; 17 | 18 | import lombok.Data; 19 | 20 | /** 21 | *

ServerProperties class.

22 | * 23 | * @author : zhouhailin 24 | * @version 1.0.0 25 | */ 26 | @Data 27 | public class ServerProperties { 28 | private String host; 29 | private int port = 8021; 30 | private int timeoutSeconds; 31 | private String password; 32 | } 33 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/template/DefaultInboundClientOptionHandlerTemplate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.template; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 19 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.AbstractInboundClientOptionHandler; 20 | 21 | /** 22 | *

DefaultInboundClientOptionHandlerTemplate class.

23 | * 24 | * @author zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public class DefaultInboundClientOptionHandlerTemplate extends AbstractInboundClientOptionHandler { 28 | 29 | /** 30 | * {@inheritDoc} 31 | */ 32 | @Override 33 | protected void intercept(InboundClientOption option) { 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/template/IEslEventListenerTemplate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.template; 17 | 18 | import link.thingscloud.freeswitch.esl.IEslEventListener; 19 | import link.thingscloud.freeswitch.esl.InboundClient; 20 | import link.thingscloud.freeswitch.esl.spring.boot.starter.annotation.EslEventName; 21 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.DefaultEslEventHandler; 22 | import link.thingscloud.freeswitch.esl.spring.boot.starter.handler.EslEventHandler; 23 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 24 | import link.thingscloud.freeswitch.esl.util.ArrayUtils; 25 | import link.thingscloud.freeswitch.esl.util.StringUtils; 26 | import lombok.extern.slf4j.Slf4j; 27 | import org.springframework.beans.factory.InitializingBean; 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | import org.springframework.util.CollectionUtils; 30 | 31 | import java.util.*; 32 | 33 | /** 34 | *

IEslEventListenerTemplate class.

35 | * 36 | * @author : zhouhailin 37 | * @version 1.0.0 38 | */ 39 | @Slf4j 40 | public class IEslEventListenerTemplate implements IEslEventListener, InitializingBean { 41 | 42 | @Autowired 43 | private InboundClient inboundClient; 44 | @Autowired(required = false) 45 | private final List eslEventHandlers = Collections.emptyList(); 46 | 47 | private EslEventHandler defaultEventHandler = new DefaultEslEventHandler(); 48 | private final Map> handlerTable = new HashMap<>(16); 49 | 50 | /** 51 | * {@inheritDoc} 52 | */ 53 | @Override 54 | public void eventReceived(String addr, EslEvent event) { 55 | handleEslEvent(addr, event); 56 | } 57 | 58 | /** 59 | * {@inheritDoc} 60 | */ 61 | @Override 62 | public void backgroundJobResultReceived(String addr, EslEvent event) { 63 | handleEslEvent(addr, event); 64 | } 65 | 66 | private void handleEslEvent(String addr, EslEvent event) { 67 | String eventName = event.getEventName(); 68 | List handlers = handlerTable.get(eventName); 69 | if (!CollectionUtils.isEmpty(handlers)) { 70 | handlers.forEach(eventHandler -> eventHandler.handle(addr, event)); 71 | return; 72 | } 73 | defaultEventHandler.handle(addr, event); 74 | } 75 | 76 | 77 | /** 78 | * {@inheritDoc} 79 | */ 80 | @Override 81 | public void afterPropertiesSet() { 82 | log.info("IEslEventListener init ..."); 83 | for (EslEventHandler eventHandler : eslEventHandlers) { 84 | // link.thingscloud.freeswitch.esl.spring.boot.starter.example.HeartbeatEslEventHandler 85 | // link.thingscloud.freeswitch.esl.spring.boot.starter.example.ReScheduleEslEventHandler$$EnhancerBySpringCGLIB$$1b4e8d 86 | EslEventName eventName = eventHandler.getClass().getAnnotation(EslEventName.class); 87 | if (eventName == null) { 88 | // FIXED : AOP 89 | eventName = eventHandler.getClass().getSuperclass().getAnnotation(EslEventName.class); 90 | } 91 | if (eventName == null || ArrayUtils.isEmpty(eventName.value())) { 92 | continue; 93 | } 94 | for (String value : eventName.value()) { 95 | if (StringUtils.isBlank(value)) { 96 | continue; 97 | } 98 | log.info("IEslEventListener add EventName[{}], EventHandler[{}] ...", value, eventHandler.getClass()); 99 | if (StringUtils.equals(EslEventHandler.DEFAULT_ESL_EVENT_HANDLER, value)) { 100 | defaultEventHandler = eventHandler; 101 | } else { 102 | handlerTable.computeIfAbsent(value, k -> new ArrayList<>(4)).add(eventHandler); 103 | } 104 | } 105 | } 106 | inboundClient.option().addListener(this); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/java/link/thingscloud/freeswitch/esl/spring/boot/starter/template/ServerConnectionListenerTemplate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.spring.boot.starter.template; 17 | 18 | import link.thingscloud.freeswitch.esl.ServerConnectionListener; 19 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 20 | import lombok.extern.slf4j.Slf4j; 21 | 22 | /** 23 | *

ServerConnectionListenerTemplate class.

24 | * 25 | * @author : zhouhailin 26 | * @version 1.0.0 27 | */ 28 | @Slf4j 29 | public class ServerConnectionListenerTemplate implements ServerConnectionListener { 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | public void onOpened(ServerOption serverOption) { 35 | log.info("onOpened serverOption : {}", serverOption.host() + ":" + serverOption.port()); 36 | } 37 | 38 | /** 39 | * {@inheritDoc} 40 | */ 41 | @Override 42 | public void onClosed(ServerOption serverOption) { 43 | log.info("onClosed serverOption : {}", serverOption.host() + ":" + serverOption.port()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | link.thingscloud.freeswitch.esl.spring.boot.starter.config.FreeswitchEslAutoConfiguration 3 | -------------------------------------------------------------------------------- /freeswitch-esl-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | link.thingscloud.freeswitch.esl.spring.boot.starter.config.FreeswitchEslAutoConfiguration -------------------------------------------------------------------------------- /freeswitch-esl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 21 | link.thingscloud 22 | freeswitch-externals 23 | 2.3.0-SNAPSHOT 24 | 25 | 4.0.0 26 | 27 | freeswitch-esl 28 | freeswitch-esl-${project.version} 29 | freeswitch event socket library on netty 4.1 30 | 31 | 32 | 33 | 34 | io.netty 35 | netty-handler 36 | 37 | 38 | io.netty 39 | netty-transport 40 | 41 | 42 | io.netty 43 | netty-transport-native-epoll 44 | linux-x86_64 45 | 46 | 47 | io.netty 48 | netty-transport-native-kqueue 49 | osx-x86_64 50 | 51 | 52 | 53 | org.slf4j 54 | slf4j-api 55 | 56 | 57 | ch.qos.logback 58 | logback-classic 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/IEslEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl; 17 | 18 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 19 | 20 | /** 21 | *

IEslEventListener interface.

22 | * 23 | * @author : zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public interface IEslEventListener { 27 | 28 | /** 29 | * Signal of a server initiated event. 30 | * 31 | * @param addr addr 32 | * @param event as an {@link link.thingscloud.freeswitch.esl.transport.event.EslEvent} 33 | */ 34 | void eventReceived(String addr, EslEvent event); 35 | 36 | /** 37 | * Signal of an event containing the result of a client requested background job. The Job-UUID will 38 | * be available as an event header of that name. 39 | * 40 | * @param addr addr 41 | * @param event as an {@link link.thingscloud.freeswitch.esl.transport.event.EslEvent} 42 | */ 43 | void backgroundJobResultReceived(String addr, EslEvent event); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/InboundClientBootstrap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl; 17 | 18 | /** 19 | * @author zhouhailin 20 | * @since 2.1.0 21 | */ 22 | public class InboundClientBootstrap { 23 | 24 | private final InboundClient inboundClient; 25 | 26 | public InboundClientBootstrap(InboundClient inboundClient) { 27 | this.inboundClient = inboundClient; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/InboundClientFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl; 17 | 18 | import link.thingscloud.freeswitch.esl.exception.InboundClientException; 19 | import link.thingscloud.freeswitch.esl.inbound.NettyInboundClient; 20 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 21 | 22 | /** 23 | * 保证单例对象 24 | * 25 | * @author : zhouhailin 26 | */ 27 | class InboundClientFactory { 28 | 29 | private InboundClient inboundClient = null; 30 | 31 | private InboundClientFactory() { 32 | } 33 | 34 | static InboundClientFactory getInstance() { 35 | return InboundClientFactoryInstance.INSTANCE; 36 | } 37 | 38 | synchronized InboundClient newInboundClient(InboundClientOption option) { 39 | if (inboundClient == null) { 40 | inboundClient = new NettyInboundClient(option == null ? new InboundClientOption() : option); 41 | return inboundClient; 42 | } 43 | throw new InboundClientException("InboundClient has been created already, instance : [" + inboundClient + "]!"); 44 | } 45 | 46 | InboundClient getInboundClient() { 47 | if (inboundClient == null) { 48 | throw new InboundClientException("InboundClient is null, you must be create it first."); 49 | } 50 | return inboundClient; 51 | } 52 | 53 | private static class InboundClientFactoryInstance { 54 | private static final InboundClientFactory INSTANCE = new InboundClientFactory(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/InboundClientService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl; 17 | 18 | /** 19 | *

InboundClientService interface.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public interface InboundClientService { 25 | 26 | /** 27 | *

start.

28 | */ 29 | void start(); 30 | 31 | /** 32 | *

shutdown.

33 | */ 34 | void shutdown(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/ServerConnectionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 19 | 20 | /** 21 | *

ServerConnectionListener interface.

22 | * 23 | * @author : zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public interface ServerConnectionListener { 27 | 28 | /** 29 | *

onOpened.

30 | * 31 | * @param serverOption a {@link link.thingscloud.freeswitch.esl.inbound.option.ServerOption} object. 32 | */ 33 | void onOpened(ServerOption serverOption); 34 | 35 | /** 36 | *

onClosed.

37 | * 38 | * @param serverOption a {@link link.thingscloud.freeswitch.esl.inbound.option.ServerOption} object. 39 | */ 40 | void onClosed(ServerOption serverOption); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/constant/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.constant; 17 | 18 | /** 19 | *

EslConstant class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class Constants { 25 | 26 | /** 27 | * Constant BACKGROUND_JOB="BACKGROUND_JOB" 28 | */ 29 | public static final String BACKGROUND_JOB = "BACKGROUND_JOB"; 30 | /** 31 | * Constant PLAIN="plain" 32 | */ 33 | public static final String PLAIN = "plain"; 34 | 35 | public static final String SMF_ALEG = "aleg"; 36 | public static final String SMF_BLEG = "bleg"; 37 | public static final String SMF_HOLDB = "holdb"; 38 | public static final String SMF_BOTH = "both"; 39 | 40 | public static final String UUID_ANSWER = "uuid_answer"; 41 | public static final String UUID_BRIDGE = "uuid_bridge"; 42 | public static final String UUID_BROADCAST = "uuid_broadcast"; 43 | public static final String UUID_BREAK = "uuid_break"; 44 | public static final String UUID_HOLD = "uuid_hold"; 45 | public static final String UUID_GETVAR = "uuid_getvar"; 46 | public static final String UUID_SETVAR = "uuid_setvar"; 47 | public static final String UUID_SETVAR_MULTI = "uuid_setvar_multi"; 48 | public static final String UUID_RECORD = "uuid_record"; 49 | public static final String UUID_TRANSFER = "uuid_transfer"; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/constant/VariableConstant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.constant; 17 | 18 | /** 19 | * @author zhouhailin 20 | * @version 1.5.0 21 | */ 22 | public class VariableConstant { 23 | 24 | public static final String PREFIX = "variable_"; 25 | 26 | private VariableConstant() { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/exception/EslDecoderException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.exception; 17 | 18 | /** 19 | *

EslDecoderException class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class EslDecoderException extends RuntimeException { 25 | /** 26 | *

Constructor for EslDecoderException.

27 | * 28 | * @param message a {@link java.lang.String} object. 29 | */ 30 | public EslDecoderException(String message) { 31 | super(message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/exception/InboundClientException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.exception; 17 | 18 | /** 19 | *

InboundClientException class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class InboundClientException extends RuntimeException { 25 | /** 26 | *

Constructor for InboundClientException.

27 | * 28 | * @param message a {@link java.lang.String} object. 29 | */ 30 | public InboundClientException(String message) { 31 | super(message); 32 | } 33 | 34 | /** 35 | *

Constructor for InboundClientException.

36 | * 37 | * @param message a {@link java.lang.String} object. 38 | * @param cause a {@link java.lang.Throwable} object. 39 | */ 40 | public InboundClientException(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | 44 | /** 45 | *

Constructor for InboundClientException.

46 | * 47 | * @param cause a {@link java.lang.Throwable} object. 48 | */ 49 | public InboundClientException(Throwable cause) { 50 | super(cause); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/exception/InboundTimeoutExcetion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.exception; 17 | 18 | /** 19 | *

InboundTimeoutExcetion class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class InboundTimeoutExcetion extends InboundClientException { 25 | /** 26 | *

Constructor for InboundTimeoutExcetion.

27 | * 28 | * @param message a {@link java.lang.String} object. 29 | */ 30 | public InboundTimeoutExcetion(String message) { 31 | super(message); 32 | } 33 | 34 | /** 35 | *

Constructor for InboundTimeoutExcetion.

36 | * 37 | * @param message a {@link java.lang.String} object. 38 | * @param cause a {@link java.lang.Throwable} object. 39 | */ 40 | public InboundTimeoutExcetion(String message, Throwable cause) { 41 | super(message, cause); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/helper/CommandHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.helper; 17 | 18 | /** 19 | * @author zhouhailin 20 | * @since 1.6.5 21 | */ 22 | public class CommandHelper { 23 | 24 | private final StringBuilder builder = new StringBuilder(); 25 | 26 | private CommandHelper(String cmd) { 27 | builder.append(cmd); 28 | } 29 | 30 | public static CommandHelper cmd(String cmd) { 31 | return new CommandHelper(cmd); 32 | } 33 | 34 | public CommandHelper arg(String arg) { 35 | builder.append(" ").append(arg); 36 | return this; 37 | } 38 | 39 | public CommandHelper arg(boolean arg) { 40 | builder.append(" ").append(arg); 41 | return this; 42 | } 43 | 44 | public CommandHelper arg(int arg) { 45 | builder.append(" ").append(arg); 46 | return this; 47 | } 48 | 49 | public CommandHelper arg(long arg) { 50 | builder.append(" ").append(arg); 51 | return this; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return builder.toString(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/helper/EslHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.helper; 17 | 18 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 19 | import link.thingscloud.freeswitch.esl.transport.message.EslHeaders; 20 | import link.thingscloud.freeswitch.esl.transport.message.EslMessage; 21 | 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | /** 26 | *

EslHelper class.

27 | * 28 | * @author : zhouhailin 29 | * @version 1.0.0 30 | */ 31 | public class EslHelper { 32 | 33 | /** 34 | * private constructor 35 | */ 36 | private EslHelper() { 37 | } 38 | 39 | /** 40 | *

formatEslEvent.

41 | * 42 | * @param event a {@link link.thingscloud.freeswitch.esl.transport.event.EslEvent} object. 43 | * @return a {@link java.lang.String} object. 44 | */ 45 | public static String formatEslEvent(EslEvent event) { 46 | 47 | StringBuilder sb = new StringBuilder(); 48 | 49 | sb.append(System.lineSeparator()); 50 | sb.append("#").append(System.lineSeparator()); 51 | sb.append("## message header : ").append(System.lineSeparator()); 52 | Map messageHeaders = 53 | event.getMessageHeaders(); 54 | for (Map.Entry entry : messageHeaders.entrySet()) { 55 | sb.append(entry.getKey()).append("=").append(entry.getValue()).append(System.lineSeparator()); 56 | } 57 | 58 | sb.append("## event header : ").append(System.lineSeparator()); 59 | Map eventHeaders = event.getEventHeaders(); 60 | for (Map.Entry entry : eventHeaders.entrySet()) { 61 | sb.append(entry.getKey()).append("=").append(entry.getValue()).append(System.lineSeparator()); 62 | 63 | } 64 | 65 | sb.append("## event body lines : ").append(System.lineSeparator()); 66 | List eventBodyLines = event.getEventBodyLines(); 67 | for (String eventBodyLine : eventBodyLines) { 68 | sb.append(eventBodyLine).append(System.lineSeparator()); 69 | } 70 | sb.append("#").append(System.lineSeparator()); 71 | 72 | return sb.toString(); 73 | } 74 | 75 | 76 | /** 77 | *

formatEslMessage.

78 | * 79 | * @param message a {@link link.thingscloud.freeswitch.esl.transport.message.EslMessage} object. 80 | * @return a {@link java.lang.String} object. 81 | */ 82 | public static String formatEslMessage(EslMessage message) { 83 | StringBuilder sb = new StringBuilder(); 84 | 85 | sb.append(System.lineSeparator()); 86 | sb.append("#").append(System.lineSeparator()); 87 | sb.append("## message header : ").append(System.lineSeparator()); 88 | 89 | Map headers = 90 | message.getHeaders(); 91 | for (Map.Entry entry : headers.entrySet()) { 92 | sb.append(entry.getKey()).append("=").append(entry.getValue()).append(System.lineSeparator()); 93 | } 94 | 95 | sb.append("## event body lines : ").append(System.lineSeparator()); 96 | List eventBodyLines = message.getBodyLines(); 97 | for (String eventBodyLine : eventBodyLines) { 98 | sb.append(eventBodyLine).append(System.lineSeparator()); 99 | } 100 | sb.append("#").append(System.lineSeparator()); 101 | 102 | return sb.toString(); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/AbstractNettyInboundClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound; 17 | 18 | import io.netty.bootstrap.Bootstrap; 19 | import io.netty.channel.ChannelInitializer; 20 | import io.netty.channel.ChannelOption; 21 | import io.netty.channel.ChannelPipeline; 22 | import io.netty.channel.EventLoopGroup; 23 | import io.netty.channel.nio.NioEventLoopGroup; 24 | import io.netty.channel.socket.SocketChannel; 25 | import io.netty.channel.socket.nio.NioSocketChannel; 26 | import io.netty.handler.codec.string.StringEncoder; 27 | import io.netty.handler.timeout.IdleStateHandler; 28 | import io.netty.handler.timeout.ReadTimeoutHandler; 29 | import io.netty.util.concurrent.DefaultThreadFactory; 30 | import link.thingscloud.freeswitch.esl.InboundClientService; 31 | import link.thingscloud.freeswitch.esl.inbound.handler.InboundChannelHandler; 32 | import link.thingscloud.freeswitch.esl.inbound.listener.ChannelEventListener; 33 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 34 | import link.thingscloud.freeswitch.esl.transport.message.EslFrameDecoder; 35 | import org.slf4j.Logger; 36 | import org.slf4j.LoggerFactory; 37 | 38 | import java.util.concurrent.ExecutorService; 39 | import java.util.concurrent.ScheduledThreadPoolExecutor; 40 | 41 | /** 42 | * @author : zhouhailin 43 | */ 44 | abstract class AbstractNettyInboundClient implements ChannelEventListener, InboundClientService { 45 | 46 | final Bootstrap bootstrap; 47 | final EventLoopGroup workerGroup; 48 | final ExecutorService publicExecutor; 49 | final ExecutorService privateExecutor; 50 | 51 | final InboundClientOption option; 52 | 53 | final Logger log = LoggerFactory.getLogger(getClass()); 54 | 55 | AbstractNettyInboundClient(InboundClientOption option) { 56 | this.option = option; 57 | 58 | bootstrap = new Bootstrap(); 59 | 60 | publicExecutor = new ScheduledThreadPoolExecutor(option.publicExecutorThread(), 61 | new DefaultThreadFactory("publicExecutor", true)); 62 | privateExecutor = new ScheduledThreadPoolExecutor(option.privateExecutorThread(), 63 | new DefaultThreadFactory("privateExecutor", true)); 64 | 65 | workerGroup = new NioEventLoopGroup(option.workerGroupThread()); 66 | bootstrap.group(workerGroup) 67 | .channel(NioSocketChannel.class) 68 | .option(ChannelOption.TCP_NODELAY, true) 69 | .option(ChannelOption.SO_KEEPALIVE, false) 70 | .option(ChannelOption.SO_SNDBUF, option.sndBufSize()) 71 | .option(ChannelOption.SO_RCVBUF, option.rcvBufSize()) 72 | .handler(new ChannelInitializer() { 73 | @Override 74 | protected void initChannel(SocketChannel ch) throws Exception { 75 | ChannelPipeline pipeline = ch.pipeline(); 76 | pipeline.addLast("encoder", new StringEncoder()); 77 | pipeline.addLast("decoder", new EslFrameDecoder(8192)); 78 | if (option.readerIdleTimeSeconds() > 0 && option.readTimeoutSeconds() > 0 79 | && option.readerIdleTimeSeconds() < option.readTimeoutSeconds()) { 80 | pipeline.addLast("idleState", new IdleStateHandler(option.readerIdleTimeSeconds(), 0, 0)); 81 | pipeline.addLast("readTimeout", new ReadTimeoutHandler(option.readTimeoutSeconds())); 82 | } 83 | // now the inbound client logic 84 | pipeline.addLast("clientHandler", new InboundChannelHandler(AbstractNettyInboundClient.this, publicExecutor, privateExecutor, option.disablePublicExecutor())); 85 | } 86 | }); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/NettyInboundClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound; 17 | 18 | import link.thingscloud.freeswitch.esl.InboundClient; 19 | import link.thingscloud.freeswitch.esl.constant.Constants; 20 | import link.thingscloud.freeswitch.esl.constant.EventNames; 21 | import link.thingscloud.freeswitch.esl.exception.InboundTimeoutExcetion; 22 | import link.thingscloud.freeswitch.esl.inbound.handler.InboundChannelHandler; 23 | import link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption; 24 | import link.thingscloud.freeswitch.esl.transport.CommandResponse; 25 | import link.thingscloud.freeswitch.esl.transport.SendEvent; 26 | import link.thingscloud.freeswitch.esl.transport.SendMsg; 27 | import link.thingscloud.freeswitch.esl.transport.message.EslMessage; 28 | import link.thingscloud.freeswitch.esl.util.StringUtils; 29 | 30 | import java.util.concurrent.TimeUnit; 31 | import java.util.function.Consumer; 32 | 33 | import static link.thingscloud.freeswitch.esl.constant.EventNames.ALL; 34 | import static link.thingscloud.freeswitch.esl.constant.EventNames.BACKGROUND_JOB; 35 | 36 | 37 | /** 38 | *

NettyInboundClient class.

39 | * 40 | * @author : zhouhailin 41 | * @version 1.0.0 42 | */ 43 | public class NettyInboundClient extends AbstractInboundClient { 44 | 45 | private volatile boolean subscribeBackgroundJob = false; 46 | 47 | /** 48 | *

Constructor for NettyInboundClient.

49 | * 50 | * @param option a {@link link.thingscloud.freeswitch.esl.inbound.option.InboundClientOption} object. 51 | */ 52 | public NettyInboundClient(InboundClientOption option) { 53 | super(option); 54 | } 55 | 56 | @Override 57 | public boolean subscribeBackgroundJob() { 58 | return subscribeBackgroundJob; 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | */ 64 | @Override 65 | public EslMessage sendSyncApiCommand(String addr, String command, String arg) { 66 | InboundChannelHandler handler = getAuthedHandler(addr); 67 | StringBuilder sb = new StringBuilder(); 68 | if (command != null && !command.isEmpty()) { 69 | sb.append("api "); 70 | sb.append(command); 71 | } 72 | if (arg != null && !arg.isEmpty()) { 73 | sb.append(' '); 74 | sb.append(arg); 75 | } 76 | log.debug("sendSyncApiCommand addr : {}, command : {}, arg : {}", addr, command, arg); 77 | return handler.sendSyncSingleLineCommand(sb.toString()); 78 | } 79 | 80 | /** 81 | * {@inheritDoc} 82 | */ 83 | @Override 84 | public EslMessage sendSyncApiCommand(String addr, String command, String arg, long timeoutSeconds) throws InboundTimeoutExcetion { 85 | try { 86 | return publicExecutor.submit(() -> sendSyncApiCommand(addr, command, arg)).get(timeoutSeconds, TimeUnit.SECONDS); 87 | } catch (Exception e) { 88 | throw new InboundTimeoutExcetion(String.format("sendSyncApiCommand addr : %s, command : %s, arg : %s, timeoutSeconds : %s", addr, command, arg, timeoutSeconds), e); 89 | } 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | @Override 96 | public void sendSyncApiCommand(String addr, String command, String arg, Consumer consumer) { 97 | publicExecutor.execute(() -> { 98 | EslMessage msg = sendSyncApiCommand(addr, command, arg); 99 | if (consumer != null) { 100 | consumer.accept(msg); 101 | } 102 | }); 103 | } 104 | 105 | /** 106 | * {@inheritDoc} 107 | */ 108 | @Override 109 | public String sendAsyncApiCommand(String addr, String command, String arg) { 110 | InboundChannelHandler handler = getAuthedHandler(addr); 111 | StringBuilder sb = new StringBuilder(); 112 | if (command != null && !command.isEmpty()) { 113 | sb.append("bgapi "); 114 | sb.append(command); 115 | } 116 | if (arg != null && !arg.isEmpty()) { 117 | sb.append(' '); 118 | sb.append(arg); 119 | } 120 | return handler.sendAsyncCommand(sb.toString()); 121 | } 122 | 123 | /** 124 | * {@inheritDoc} 125 | */ 126 | @Override 127 | public void sendAsyncApiCommand(String addr, String command, String arg, Consumer consumer) { 128 | publicExecutor.execute(() -> { 129 | String msg = sendAsyncApiCommand(addr, command, arg); 130 | if (consumer != null) { 131 | consumer.accept(msg); 132 | } 133 | }); 134 | } 135 | 136 | /** 137 | * {@inheritDoc} 138 | */ 139 | @Override 140 | public CommandResponse setEventSubscriptions(String addr, String format, String events) { 141 | if (!StringUtils.equals(format, Constants.PLAIN)) { 142 | throw new IllegalStateException("Only 'plain' event format is supported at present"); 143 | } 144 | InboundChannelHandler handler = getAuthedHandler(addr); 145 | 146 | 147 | if (StringUtils.contains(events, EventNames.BACKGROUND_JOB) || StringUtils.contains(events, EventNames.ALL)) { 148 | subscribeBackgroundJob = true; 149 | } 150 | 151 | StringBuilder sb = new StringBuilder(); 152 | sb.append("event "); 153 | sb.append(format); 154 | if (events != null && !events.isEmpty()) { 155 | sb.append(' '); 156 | sb.append(events); 157 | } 158 | EslMessage response = handler.sendSyncSingleLineCommand(sb.toString()); 159 | return new CommandResponse(sb.toString(), response); 160 | } 161 | 162 | /** 163 | * {@inheritDoc} 164 | */ 165 | @Override 166 | public CommandResponse cancelEventSubscriptions(String addr) { 167 | InboundChannelHandler handler = getAuthedHandler(addr); 168 | EslMessage response = handler.sendSyncSingleLineCommand("noevents"); 169 | subscribeBackgroundJob = false; 170 | return new CommandResponse("noevents", response); 171 | } 172 | 173 | /** 174 | * {@inheritDoc} 175 | */ 176 | @Override 177 | public CommandResponse addEventFilter(String addr, String eventHeader, String valueToFilter) { 178 | InboundChannelHandler handler = getAuthedHandler(addr); 179 | StringBuilder sb = new StringBuilder(); 180 | if (eventHeader != null && !eventHeader.isEmpty()) { 181 | sb.append("filter "); 182 | sb.append(eventHeader); 183 | } 184 | if (valueToFilter != null && !valueToFilter.isEmpty()) { 185 | sb.append(' '); 186 | sb.append(valueToFilter); 187 | } 188 | EslMessage response = handler.sendSyncSingleLineCommand(sb.toString()); 189 | 190 | return new CommandResponse(sb.toString(), response); 191 | } 192 | 193 | /** 194 | * {@inheritDoc} 195 | */ 196 | @Override 197 | public CommandResponse deleteEventFilter(String addr, String eventHeader, String valueToFilter) { 198 | InboundChannelHandler handler = getAuthedHandler(addr); 199 | 200 | StringBuilder sb = new StringBuilder(); 201 | if (eventHeader != null && !eventHeader.isEmpty()) { 202 | sb.append("filter delete "); 203 | sb.append(eventHeader); 204 | } 205 | if (valueToFilter != null && !valueToFilter.isEmpty()) { 206 | sb.append(' '); 207 | sb.append(valueToFilter); 208 | } 209 | EslMessage response = handler.sendSyncSingleLineCommand(sb.toString()); 210 | return new CommandResponse(sb.toString(), response); 211 | } 212 | 213 | /** 214 | * {@inheritDoc} 215 | */ 216 | @Override 217 | public CommandResponse sendEvent(String addr, SendEvent sendEvent) { 218 | InboundChannelHandler handler = getAuthedHandler(addr); 219 | EslMessage response = handler.sendSyncMultiLineCommand(sendEvent.getMsgLines()); 220 | return new CommandResponse(sendEvent.toString(), response); 221 | } 222 | 223 | /** 224 | * {@inheritDoc} 225 | */ 226 | @Override 227 | public void sendEvent(String addr, SendEvent sendEvent, Consumer consumer) { 228 | publicExecutor.execute(() -> { 229 | CommandResponse response = sendEvent(addr, sendEvent); 230 | if (consumer != null) { 231 | consumer.accept(response); 232 | } 233 | }); 234 | } 235 | 236 | /** 237 | * {@inheritDoc} 238 | */ 239 | @Override 240 | public CommandResponse sendMessage(String addr, SendMsg sendMsg) { 241 | InboundChannelHandler handler = getAuthedHandler(addr); 242 | EslMessage response = handler.sendSyncMultiLineCommand(sendMsg.getMsgLines()); 243 | return new CommandResponse(sendMsg.toString(), response); 244 | } 245 | 246 | /** 247 | * {@inheritDoc} 248 | */ 249 | @Override 250 | public void sendMessage(String addr, SendMsg sendMsg, Consumer consumer) { 251 | publicExecutor.execute(() -> { 252 | CommandResponse response = sendMessage(addr, sendMsg); 253 | if (consumer != null) { 254 | consumer.accept(response); 255 | } 256 | }); 257 | } 258 | 259 | /** 260 | * {@inheritDoc} 261 | */ 262 | @Override 263 | public CommandResponse setLoggingLevel(String addr, String level) { 264 | InboundChannelHandler handler = getAuthedHandler(addr); 265 | StringBuilder sb = new StringBuilder(); 266 | if (level != null && !level.isEmpty()) { 267 | sb.append("log "); 268 | sb.append(level); 269 | } 270 | EslMessage response = handler.sendSyncSingleLineCommand(sb.toString()); 271 | return new CommandResponse(sb.toString(), response); 272 | } 273 | 274 | /** 275 | * {@inheritDoc} 276 | */ 277 | @Override 278 | public CommandResponse cancelLogging(String addr) { 279 | InboundChannelHandler handler = getAuthedHandler(addr); 280 | EslMessage response = handler.sendSyncSingleLineCommand("nolog"); 281 | return new CommandResponse("nolog", response); 282 | } 283 | 284 | /** 285 | * {@inheritDoc} 286 | */ 287 | @Override 288 | public CommandResponse close(String addr) { 289 | InboundChannelHandler handler = getAuthedHandler(addr); 290 | EslMessage response = handler.sendSyncSingleLineCommand("exit"); 291 | return new CommandResponse("exit", response); 292 | } 293 | 294 | /** 295 | * {@inheritDoc} 296 | */ 297 | @Override 298 | public InboundClient closeChannel(String addr) { 299 | getAuthedHandler(addr).close(); 300 | return this; 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/listener/ChannelEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound.listener; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.handler.InboundChannelHandler; 19 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 20 | 21 | /** 22 | *

ChannelEventListener interface.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public interface ChannelEventListener { 28 | 29 | /** 30 | *

onChannelActive.

31 | * 32 | * @param remoteAddr a {@link java.lang.String} object. 33 | * @param inboundChannelHandler a {@link link.thingscloud.freeswitch.esl.inbound.handler.InboundChannelHandler} object. 34 | */ 35 | void onChannelActive(String remoteAddr, InboundChannelHandler inboundChannelHandler); 36 | 37 | /** 38 | *

onChannelClosed.

39 | * 40 | * @param remoteAddr a {@link java.lang.String} object. 41 | */ 42 | void onChannelClosed(String remoteAddr); 43 | 44 | /** 45 | *

handleAuthRequest.

46 | * 47 | * @param remoteAddr a {@link java.lang.String} object. 48 | * @param inboundChannelHandler a {@link link.thingscloud.freeswitch.esl.inbound.handler.InboundChannelHandler} object. 49 | */ 50 | void handleAuthRequest(String remoteAddr, InboundChannelHandler inboundChannelHandler); 51 | 52 | /** 53 | *

handleEslEvent.

54 | * 55 | * @param remoteAddr a {@link java.lang.String} object. 56 | * @param event a {@link link.thingscloud.freeswitch.esl.transport.event.EslEvent} object. 57 | */ 58 | void handleEslEvent(String remoteAddr, EslEvent event); 59 | 60 | /** 61 | *

handleDisconnectNotice.

62 | * 63 | * @param remoteAddr a {@link java.lang.String} object. 64 | */ 65 | void handleDisconnectNotice(String remoteAddr); 66 | 67 | /** 68 | *

handleRudeRejection.

69 | * 70 | * @param remoteAddr a {@link java.lang.String} object. 71 | */ 72 | void handleRudeRejection(String remoteAddr); 73 | } 74 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/listener/EventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound.listener; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | *

EventListener interface.

22 | * 23 | * @author : zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public interface EventListener { 27 | 28 | /** 29 | *

addEvents.

30 | * 31 | * @param list a {@link java.util.List} object. 32 | */ 33 | void addEvents(List list); 34 | 35 | /** 36 | *

cancelEvents.

37 | */ 38 | void cancelEvents(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/listener/ServerOptionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound.listener; 17 | 18 | import link.thingscloud.freeswitch.esl.inbound.option.ServerOption; 19 | 20 | /** 21 | *

ServerOptionListener interface.

22 | * 23 | * @author : zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public interface ServerOptionListener { 27 | 28 | /** 29 | *

onAdded.

30 | * 31 | * @param serverOption a {@link link.thingscloud.freeswitch.esl.inbound.option.ServerOption} object. 32 | */ 33 | void onAdded(ServerOption serverOption); 34 | 35 | /** 36 | *

onRemoved.

37 | * 38 | * @param serverOption a {@link link.thingscloud.freeswitch.esl.inbound.option.ServerOption} object. 39 | */ 40 | void onRemoved(ServerOption serverOption); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/option/ConnectState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound.option; 17 | 18 | /** 19 | *

ConnectState class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public enum ConnectState { 25 | /** 26 | * 初始化状态 27 | */ 28 | INIT, 29 | /** 30 | * 正在连接 31 | */ 32 | CONNECTING, 33 | /** 34 | * 连接失败 35 | */ 36 | FAILED, 37 | /** 38 | * 连接成功 39 | */ 40 | CONNECTED, 41 | /** 42 | * 认证成功 43 | */ 44 | AUTHED, 45 | /** 46 | * 认证失败 47 | */ 48 | AUTHED_FAILED, 49 | /** 50 | * 正在关闭连接 51 | */ 52 | CLOSING, 53 | /** 54 | * 连接已关闭 55 | */ 56 | CLOSED, 57 | /** 58 | * 应用已停止 59 | */ 60 | SHUTDOWN 61 | } 62 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/option/ServerAddrOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound.option; 17 | 18 | 19 | import link.thingscloud.freeswitch.esl.util.RandomUtils; 20 | import link.thingscloud.freeswitch.esl.util.Validate; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | *

ServerAddrOption class.

26 | * 27 | * @author : zhouhailin 28 | * @version 1.0.0 29 | */ 30 | public class ServerAddrOption { 31 | private final List serverOptions; 32 | private static final String VALIDATE_MESSAGE_1 = "serverOptions must be not empty!"; 33 | 34 | ServerAddrOption(List serverOptions) { 35 | this.serverOptions = serverOptions; 36 | } 37 | 38 | /** 39 | *

first.

40 | * 41 | * @return a {@link java.lang.String} object. 42 | */ 43 | public String first() { 44 | Validate.notEmpty(serverOptions, VALIDATE_MESSAGE_1); 45 | return serverOptions.get(0).addr(); 46 | } 47 | 48 | /** 49 | *

last.

50 | * 51 | * @return a {@link java.lang.String} object. 52 | */ 53 | public String last() { 54 | Validate.notEmpty(serverOptions, VALIDATE_MESSAGE_1); 55 | return serverOptions.get(serverOptions.size() - 1).addr(); 56 | } 57 | 58 | /** 59 | *

random.

60 | * 61 | * @return a {@link java.lang.String} object. 62 | */ 63 | public String random() { 64 | Validate.notEmpty(serverOptions, VALIDATE_MESSAGE_1); 65 | return serverOptions.get(RandomUtils.nextInt(0, serverOptions.size())).addr(); 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/inbound/option/ServerOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.inbound.option; 17 | 18 | import lombok.Data; 19 | import lombok.experimental.Accessors; 20 | 21 | /** 22 | *

ServerOption class.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | 28 | @Data 29 | @Accessors(fluent = true) 30 | public class ServerOption { 31 | private final String host; 32 | private final int port; 33 | private int timeoutSeconds; 34 | private String password; 35 | 36 | private ConnectState state = ConnectState.INIT; 37 | 38 | private int connectTimes = 0; 39 | 40 | /** 41 | *

addr.

42 | * 43 | * @return a {@link java.lang.String} object. 44 | */ 45 | public String addr() { 46 | return host + ":" + port; 47 | } 48 | 49 | /** 50 | *

addConnectTimes.

51 | */ 52 | public void addConnectTimes() { 53 | connectTimes++; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/CommandResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport; 17 | 18 | 19 | import link.thingscloud.freeswitch.esl.transport.message.EslHeaders; 20 | import link.thingscloud.freeswitch.esl.transport.message.EslMessage; 21 | 22 | /** 23 | *

CommandResponse class.

24 | * 25 | * @author : zhouhailin 26 | * @version 1.0.0 27 | */ 28 | public class CommandResponse { 29 | 30 | private final String command; 31 | private final String replyText; 32 | private final EslMessage response; 33 | private final boolean success; 34 | 35 | /** 36 | *

Constructor for CommandResponse.

37 | * 38 | * @param command a {@link java.lang.String} object. 39 | * @param response a {@link link.thingscloud.freeswitch.esl.transport.message.EslMessage} object. 40 | */ 41 | public CommandResponse(String command, EslMessage response) { 42 | this.command = command; 43 | this.response = response; 44 | this.replyText = response == null ? "" : response.getHeaderValue(EslHeaders.Name.REPLY_TEXT); 45 | this.success = replyText.startsWith("+OK"); 46 | } 47 | 48 | /** 49 | *

Getter for the field command.

50 | * 51 | * @return the original command sent to the server 52 | */ 53 | public String getCommand() { 54 | return command; 55 | } 56 | 57 | /** 58 | *

isOk.

59 | * 60 | * @return true if and only if the response Reply-Text line starts with "+OK" 61 | */ 62 | public boolean isOk() { 63 | return success; 64 | } 65 | 66 | /** 67 | *

Getter for the field replyText.

68 | * 69 | * @return the full response Reply-Text line. 70 | */ 71 | public String getReplyText() { 72 | return replyText; 73 | } 74 | 75 | /** 76 | *

Getter for the field response.

77 | * 78 | * @return {@link link.thingscloud.freeswitch.esl.transport.message.EslMessage} the full response from the server 79 | */ 80 | public EslMessage getResponse() { 81 | return response; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/SendEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /** 22 | *

SendEvent class.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public class SendEvent { 28 | 29 | private final List msgLines = new ArrayList<>(); 30 | 31 | /** 32 | * Constructor for use with outbound socket client only. This client mode does not need a call 33 | * UUID for context. 34 | * 35 | * @param name part of line 36 | */ 37 | public SendEvent(String name) { 38 | msgLines.add("sendevent " + name); 39 | } 40 | 41 | /** 42 | * A generic method to add a message line. The constructed line in the sent message will be in the 43 | * form: 44 | *
45 |      *   name: value
46 |      * 
47 | * 48 | * @param name part of line 49 | * @param value part of line 50 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendEvent} object. 51 | */ 52 | public SendEvent addLine(String name, String value) { 53 | msgLines.add(name + ": " + value); 54 | return this; 55 | } 56 | 57 | /** 58 | * A generic method to add a message line. The constructed line in the sent message will be in the 59 | * form: 60 | *
61 |      *   name: value
62 |      * 
63 | * 64 | * @param line part of line 65 | */ 66 | public void addBody(String line) { 67 | msgLines.add(line); 68 | } 69 | 70 | /** 71 | * The list of strings that make up the message to send to FreeSWITCH. 72 | * 73 | * @return list of strings, as they were added to this message. 74 | */ 75 | public List getMsgLines() { 76 | return msgLines; 77 | } 78 | 79 | /** 80 | * {@inheritDoc} 81 | */ 82 | @Override 83 | public String toString() { 84 | StringBuilder sb = new StringBuilder("SendEvent: "); 85 | if (msgLines.size() > 1) { 86 | sb.append(msgLines.get(1)); 87 | } else if (msgLines.size() > 0) { 88 | sb.append(0); 89 | } 90 | 91 | return sb.toString(); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/SendMsg.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /** 22 | *

SendMsg class.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public class SendMsg { 28 | 29 | private final List msgLines = new ArrayList<>(); 30 | private final boolean hasUuid; 31 | 32 | /** 33 | * Constructor for use with outbound socket client only. This client mode does not need a call 34 | * UUID for context. 35 | */ 36 | public SendMsg() { 37 | msgLines.add("sendmsg"); 38 | hasUuid = false; 39 | } 40 | 41 | /** 42 | * Constructor for use with the inbound client. 43 | * 44 | * @param uuid of the call to send message to (it should be in 'park' to be operated on). 45 | */ 46 | public SendMsg(String uuid) { 47 | msgLines.add("sendmsg " + uuid); 48 | hasUuid = true; 49 | } 50 | 51 | /** 52 | * Adds the following line to the message: 53 | *
 54 |      *   call-command: command
 55 |      * 
56 | * 57 | * @param command the string command [ execute | hangup ] 58 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 59 | */ 60 | public SendMsg addCallCommand(String command) { 61 | msgLines.add("call-command: " + command); 62 | return this; 63 | } 64 | 65 | /** 66 | * Adds the following line to the message: 67 | *
 68 |      *   execute-app-name: appName
 69 |      * 
70 | * 71 | * @param appName the string app name to execute 72 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 73 | */ 74 | public SendMsg addExecuteAppName(String appName) { 75 | msgLines.add("execute-app-name: " + appName); 76 | return this; 77 | } 78 | 79 | /** 80 | * Adds the following line to the message: 81 | *
 82 |      *   execute-app-arg: arg
 83 |      * 
84 | * 85 | * @param arg the string arg 86 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 87 | */ 88 | public SendMsg addExecuteAppArg(String arg) { 89 | msgLines.add("execute-app-arg: " + arg); 90 | return this; 91 | } 92 | 93 | /** 94 | * Adds the following line to the message: 95 | *
 96 |      *   loops: count
 97 |      * 
98 | * 99 | * @param count the int number of times to loop 100 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 101 | */ 102 | public SendMsg addLoops(int count) { 103 | msgLines.add("loops: " + count); 104 | return this; 105 | } 106 | 107 | /** 108 | * Adds the following line to the message: 109 | *
110 |      *   hangup-cause: cause
111 |      * 
112 | * 113 | * @param cause the string cause 114 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 115 | */ 116 | public SendMsg addHangupCause(String cause) { 117 | msgLines.add("hangup-cause: " + cause); 118 | return this; 119 | } 120 | 121 | /** 122 | * Adds the following line to the message: 123 | *
124 |      *   nomedia-uid: value
125 |      * 
126 | * 127 | * @param value the string value part of the line 128 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 129 | */ 130 | public SendMsg addNomediaUuid(String value) { 131 | msgLines.add("nomedia-uuid: " + value); 132 | return this; 133 | } 134 | 135 | /** 136 | * Adds the following line to the message: 137 | *
138 |      *    event-lock: true
139 |      *  
140 | * 141 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 142 | */ 143 | public SendMsg addEventLock() { 144 | msgLines.add("event-lock: true"); 145 | return this; 146 | } 147 | 148 | /** 149 | * A generic method to add a message line. The constructed line in the sent message will be in the 150 | * form: 151 | *
152 |      *   name: value
153 |      * 
154 | * 155 | * @param name part of line 156 | * @param value part of line 157 | * @return a {@link link.thingscloud.freeswitch.esl.transport.SendMsg} object. 158 | */ 159 | public SendMsg addGenericLine(String name, String value) { 160 | msgLines.add(name + ": " + value); 161 | return this; 162 | } 163 | 164 | /** 165 | * The list of strings that make up the message to send to FreeSWITCH. 166 | * 167 | * @return list of strings, as they were added to this message. 168 | */ 169 | public List getMsgLines() { 170 | return msgLines; 171 | } 172 | 173 | /** 174 | * Indicate if message was constructed with a UUID. 175 | * 176 | * @return true if constructed with a UUID. 177 | */ 178 | public boolean hasUuid() { 179 | return hasUuid; 180 | } 181 | 182 | /** 183 | * {@inheritDoc} 184 | */ 185 | @Override 186 | public String toString() { 187 | StringBuilder sb = new StringBuilder("SendMsg: "); 188 | if (msgLines.size() > 1) { 189 | sb.append(msgLines.get(1)); 190 | } else if (msgLines.size() > 0) { 191 | sb.append(0); 192 | } 193 | 194 | return sb.toString(); 195 | } 196 | 197 | 198 | } 199 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/event/EslEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.event; 17 | 18 | import link.thingscloud.freeswitch.esl.transport.message.EslHeaders; 19 | import link.thingscloud.freeswitch.esl.transport.message.EslMessage; 20 | import link.thingscloud.freeswitch.esl.transport.util.HeaderParser; 21 | import lombok.extern.slf4j.Slf4j; 22 | 23 | import java.io.UnsupportedEncodingException; 24 | import java.net.URLDecoder; 25 | import java.util.ArrayList; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | 30 | /** 31 | * FreeSWITCH Event Socket events are decoded into this data object. 32 | *

33 | * An ESL event is modelled as a collection of text lines. An event always has several eventHeader 34 | * lines, and optionally may have some eventBody lines. In addition the messageHeaders of the 35 | * original containing {@link link.thingscloud.freeswitch.esl.transport.message.EslMessage} which carried the event are also available. 36 | *

37 | * The eventHeader lines are parsed and cached in a map keyed by the eventHeader name string. An event 38 | * is always expected to have an "Event-Name" eventHeader. Commonly used eventHeader names are coded 39 | * in {@link link.thingscloud.freeswitch.esl.transport.event.EslEventHeaderNames} 40 | *

41 | * Any eventBody lines are cached in a list. 42 | *

43 | * The messageHeader lines from the original message are cached in a map keyed by {@link link.thingscloud.freeswitch.esl.transport.message.EslHeaders.Name}. 44 | * 45 | * @author : zhouhailin 46 | * @version 1.0.0 47 | * @see EslEventHeaderNames 48 | */ 49 | @Slf4j 50 | public class EslEvent { 51 | 52 | private final Map messageHeaders; 53 | private final Map eventHeaders; 54 | private final List eventBody; 55 | private final boolean decodeEventHeaders = true; 56 | 57 | /** 58 | *

Constructor for EslEvent.

59 | * 60 | * @param rawMessage a {@link link.thingscloud.freeswitch.esl.transport.message.EslMessage} object. 61 | */ 62 | public EslEvent(EslMessage rawMessage) { 63 | this(rawMessage, false); 64 | } 65 | 66 | /** 67 | *

Constructor for EslEvent.

68 | * 69 | * @param rawMessage a {@link link.thingscloud.freeswitch.esl.transport.message.EslMessage} object. 70 | * @param parseCommandReply a boolean. 71 | */ 72 | public EslEvent(EslMessage rawMessage, boolean parseCommandReply) { 73 | messageHeaders = rawMessage.getHeaders(); 74 | eventHeaders = new HashMap<>(rawMessage.getBodyLines().size()); 75 | eventBody = new ArrayList<>(); 76 | // plain or xml body 77 | if (rawMessage.getContentType().equals(EslHeaders.Value.TEXT_EVENT_PLAIN)) { 78 | parsePlainBody(rawMessage.getBodyLines()); 79 | } else if (rawMessage.getContentType().equals(EslHeaders.Value.TEXT_EVENT_XML)) { 80 | throw new IllegalStateException("XML events are not yet supported"); 81 | } else if (rawMessage.getContentType().equals(EslHeaders.Value.COMMAND_REPLY) && parseCommandReply) { 82 | parsePlainBody(rawMessage.getBodyLines()); 83 | } else { 84 | throw new IllegalStateException("Unexpected EVENT content-type: " + 85 | rawMessage.getContentType()); 86 | } 87 | } 88 | 89 | /** 90 | * The message headers of the original ESL message from which this event was decoded. 91 | * The message headers are stored in a map keyed by {@link link.thingscloud.freeswitch.esl.transport.message.EslHeaders.Name}. The string mapped value 92 | * is the parsed content of the header line (ie, it does not include the header name). 93 | * 94 | * @return map of header values 95 | */ 96 | public Map getMessageHeaders() { 97 | return messageHeaders; 98 | } 99 | 100 | /** 101 | * The event headers of this event. The headers are parsed and stored in a map keyed by the string 102 | * name of the header, and the string mapped value is the parsed content of the event header line 103 | * (ie, it does not include the header name). 104 | * 105 | * @return map of event header values 106 | */ 107 | public Map getEventHeaders() { 108 | return eventHeaders; 109 | } 110 | 111 | /** 112 | * Any event body lines that were present in the event. 113 | * 114 | * @return list of decoded event body lines, may be an empty list. 115 | */ 116 | public List getEventBodyLines() { 117 | return eventBody; 118 | } 119 | 120 | /** 121 | * Convenience method. 122 | * 123 | * @return the string value of the event header "Event-Name" 124 | */ 125 | public String getEventName() { 126 | return getEventHeaders().get(EslEventHeaderNames.EVENT_NAME); 127 | } 128 | 129 | /** 130 | * Convenience method. 131 | * 132 | * @return long value of the event header "Event-Date-Timestamp" 133 | */ 134 | public long getEventDateTimestamp() { 135 | return Long.valueOf(getEventHeaders().get(EslEventHeaderNames.EVENT_DATE_TIMESTAMP)); 136 | } 137 | 138 | /** 139 | * Convenience method. 140 | * 141 | * @return long value of the event header "Event-Date-Local" 142 | */ 143 | public String getEventDateLocal() { 144 | return getEventHeaders().get(EslEventHeaderNames.EVENT_DATE_LOCAL); 145 | } 146 | 147 | /** 148 | * Convenience method. 149 | * 150 | * @return long value of the event header "Event-Date-GMT" 151 | */ 152 | public String getEventDateGmt() { 153 | return getEventHeaders().get(EslEventHeaderNames.EVENT_DATE_GMT); 154 | } 155 | 156 | /** 157 | * Convenience method. 158 | * 159 | * @return true if the eventBody list is not empty. 160 | */ 161 | public boolean hasEventBody() { 162 | return !eventBody.isEmpty(); 163 | } 164 | 165 | private void parsePlainBody(final List rawBodyLines) { 166 | boolean isEventBody = false; 167 | for (String rawLine : rawBodyLines) { 168 | if (!isEventBody) { 169 | // split the line 170 | String[] headerParts = HeaderParser.splitHeader(rawLine); 171 | if (decodeEventHeaders) { 172 | try { 173 | String decodedValue = URLDecoder.decode(headerParts[1], "UTF-8"); 174 | log.trace("decoded from: [{}]", headerParts[1]); 175 | log.trace("decoded to: [{}]", decodedValue); 176 | eventHeaders.put(headerParts[0], decodedValue); 177 | } catch (UnsupportedEncodingException e) { 178 | log.warn("Could not URL decode [{}]", headerParts[1]); 179 | eventHeaders.put(headerParts[0], headerParts[1]); 180 | } 181 | } else { 182 | eventHeaders.put(headerParts[0], headerParts[1]); 183 | } 184 | if (headerParts[0].equals(EslEventHeaderNames.CONTENT_LENGTH)) { 185 | // the remaining lines will be considered body lines 186 | isEventBody = true; 187 | } 188 | } else { 189 | // ignore blank line (always is one following the content-length 190 | if (rawLine.length() > 0) { 191 | eventBody.add(rawLine); 192 | } 193 | } 194 | } 195 | 196 | } 197 | 198 | /** 199 | * {@inheritDoc} 200 | */ 201 | @Override 202 | public String toString() { 203 | StringBuilder sb = new StringBuilder("EslEvent: name=["); 204 | sb.append(getEventName()); 205 | sb.append("] headers="); 206 | sb.append(messageHeaders.size()); 207 | sb.append(", eventHeaders="); 208 | sb.append(eventHeaders.size()); 209 | sb.append(", eventBody="); 210 | sb.append(eventBody.size()); 211 | sb.append(" lines."); 212 | return sb.toString(); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/event/EslEventHeaderNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.event; 17 | 18 | /** 19 | *

EslEventHeaderNames class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class EslEventHeaderNames { 25 | /** 26 | * {@code "Event-Name"} 27 | */ 28 | public static final String EVENT_NAME = "Event-Name"; 29 | /** 30 | * {@code "Event-Date-Local"} 31 | */ 32 | public static final String EVENT_DATE_LOCAL = "Event-Date-Local"; 33 | /** 34 | * {@code "Event-Date-GMT"} 35 | */ 36 | public static final String EVENT_DATE_GMT = "Event-Date-GMT"; 37 | /** 38 | * {@code "Event-Date-Timestamp"} 39 | */ 40 | public static final String EVENT_DATE_TIMESTAMP = "Event-Date-Timestamp"; 41 | /** 42 | * {@code "Event-Calling-File"} 43 | */ 44 | public static final String EVENT_CALLING_FILE = "Event-Calling-File"; 45 | /** 46 | * {@code "Event-Calling-Function"} 47 | */ 48 | public static final String EVENT_CALLING_FUNCTION = "Event-Calling-Function"; 49 | /** 50 | * {@code "Event-Calling-Line-Number"} 51 | */ 52 | public static final String EVENT_CALLING_LINE_NUMBER = "Event-Calling-Line-Number"; 53 | /** 54 | * {@code "FreeSWITCH-Hostname"} 55 | */ 56 | public static final String FREESWITCH_HOSTNAME = "FreeSWITCH-Hostname"; 57 | /** 58 | * {@code "FreeSWITCH-IPv4"} 59 | */ 60 | public static final String FREESWITCH_IPV4 = "FreeSWITCH-IPv4"; 61 | /** 62 | * {@code "FreeSWITCH-IPv6"} 63 | */ 64 | public static final String FREESWITCH_IPV6 = "FreeSWITCH-IPv6"; 65 | /** 66 | * {@code "Core-UUID"} 67 | */ 68 | public static final String CORE_UUID = "Core-UUID"; 69 | /** 70 | * {@code "Content-Length"} 71 | */ 72 | public static final String CONTENT_LENGTH = "Content-Length"; 73 | /** 74 | * {@code "Job-Command"} 75 | */ 76 | public static final String JOB_COMMAND = "Job-Command"; 77 | /** 78 | * {@code "Job-UUID"} 79 | */ 80 | public static final String JOB_UUID = "Job-UUID"; 81 | 82 | private EslEventHeaderNames() { 83 | /* private class */ 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/message/EslFrameDecoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.message; 17 | 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.channel.ChannelHandlerContext; 20 | import io.netty.handler.codec.ReplayingDecoder; 21 | import io.netty.handler.codec.TooLongFrameException; 22 | import io.netty.util.ReferenceCountUtil; 23 | import link.thingscloud.freeswitch.esl.exception.EslDecoderException; 24 | import link.thingscloud.freeswitch.esl.transport.util.ByteBuilder; 25 | import link.thingscloud.freeswitch.esl.transport.util.HeaderParser; 26 | import lombok.extern.slf4j.Slf4j; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | *

EslFrameDecoder class.

32 | * 33 | * @author : zhouhailin 34 | * @version 1.0.0 35 | */ 36 | @Slf4j 37 | public class EslFrameDecoder extends ReplayingDecoder { 38 | /** 39 | * Line feed character 40 | */ 41 | private static final byte LF = 10; 42 | private final int maxHeaderSize; 43 | private EslMessage currentMessage; 44 | private boolean treatUnknownHeadersAsBody = false; 45 | 46 | /** 47 | *

Constructor for EslFrameDecoder.

48 | * 49 | * @param maxHeaderSize a int. 50 | */ 51 | public EslFrameDecoder(int maxHeaderSize) { 52 | super(State.READ_HEADER); 53 | if (maxHeaderSize <= 0) { 54 | throw new IllegalArgumentException( 55 | "maxHeaderSize must be a positive integer: " + 56 | maxHeaderSize); 57 | } 58 | this.maxHeaderSize = maxHeaderSize; 59 | } 60 | 61 | /** 62 | *

Constructor for EslFrameDecoder.

63 | * 64 | * @param maxHeaderSize a int. 65 | * @param treatUnknownHeadersAsBody a boolean. 66 | */ 67 | public EslFrameDecoder(int maxHeaderSize, boolean treatUnknownHeadersAsBody) { 68 | this(maxHeaderSize); 69 | this.treatUnknownHeadersAsBody = treatUnknownHeadersAsBody; 70 | } 71 | 72 | /** 73 | * {@inheritDoc} 74 | */ 75 | @Override 76 | protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) { 77 | log.trace("decode() : state [{}]", state()); 78 | switch (state()) { 79 | case READ_HEADER: 80 | if (currentMessage == null) { 81 | currentMessage = new EslMessage(); 82 | } 83 | /* 84 | * read '\n' terminated lines until reach a single '\n' 85 | */ 86 | boolean reachedDoubleLF = false; 87 | while (!reachedDoubleLF) { 88 | // this will read or fail 89 | String headerLine = readToLineFeedOrFail(buffer, maxHeaderSize); 90 | log.trace("read header line [{}]", headerLine); 91 | if (!headerLine.isEmpty()) { 92 | // split the header line 93 | String[] headerParts = HeaderParser.splitHeader(headerLine); 94 | EslHeaders.Name headerName = EslHeaders.Name.fromLiteral(headerParts[0]); 95 | if (headerName == null) { 96 | if (treatUnknownHeadersAsBody) { 97 | // cache this 'header' as a body line <-- useful for Outbound client mode 98 | currentMessage.addBodyLine(headerLine); 99 | } else { 100 | throw new IllegalStateException("Unhandled ESL header [" + headerParts[0] + ']'); 101 | } 102 | } 103 | currentMessage.addHeader(headerName, headerParts[1]); 104 | } else { 105 | reachedDoubleLF = true; 106 | } 107 | // do not read in this line again 108 | checkpoint(); 109 | } 110 | // have read all headers - check for content-length 111 | if (currentMessage.hasContentLength()) { 112 | checkpoint(State.READ_BODY); 113 | log.trace("have content-length, decoding body .."); 114 | // force the next section 115 | return; 116 | } else { 117 | // end of message 118 | checkpoint(State.READ_HEADER); 119 | // send message upstream 120 | EslMessage decodedMessage = currentMessage; 121 | currentMessage = null; 122 | 123 | out.add(decodedMessage); 124 | return; 125 | } 126 | case READ_BODY: 127 | /* 128 | * read the content-length specified 129 | */ 130 | int contentLength = currentMessage.getContentLength(); 131 | ByteBuf bodyBytes = buffer.readBytes(contentLength); 132 | log.trace("read [{}] body bytes", bodyBytes.writerIndex()); 133 | // most bodies are line based, so split on LF 134 | while (bodyBytes.isReadable()) { 135 | String bodyLine = readLine(bodyBytes, contentLength); 136 | log.trace("read body line [{}]", bodyLine); 137 | currentMessage.addBodyLine(bodyLine); 138 | } 139 | // release bodyBytes 140 | if (bodyBytes.refCnt() > 0) { 141 | ReferenceCountUtil.safeRelease(bodyBytes); 142 | } 143 | 144 | // end of message 145 | checkpoint(State.READ_HEADER); 146 | // send message upstream 147 | EslMessage decodedMessage = currentMessage; 148 | currentMessage = null; 149 | 150 | out.add(decodedMessage); 151 | return; 152 | default: 153 | throw new EslDecoderException("Illegal state: [" + state() + ']'); 154 | } 155 | } 156 | 157 | private String readToLineFeedOrFail(ByteBuf buffer, int maxLineLegth) { 158 | ByteBuilder builder = ByteBuilder.newBuilder(); 159 | while (true) { 160 | // this read might fail 161 | byte nextByte = buffer.readByte(); 162 | if (nextByte == LF) { 163 | return builder.string(); 164 | } else { 165 | // Abort decoding if the decoded line is too large. 166 | if (builder.length() >= maxLineLegth) { 167 | throw new TooLongFrameException( 168 | "ESL header line is longer than " + maxLineLegth + " bytes."); 169 | } 170 | builder.append(nextByte); 171 | } 172 | } 173 | } 174 | 175 | private String readLine(ByteBuf buffer, int maxLineLength) { 176 | ByteBuilder builder = ByteBuilder.newBuilder(); 177 | while (buffer.isReadable()) { 178 | // this read should always succeed 179 | byte nextByte = buffer.readByte(); 180 | if (nextByte == LF) { 181 | return builder.string(); 182 | } else { 183 | // Abort decoding if the decoded line is too large. 184 | if (builder.length() >= maxLineLength) { 185 | throw new TooLongFrameException( 186 | "ESL message line is longer than " + maxLineLength + " bytes."); 187 | } 188 | builder.append(nextByte); 189 | } 190 | } 191 | 192 | return builder.string(); 193 | } 194 | 195 | protected enum State { 196 | /** 197 | * 包头 198 | */ 199 | READ_HEADER, 200 | /** 201 | * 包体 202 | */ 203 | READ_BODY, 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/message/EslHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.message; 17 | 18 | /** 19 | *

EslHeaders class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class EslHeaders { 25 | 26 | /** 27 | * Standard ESL header names. 28 | *

29 | * Note this enum will need to be kept in synch with any new headers introduced on the server side. 30 | * 31 | * @author : zhouhailin 32 | */ 33 | public enum Name { 34 | /* 35 | * Minor optimization - put most often used headers at the top for fastest resolution 36 | * in static fromLiteral(). 37 | */ 38 | 39 | /** 40 | * {@code "Content-Type"} 41 | */ 42 | CONTENT_TYPE("Content-Type"), 43 | /** 44 | * {@code "Content-Length"} 45 | */ 46 | CONTENT_LENGTH("Content-Length"), 47 | /** 48 | * {@code "Reply-Text"} 49 | */ 50 | REPLY_TEXT("Reply-Text"), 51 | /** 52 | * {@code "Job-UUID"} 53 | */ 54 | JOB_UUID("Job-UUID"), 55 | /** 56 | * {@code "Socket-Mode"} 57 | */ 58 | SOCKET_MODE("Socket-Mode"), 59 | /** 60 | * {@code "CONTROL"} 61 | */ 62 | CONTROL("CONTROL"), 63 | ; 64 | 65 | private final String literal; 66 | 67 | Name(String literal) { 68 | this.literal = literal; 69 | } 70 | 71 | public static Name fromLiteral(String literal) { 72 | for (Name name : values()) { 73 | if (name.literal.equalsIgnoreCase(literal)) { 74 | return name; 75 | } 76 | } 77 | 78 | return null; 79 | } 80 | 81 | public String literal() { 82 | return literal; 83 | } 84 | } 85 | 86 | /** 87 | * Some common ESL header values. These are provided as a convenience for commonly used values. 88 | *

89 | * This values are not coded as an enum to allow for the very large range of possible values, 90 | * since they are just Strings. 91 | * 92 | * @author : zhouhailin 93 | */ 94 | public static final class Value { 95 | /** 96 | * {@code "+OK"} 97 | */ 98 | public static final String OK = "+OK"; 99 | /** 100 | * {@code "auth/request"} 101 | */ 102 | public static final String AUTH_REQUEST = "auth/request"; 103 | /** 104 | * {@code "api/response"} 105 | */ 106 | public static final String API_RESPONSE = "api/response"; 107 | /** 108 | * {@code "command/reply"} 109 | */ 110 | public static final String COMMAND_REPLY = "command/reply"; 111 | /** 112 | * {@code "text/event-plain"} 113 | */ 114 | public static final String TEXT_EVENT_PLAIN = "text/event-plain"; 115 | /** 116 | * {@code "text/event-xml"} 117 | */ 118 | public static final String TEXT_EVENT_XML = "text/event-xml"; 119 | /** 120 | * {@code "text/disconnect-notice"} 121 | */ 122 | public static final String TEXT_DISCONNECT_NOTICE = "text/disconnect-notice"; 123 | /** 124 | * {@code "text/rude-rejection"} 125 | */ 126 | public static final String TEXT_RUDE_REJECTION = "text/rude-rejection"; 127 | /** 128 | * {@code "-ERR invalid"} 129 | */ 130 | public static final String ERR_INVALID = "-ERR invalid"; 131 | 132 | private Value() { 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/message/EslMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.message; 17 | 18 | import lombok.extern.slf4j.Slf4j; 19 | 20 | import java.util.ArrayList; 21 | import java.util.EnumMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | /** 26 | * Basic FreeSWITCH Event Socket messages from the server are decoded into this data object. 27 | *

28 | * An ESL message is modelled as text lines. A message always has one or more header lines, and 29 | * optionally may have some body lines. 30 | *

31 | * Header lines are parsed and cached in a map keyed by the {@link link.thingscloud.freeswitch.esl.transport.message.EslHeaders.Name} enum. A message 32 | * is always expected to have a "Content-Type" header 33 | *

34 | * Any Body lines are cached in a list. 35 | * 36 | * @author : zhouhailin 37 | * @version 1.0.0 38 | * @see EslHeaders.Name 39 | */ 40 | @Slf4j 41 | public class EslMessage { 42 | 43 | private final Map headers = new EnumMap<>(EslHeaders.Name.class); 44 | private final List body = new ArrayList<>(); 45 | 46 | private Integer contentLength = null; 47 | 48 | /** 49 | * All the received message headers in a map keyed by {@link link.thingscloud.freeswitch.esl.transport.message.EslHeaders.Name}. The string mapped value 50 | * is the parsed content of the header line (ie, it does not include the header name). 51 | * 52 | * @return map of header values 53 | */ 54 | public Map getHeaders() { 55 | return headers; 56 | } 57 | 58 | /** 59 | * Convenience method 60 | * 61 | * @param headerName as a {@link link.thingscloud.freeswitch.esl.transport.message.EslHeaders.Name} 62 | * @return true if an only if there is a header entry with the supplied header name 63 | */ 64 | public boolean hasHeader(EslHeaders.Name headerName) { 65 | return headers.containsKey(headerName); 66 | } 67 | 68 | /** 69 | * Convenience method 70 | * 71 | * @param headerName as a {@link link.thingscloud.freeswitch.esl.transport.message.EslHeaders.Name} 72 | * @return same as getHeaders().get( headerName ) 73 | */ 74 | public String getHeaderValue(EslHeaders.Name headerName) { 75 | return headers.get(headerName); 76 | } 77 | 78 | /** 79 | * Convenience method 80 | * 81 | * @return true if and only if a header exists with name "Content-Length" 82 | */ 83 | public boolean hasContentLength() { 84 | return headers.containsKey(EslHeaders.Name.CONTENT_LENGTH); 85 | } 86 | 87 | /** 88 | * Convenience method 89 | * 90 | * @return integer value of header with name "Content-Length" 91 | */ 92 | public Integer getContentLength() { 93 | if (contentLength != null) { 94 | return contentLength; 95 | } 96 | if (hasContentLength()) { 97 | contentLength = Integer.valueOf(headers.get(EslHeaders.Name.CONTENT_LENGTH)); 98 | } 99 | return contentLength; 100 | } 101 | 102 | /** 103 | * Convenience method 104 | * 105 | * @return header value of header with name "Content-Type" 106 | */ 107 | public String getContentType() { 108 | return headers.get(EslHeaders.Name.CONTENT_TYPE); 109 | } 110 | 111 | /** 112 | * Any received message body lines 113 | * 114 | * @return list with a string for each line received, may be an empty list 115 | */ 116 | public List getBodyLines() { 117 | return body; 118 | } 119 | 120 | /** 121 | * Used by the {@link EslFrameDecoder}. 122 | * 123 | * @param name 124 | * @param value 125 | */ 126 | void addHeader(EslHeaders.Name name, String value) { 127 | log.trace("adding header [{}] [{}]", name, value); 128 | headers.put(name, value); 129 | } 130 | 131 | /** 132 | * Used by the {@link EslFrameDecoder} 133 | * 134 | * @param line 135 | */ 136 | void addBodyLine(String line) { 137 | if (line == null) { 138 | return; 139 | } 140 | body.add(line); 141 | } 142 | 143 | /** 144 | * {@inheritDoc} 145 | */ 146 | @Override 147 | public String toString() { 148 | StringBuilder sb = new StringBuilder("EslMessage: contentType=["); 149 | sb.append(getContentType()); 150 | sb.append("] headers="); 151 | sb.append(headers.size()); 152 | sb.append(", body="); 153 | sb.append(body.size()); 154 | sb.append(" lines."); 155 | 156 | return sb.toString(); 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/util/ByteBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.util; 17 | 18 | /** 19 | *

ByteBuilder class.

20 | * 21 | * @author zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class ByteBuilder { 25 | 26 | private byte[] b = new byte[128]; 27 | private int index = 0; 28 | 29 | private ByteBuilder() { 30 | } 31 | 32 | /** 33 | *

newBuilder.

34 | * 35 | * @return a {@link link.thingscloud.freeswitch.esl.transport.util.ByteBuilder} object. 36 | */ 37 | public static ByteBuilder newBuilder() { 38 | return new ByteBuilder(); 39 | } 40 | 41 | /** 42 | *

append.

43 | * 44 | * @param byte0 a byte. 45 | * @return a {@link link.thingscloud.freeswitch.esl.transport.util.ByteBuilder} object. 46 | */ 47 | public ByteBuilder append(byte byte0) { 48 | if (this.b.length <= (index + 1)) { 49 | byte[] newB = new byte[this.b.length * 2]; 50 | System.arraycopy(this.b, 0, newB, 0, this.b.length); 51 | this.b = newB; 52 | } 53 | this.b[index] = byte0; 54 | index++; 55 | return this; 56 | } 57 | 58 | /** 59 | *

length.

60 | * 61 | * @return a int. 62 | */ 63 | public int length() { 64 | return index; 65 | } 66 | 67 | /** 68 | *

build.

69 | * 70 | * @return an array of {@link byte} objects. 71 | */ 72 | public byte[] build() { 73 | return b; 74 | } 75 | 76 | /** 77 | *

string.

78 | * 79 | * @return a {@link java.lang.String} object. 80 | */ 81 | public String string() { 82 | return new String(b, 0, index); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/transport/util/HeaderParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.util; 17 | 18 | /** 19 | *

HeaderParser class.

20 | * 21 | * @author : zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class HeaderParser { 25 | private HeaderParser() { 26 | } 27 | 28 | /** 29 | * Split a header in the form 30 | *
31 |      *   Header-Name: Some_header-value
32 |      * 
33 | * into a String array. 34 | * 35 | * @param sb the string header to parse 36 | * @return a String[] array with header name at 0 and header value at 1 37 | */ 38 | public static String[] splitHeader(String sb) { 39 | final int length = sb.length(); 40 | int nameStart; 41 | int nameEnd; 42 | int colonEnd; 43 | int valueStart; 44 | int valueEnd; 45 | 46 | nameStart = findNonWhitespace(sb, 0); 47 | for (nameEnd = nameStart; nameEnd < length; nameEnd++) { 48 | char ch = sb.charAt(nameEnd); 49 | if (ch == ':' || Character.isWhitespace(ch)) { 50 | break; 51 | } 52 | } 53 | 54 | for (colonEnd = nameEnd; colonEnd < length; colonEnd++) { 55 | if (sb.charAt(colonEnd) == ':') { 56 | colonEnd++; 57 | break; 58 | } 59 | } 60 | 61 | valueStart = findNonWhitespace(sb, colonEnd); 62 | if (valueStart == length) { 63 | return new String[]{ 64 | sb.substring(nameStart, nameEnd), 65 | "" 66 | }; 67 | } 68 | 69 | valueEnd = findEndOfString(sb); 70 | return new String[]{ 71 | sb.substring(nameStart, nameEnd), 72 | sb.substring(valueStart, valueEnd) 73 | }; 74 | } 75 | 76 | private static int findNonWhitespace(String sb, int offset) { 77 | int result; 78 | for (result = offset; result < sb.length(); result++) { 79 | if (!Character.isWhitespace(sb.charAt(result))) { 80 | break; 81 | } 82 | } 83 | return result; 84 | } 85 | 86 | private static int findEndOfString(String sb) { 87 | int result; 88 | for (result = sb.length(); result > 0; result--) { 89 | if (!Character.isWhitespace(sb.charAt(result - 1))) { 90 | break; 91 | } 92 | } 93 | return result; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | import java.lang.reflect.Array; 19 | 20 | /** 21 | *

ArrayUtils class.

22 | * 23 | * @author zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public class ArrayUtils { 27 | 28 | /** 29 | *

isEmpty.

30 | * 31 | * @param array an array of {@link java.lang.Object} objects. 32 | * @return a boolean. 33 | */ 34 | public static boolean isEmpty(final Object[] array) { 35 | return getLength(array) == 0; 36 | } 37 | 38 | /** 39 | *

getLength.

40 | * 41 | * @param array a {@link java.lang.Object} object. 42 | * @return a int. 43 | */ 44 | public static int getLength(final Object array) { 45 | if (array == null) { 46 | return 0; 47 | } 48 | return Array.getLength(array); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/EslEventUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 19 | 20 | /** 21 | * @author zhouhailin 22 | * @version 1.5.0 23 | */ 24 | public class EslEventUtil { 25 | 26 | public static final String CORE_UUID = "Core-UUID"; 27 | public static final String UNIQUE_ID = "Unique-ID"; 28 | 29 | public static final String EVENT_NAME = "Event-Name"; 30 | public static final String EVENT_SEQUENCE = "Event-Sequence"; 31 | public static final String EVENT_DATE_LOCAL = "Event-Date-Local"; 32 | public static final String EVENT_DATE_GMT = "Event-Date-GMT"; 33 | public static final String EVENT_DATE_TIMESTAMP = "Event-Date-Timestamp"; 34 | 35 | public static final String EVENT_CALLING_FILE = "Event-Calling-File"; 36 | public static final String EVENT_CALLING_FUNCTION = "Event-Calling-Function"; 37 | public static final String EVENT_CALLING_LINE_NUMBER = "Event-Calling-Line-Number"; 38 | 39 | public static final String FREESWITCH_IPV4 = "FreeSWITCH-IPv4"; 40 | public static final String FREESWITCH_IPV6 = "FreeSWITCH-IPv6"; 41 | public static final String FREESWITCH_HOSTNAME = "FreeSWITCH-Hostname"; 42 | public static final String FREESWITCH_SWITCHNAME = "FreeSWITCH-Switchname"; 43 | 44 | public static final String CALLER_UNIQUE_ID = "Caller-Unique-ID"; 45 | public static final String CALLER_NETWORK_ADDR = "Caller-Network-Addr"; 46 | 47 | public static final String CALLER_CONTEXT = "Caller-Context"; 48 | public static final String CALLER_DIALPLAN = "Caller-Dialplan"; 49 | public static final String CALLER_DIRECTION = "Caller-Direction"; 50 | public static final String CALLER_LOGICAL_DIRECTION = "Caller-Logical-Direction"; 51 | public static final String CALLER_PROFILE_INDEX = "Caller-Profile-Index"; 52 | 53 | public static final String CALLER_ANI = "Caller-ANI"; 54 | public static final String CALLER_USERNAME = "Caller-Username"; 55 | public static final String CALLER_DESTINATION_NUMBER = "Caller-Destination-Number"; 56 | public static final String CALLER_CALLER_ID_NAME = "Caller-Caller-ID-Name"; 57 | public static final String CALLER_CALLER_ID_NUMBER = "Caller-Caller-ID-Number"; 58 | 59 | public static final String CALLER_ORIG_CALLER_ID_NAME = "Caller-Orig-Caller-ID-Name"; 60 | public static final String CALLER_ORIG_CALLER_ID_NUMBER = "Caller-Orig-Caller-ID-Number"; 61 | 62 | public static final String CALLER_PROFILE_CREATED_TIME = "Caller-Profile-Created-Time"; 63 | 64 | public static final String CALLER_CHANNEL_CREATED_TIME = "Caller-Channel-Created-Time"; 65 | public static final String CALLER_CHANNEL_PROGRESS_TIME = "Caller-Channel-Progress-Time"; 66 | public static final String CALLER_CHANNEL_PROGRESS_MEDIA_TIME = "Caller-Channel-Progress-Media-Time"; 67 | public static final String CALLER_CHANNEL_ANSWERED_TIME = "Caller-Channel-Answered-Time"; 68 | public static final String CALLER_CHANNEL_HANGUP_TIME = "Caller-Channel-Hangup-Time"; 69 | public static final String CALLER_CHANNEL_BRIDGED_TIME = "Caller-Channel-Bridged-Time"; 70 | 71 | public static final String CALLER_CHANNEL_NAME = "Caller-Channel-Name"; 72 | public static final String CALLER_CHANNEL_HOLD_ACCUM = "Caller-Channel-Hold-Accum"; 73 | public static final String CALLER_CHANNEL_LAST_HOLD = "Caller-Channel-Last-Hold"; 74 | public static final String CALLER_CHANNEL_TRANSFER_TIME = "Caller-Channel-Transfer-Time"; 75 | public static final String CALLER_CHANNEL_RESURRECT_TIME = "Caller-Channel-Resurrect-Time"; 76 | 77 | 78 | private EslEventUtil() { 79 | } 80 | 81 | public static String getCoreUuid(EslEvent event) { 82 | return event.getEventHeaders().get(CORE_UUID); 83 | } 84 | 85 | public static String getUniqueId(EslEvent event) { 86 | return event.getEventHeaders().get(UNIQUE_ID); 87 | } 88 | 89 | public static String getCallerUniqueId(EslEvent event) { 90 | return event.getEventHeaders().get(CALLER_UNIQUE_ID); 91 | } 92 | 93 | public static String getEventName(EslEvent event) { 94 | return event.getEventHeaders().get(EVENT_NAME); 95 | } 96 | 97 | public static String getEventSequence(EslEvent event) { 98 | return event.getEventHeaders().get(EVENT_SEQUENCE); 99 | } 100 | 101 | public static String getEventDateLocal(EslEvent event) { 102 | return event.getEventHeaders().get(EVENT_DATE_LOCAL); 103 | } 104 | 105 | public static String getEventDateGmt(EslEvent event) { 106 | return event.getEventHeaders().get(EVENT_DATE_GMT); 107 | } 108 | 109 | public static String getEventCallingFile(EslEvent event) { 110 | return event.getEventHeaders().get(EVENT_CALLING_FILE); 111 | } 112 | 113 | public static String getEventCallingFunction(EslEvent event) { 114 | return event.getEventHeaders().get(EVENT_CALLING_FUNCTION); 115 | } 116 | 117 | public static String getEventCallingLineNumber(EslEvent event) { 118 | return event.getEventHeaders().get(EVENT_CALLING_LINE_NUMBER); 119 | } 120 | 121 | public static String getFreeswitchIpv4(EslEvent event) { 122 | return event.getEventHeaders().get(FREESWITCH_IPV4); 123 | } 124 | 125 | public static String getFreeswitchIpv6(EslEvent event) { 126 | return event.getEventHeaders().get(FREESWITCH_IPV6); 127 | } 128 | 129 | public static String getFreeswitchHostname(EslEvent event) { 130 | return event.getEventHeaders().get(FREESWITCH_HOSTNAME); 131 | } 132 | 133 | public static String getFreeswitchSwitchname(EslEvent event) { 134 | return event.getEventHeaders().get(FREESWITCH_SWITCHNAME); 135 | } 136 | 137 | public static String getEventDateTimestamp(EslEvent event) { 138 | return event.getEventHeaders().get(EVENT_DATE_TIMESTAMP); 139 | } 140 | 141 | public static String getCallerProfileCreatedTime(EslEvent event) { 142 | return event.getEventHeaders().get(CALLER_PROFILE_CREATED_TIME); 143 | } 144 | 145 | public static String getCallerChannelCreatedTime(EslEvent event) { 146 | return event.getEventHeaders().get(CALLER_CHANNEL_CREATED_TIME); 147 | } 148 | 149 | public static String getCallerChannelProgressTime(EslEvent event) { 150 | return event.getEventHeaders().get(CALLER_CHANNEL_PROGRESS_TIME); 151 | } 152 | 153 | public static String getCallerChannelProgressMediaTime(EslEvent event) { 154 | return event.getEventHeaders().get(CALLER_CHANNEL_PROGRESS_MEDIA_TIME); 155 | } 156 | 157 | public static String getCallerChannelAnsweredTime(EslEvent event) { 158 | return event.getEventHeaders().get(CALLER_CHANNEL_ANSWERED_TIME); 159 | } 160 | 161 | public static String getCallerChannelHangupTime(EslEvent event) { 162 | return event.getEventHeaders().get(CALLER_CHANNEL_HANGUP_TIME); 163 | } 164 | 165 | public static String getCallerChannelBridgedTime(EslEvent event) { 166 | return event.getEventHeaders().get(CALLER_CHANNEL_BRIDGED_TIME); 167 | } 168 | 169 | public static String getCallerNetworkAddr(EslEvent event) { 170 | return event.getEventHeaders().get(CALLER_NETWORK_ADDR); 171 | } 172 | 173 | public static String getCallerContext(EslEvent event) { 174 | return event.getEventHeaders().get(CALLER_CONTEXT); 175 | } 176 | 177 | public static String getCallerDialplan(EslEvent event) { 178 | return event.getEventHeaders().get(CALLER_DIALPLAN); 179 | } 180 | 181 | public static String getCallerDirection(EslEvent event) { 182 | return event.getEventHeaders().get(CALLER_DIRECTION); 183 | } 184 | 185 | public static String getCallerLogicalDirection(EslEvent event) { 186 | return event.getEventHeaders().get(CALLER_LOGICAL_DIRECTION); 187 | } 188 | 189 | public static String getCallerProfileIndex(EslEvent event) { 190 | return event.getEventHeaders().get(CALLER_PROFILE_INDEX); 191 | } 192 | 193 | public static String getCallerChannelName(EslEvent event) { 194 | return event.getEventHeaders().get(CALLER_CHANNEL_NAME); 195 | } 196 | 197 | public static String getCallerChannelHoldAccum(EslEvent event) { 198 | return event.getEventHeaders().get(CALLER_CHANNEL_HOLD_ACCUM); 199 | } 200 | 201 | public static String getCallerChannelLastHold(EslEvent event) { 202 | return event.getEventHeaders().get(CALLER_CHANNEL_LAST_HOLD); 203 | } 204 | 205 | public static String getCallerChannelTransferTime(EslEvent event) { 206 | return event.getEventHeaders().get(CALLER_CHANNEL_TRANSFER_TIME); 207 | } 208 | 209 | public static String getCallerChannelResurrectTime(EslEvent event) { 210 | return event.getEventHeaders().get(CALLER_CHANNEL_RESURRECT_TIME); 211 | } 212 | 213 | public static String getCallerAni(EslEvent event) { 214 | return event.getEventHeaders().get(CALLER_ANI); 215 | } 216 | 217 | public static String getCallerUsername(EslEvent event) { 218 | return event.getEventHeaders().get(CALLER_USERNAME); 219 | } 220 | 221 | public static String getCallerDestinationNumber(EslEvent event) { 222 | return event.getEventHeaders().get(CALLER_DESTINATION_NUMBER); 223 | } 224 | 225 | public static String getCallerCallerIdName(EslEvent event) { 226 | return event.getEventHeaders().get(CALLER_CALLER_ID_NAME); 227 | } 228 | 229 | public static String getCallerCallerIdNumber(EslEvent event) { 230 | return event.getEventHeaders().get(CALLER_CALLER_ID_NUMBER); 231 | } 232 | 233 | public static String getCallerOrigCallerIdName(EslEvent event) { 234 | return event.getEventHeaders().get(CALLER_ORIG_CALLER_ID_NAME); 235 | } 236 | 237 | public static String getCallerOrigCallerIdNumber(EslEvent event) { 238 | return event.getEventHeaders().get(CALLER_ORIG_CALLER_ID_NUMBER); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/RandomUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | import java.util.Random; 19 | 20 | /** 21 | *

RandomUtils class.

22 | * 23 | * @author zhouhailin 24 | * @version 1.0.0 25 | */ 26 | public class RandomUtils { 27 | 28 | private static final Random RANDOM = new Random(); 29 | 30 | /** 31 | *

nextInt.

32 | * 33 | * @param startInclusive a int. 34 | * @param endExclusive a int. 35 | * @return a int. 36 | */ 37 | public static int nextInt(final int startInclusive, final int endExclusive) { 38 | Validate.isTrue(endExclusive >= startInclusive, 39 | "Start value must be smaller or equal to end value."); 40 | Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 41 | 42 | if (startInclusive == endExclusive) { 43 | return startInclusive; 44 | } 45 | 46 | return startInclusive + RANDOM.nextInt(endExclusive - startInclusive); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/RemotingUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | import java.net.InetSocketAddress; 19 | import java.net.SocketAddress; 20 | 21 | /** 22 | *

RemotingUtil class.

23 | * 24 | * @author : zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public class RemotingUtil { 28 | 29 | /** 30 | * private constructor 31 | */ 32 | private RemotingUtil() { 33 | } 34 | 35 | /** 36 | *

socketAddress2String.

37 | * 38 | * @param addr a {@link java.net.SocketAddress} object. 39 | * @return a {@link java.lang.String} object. 40 | */ 41 | public static String socketAddress2String(final SocketAddress addr) { 42 | InetSocketAddress inetSocketAddress = (InetSocketAddress) addr; 43 | return inetSocketAddress.getAddress().getHostAddress() + 44 | ":" + 45 | inetSocketAddress.getPort(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | /** 19 | *

StringUtils class.

20 | * 21 | * @author zhouhailin 22 | * @version 1.0.0 23 | */ 24 | public class StringUtils { 25 | 26 | public static final String EMPTY = ""; 27 | public static final String BLANK = " "; 28 | 29 | private StringUtils() { 30 | } 31 | 32 | /** 33 | *

length.

34 | * 35 | * @param cs a {@link java.lang.CharSequence} object. 36 | * @return a int. 37 | */ 38 | public static int length(final CharSequence cs) { 39 | return cs == null ? 0 : cs.length(); 40 | } 41 | 42 | /** 43 | *

isNotBlank.

44 | * 45 | * @param cs a {@link java.lang.CharSequence} object. 46 | * @return a boolean. 47 | */ 48 | public static boolean isNotBlank(final CharSequence cs) { 49 | return !isBlank(cs); 50 | } 51 | 52 | /** 53 | *

contains.

54 | * 55 | * @param str a {@link java.lang.String} object. 56 | * @return a boolean. 57 | */ 58 | public static boolean contains(final String str, String str0) { 59 | return str != null && str.contains(str0); 60 | } 61 | 62 | /** 63 | *

isBlank.

64 | * 65 | * @param cs a {@link java.lang.CharSequence} object. 66 | * @return a boolean. 67 | */ 68 | public static boolean isBlank(final CharSequence cs) { 69 | final int strLen = length(cs); 70 | if (strLen == 0) { 71 | return true; 72 | } 73 | for (int i = 0; i < strLen; i++) { 74 | if (!Character.isWhitespace(cs.charAt(i))) { 75 | return false; 76 | } 77 | } 78 | return true; 79 | } 80 | 81 | /** 82 | *

equals.

83 | * 84 | * @param cs1 a {@link java.lang.CharSequence} object. 85 | * @param cs2 a {@link java.lang.CharSequence} object. 86 | * @return a boolean. 87 | */ 88 | public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 89 | if (cs1 == cs2) { 90 | return true; 91 | } 92 | if (cs1 == null || cs2 == null) { 93 | return false; 94 | } 95 | if (cs1.length() != cs2.length()) { 96 | return false; 97 | } 98 | if (cs1 instanceof String && cs2 instanceof String) { 99 | return cs1.equals(cs2); 100 | } 101 | // Step-wise comparison 102 | final int length = cs1.length(); 103 | for (int i = 0; i < length; i++) { 104 | if (cs1.charAt(i) != cs2.charAt(i)) { 105 | return false; 106 | } 107 | } 108 | return true; 109 | } 110 | 111 | public static boolean inEquals(String str, String... strs) { 112 | for (String s : strs) { 113 | if (equals(str, s)) { 114 | return true; 115 | } 116 | } 117 | return false; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/Validate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | import java.util.Collection; 19 | import java.util.Objects; 20 | 21 | /** 22 | *

Validate class.

23 | * 24 | * @author zhouhailin 25 | * @version 1.0.0 26 | */ 27 | public class Validate { 28 | 29 | /** 30 | *

isTrue.

31 | * 32 | * @param expression a boolean. 33 | * @param message a {@link java.lang.String} object. 34 | * @param values a {@link java.lang.Object} object. 35 | */ 36 | public static void isTrue(final boolean expression, final String message, final Object... values) { 37 | if (!expression) { 38 | throw new IllegalArgumentException(String.format(message, values)); 39 | } 40 | } 41 | 42 | /** 43 | *

notEmpty.

44 | * 45 | * @param collection a T object. 46 | * @param message a {@link java.lang.String} object. 47 | * @param values a {@link java.lang.Object} object. 48 | * @param T 49 | * @return a T object. 50 | */ 51 | public static > T notEmpty(final T collection, final String message, final Object... values) { 52 | Objects.requireNonNull(collection, () -> String.format(message, values)); 53 | if (collection.isEmpty()) { 54 | throw new IllegalArgumentException(String.format(message, values)); 55 | } 56 | return collection; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /freeswitch-esl/src/main/java/link/thingscloud/freeswitch/esl/util/VariableUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.util; 17 | 18 | import link.thingscloud.freeswitch.esl.transport.event.EslEvent; 19 | 20 | import java.util.Map; 21 | 22 | /** 23 | * @author zhouhailin 24 | * @version 1.5.1 25 | */ 26 | public class VariableUtil { 27 | 28 | private static final String VARIABLE_PREFIX = "variable_"; 29 | 30 | public static String get(EslEvent event, String key) { 31 | return event.getEventHeaders().get(key); 32 | } 33 | 34 | public static long getLongVar(EslEvent event, String key) { 35 | return Long.parseLong(getVar(event.getEventHeaders(), key)); 36 | } 37 | 38 | public static int getIntVar(EslEvent event, String key) { 39 | return Integer.parseInt(getVar(event.getEventHeaders(), key)); 40 | } 41 | 42 | public static String getVar(EslEvent event, String key) { 43 | return getVar(event.getEventHeaders(), key); 44 | } 45 | 46 | public static String getVar(Map eventHeaders, String key) { 47 | if (key.startsWith(VARIABLE_PREFIX)) { 48 | return eventHeaders.get(key); 49 | } 50 | return eventHeaders.get(VARIABLE_PREFIX + key); 51 | } 52 | 53 | private VariableUtil() { 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /freeswitch-esl/src/test/java/link/thingscloud/freeswitch/esl/helper/CommandHelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.helper; 17 | 18 | import junit.framework.TestCase; 19 | 20 | /** 21 | * @author zhouhailin 22 | * @since 1.6.5 23 | */ 24 | public class CommandHelperTest extends TestCase { 25 | 26 | 27 | } -------------------------------------------------------------------------------- /freeswitch-esl/src/test/java/link/thingscloud/freeswitch/esl/transport/util/ByteBuilderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package link.thingscloud.freeswitch.esl.transport.util; 17 | 18 | import junit.framework.TestCase; 19 | 20 | /** 21 | *

ByteBuilderTest class.

22 | * 23 | * @author zhouhailin 24 | * @version 1.0.0 25 | * @since 1.4.0.SNAPSHOT 26 | */ 27 | public class ByteBuilderTest extends TestCase { 28 | 29 | } 30 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 4.0.0 21 | 22 | link.thingscloud 23 | freeswitch-externals 24 | pom 25 | 2.3.0-SNAPSHOT 26 | 27 | freeswitch-esl-all-${project.version} 28 | freeswitch event socket library on netty 4.1 29 | https://github.com/zhouhailin/freeswitch-esl-all 30 | 2019 31 | 32 | 33 | freeswitch-esl 34 | freeswitch-esl-example 35 | freeswitch-esl-spring-boot-starter 36 | freeswitch-esl-spring-boot-starter-example 37 | freeswitch-cdr 38 | freeswitch-cdr-example 39 | freeswitch-cdr-spring-boot-starter 40 | freeswitch-cdr-spring-boot-starter-example 41 | 42 | 43 | 44 | 8 45 | 46 | 2.7.16 47 | 48 | ${java.version} 49 | ${java.version} 50 | UTF-8 51 | UTF-8 52 | 53 | 3.11.0 54 | 3.3.0 55 | 3.5.0 56 | 3.2.1 57 | 58 | 2.15.0 59 | 5.0.0 60 | 3.3.0 61 | 62 | 63 | 64 | https://github.com/zhouhailin/freeswitch-esl-all 65 | scm:git:https://github.com/zhouhailin/freeswitch-esl-all.git 66 | scm:git:https://github.com/zhouhailin/freeswitch-esl-all.git 67 | HEAD 68 | 69 | 70 | 71 | 72 | Apache License, Version 2.0 73 | https://www.apache.org/licenses/LICENSE-2.0 74 | repo 75 | 76 | 77 | 78 | 79 | 80 | zhouhailin 81 | zhouhailin555@aliyun.com 82 | 83 | 84 | 85 | 86 | 87 | 88 | ${project.groupId} 89 | freeswitch-esl 90 | ${project.version} 91 | 92 | 93 | ${project.groupId} 94 | freeswitch-esl-spring-boot-starter 95 | ${project.version} 96 | 97 | 98 | 99 | ${project.groupId} 100 | freeswitch-cdr 101 | ${project.version} 102 | 103 | 104 | ${project.groupId} 105 | freeswitch-cdr-spring-boot-starter 106 | ${project.version} 107 | 108 | 109 | 110 | 111 | org.dom4j 112 | dom4j 113 | 2.1.4 114 | 115 | 116 | 117 | 118 | org.springframework.boot 119 | spring-boot-dependencies 120 | ${spring-boot.version} 121 | pom 122 | import 123 | 124 | 125 | 126 | 127 | 128 | 129 | org.projectlombok 130 | lombok 131 | provided 132 | 133 | 134 | junit 135 | junit 136 | test 137 | 138 | 139 | 140 | 141 | 142 | 143 | kr.motd.maven 144 | os-maven-plugin 145 | 1.5.0.Final 146 | 147 | 148 | 149 | 150 | org.codehaus.mojo 151 | versions-maven-plugin 152 | ${versions-maven-plugin.version} 153 | 154 | 155 | org.apache.maven.plugins 156 | maven-compiler-plugin 157 | 3.13.0 158 | 159 | ${maven.compiler.source} 160 | ${maven.compiler.target} 161 | 162 | 163 | 164 | 165 | org.apache.maven.plugins 166 | maven-source-plugin 167 | 3.3.1 168 | 169 | 170 | package 171 | 172 | jar-no-fork 173 | 174 | 175 | 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-javadoc-plugin 180 | 3.11.2 181 | 182 | 183 | package 184 | 185 | jar 186 | 187 | 188 | none 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | release 199 | 200 | false 201 | 202 | 203 | 204 | oss 205 | https://oss.sonatype.org/content/repositories/snapshots/ 206 | 207 | 208 | oss 209 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 210 | 211 | 212 | 213 | 214 | 215 | 216 | org.codehaus.mojo 217 | cobertura-maven-plugin 218 | 2.7 219 | 220 | 221 | html 222 | xml 223 | 224 | 225 | 226 | 227 | 228 | 229 | org.apache.maven.plugins 230 | maven-gpg-plugin 231 | 3.2.7 232 | 233 | 234 | verify 235 | 236 | sign 237 | 238 | 239 | 240 | 241 | 242 | org.sonatype.central 243 | central-publishing-maven-plugin 244 | 0.6.0 245 | true 246 | 247 | central 248 | true 249 | published 250 | 251 | 252 | 253 | 254 | 255 | 256 | github 257 | 258 | false 259 | 260 | 261 | 262 | github 263 | https://maven.pkg.github.com/zhouhailin/freeswitch-esl-all 264 | 265 | 266 | github 267 | https://maven.pkg.github.com/zhouhailin/freeswitch-esl-all 268 | 269 | 270 | 271 | 272 | 273 | 274 | --------------------------------------------------------------------------------