/*
* Copyright (C) 2017 by Fonoster Inc (http://fonoster.com)
* http://astivetoolkit.org
*
* This file is part of Astive Toolkit(ATK)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.astivetoolkit.agi;
import org.astivetoolkit.util.AppLocale;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Handle communication with Asterisk, at the lowest level.
*
* @since 1.0
*/
public class AgiCommandHandler {
private Connection conn;
/**
* Construct a new handler to manage communication with Asterisk, at the
* lowest level.
*
* @param conn an object that implement {@link Connection} interface.
*/
public AgiCommandHandler(Connection conn) {
this.conn = conn;
}
/**
* Get the initial package sent by the AGI protocol.
*
* @return info about client request, such as script to be executed, channel
* name etc... {@link AgiRequest}
* @throws AgiException if is unable to perform I/O with Asterisk.
*/
public AgiRequest getAgiRequest() throws AgiException {
ArrayList<String> lines = new ArrayList<String>();
String line;
try {
while (!(line = conn.readLine()).isEmpty()) {
lines.add(line);
}
} catch (IOException ex) {
throw new AgiException(AppLocale.getI18n("unableToCommunicateWithAsteriskError",
new Object[]{ex.getMessage()}));
}
return (new AgiRequest(lines));
}
/**
* Get the last reply sent by Asterisk as result of an command.
*
* @return reply to a command
* @throws AgiException if the connection has been closed.
*/
private AgiCommandReply readAgiCommandReply() throws AgiException {
AgiCommandReply reply;
List<String> lines;
String line = null;
lines = new ArrayList<String>();
try {
line = conn.readLine();
} catch (IOException e) {
throw new AgiException(AppLocale.getI18n("errorConnectionClosed"));
}
if (line == null) {
throw new AgiException();
}
if (line.startsWith("HANGUP")) {
if (line.length() > 6) {
line = line.substring(6);
} else {
return readAgiCommandReply();
}
}
lines.add(line);
if (line.startsWith(Integer.toString(AgiCommandReply.SC_INVALID_COMMAND_SYNTAX))) {
try {
while ((line = conn.readLine()) != null) {
lines.add(line);
if (line.startsWith(Integer.toString(AgiCommandReply.SC_INVALID_COMMAND_SYNTAX))) {
break;
}
}
} catch (IOException ex) {
throw new AgiException(AppLocale.getI18n("errorUnableToCommunicateWithAsterisk"));
}
}
reply = new AgiCommandReply(lines);
// Special handling for gosub, see AJ-257
if (reply.getStatus() == AgiCommandReply.SC_TRYING) {
return readAgiCommandReply();
} else {
return reply;
}
}
/**
* Send a command to Asterisk
* <code>channel</code>.
*
* @param command command to send.
* @return the reply for the sent command.
* @throws AgiException if is unable to perform I/O operations.
*/
public AgiCommandReply sendAgiCommand(Object command)
throws AgiException {
try {
if (command instanceof String) {
conn.write((String) command);
} else {
conn.write(CommandProcessor.buildCommand(command));
}
} catch (IOException ex) {
throw new AgiException();
}
return readAgiCommandReply();
}
}