29 | * You can implement various thread model by adding this handler to a 30 | * {@link ChannelPipeline}. The most common use case of this handler is to add a 31 | * {@link ExecutionHandler} which was specified with 32 | * {@link OrderedMemoryAwareThreadPoolExecutor}: 33 | *
34 | * ChannelPipeline pipeline = ...;
35 | * pipeline.addLast("decoder", new MyProtocolDecoder());
36 | * pipeline.addLast("encoder", new MyProtocolEncoder());
37 | *
38 | * // HERE
39 | * pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));
40 | *
41 | * pipeline.addLast("handler", new MyBusinessLogicHandler());
42 | * to utilize more processors to handle {@link ChannelEvent}s. You can
43 | * also use other {@link Executor} implementation than the recommended
44 | * {@link OrderedMemoryAwareThreadPoolExecutor}.
45 | *
46 | * @author The Netty Project (netty-dev@lists.jboss.org)
47 | * @author Trustin Lee (tlee@redhat.com)
48 | * @version $Rev: 1685 $, $Date: 2009-08-28 16:15:49 +0900 (금, 28 8 2009) $
49 | * @apiviz.landmark
50 | * @apiviz.has java.util.concurrent.ThreadPoolExecutor
51 | */
52 | public class ExecutionHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler, ExternalResourceReleasable {
53 |
54 | private final Executor executor;
55 |
56 | /**
57 | * Creates a new instance with the specified {@link Executor}. Specify an
58 | * {@link OrderedMemoryAwareThreadPoolExecutor} if unsure.
59 | */
60 | public ExecutionHandler(Executor executor) {
61 | if (executor == null) {
62 | throw new NullPointerException("executor");
63 | }
64 | this.executor = executor;
65 | }
66 |
67 | /**
68 | * Returns the {@link Executor} which was specified with the constructor.
69 | */
70 | public Executor getExecutor() {
71 | return executor;
72 | }
73 |
74 | /**
75 | * Shuts down the {@link Executor} which was specified with the constructor
76 | * and wait for its termination.
77 | */
78 | public void releaseExternalResources() {
79 | ExecutorUtil.terminate(getExecutor());
80 | }
81 |
82 | public void handleUpstream(
83 | ChannelHandlerContext context, ChannelEvent e) throws Exception {
84 | executor.execute(new ChannelEventRunnable(context, e));
85 | }
86 |
87 | public void handleDownstream(
88 | ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
89 | if (e instanceof ChannelStateEvent) {
90 | ChannelStateEvent cse = (ChannelStateEvent) e;
91 | if (cse.getState() == ChannelState.INTEREST_OPS
92 | && (((Integer) cse.getValue()).intValue() & Channel.OP_READ) != 0) {
93 |
94 | // setReadable(true) requested
95 | boolean readSuspended = ctx.getAttachment() != null;
96 | if (readSuspended) {
97 | // Drop the request silently if MemoryAwareThreadPool has
98 | // set the flag.
99 | e.getFuture().setSuccess();
100 | return;
101 | }
102 | }
103 | }
104 |
105 | ctx.sendDownstream(e);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/IEndPoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch;
17 |
18 | /**
19 | * An address for an FreeSWITCH end point. Can be a SIP address, an sofia
20 | * address or event an application
21 | *
22 | * @author Arsene Tochemey GANDOTE
23 | */
24 | public interface IEndPoint {
25 |
26 | /**
27 | * Format the address as a string which could be dialed using the
28 | * "originate" or "bridge" command
29 | *
30 | * @return Properly formatted string
31 | */
32 | public String toDialString();
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/IProtocolListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch;
17 |
18 | import io.freeswitch.event.EslEvent;
19 | import io.freeswitch.message.CommandReply;
20 |
21 | /**
22 | * End users of the {@link io.freeswitch.outbound.FreeSwitchClient} should not need to use this class.
23 | *
24 | * @author Arsene Tochemey GANDOTE
25 | */
26 | public interface IProtocolListener {
27 |
28 | /**
29 | * Raised when authentication response is received
30 | *
31 | * @param response
32 | */
33 | void authResponseReceived(CommandReply response);
34 |
35 | /**
36 | * Raised whenever an event is received from FreeSwitch
37 | *
38 | * @param event FreeSwitch event
39 | */
40 | void eventReceived(EslEvent event);
41 |
42 | /**
43 | * Raised when the client is disconnected.
44 | */
45 | void disconnected();
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/SayGender.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch;
17 |
18 | /**
19 | * @author Arsene Tochemey GANDOTE
20 | */
21 | public enum SayGender {
22 | FEMININE, MASCULINE, NEUTER
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/SayMethod.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch;
17 |
18 | /**
19 | * @author Arsene Tochemey GANDOTE
20 | */
21 | public enum SayMethod {
22 | N_A, PRONOUNCED, ITERATED, COUNTED
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/SayType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch;
17 |
18 | /**
19 | * @author Arsene Tochemey GANDOTE
20 | */
21 | public enum SayType {
22 | NUMBER, ITEMS, PERSONS, MESSAGES, CURRENCY, TIME_MEASUREMENT, CURRENT_DATE, CURRENT_TIME, CURRENT_DATE_TIME, TELEPHONE_NUMBER, TELEPHONE_EXTENSION, URL, IP_ADDRESS, EMAIL_ADDRESS, POSTAL_ADDRESS, ACCOUNT_NUMBER, NAME_SPELLED, NAME_PHONETIC, SHORT_DATE_TIME
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/codec/FreeSwitchDecoder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch.codec;
17 |
18 | import io.freeswitch.codec.FreeSwitchMessageHeaders.HeaderName;
19 | import io.freeswitch.message.FreeSwitchMessage;
20 | import org.jboss.netty.buffer.ChannelBuffer;
21 | import org.jboss.netty.channel.Channel;
22 | import org.jboss.netty.channel.ChannelHandlerContext;
23 | import org.jboss.netty.handler.codec.frame.TooLongFrameException;
24 | import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
25 | import org.slf4j.Logger;
26 | import org.slf4j.LoggerFactory;
27 |
28 | /**
29 | * @author Arsene Tochemey GANDOTE
30 | * @author david varnes
31 | */
32 | public class FreeSwitchDecoder extends
33 | ReplayingDecoder26 | * Note this enum will need to be kept in synch with any new headers 27 | * introduced on the server side. 28 | */ 29 | public enum HeaderName { 30 | /* 31 | * Minor optimization - put most often used headers at the top for 32 | * fastest resolution in static fromLiteral(). 33 | */ 34 | 35 | /** 36 | * {@code "Content-Type"} 37 | */ 38 | CONTENT_TYPE("Content-Type"), 39 | /** 40 | * {@code "Content-Length"} 41 | */ 42 | CONTENT_LENGTH("Content-Length"), 43 | /** 44 | * {@code "Reply-Text"} 45 | */ 46 | REPLY_TEXT("Reply-Text"), 47 | /** 48 | * {@code "Job-UUID"} 49 | */ 50 | JOB_UUID("Job-UUID"), 51 | /** 52 | * {@code "Socket-Mode"} 53 | */ 54 | SOCKET_MODE("Socket-Mode"), 55 | /** 56 | * {@code "Control"} 57 | */ 58 | Control("Control"),; 59 | 60 | private final String literal; 61 | 62 | private HeaderName(String literal) { 63 | this.literal = literal; 64 | } 65 | 66 | public static HeaderName fromLiteral(String literal) { 67 | for (HeaderName name : values()) { 68 | if (name.literal.equalsIgnoreCase(literal)) { 69 | return name; 70 | } 71 | } 72 | 73 | return null; 74 | } 75 | 76 | public String literal() { 77 | return literal; 78 | } 79 | } 80 | 81 | /** 82 | * Some common ESL header values. These are provided as a convenience for 83 | * commonly used values. 84 | *
85 | * This values are not coded as an enum to allow for the very large range of 86 | * possible values, since they are just Strings. 87 | */ 88 | public static final class HeaderValue { 89 | /** 90 | * {@code "+OK"} 91 | */ 92 | public static final String OK = "+OK"; 93 | /** 94 | * {@code "auth/request"} 95 | */ 96 | public static final String AUTH_REQUEST = "auth/request"; 97 | /** 98 | * {@code "api/response"} 99 | */ 100 | public static final String API_RESPONSE = "api/response"; 101 | /** 102 | * {@code "command/reply"} 103 | */ 104 | public static final String COMMAND_REPLY = "command/reply"; 105 | /** 106 | * {@code "text/event-plain"} 107 | */ 108 | public static final String TEXT_EVENT_PLAIN = "text/event-plain"; 109 | /** 110 | * {@code "text/event-xml"} 111 | */ 112 | public static final String TEXT_EVENT_XML = "text/event-xml"; 113 | /** 114 | * {@code "text/disconnect-notice"} 115 | */ 116 | public static final String TEXT_DISCONNECT_NOTICE = "text/disconnect-notice"; 117 | /** 118 | * {@code "-ERR invalid"} 119 | */ 120 | public static final String ERR_INVALID = "-ERR invalid"; 121 | /** 122 | * {@code "text/rude-rejection"}} 123 | */ 124 | public static final String TEXT_RUDE_REJECTION = "text/rude-rejection"; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/codec/HeaderParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.codec; 17 | 18 | /** 19 | * @author david varnes 20 | * @author Arsene Tochemey GANDOTE 21 | * @author Trustin Lee 22 | */ 23 | public class HeaderParser { 24 | /** 25 | * Split a header in the form 26 | *
27 | * Header-HeaderName: Some_header-value 28 | *29 | * into a String array. 30 | * 31 | * @param sb the string header to parse 32 | * @return a String[] array with header name at 0 and header value at 1 33 | */ 34 | public static String[] splitHeader(String sb) { 35 | final int length = sb.length(); 36 | int nameStart; 37 | int nameEnd; 38 | int colonEnd; 39 | int valueStart; 40 | int valueEnd; 41 | 42 | nameStart = findNonWhitespace(sb, 0); 43 | for (nameEnd = nameStart; nameEnd < length; nameEnd++) { 44 | char ch = sb.charAt(nameEnd); 45 | if (ch == ':' || Character.isWhitespace(ch)) { 46 | break; 47 | } 48 | } 49 | 50 | for (colonEnd = nameEnd; colonEnd < length; colonEnd++) { 51 | if (sb.charAt(colonEnd) == ':') { 52 | colonEnd++; 53 | break; 54 | } 55 | } 56 | 57 | valueStart = findNonWhitespace(sb, colonEnd); 58 | if (valueStart == length) { 59 | return new String[]{ 60 | sb.substring(nameStart, nameEnd), 61 | "" 62 | }; 63 | } 64 | 65 | valueEnd = findEndOfString(sb); 66 | return new String[]{ 67 | sb.substring(nameStart, nameEnd), 68 | sb.substring(valueStart, valueEnd) 69 | }; 70 | } 71 | 72 | private static int findNonWhitespace(String sb, int offset) { 73 | int result; 74 | for (result = offset; result < sb.length(); result++) { 75 | if (!Character.isWhitespace(sb.charAt(result))) { 76 | break; 77 | } 78 | } 79 | return result; 80 | } 81 | 82 | private static int findEndOfString(String sb) { 83 | int result; 84 | for (result = sb.length(); result > 0; result--) { 85 | if (!Character.isWhitespace(sb.charAt(result - 1))) { 86 | break; 87 | } 88 | } 89 | return result; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/ApiCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * ApiCommand. Send an api command (blocking mode) 20 | * 21 | * @author Arsene Tochemey GANDOTE 22 | */ 23 | public class ApiCommand extends BaseCommand { 24 | 25 | public ApiCommand(String command) { 26 | this._command = command; 27 | } 28 | 29 | @Override 30 | public String command() { 31 | return "api"; 32 | } 33 | 34 | @Override 35 | public String argument() { 36 | return this._command; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/AuthCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * AuthCommand. It is used to send an authentication credentials to freeSwitch 20 | * while connected to freeSwitch. 21 | * 22 | * @author Arsene Tochemey GANDOTE 23 | */ 24 | public class AuthCommand extends BaseCommand { 25 | 26 | public AuthCommand(String password) { 27 | this._command = password; 28 | } 29 | 30 | @Override 31 | public String argument() { 32 | return this._command; 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "auth"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/BaseCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | import io.freeswitch.common.UuidFactory; 19 | 20 | import java.util.Objects; 21 | import java.util.UUID; 22 | 23 | /** 24 | * @author Arsene Tochemey GANDOTE 25 | */ 26 | public abstract class BaseCommand { 27 | 28 | /** 29 | * Command sequence number. It helps identify each command that is sent to 30 | * the FreeSwitch server 31 | */ 32 | private final UUID sequence; 33 | /** 34 | * Additional data to add to the command 35 | */ 36 | public Object optional; 37 | /** 38 | * Property that helps set the command argument 39 | */ 40 | protected String _command; 41 | 42 | 43 | public BaseCommand() { 44 | this.sequence = UuidFactory.create(); 45 | } 46 | 47 | public UUID getSequence() { 48 | return this.sequence; 49 | } 50 | 51 | /** 52 | * The command argument 53 | */ 54 | public abstract String argument(); 55 | 56 | /** 57 | * The command name 58 | */ 59 | public abstract String command(); 60 | 61 | @Override 62 | public boolean equals(Object obj) { 63 | if (obj == null || obj.getClass() != this.getClass()) { 64 | return false; 65 | } 66 | if (obj == this) { 67 | return true; 68 | } 69 | 70 | BaseCommand cmd = (BaseCommand) obj; 71 | return cmd.toString().equals(toString()) && this.sequence.equals(cmd.getSequence()); 72 | } 73 | 74 | @Override 75 | public int hashCode() { 76 | int hash = 7; 77 | hash = 31 * hash + Objects.hashCode(this.sequence); 78 | hash = 31 * hash + Objects.hashCode(this.command()); 79 | hash = 31 * hash + Objects.hashCode(this.argument()); 80 | return hash; 81 | } 82 | 83 | @Override 84 | public String toString() { 85 | return String.format("%s %s", command(), argument()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/BgApiCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | import java.util.UUID; 19 | 20 | /** 21 | * BgApiCommand. 22 | * It is used to Execute an API command in a thread different from 23 | * the main thread running freeSwitch. In other words it sends an api command 24 | * (non-blocking mode) this will let you execute a job in the background and the 25 | * result will be sent as an event with an indicated uuid to match the reply to 26 | * the command) 27 | * 28 | * @author Arsene Tochemey GANDOTE 29 | */ 30 | public class BgApiCommand extends BaseCommand { 31 | 32 | /** 33 | * The command Id. Each bgapi command can explicitly have an Id since bgapi 34 | * generates a UUID for each command executed on FreeSwitch 35 | */ 36 | public UUID CommandId; 37 | 38 | public BgApiCommand(String command, String argument) { 39 | this._command = String.format("%s %s", command, argument); 40 | } 41 | 42 | @Override 43 | public String argument() { 44 | return this._command; 45 | } 46 | 47 | @Override 48 | public String command() { 49 | return "bgapi"; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/ConnectCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * ConnectCommand. 20 | * This command is used to connect to FreeSwitch to retrieve the 21 | * details of an inbound call. This function will be used in an application 22 | * server to which FreeSwitch will connect to via its mode outbound event 23 | * socket. 24 | * 25 | * @author Arsene Tochemey GANDOTE 26 | */ 27 | public class ConnectCommand extends BaseCommand { 28 | 29 | @Override 30 | public String argument() { 31 | return ""; 32 | } 33 | 34 | @Override 35 | public String command() { 36 | return "connect"; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/DivertEventsCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * DivertEventsCommand. The divert_events switch is available to allow event 20 | * that an embedded script would expect to get in the inputcallback to be 21 | * diverted to the event socket. 22 | * 23 | * @author Arsene Tochemey GANDOTE 24 | */ 25 | public class DivertEventsCommand extends BaseCommand { 26 | 27 | public DivertEventsCommand(boolean on) { 28 | if (on) 29 | this._command = "on"; 30 | else 31 | this._command = "off"; 32 | } 33 | 34 | @Override 35 | public String argument() { 36 | return this._command; 37 | } 38 | 39 | @Override 40 | public String command() { 41 | return "divert_events"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/EventCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * EventCommand. Enable or disable event by class or all (plain or xml or json 20 | * output format) 21 | * 22 | * @author Arsene Tochemey GANDOTE 23 | */ 24 | public class EventCommand extends BaseCommand { 25 | 26 | public EventCommand(String eventlist) { 27 | this._command = eventlist; 28 | } 29 | 30 | @Override 31 | public String argument() { 32 | return this._command; 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "event"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/EventsCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * EventsCommand. Enable or disable event by class or all (plain or xml or json 20 | * output format) 21 | * 22 | * @author Arsene Tochemey GANDOTE 23 | */ 24 | public class EventsCommand extends BaseCommand { 25 | 26 | public EventsCommand(String eventlist) { 27 | this._command = eventlist; 28 | } 29 | 30 | @Override 31 | public String argument() { 32 | return this._command; 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "event"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/ExitCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * ExitCommand. 20 | * It is used to disconnect from FreeSwitch 21 | * 22 | * @author Arsene Tochemey GANDOTE 23 | */ 24 | public class ExitCommand extends BaseCommand { 25 | 26 | @Override 27 | public String argument() { 28 | return ""; 29 | } 30 | 31 | @Override 32 | public String command() { 33 | return "exit"; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/FilterCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * Specify event types to listen for. Note, this is not a filter out but rather 20 | * a "filter in," that is, when a filter is applied only the filtered values are 21 | * received. Multiple filters on a socket connection are allowed. 22 | * 23 | * @author Arsene Tochemey GANDOTE 24 | */ 25 | public class FilterCommand extends BaseCommand { 26 | 27 | /** 28 | * 29 | */ 30 | public FilterCommand(String filter) { 31 | this._command = filter; 32 | } 33 | 34 | @Override 35 | public String argument() { 36 | return this._command; 37 | } 38 | 39 | @Override 40 | public String command() { 41 | return "filter"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/GetVarCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | import java.util.UUID; 19 | 20 | /** 21 | * GetVarCommand. 22 | * It is used to retrieve a channel variable based upon the channel id 23 | * 24 | * @author Arsene Tochemey GANDOTE 25 | */ 26 | public class GetVarCommand extends BaseCommand { 27 | 28 | public GetVarCommand(UUID channelId, String variable) { 29 | this._command = String.format("%s %s", channelId, variable); 30 | } 31 | 32 | @Override 33 | public String argument() { 34 | return this._command; 35 | } 36 | 37 | @Override 38 | public String command() { 39 | return "uuid_getvar"; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/HangupCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | import java.util.UUID; 19 | 20 | /** 21 | * HangupCommand. It is used to hangup a live call with a specific reason. 22 | * 23 | * @author Arsene Tochemey GANDOTE 24 | */ 25 | public class HangupCommand extends BaseCommand { 26 | 27 | public HangupCommand(UUID channelId, String reason) { 28 | this._command = String.format( 29 | "sendmsg %1$s\ncall-command: %2$s\nhangup-cause: %3$s", channelId, 30 | "hangup", reason); 31 | } 32 | 33 | @Override 34 | public String argument() { 35 | return ""; 36 | } 37 | 38 | @Override 39 | public String command() { 40 | return this._command; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/LogCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | import io.freeswitch.common.LogLevels; 19 | 20 | /** 21 | * @author Arsene Tochemey GANDOTE 22 | */ 23 | public class LogCommand extends BaseCommand { 24 | 25 | /** 26 | * 27 | */ 28 | public LogCommand(LogLevels level) { 29 | this._command = level.toString().toLowerCase(); 30 | } 31 | 32 | 33 | @Override 34 | public String argument() { 35 | return this._command; 36 | } 37 | 38 | @Override 39 | public String command() { 40 | return "log"; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/MyEventsCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | import java.util.UUID; 19 | 20 | /** 21 | * MyEvents. The 'myevents' subscription allows your inbound socket connection 22 | * to behave like an outbound socket connect. It will "lock on" to the event 23 | * for a particular uuid and will ignore all other event, closing the socket 24 | * when the channel goes away or closing the channel when the socket disconnects 25 | * and all applications have finished executing 26 | * 27 | * @author Arsene Tochemey GANDOTE 28 | */ 29 | public class MyEventsCommand extends BaseCommand { 30 | 31 | public MyEventsCommand(UUID channelId) { 32 | this._command = channelId.toString(); 33 | } 34 | 35 | @Override 36 | public String argument() { 37 | return this._command; 38 | } 39 | 40 | @Override 41 | public String command() { 42 | return "myevents"; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/NixEventCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * @author Arsene Tochemey GANDOTE 20 | */ 21 | public class NixEventCommand extends BaseCommand { 22 | 23 | public NixEventCommand(String eventName) { 24 | this._command = eventName; 25 | } 26 | 27 | @Override 28 | public String argument() { 29 | return this._command; 30 | } 31 | 32 | @Override 33 | public String command() { 34 | return "nixevent"; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/NoEventsCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * @author Arsene Tochemey GANDOTE 20 | */ 21 | public class NoEventsCommand extends BaseCommand { 22 | 23 | /** 24 | * 25 | */ 26 | public NoEventsCommand() { 27 | } 28 | 29 | 30 | @Override 31 | public String argument() { 32 | return ""; 33 | } 34 | 35 | @Override 36 | public String command() { 37 | return "noevents"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/NologCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | /** 19 | * Disable any logging previously enabled with setLogLevel() 20 | * 21 | * @author Arsene Tochemey GANDOTE 22 | */ 23 | public class NologCommand extends BaseCommand { 24 | 25 | /** 26 | * 27 | */ 28 | public NologCommand() { 29 | } 30 | 31 | 32 | @Override 33 | public String argument() { 34 | return ""; 35 | } 36 | 37 | 38 | @Override 39 | public String command() { 40 | return "nolog"; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/freeswitch/command/OriginateCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.freeswitch.command; 17 | 18 | 19 | import io.freeswitch.ChannelVariable; 20 | import io.freeswitch.IEndPoint; 21 | import org.apache.commons.lang3.StringUtils; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | import java.util.UUID; 26 | 27 | /** 28 | * Originate. It is used to originate a new call. 29 | * 30 | * @author Arsene Tochemey GANDOTE 31 | */ 32 | public class OriginateCommand extends BaseCommand { 33 | 34 | /** 35 | * originate uuid. 36 | */ 37 | public UUID originateId; 38 | /** 39 | * call session heartbeat. very useful while billing a call. 40 | */ 41 | public int sessionHeartbeat; 42 | /** 43 | * Additional attributes to add to the originate command 44 | */ 45 | public String option; 46 | /** 47 | * originate channel variables 48 | */ 49 | private List
34 | * An ESL event is modelled as a collection of text lines. An event always has 35 | * several eventHeader lines, and optionally may have some eventBody lines. In 36 | * addition the messageHeaders of the original containing {@link FreeSwitchMessage} 37 | * which carried the event are also available. 38 | *
39 | * The eventHeader lines are parsed and cached in a map keyed by the eventHeader 40 | * name string. An event is always expected to have an "Event-HeaderName" eventHeader. 41 | * Commonly used eventHeader names are coded in {@link EslEventHeaderNames} 42 | *
43 | * Any eventBody lines are cached in a list. 44 | *
45 | * The messageHeader lines from the original message are cached in a map keyed
46 | * by {@link FreeSwitchMessageHeaders.HeaderName}.
47 | *
48 | * @author david varnes
49 | * @author Arsene Tochemey GANDOTE
50 | * @see EventHeaders
51 | */
52 | public class EslEvent {
53 | private final Logger log = LoggerFactory.getLogger(this.getClass());
54 |
55 | private final Map
21 | * Incoming event arrive asynchronously and are processed into two queues, one for server
22 | * initiated event, and one for the results of client requested background jobs.
23 | *
24 | * Each queue is serviced by a different thread pool (to ensure lowest latency for event-driven event)
25 | * and each queue is guaranteed to be processed (and listeners notified) in the order in which the
26 | * event are received off the wire.
27 | *
28 | * This design ensures that incoming event processing is not blocked by any long-running listener process.
29 | * However multiple listeners will be notified sequentially, and so one slow listener can cause latency
30 | * to other listeners.
31 | *
32 | * @author david varnes
33 | * @author Arsene Tochemey GANDOTE
34 | */
35 | public interface IEventsListener {
36 | /**
37 | * Signal of a server initiated event.
38 | *
39 | * @param event as an {@link EslEvent}
40 | */
41 | void eventReceived(EslEvent event);
42 |
43 | /**
44 | * Signal of an event containing the result of a client requested background job. The Job-UUID will
45 | * be available as an event header of that name.
46 | *
47 | * @param event as an {@link EslEvent}
48 | */
49 | void backgroundJobEventReceived(EslEvent event);
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/event/RecordStop.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch.event;
17 |
18 | /**
19 | * @author Arsene Tochemey GANDOTE
20 | */
21 | public class RecordStop extends AbstractEvent {
22 |
23 | /**
24 | * @param event
25 | */
26 | public RecordStop(EslEvent event) {
27 | super(event);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/event/SessionHeartbeat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch.event;
17 |
18 | /**
19 | * @author Arsene Tochemey GANDOTE
20 | */
21 | public class SessionHeartbeat extends AbstractEvent {
22 |
23 | /**
24 | * @param event
25 | */
26 | public SessionHeartbeat(EslEvent event) {
27 | super(event);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/inbound/DefaultFreeSwitchHandler.java:
--------------------------------------------------------------------------------
1 | package io.freeswitch.inbound;
2 |
3 | import io.freeswitch.event.EslEvent;
4 | import org.apache.commons.lang3.StringUtils;
5 | import org.jboss.netty.channel.ChannelHandlerContext;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.net.SocketAddress;
10 | import java.util.UUID;
11 |
12 | /**
13 | * Created by Arsene Tochemey GANDOTE on 19/11/2015.
14 | */
15 | public class DefaultFreeSwitchHandler extends FreeSwitchHandler {
16 |
17 | private final Logger log = LoggerFactory.getLogger(this.getClass());
18 |
19 | /**
20 | * instance of the connected freeSwitch
21 | */
22 | private FreeSwitchSession _session;
23 |
24 | @Override
25 | protected void handleConnectResponse(ChannelHandlerContext ctx, EslEvent event) {
26 | if(StringUtils.equalsIgnoreCase(event.eventName(), "CHANNEL_DATA")){
27 | // Let us get the necessary data to set the session
28 | SocketAddress address = ctx.getChannel().getRemoteAddress();
29 | UUID sessionId = event.uniqueId();
30 | UUID callerId = UUID.fromString(event.eventHeaders().get("Caller-Unique-ID"));
31 | String callerIdNumber = event.eventHeaders().get("Caller-Caller-ID-Number");
32 | String destinationNumber = event.eventHeaders().get("Channel-Destination-Number");
33 | _session = new FreeSwitchSession(sessionId, callerId, callerIdNumber, destinationNumber, event.eventHeaders(), address);
34 | return;
35 | }
36 | throw new IllegalStateException( "Unexpected event after connect: [" + event.eventName() + ']' );
37 | }
38 |
39 | @Override
40 | protected void handleDisconnectionNotice(ChannelHandlerContext ctx) {
41 |
42 | }
43 |
44 | @Override
45 | protected void handleEslEvent(ChannelHandlerContext ctx, EslEvent event) {
46 | // // TODO: 19/11/2015 implements the events handlers
47 | }
48 |
49 | @Override
50 | protected void handleException(ChannelHandlerContext ctx, Throwable cause) {
51 | // // TODO: 19/11/2015 implements the exception handling
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/inbound/DefaultInboundPipelineFactory.java:
--------------------------------------------------------------------------------
1 | package io.freeswitch.inbound;
2 |
3 | /**
4 | * Created by Arsene Tochemey GANDOTE on 19/11/2015.
5 | */
6 | public class DefaultInboundPipelineFactory extends FreeSwitchPipelineFactory {
7 | @Override
8 | protected FreeSwitchHandler buildHandler() {
9 | return null;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/inbound/FreeSwitchHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch.inbound;
17 |
18 | import io.freeswitch.codec.FreeSwitchMessageHeaders.HeaderName;
19 | import io.freeswitch.codec.FreeSwitchMessageHeaders.HeaderValue;
20 | import io.freeswitch.command.ConnectCommand;
21 | import io.freeswitch.event.EslEvent;
22 | import io.freeswitch.message.FreeSwitchMessage;
23 | import org.jboss.netty.channel.*;
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 |
27 | import java.util.Queue;
28 | import java.util.concurrent.ConcurrentLinkedQueue;
29 | import java.util.concurrent.CountDownLatch;
30 | import java.util.concurrent.locks.Lock;
31 | import java.util.concurrent.locks.ReentrantLock;
32 |
33 | /**
34 | * @author Arsene Tochemey GANDOTE
35 | */
36 | @ChannelHandler.Sharable
37 | public abstract class FreeSwitchHandler extends SimpleChannelUpstreamHandler {
38 |
39 | public static final String MESSAGE_TERMINATOR = "\n\n";
40 | public static final String LINE_TERMINATOR = "\n";
41 | protected final Logger log = LoggerFactory.getLogger(this.getClass());
42 | private final Lock syncLock = new ReentrantLock();
43 | private final Queue
35 | * This class provides for what the FreeSWITCH documentation refers to as
36 | * 'Outbound' connections from the Event Socket module. That is, with reference
37 | * to the module running on the FreeSWITCH server, this client accepts an
38 | * outbound connection from the server module.
39 | *
40 | * See http://wiki.
41 | * freeswitch.org/wiki/Mod_event_socket
42 | *
43 | * @author Arsene Tochemey GANDOTE
44 | */
45 | public class FreeSwitchServer {
46 |
47 | private final Logger log = LoggerFactory.getLogger(this.getClass());
48 |
49 | /**
50 | * Binding port.
51 | */
52 | private final int port;
53 | private final ChannelGroup allChannels = new DefaultChannelGroup("esl-socket-server");
54 |
55 | private final ChannelFactory channelFactory;
56 | private final FreeSwitchPipelineFactory pipelineFactory;
57 |
58 | /**
59 | *
60 | */
61 | public FreeSwitchServer(int port,
62 | FreeSwitchPipelineFactory pipelineFactory) {
63 | this.port = port;
64 | this.pipelineFactory = pipelineFactory;
65 | this.channelFactory = new NioServerSocketChannelFactory(
66 | Executors.newCachedThreadPool(),
67 | Executors.newCachedThreadPool());
68 | }
69 |
70 | /**
71 | * start()
72 | *
73 | * @throws InterruptedException
74 | */
75 | public void start() throws InterruptedException {
76 | ServerBootstrap bootstrap = new ServerBootstrap(channelFactory);
77 |
78 | bootstrap.setPipelineFactory(pipelineFactory);
79 | bootstrap.setOption("child.tcpNoDelay", true);
80 | bootstrap.setOption("child.keepAlive", true);
81 | Channel serverChannel = bootstrap.bind(new InetSocketAddress(port));
82 | allChannels.add(serverChannel);
83 | log.info("SocketClient waiting for connections on port [{}] ...", port);
84 | }
85 |
86 | /**
87 | * stop()
88 | *
89 | * @throws InterruptedException
90 | */
91 | public void stop() throws InterruptedException {
92 | // Wait until the server socket is closed.
93 | ChannelGroupFuture future = allChannels.close();
94 | future.awaitUninterruptibly();
95 | channelFactory.releaseExternalResources();
96 | log.info("SocketClient stopped");
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/inbound/FreeSwitchSession.java:
--------------------------------------------------------------------------------
1 | package io.freeswitch.inbound;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.net.SocketAddress;
7 | import java.util.Map;
8 | import java.util.UUID;
9 |
10 | /**
11 | * Created by Arsene Tochemey GANDOTE on 19/11/2015.
12 | */
13 | public class FreeSwitchSession {
14 | private final Logger log = LoggerFactory.getLogger(this.getClass());
15 |
16 | /**
17 | * Unique Identifier of the connected freeSwitch. It is the same as the Unique-ID of the connected call.
18 | */
19 | private final UUID _sessionId;
20 |
21 | /**
22 | * The caller id. Value of the channel variable Caller-Unique-ID
23 | */
24 | private final UUID _callerId;
25 |
26 | /**
27 | * The caller id number. Value of the channel variable Caller-Caller-ID-Number
28 | */
29 | private final String _callerIdNumber;
30 |
31 | /**
32 | * The destination number. Value of the channel variable Channel-Destination-Number
33 | */
34 | private final String _destinationNumber;
35 |
36 | /**
37 | * Other channel variables
38 | */
39 | private final Map
45 | * This class provides what the FreeSWITCH documentation refers to as an
46 | * 'Inbound' connection to the Event Socket module. That is, with reference to
47 | * the socket listening on the FreeSWITCH server, this client occurs as an
48 | * inbound connection to the server.
49 | *
50 | * See http://wiki.
51 | * freeswitch.org/wiki/Mod_event_socket
52 | *
53 | * @author Arsene Tochemey GANDOTE
54 | */
55 | public class FreeSwitchClient {
56 |
57 | private final Logger log = LoggerFactory.getLogger(this.getClass());
58 |
59 | private final List
151 | * The outcome of the command from the server is returned in an
152 | * {@link FreeSwitchMessage} object.
153 | *
154 | * @param command API command to send
155 | * @param arg command arguments
156 | * @return an {@link FreeSwitchMessage} containing command results
157 | */
158 | public FreeSwitchMessage api(String command, String arg) {
159 | checkConnected();
160 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
161 |
162 | StringBuilder sb = new StringBuilder();
163 | if (!StringUtils.isEmpty(command)) {
164 | sb.append(command);
165 | }
166 | if (!StringUtils.isEmpty(arg)) {
167 | sb.append(' ');
168 | sb.append(arg);
169 | }
170 |
171 | // Here no command is really set to be executed
172 | if (StringUtils.isEmpty(sb.toString())) {
173 | return null;
174 | }
175 |
176 | ApiCommand api = new ApiCommand(sb.toString());
177 | return handler.sendSyncCommand(channel, api.toString());
178 | }
179 |
180 | /**
181 | * Submit a FreeSWITCH API command to the server to be executed in
182 | * background mode. A synchronous response from the server provides a UUID
183 | * to identify the job execution results. When the server has completed the
184 | * job execution it fires a BACKGROUND_JOB Event with the execution results.
185 | *
186 | * Note that this Client must be subscribed in the normal way to
187 | * BACKGOUND_JOB Events, in order to receive this event.
188 | *
189 | * @param command API command to send
190 | * @param arg command arguments
191 | * @return UUID Job-UUID that the server will tag result event with.
192 | */
193 | public UUID bgApi(String command, String arg) {
194 | checkConnected();
195 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
196 | if (StringUtils.isEmpty(command)) {
197 | // Here no command is set to be executed.
198 | return null;
199 | }
200 |
201 | BgApiCommand bgapi = new BgApiCommand(command, arg);
202 | return UUID.fromString(handler.sendAsyncCommand(channel,
203 | bgapi.toString()));
204 | }
205 |
206 | public boolean canSend() {
207 | return channel != null && channel.isConnected() && authenticated;
208 | }
209 |
210 | /**
211 | * Check whether the connection to the FreeSwitch mod_event_socket is alive
212 | * or not.
213 | */
214 | private void checkConnected() {
215 | if (!canSend()) {
216 | throw new IllegalStateException(
217 | "Not connected to FreeSWITCH Event Socket");
218 | }
219 | }
220 |
221 | /**
222 | * Close the socket connection
223 | *
224 | * @return a {@link CommandReply} with the server's response.
225 | */
226 | public CommandReply close() {
227 | checkConnected();
228 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
229 | ExitCommand exit = new ExitCommand();
230 | FreeSwitchMessage response = handler.sendSyncCommand(channel,
231 | exit.toString());
232 |
233 | return new CommandReply(exit.toString(), response);
234 | }
235 |
236 | /**
237 | * Attempt to establish an authenticated connection to the nominated
238 | * FreeSWITCH ESL server socket. This call will block, waiting for an
239 | * authentication handshake to occur, or timeout after the supplied number
240 | * of seconds.
241 | *
242 | * @param host can be either ip address or hostname
243 | * @param port tcp port that server socket is listening on (set in
244 | * event_socket_conf.xml)
245 | * @param password server event socket is expecting (set in
246 | * event_socket_conf.xml)
247 | * @param timeoutSeconds number of seconds to wait for the server socket
248 | * before aborting
249 | * @throws ConnectionFailure
250 | * @throws java.lang.InterruptedException
251 | */
252 | public void connect(String host, int port, String password,
253 | int timeoutSeconds) throws ConnectionFailure, InterruptedException {
254 |
255 | // If already connected, disconnect first
256 | if (canSend()) {
257 | close();
258 | }
259 |
260 | // Configure this client
261 | ClientBootstrap bootstrap = new ClientBootstrap(
262 | new NioClientSocketChannelFactory(
263 | Executors.newCachedThreadPool(),
264 | Executors.newCachedThreadPool()));
265 |
266 | // Add ESL handler
267 | DefaultFreeSwitchClientHandler handler = new DefaultFreeSwitchClientHandler(password, protocolListener);
268 | bootstrap.setPipelineFactory(new DefaultFreeSwitchClientPipelineFactory(handler));
269 |
270 | // Make the connection attempt.
271 | ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
272 |
273 | // Wait till attempt succeeds, fails or timeouts
274 | if (!future.awaitUninterruptibly(timeoutSeconds, TimeUnit.SECONDS)) {
275 | throw new ConnectionFailure("Timeout connecting to " + host + ":" + port);
276 | }
277 |
278 | // But may have failed anyway
279 | if (!future.isSuccess()) {
280 | log.warn("Failed to connect to [{}:{}]", host, port);
281 | channel = null;
282 | bootstrap.releaseExternalResources();
283 | throw new ConnectionFailure("Could not connect to " + host + ":"
284 | + port, future.getCause());
285 | }
286 |
287 | channel = future.getChannel();
288 | // Wait for the authentication handshake to call back
289 | while (!authenticatorResponded.get()) {
290 | try {
291 | Thread.sleep(250);
292 | } catch (InterruptedException e) {
293 | // ignore
294 | }
295 | }
296 |
297 | if (!authenticated) {
298 | throw new ConnectionFailure("Authentication failed: "
299 | + authenticationResponse.replyText());
300 | }
301 | }
302 |
303 | /**
304 | * Set the current event subscription for this connection to the server.
305 | * Examples of the event argument are:
306 | *
307 | *
314 | * Subsequent calls to this method replaces any previous subscriptions that
315 | * were set.
373 | *
308 | * ALL
309 | * CHANNEL_CREATE CHANNEL_DESTROY HEARTBEAT
310 | * CUSTOM conference::maintenance
311 | * CHANNEL_CREATE CHANNEL_DESTROY CUSTOM conference::maintenance sofia::register sofia::expire
312 | *
313 | *
374 | * eventHeader valueToFilter
375 | * ----------------------------------
376 | * Event-HeaderName CHANNEL_EXECUTE
377 | * Channel-State CS_NEW
378 | *
379 | *
380 | * @param eventHeader to filter on
381 | * @param valueToFilter the value to match
382 | * @return a {@link CommandReply} with the server's response.
383 | */
384 | public CommandReply filter(String eventHeader, String valueToFilter) {
385 | checkConnected();
386 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
387 | StringBuilder sb = new StringBuilder();
388 | if (eventHeader != null && !eventHeader.isEmpty()) {
389 | sb.append(eventHeader);
390 | }
391 | if (valueToFilter != null && !valueToFilter.isEmpty()) {
392 | sb.append(' ');
393 | sb.append(valueToFilter);
394 | }
395 |
396 | if (StringUtils.isEmpty(sb.toString())) {
397 | return null;
398 | }
399 |
400 | FilterCommand filter = new FilterCommand(sb.toString());
401 | FreeSwitchMessage response = handler.sendSyncCommand(channel,
402 | filter.toString());
403 | return new CommandReply(filter.toString(), response);
404 | }
405 |
406 | /**
407 | * Delete an event filter from the current set of event filters on this
408 | * connection.
409 | *
410 | * @param eventHeader to remove
411 | * @param valueToFilter to remove
412 | * @return a {@link CommandReply} with the server's response.
413 | */
414 | public CommandReply filterDelete(String eventHeader, String valueToFilter) {
415 | checkConnected();
416 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
417 | StringBuilder sb = new StringBuilder();
418 | if (eventHeader != null && !eventHeader.isEmpty()) {
419 | sb.append("delete ");
420 | sb.append(eventHeader);
421 | }
422 | if (valueToFilter != null && !valueToFilter.isEmpty()) {
423 | sb.append(' ');
424 | sb.append(valueToFilter);
425 | }
426 | if (StringUtils.isEmpty(sb.toString())) {
427 | return null;
428 | }
429 |
430 | FilterCommand filter = new FilterCommand(sb.toString());
431 | FreeSwitchMessage response = handler.sendSyncCommand(channel,
432 | filter.toString());
433 | return new CommandReply(filter.toString(), response);
434 | }
435 |
436 | /**
437 | * Cancel any existing event subscription.
438 | *
439 | * @return a {@link CommandReply} with the server's response.
440 | */
441 | public CommandReply noevents() {
442 | checkConnected();
443 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
444 | NoEventsCommand noevents = new NoEventsCommand();
445 | FreeSwitchMessage response = handler.sendSyncCommand(channel,
446 | noevents.toString());
447 | return new CommandReply(noevents.toString(), response);
448 | }
449 |
450 | /**
451 | * Disable any logging previously enabled with setLogLevel().
452 | *
453 | * @return a {@link CommandReply} with the server's response.
454 | */
455 | public CommandReply nolog() {
456 | checkConnected();
457 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
458 | FreeSwitchMessage response = handler.sendSyncCommand(channel,
459 | new NologCommand().toString());
460 |
461 | return new CommandReply("nolog", response);
462 | }
463 |
464 | /**
465 | * Enable log output.
466 | *
467 | * @param level using the same values as in console.conf
468 | * @return a {@link CommandReply} with the server's response.
469 | */
470 | public CommandReply setLogLevel(LogLevels level) {
471 | checkConnected();
472 | DefaultFreeSwitchClientHandler handler = (DefaultFreeSwitchClientHandler) channel.getPipeline().getLast();
473 | LogCommand log = new LogCommand(level);
474 | FreeSwitchMessage response = handler.sendSyncCommand(channel,
475 | log.toString());
476 |
477 | return new CommandReply(log.toString(), response);
478 | }
479 |
480 | }
481 |
--------------------------------------------------------------------------------
/src/main/java/io/freeswitch/outbound/FreeSwitchClientHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.freeswitch.outbound;
17 |
18 | import io.freeswitch.codec.FreeSwitchMessageHeaders;
19 | import io.freeswitch.codec.FreeSwitchMessageHeaders.HeaderValue;
20 | import io.freeswitch.event.EslEvent;
21 | import io.freeswitch.message.FreeSwitchMessage;
22 | import org.jboss.netty.channel.*;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | import java.util.Queue;
27 | import java.util.concurrent.ConcurrentLinkedQueue;
28 | import java.util.concurrent.CountDownLatch;
29 | import java.util.concurrent.locks.Lock;
30 | import java.util.concurrent.locks.ReentrantLock;
31 |
32 | /**
33 | * @author Arsene Tochemey GANDOTE
34 | * @author david varnes
35 | */
36 | @ChannelHandler.Sharable
37 | public abstract class FreeSwitchClientHandler extends
38 | SimpleChannelUpstreamHandler {
39 |
40 | public static final String MESSAGE_TERMINATOR = "\n\n";
41 | public static final String LINE_TERMINATOR = "\n";
42 |
43 | protected final Logger log = LoggerFactory.getLogger(this.getClass());
44 |
45 | private final Lock syncLock = new ReentrantLock();
46 | private final Queue