All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sunlabs.brazil.asterisk.AsteriskAGIHandler Maven / Gradle / Ivy

The newest version!
/*
 * AsteriskAGIHandler.java
 *
 * Brazil project web application toolkit,
 * export version: 2.3 
 * Copyright (c) 2005-2006 Sun Microsystems, Inc.
 *
 * Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version 
 * 1.0 (the "License"). You may not use this file except in compliance with 
 * the License. A copy of the License is included as the file "license.terms",
 * and also available at http://www.sun.com/
 * 
 * The Original Code is from:
 *    Brazil project web application toolkit release 2.3.
 * The Initial Developer of the Original Code is: suhler.
 * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): suhler.
 *
 * Version:  1.7
 * Created by suhler on 05/06/06
 * Last modified by suhler on 06/05/08 10:28:13
 *
 * Version Histories:
 *
 * 1.7 06/05/08-10:28:13 (suhler)
 *   add "agi_host" parameter containing the asterisk server's hostname
 *   .
 *
 * 1.6 06/05/08-09:59:48 (suhler)
 *   prefix session id with properties prefix
 *   .
 *
 * 1.5 06/04/25-14:54:41 (suhler)
 *   doc fixes
 *
 * 1.4 05/11/10-10:56:48 (suhler)
 *   doc cleanup
 *
 * 1.3 05/06/07-15:58:07 (suhler)
 *   redo the way the socket streams are handled
 *   make sure commands are written in a single packet
 *   misc cleanups
 *
 * 1.2 05/06/07-15:54:35 (suhler)
 *   checkpoint
 *
 * 1.2 05/06/06-21:03:10 (Codemgr)
 *   SunPro Code Manager data about conflicts, renames, etc...
 *   Name history : 1 0 asterisk/AsteriskAGIHandler.java
 *
 * 1.1 05/06/06-21:03:09 (suhler)
 *   date and time created 05/06/06 21:03:09 by suhler
 *
 */

package sunlabs.brazil.asterisk;

import java.io.OutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import sunlabs.brazil.server.FileHandler;
import sunlabs.brazil.server.Handler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.server.TestRequest;
import sunlabs.brazil.template.RewriteContext;
import sunlabs.brazil.template.Template;
import sunlabs.brazil.template.TemplateRunner;
import sunlabs.brazil.util.http.HttpInputStream;
import sunlabs.brazil.util.http.MimeHeaders;

/**
 * FAGI (fast AGI) handler and template for Asterisk.  
 * This handler/template starts a server listening on the * FAGI port.
 * Anytime it gets an agi request from * it creates a dummy
 * request object (sort of like TestRequest) to simulate an http
 * request, reads a file implied by the request agi:... string, and
 * processes the file through the template runner.
 * The  template can be used to interact with * via
 * standard agi commands, and the web via the SetTemplate and namespaces.
 * The template output is discarded (if debug is enables, it is printed on
 * the server console); everything is done via side effect.
 * This allows us to interact with the ordinary template variables and
 * namespaces.
 * I'm still not sure how to deal with sessions, so we'll use a 
 * different one for each uniqueid in the agi request. (This is a bad idea
 * unless we delete completed sessions "by hand").
 *

(Implementation notes)
* This class implements 4 different threads: * - handler/init: to get the config params and start the listening socket * - The thread that listens and accepts connections from * * - the threads that handle the incoming agi requests * - the threads that do the template stuff */ public class AsteriskAGIHandler extends Template implements Handler, Runnable { Server server; String prefix; Socket sock; // socket from * ServerSocket listen; // server socket // these are for tag_agi. HttpInputStream in = null; Request.HttpOutputStream out = null; public AsteriskAGIHandler() { listen = null; sock = null; } /** * Constructor to create the listener instance. */ AsteriskAGIHandler(Server server, String prefix, ServerSocket listen) { this.server = server; this.prefix = prefix; this.listen = listen; sock = null; } /** * Constructor to create an AGI request handler thread. */ AsteriskAGIHandler(Server server, String prefix, Socket sock) { this.server = server; this.prefix = prefix; this.sock = sock; listen = null; } /** * Start a Listening socket thread, and wait for AGI connections. */ public boolean init(Server server, String prefix) { this.server = server; this.prefix = prefix; int port = 4573; // default agi port try { String str = server.props.getProperty(prefix + "port"); port = Integer.decode(str).intValue(); } catch (Exception e) {} try { ServerSocket listen = new ServerSocket(port); new Thread(new AsteriskAGIHandler(server, prefix, listen)).start(); } catch (IOException e) { server.log(Server.LOG_ERROR, prefix, "Server socket failed: " + e); return false; } // We should verify we are one of the templates, otherwise this // isn't useful. String tokens = server.props.getProperty(prefix + "templates", ""); String token = prefix.substring(0, prefix.length()-1); if (tokens.indexOf(token) < 0) { server.log(Server.LOG_WARNING, prefix, "templates don't include: " + token); } return true; } /** * We don't handle any "normal" requests. * @return always false */ public boolean respond(Request request) throws IOException { return false; } /** * Open the socket's streams at top of page. * This will be used by the <agi> calls. */ public boolean init(RewriteContext hr) { try { in = new HttpInputStream(hr.request.sock.getInputStream()); out = new Request.HttpOutputStream( hr.request.sock.getOutputStream()); } catch (IOException e) { hr.request.log(Server.LOG_WARNING, "Oops getting * stream: " + e); return false; } return super.init(hr); } /** * Close the socket connection. */ public boolean done(RewriteContext hr) { try { in.close(); out.close(); hr.request.sock.close(); } catch (IOException e) { hr.request.log(Server.LOG_WARNING, "Oops closing * stream: " + e); } return true; } /** * Provide the 'agi' tag. * <agi command="agi command"> * The result is placed in "agi_result". * NOTE: the thread running this instance doesn't set * any of the instance variables. We get everything from "hr". */ public void tag_agi(RewriteContext hr) { debug(hr); hr.killToken(); String cmd = hr.get("command").trim(); if (cmd==null) { debug(hr, "No agi command!"); return; } String line; try { hr.server.log(Server.LOG_DIAGNOSTIC, hr.prefix, "Write: (" + cmd + ")"); writeLine(out, cmd); line = in.readLine(); debug(hr, line); hr.server.log(Server.LOG_DIAGNOSTIC, hr.prefix, "Read: (" + line + ")"); } catch (IOException e) { line="Error: " + e; } hr.request.props.put("agi_result", line); return; } /** * Write a NL string as ASCII in one network packet. * Some older Asterisk's AGI interface requires each agi command * must be in its own network packet. This tries to * insure that happens. */ void writeLine(OutputStream out, String s) throws IOException { int len = s.length(); byte[] b = new byte[len+1]; for (int i=0;i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy