Package org.smslib.modem

Source Code of org.smslib.modem.AModemDriver$CNMIEmulatorProcessor

// SMSLib for Java v3
// A Java API library for sending and receiving SMS via a GSM modem
// or other supported gateways.
// Web Site: http://www.smslib.org
//
// Copyright (C) 2002-2012, Thanasis Delenikas, Athens/GREECE.
// SMSLib is distributed under the terms of the Apache License version 2.0
//
// 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.smslib.modem;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.smslib.GatewayException;
import org.smslib.InboundMessage;
import org.smslib.InvalidMessageException;
import org.smslib.Service;
import org.smslib.TimeoutException;
import org.smslib.USSDResponse;
import org.smslib.AGateway.AsyncEvents;
import org.smslib.AGateway.GatewayStatuses;
import org.smslib.AGateway.Protocols;
import org.smslib.InboundMessage.MessageClasses;
import org.smslib.helper.Logger;
import org.smslib.notify.CallNotification;
import org.smslib.notify.InboundMessageNotification;
import org.smslib.threading.AServiceThread;

/**
* Abstract implementation of a generic GSM modem driver.
*/
public abstract class AModemDriver
{
  private static final String rxErrorWithCode = "\\s*[\\p{ASCII}]*\\s*\\+(CM[ES])\\s+ERROR: (\\d+)\\s";

  private static final String rxPlainError = "\\s*[\\p{ASCII}]*\\s*(ERROR|NO CARRIER|NO DIALTONE)\\s";

  private Object SYNC_Reader, SYNC_Commander, SYNC_InboundReader;

  private ModemGateway gateway;

  private boolean dataReceived;

  private volatile boolean connected;

  private CharQueue charQueue;

  private ModemReader modemReader;

  private KeepAlive keepAlive;

  private AsyncNotifier asyncNotifier;

  private AsyncMessageProcessor asyncMessageProcessor;

  private CNMIEmulatorProcessor cnmiEmulationProcessor;

  /**
   * Code of last error
   *
   * <pre>
   *   -1 = empty or invalid response
   *    0 = OK
   * 5xxx = CME error xxx
   * 6xxx = CMS error xxx
   * 9000 = ERROR
   * </pre>
   */
  private int lastError;

  static int OK = 0;

  protected AModemDriver(ModemGateway myGateway, String deviceParms)
  {
    setSYNCReader(new Object());
    setSYNCCommander(new Object());
    setSYNCInboundReader(new Object());
    setGateway(myGateway);
    setConnected(false);
    setDataReceived(false);
    setCharQueue(new CharQueue());
  }

  protected abstract void connectPort() throws GatewayException, IOException, InterruptedException;

  protected abstract void disconnectPort() throws IOException, InterruptedException;

  protected abstract void clear() throws IOException;

  protected void connect() throws TimeoutException, GatewayException, IOException, InterruptedException
  {
    String response;
    synchronized (getSYNCCommander())
    {
      try
      {
        connectPort();
        setConnected(true);
        setKeepAlive(new KeepAlive("KeepAlive [" + getGateway().getGatewayId() + "]", Service.getInstance().getSettings().SERIAL_KEEPALIVE_INTERVAL * 1000));
        setCnmiEmulationProcessor(new CNMIEmulatorProcessor("CNMIEmulatorProcessor [" + getGateway().getGatewayId() + "]", Service.getInstance().getSettings().CNMI_EMULATOR_INTERVAL * 1000));
        setModemReader(new ModemReader());
        setAsyncNotifier(new AsyncNotifier());
        setAsyncMessageProcessor(new AsyncMessageProcessor());
        clearBuffer();
        getGateway().getATHandler().reset();
        getGateway().getATHandler().sync();
        getGateway().getATHandler().echoOff();
        if ((getGateway().getCustomInitString() != null) && (getGateway().getCustomInitString().length() > 0))
        {
          write(getGateway().getCustomInitString() + "\r");
          getGateway().getATHandler().echoOff();
        }
        while (true)
        {
          response = getGateway().getATHandler().getSimStatus();
          while (response.indexOf("BUSY") >= 0)
          {
            Logger.getInstance().logDebug("SIM found busy, waiting...", null, getGateway().getGatewayId());
            Thread.sleep(Service.getInstance().getSettings().AT_WAIT_SIMPIN);
            response = getGateway().getATHandler().getSimStatus();
          }
          if (response.indexOf("SIM PIN2") >= 0)
          {
            Logger.getInstance().logDebug("SIM requesting PIN2.", null, getGateway().getGatewayId());
            if ((getGateway().getSimPin2() == null) || (getGateway().getSimPin2().length() == 0)) throw new GatewayException("The GSM modem requires SIM PIN2 to operate.");
            if (!getGateway().getATHandler().enterPin(getGateway().getSimPin2())) throw new GatewayException("SIM PIN2 provided is not accepted by the GSM modem.");
            Thread.sleep(Service.getInstance().getSettings().AT_WAIT_SIMPIN);
            continue;
          }
          else if (response.indexOf("SIM PIN") >= 0)
          {
            Logger.getInstance().logDebug("SIM requesting PIN.", null, getGateway().getGatewayId());
            if ((getGateway().getSimPin() == null) || (getGateway().getSimPin().length() == 0)) throw new GatewayException("The GSM modem requires SIM PIN to operate.");
            if (!getGateway().getATHandler().enterPin(getGateway().getSimPin())) throw new GatewayException("SIM PIN provided is not accepted by the GSM modem.");
            Thread.sleep(Service.getInstance().getSettings().AT_WAIT_SIMPIN);
            continue;
          }
          else if (response.indexOf("READY") >= 0) break;
          else if (response.indexOf("OK") >= 0) break;
          else if (response.indexOf("ERROR") >= 0)
          {
            Logger.getInstance().logWarn("Erroneous CPIN response, proceeding with defaults.", null, getGateway().getGatewayId());
            break;
          }
          Logger.getInstance().logWarn("Cannot understand SIMPIN response: " + response + ", will wait for a while...", null, getGateway().getGatewayId());
          Thread.sleep(Service.getInstance().getSettings().AT_WAIT_SIMPIN);
        }
        getGateway().getATHandler().echoOff();
        getGateway().getATHandler().init();
        getGateway().getATHandler().echoOff();
        if (!waitForNetworkRegistration()) Logger.getInstance().logWarn("Network Registration failed, proceeding with defaults.", null, getGateway().getGatewayId());
        getGateway().getATHandler().setVerboseErrors();
        if (getGateway().getATHandler().getStorageLocations().length() == 0)
        {
          try
          {
            getGateway().getATHandler().readStorageLocations();
            Logger.getInstance().logInfo("MEM: Storage Locations Found: " + getGateway().getATHandler().getStorageLocations(), null, getGateway().getGatewayId());
          }
          catch (Exception e)
          {
            getGateway().getATHandler().setStorageLocations("--");
            Logger.getInstance().logWarn("Storage locations could *not* be retrieved, will proceed with defaults.", e, getGateway().getGatewayId());
          }
        }
        if (!getGateway().getATHandler().setIndications())
        {
          Logger.getInstance().logWarn("Callback indications were *not* set succesfully!", null, getGateway().getGatewayId());
          getCnmiEmulationProcessor().enable();
        }
        else
        {
          if (getGateway().getATHandler().getIndications().getMode().equals("0")) getCnmiEmulationProcessor().enable();
        }
        if (getGateway().getProtocol() == Protocols.PDU)
        {
          if (!getGateway().getATHandler().setPduProtocol()) throw new GatewayException("The GSM modem does not support the PDU protocol.");
        }
        else if (getGateway().getProtocol() == Protocols.TEXT)
        {
          if (!getGateway().getATHandler().setTextProtocol()) throw new GatewayException("The GSM modem does not support the TEXT protocol.");
        }
      }
      catch (TimeoutException t)
      {
        try
        {
          disconnect();
        }
        catch (Exception e)
        {
          // Swallow this.
        }
        throw t;
      }
      catch (GatewayException t)
      {
        try
        {
          disconnect();
        }
        catch (Exception e)
        {
          // Swallow this.
        }
        throw t;
      }
      catch (IOException t)
      {
        try
        {
          disconnect();
        }
        catch (Exception e)
        {
          // Swallow this.
        }
        throw t;
      }
      catch (InterruptedException t)
      {
        try
        {
          disconnect();
        }
        catch (Exception e)
        {
          // Swallow this.
        }
        throw t;
      }
    }
  }

  protected void disconnect() throws IOException, InterruptedException
  {
    setConnected(false);
    if (getKeepAlive() != null)
    {
      getKeepAlive().cancel();
      setKeepAlive(null);
    }
    if (getCnmiEmulationProcessor() != null)
    {
      getCnmiEmulationProcessor().cancel();
      setCnmiEmulationProcessor(null);
    }
    if (getAsyncNotifier() != null)
    {
      getAsyncNotifier().interrupt();
      getAsyncNotifier().join();
      setAsyncNotifier(null);
    }
    if (getAsyncMessageProcessor() != null)
    {
      getAsyncMessageProcessor().interrupt();
      getAsyncMessageProcessor().join();
      setAsyncMessageProcessor(null);
    }
    if (getModemReader() != null)
    {
      getModemReader().interrupt();
      getModemReader().join();
      setModemReader(null);
    }
    disconnectPort();
  }

  public abstract void write(char c) throws IOException;

  public abstract void write(byte[] s) throws IOException;

  protected abstract int read() throws IOException;

  protected abstract boolean portHasData() throws IOException;

  public boolean dataAvailable() throws InterruptedException
  {
    return (getCharQueue().peek() == -1 ? false : true);
  }

  public void write(String s) throws IOException
  {
    Logger.getInstance().logDebug("SEND :" + formatLog(s), null, getGateway().getGatewayId());
    write(s.getBytes());
  }

  public void addToQueue(String s)
  {
    for (int i = 0; i < s.length(); i++)
      getCharQueue().put((byte) s.charAt(i));
  }

  public String getResponse() throws GatewayException, TimeoutException, IOException, InterruptedException
  {
    return getResponse(AsyncEvents.NOTHING);
  }

  /*
  * Version of getResponse that looks for a particular type of unsolicited response (e.g. USSDResponse) and returns
  * response without triggering an event.  Useful if you want to get a USSD response synchronously rather
  * using the event mechanism.  eventResponse is the type of unsolicited response to look for, set it to AsyncEvents.NOTHING
  * to handle all unsolicited responses through the event mechanism.
  */
  public String getResponse(AsyncEvents eventResponse) throws GatewayException, TimeoutException, IOException, InterruptedException
  {
    String response;
    byte c;
    setLastError(-1);
    StringBuffer buffer = new StringBuffer(Service.getInstance().getSettings().SERIAL_BUFFER_SIZE);
    try
    {
      while (true)
      {
        while ((getCharQueue().peek() == 0x0a) || (getCharQueue().peek() == 0x0d))
        {
          getCharQueue().get();
        }
        while (true)
        {
          c = getCharQueue().get();
          if (System.getProperty("smslib.dumpqueues") != null) Logger.getInstance().logDebug("OUT READER QUEUE : " + (int) c + " / " + (char) c, null, getGateway().getGatewayId());
          if (c != 0x0a) buffer.append((char) c);
          else break;
        }
        if (buffer.charAt(buffer.length() - 1) != 0x0d) buffer.append((char) 0x0d);
        response = buffer.toString();
        if (getGateway().getATHandler().matchesTerminator(response))
        {
          break;
        }
      }
      Logger.getInstance().logDebug("BUFFER: " + buffer, null, getGateway().getGatewayId());
      if (getGateway().getATHandler().isUnsolicitedResponse(buffer.toString()))
      {
        AsyncEvents event = getGateway().getATHandler().processUnsolicitedEvents(buffer.toString());
        if (event == eventResponse && eventResponse != AsyncEvents.NOTHING) { return buffer.toString(); }
        if ((event == AsyncEvents.INBOUNDMESSAGE) || (event == AsyncEvents.INBOUNDSTATUSREPORTMESSAGE) || (event == AsyncEvents.INBOUNDCALL) || (event == AsyncEvents.USSDRESPONSE)) getAsyncNotifier().setEvent(event, buffer.toString());
        return getResponse();
      }
      // Try to interpret error code
      if (response.matches(rxErrorWithCode))
      {
        Pattern p = Pattern.compile(rxErrorWithCode);
        Matcher m = p.matcher(response);
        if (m.find())
        {
          try
          {
            if (m.group(1).equals("CME"))
            {
              int code = Integer.parseInt(m.group(2));
              setLastError(5000 + code);
            }
            else if (m.group(1).equals("CMS"))
            {
              int code = Integer.parseInt(m.group(2));
              setLastError(6000 + code);
            }
            else throw new GatewayException("Invalid error response: " + m.group(1));
          }
          catch (NumberFormatException e)
          {
            Logger.getInstance().logDebug("Error on number conversion while interpreting response: ", null, getGateway().getGatewayId());
            throw new GatewayException("Cannot convert error code number.");
          }
        }
        else throw new GatewayException("Cannot match error code. Should never happen!");
      }
      else if (response.matches(rxPlainError)) setLastError(9000);
      else if (response.indexOf("OK") >= 0) setLastError(0);
      else setLastError(10000);
      Logger.getInstance().logDebug("RECV :" + formatLog(buffer.toString()), null, getGateway().getGatewayId());
    }
    catch (InterruptedException e)
    {
      Logger.getInstance().logWarn("GetResponse() Interrupted.", e, getGateway().getGatewayId());
      throw e;
    }
    catch (TimeoutException e)
    {
      Logger.getInstance().logDebug("Buffer contents on timeout: " + buffer, null, getGateway().getGatewayId());
      throw e;
    }
    return buffer.toString();
  }

  public void clearBuffer() throws IOException, InterruptedException
  {
    synchronized (getSYNCCommander())
    {
      Logger.getInstance().logDebug("clearBuffer() called.", null, getGateway().getGatewayId());
      Thread.sleep(Service.getInstance().getSettings().SERIAL_CLEAR_WAIT);
      clear();
      getCharQueue().clear();
    }
  }

  protected boolean waitForNetworkRegistration() throws GatewayException, TimeoutException, IOException, InterruptedException
  {
    //TODO: Move the magic number "6" (network retries) to settings(?)
    StringTokenizer tokens;
    String response;
    int answer;
    int retries = 0;
    while (true)
    {
      response = getGateway().getATHandler().getNetworkRegistration();
      if (response.indexOf("ERROR") >= 0) return false;
      response = response.replaceAll("\\s+OK\\s+", "");
      response = response.replaceAll("\\s+", "");
      response = response.replaceAll("\\+CREG:", "");
      tokens = new StringTokenizer(response, ",");
      tokens.nextToken();
      try
      {
        answer = Integer.parseInt(tokens.nextToken());
      }
      catch (Exception e)
      {
        answer = -1;
      }
      switch (answer)
      {
        case 0:
          Logger.getInstance().logError("GSM: Auto-registration disabled!", null, getGateway().getGatewayId());
          throw new GatewayException("GSM Network Auto-Registration disabled!");
        case 1:
          Logger.getInstance().logInfo("GSM: Registered to home network.", null, getGateway().getGatewayId());
          return true;
        case 2:
          Logger.getInstance().logWarn("GSM: Not registered, searching for network...", null, getGateway().getGatewayId());
          if (++retries == 6) throw new GatewayException("GSM Network Registration failed, give up trying!");
          break;
        case 3:
          Logger.getInstance().logError("GSM: Network registration denied!", null, getGateway().getGatewayId());
          throw new GatewayException("GSM Network Registration denied!");
        case 4:
          Logger.getInstance().logError("GSM: Unknown registration error!", null, getGateway().getGatewayId());
          throw new GatewayException("GSM Network Registration error!");
        case 5:
          Logger.getInstance().logInfo("GSM: Registered to foreign network (roaming).", null, getGateway().getGatewayId());
          return true;
        case -1:
          Logger.getInstance().logInfo("GSM: Invalid CREG response.", null, getGateway().getGatewayId());
          throw new GatewayException("GSM: Invalid CREG response.");
      }
      Thread.sleep(Service.getInstance().getSettings().AT_WAIT_NETWORK);
    }
  }

  private String formatLog(String s)
  {
    StringBuffer response = new StringBuffer();
    int i;
    char c;
    for (i = 0; i < s.length(); i++)
    {
      c = s.charAt(i);
      switch (c)
      {
        case 13:
          response.append("(cr)");
          break;
        case 10:
          response.append("(lf)");
          break;
        case 9:
          response.append("(tab)");
          break;
        default:
          if ((c >= 32) && (c < 128))
          {
            response.append(c);
          }
          else
          {
            response.append("(" + (int) c + ")");
          }
          break;
      }
    }
    return response.toString();
  }

  private class CharQueue
  {
    byte[] buffer;

    int bufferStart, bufferEnd;

    public CharQueue()
    {
      this.buffer = null;
      this.bufferStart = 0;
      this.bufferEnd = 0;
    }

    public synchronized void put(byte c)
    {
      if (this.buffer == null) this.buffer = new byte[Service.getInstance().getSettings().SERIAL_BUFFER_SIZE];
      this.buffer[this.bufferEnd] = c;
      this.bufferEnd++;
      if (this.bufferEnd == Service.getInstance().getSettings().SERIAL_BUFFER_SIZE) this.bufferEnd = 0;
      if (System.getProperty("smslib.dumpqueues") != null) Logger.getInstance().logDebug("IN READER QUEUE : " + (int) c + " / " + (char) c, null, getGateway().getGatewayId());
      notifyAll();
    }

    public synchronized byte get() throws TimeoutException, InterruptedException
    {
      byte c;
      if (this.buffer == null) this.buffer = new byte[Service.getInstance().getSettings().SERIAL_BUFFER_SIZE];
      while (true)
      {
        try
        {
          if (this.bufferStart == this.bufferEnd) wait(Service.getInstance().getSettings().SERIAL_TIMEOUT);
          if (this.bufferStart == this.bufferEnd) throw new TimeoutException("No response from device.");
          c = this.buffer[this.bufferStart];
          this.bufferStart++;
          if (this.bufferStart == Service.getInstance().getSettings().SERIAL_BUFFER_SIZE) this.bufferStart = 0;
          return c;
        }
        catch (InterruptedException e)
        {
          if (getGateway().getStatus() == GatewayStatuses.STARTED) Logger.getInstance().logWarn("Ignoring InterruptedException in Queue.get().", null, getGateway().getGatewayId());
          else
          {
            Logger.getInstance().logWarn("Re-throwing InterruptedException in Queue.get() - should be during shutdown...", null, getGateway().getGatewayId());
            throw new InterruptedException();
          }
        }
      }
    }

    public synchronized byte peek() throws InterruptedException
    {
      if (this.buffer == null) this.buffer = new byte[Service.getInstance().getSettings().SERIAL_BUFFER_SIZE];
      while (true)
      {
        try
        {
          if (this.bufferStart == this.bufferEnd) wait(Service.getInstance().getSettings().SERIAL_TIMEOUT);
          if (this.bufferStart == this.bufferEnd) return -1;
          return this.buffer[this.bufferStart];
        }
        catch (InterruptedException e)
        {
          if (getGateway().getStatus() == GatewayStatuses.STARTED) Logger.getInstance().logWarn("Ignoring InterruptedException in Queue.peek().", e, getGateway().getGatewayId());
          else
          {
            Logger.getInstance().logWarn("Re-throwing InterruptedException in Queue.peek() - should be during shutdown...", e, getGateway().getGatewayId());
            throw new InterruptedException();
          }
        }
      }
    }

    public synchronized String peek(int sizeToRead)
    {
      int i, size;
      StringBuffer result;
      if (this.buffer == null) this.buffer = new byte[Service.getInstance().getSettings().SERIAL_BUFFER_SIZE];
      size = sizeToRead;
      if (this.bufferStart == this.bufferEnd) return "";
      result = new StringBuffer(size);
      i = this.bufferStart;
      while (size > 0)
      {
        if ((this.buffer[i] != 0x0a) && (this.buffer[i] != 0x0d))
        {
          result.append((char) this.buffer[i]);
          size--;
        }
        i++;
        if (i == Service.getInstance().getSettings().SERIAL_BUFFER_SIZE) i = 0;
        if (i == this.bufferEnd) break;
      }
      return result.toString();
    }

    public synchronized void clear()
    {
      this.bufferStart = 0;
      this.bufferEnd = 0;
    }
  }

  private class ModemReader extends Thread
  {
    public ModemReader()
    {
      setName("SMSlib-ModemReader-" + getGateway().getGatewayId());
      setDaemon(true);
      start();
      Logger.getInstance().logDebug("ModemReader thread started.", null, getGateway().getGatewayId());
    }

    @Override
    public void run()
    {
      int c;
      String data;
      while (isConnected())
      {
        try
        {
          synchronized (getSYNCReader())
          {
            if (!isDataReceived()) getSYNCReader().wait();
            if (!isConnected()) break;
            c = read();
            while (c != -1)
            {
              getCharQueue().put((byte) c);
              if (!portHasData()) break;
              c = read();
            }
            setDataReceived(false);
          }
          data = getCharQueue().peek(6);
          for (int i = 0; i < getGateway().getATHandler().getUnsolicitedResponses().length; i++)
          {
            if (data.indexOf(getGateway().getATHandler().getUnsolicitedResponse(i)) >= 0)
            {
              Thread.sleep(100);
              getKeepAlive().interrupt();
              break;
            }
          }
        }
        catch (InterruptedException e)
        {
          if (!isConnected()) break;
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
      Logger.getInstance().logDebug("ModemReader thread ended.", null, getGateway().getGatewayId());
    }
  }

  private class KeepAlive extends AServiceThread
  {
    public KeepAlive(String name, int delay)
    {
      super(name, delay, 0, true);
    }

    @Override
    public void process() throws Exception
    {
      try
      {
        if (!isConnected()) return;
        if (getGateway().getStatus() == GatewayStatuses.STARTED)
        {
          synchronized (getSYNCCommander())
          {
            if (!isConnected()) return;
            try
            {
              if (!getGateway().getATHandler().isAlive()) getGateway().setStatus(GatewayStatuses.RESTART);
              if (!getCnmiEmulationProcessor().isEnabled()) getAsyncMessageProcessor().setProcess();
            }
            catch (Exception e)
            {
              getGateway().setStatus(GatewayStatuses.RESTART);
            }
          }
        }
      }
      catch (Exception e)
      {
        Logger.getInstance().logError("ModemDriver: KeepAlive Error.", e, getGateway().getGatewayId());
        getGateway().setStatus(GatewayStatuses.RESTART);
      }
    }
  }

  private class AsyncNotifier extends Thread
  {
    class Event
    {
      AsyncEvents event;

      String response;

      public Event(AsyncEvents myEvent, String myResponse)
      {
        this.event = myEvent;
        this.response = myResponse;
      }

      @Override
      public String toString()
      {
        return "Event: " + this.event + " / Response: " + this.response;
      }
    }

    private BlockingQueue<Event> eventQueue;

    private Object SYNC;

    public AsyncNotifier()
    {
      this.SYNC = new Object();
      this.eventQueue = new LinkedBlockingQueue<Event>();
      setPriority(MIN_PRIORITY);
      setName("SMSLib-AsyncNotifier : " + getGateway().getGatewayId());
      setDaemon(true);
      start();
      Logger.getInstance().logDebug("AsyncNotifier thread started.", null, getGateway().getGatewayId());
    }

    protected void setEvent(AsyncEvents event, String response)
    {
      synchronized (this.SYNC)
      {
        Event ev = new Event(event, response);
        Logger.getInstance().logDebug("Storing AsyncEvent: " + ev, null, getGateway().getGatewayId());
        this.eventQueue.add(ev);
        this.SYNC.notify();
      }
    }

    protected String getOriginator(String indication)
    {
      Pattern p = Pattern.compile("\\+?\"\\S+\"");
      Matcher m = p.matcher(indication);
      if (m.find()) return indication.substring(m.start(), m.end()).replaceAll("\"", "");
      return "";
    }

    @Override
    public void run()
    {
      String response;
      Event event;
      while (isConnected())
      {
        try
        {
          event = this.eventQueue.take();
          Logger.getInstance().logDebug("Processing AsyncEvent: " + event, null, getGateway().getGatewayId());
          if (event.event == AsyncEvents.INBOUNDMESSAGE)
          {
            Logger.getInstance().logDebug("Inbound message detected!", null, getGateway().getGatewayId());
            event.event = AsyncEvents.NOTHING;
            response = event.response;
            getAsyncMessageProcessor().setProcess();
          }
          else if (event.event == AsyncEvents.INBOUNDSTATUSREPORTMESSAGE)
          {
            Logger.getInstance().logDebug("Inbound status report message detected!", null, getGateway().getGatewayId());
            event.event = AsyncEvents.NOTHING;
            response = event.response;
            getAsyncMessageProcessor().setProcess();
          }
          else if (event.event == AsyncEvents.INBOUNDCALL)
          {
            Logger.getInstance().logDebug("Inbound call detected!", null, getGateway().getGatewayId());
            event.event = AsyncEvents.NOTHING;
            synchronized (getSYNCCommander())
            {
              getGateway().getATHandler().switchToCmdMode();
              getGateway().getModemDriver().write("ATH\r");
              getGateway().getModemDriver().getResponse();
              response = event.response;
            }
            Service.getInstance().getNotifyQueueManager().getNotifyQueue().add(new CallNotification(getGateway(), getOriginator(response)));
            //if (Service.getInstance().getCallNotification() != null) Service.getInstance().getCallNotification().process(getGateway().getGatewayId(), getOriginator(response));
          }
          else if (event.event == AsyncEvents.USSDRESPONSE)
          {
            Logger.getInstance().logDebug("Inbound USSD response detected!", null, getGateway().getGatewayId());
            event.event = AsyncEvents.NOTHING;
            response = event.response;
            Logger.getInstance().logDebug("USSD response : " + formatLog(response), null, getGateway().getGatewayId());
            if (Service.getInstance().getUSSDNotification() != null)
            {
              USSDResponse ussdResponse = new USSDResponse(response, getGateway().getGatewayId());
              ussdResponse.setContent(getGateway().getATHandler().formatUSSDResponse(ussdResponse.getContent()));
              Service.getInstance().getUSSDNotification().process(getGateway(), ussdResponse);
            }
          }
        }
        catch (InterruptedException e)
        {
          if (!isConnected()) break;
        }
        catch (InvalidMessageException e)
        {
          Logger.getInstance().logInfo("Invalid Message received! Ignoring. ", e, getGateway().getGatewayId());
        }
        catch (GatewayException e)
        {
          getGateway().setStatus(GatewayStatuses.RESTART);
        }
        catch (IOException e)
        {
          getGateway().setStatus(GatewayStatuses.RESTART);
        }
        catch (TimeoutException e)
        {
          getGateway().setStatus(GatewayStatuses.RESTART);
        }
      }
      Logger.getInstance().logDebug("AsyncNotifier thread ended.", null, getGateway().getGatewayId());
    }
  }

  private class AsyncMessageProcessor extends Thread
  {
    private List<InboundMessage> msgList;

    private Object SYNC;

    private boolean process;

    public AsyncMessageProcessor()
    {
      this.msgList = new ArrayList<InboundMessage>();
      this.SYNC = new Object();
      this.process = false;
      setPriority(MAX_PRIORITY);
      setName("SMSLib-AsyncMessageProcessor : " + getGateway().getGatewayId());
      setDaemon(true);
      start();
      Logger.getInstance().logDebug("AsyncMessageProcessor thread started.", null, getGateway().getGatewayId());
    }

    public void setProcess()
    {
      synchronized (this.SYNC)
      {
        if (this.process) return;
        this.process = true;
        this.SYNC.notify();
      }
    }

    @Override
    public void run()
    {
      while (isConnected())
      {
        try
        {
          synchronized (this.SYNC)
          {
            if (!this.process)
            {
              this.SYNC.wait();
              if (!isConnected()) break;
            }
          }
          synchronized (getSYNCInboundReader())
          {
            getGateway().readMessages(this.msgList, MessageClasses.ALL);
            for (InboundMessage msg : this.msgList)
            {
              switch (msg.getType())
              {
                case INBOUND:
                case STATUSREPORT:
                  Service.getInstance().getNotifyQueueManager().getNotifyQueue().add(new InboundMessageNotification(getGateway(), msg.getType(), msg));
                  break;
                default:
                  break;
              }
            }
          }
          this.msgList.clear();
          this.process = false;
        }
        catch (InterruptedException e)
        {
          if (!isConnected()) break;
        }
        catch (GatewayException e)
        {
          getGateway().setStatus(GatewayStatuses.RESTART);
        }
        catch (IOException e)
        {
          getGateway().setStatus(GatewayStatuses.RESTART);
        }
        catch (TimeoutException e)
        {
          getGateway().setStatus(GatewayStatuses.RESTART);
        }
      }
      Logger.getInstance().logDebug("AsyncMessageProcessor thread ended.", null, getGateway().getGatewayId());
    }
  }

  private class CNMIEmulatorProcessor extends AServiceThread
  {
    private List<InboundMessage> msgList;

    public CNMIEmulatorProcessor(String name, int delay)
    {
      super(name, delay, 0, false);
    }

    @Override
    public void process() throws Exception
    {
      if ((isConnected()) && (getGateway().getStatus() == GatewayStatuses.STARTED))
      {
        synchronized (getSYNCInboundReader())
        {
          this.msgList = new ArrayList<InboundMessage>();
          getGateway().readMessages(this.msgList, MessageClasses.ALL);
          for (InboundMessage msg : this.msgList)
          {
            switch (msg.getType())
            {
              case INBOUND:
              case STATUSREPORT:
                Service.getInstance().getNotifyQueueManager().getNotifyQueue().add(new InboundMessageNotification(getGateway(), msg.getType(), msg));
                break;
            }
          }
          this.msgList.clear();
        }
      }
    }
  }

  void setLastError(int myLastError)
  {
    this.lastError = myLastError;
  }

  public int getLastError()
  {
    return this.lastError;
  }

  public String getLastErrorText()
  {
    if (getLastError() == 0) return "OK";
    else if (getLastError() == -1) return "Invalid or empty response";
    else if ((getLastError() / 1000) == 5) return "CME Error " + (getLastError() % 1000);
    else if ((getLastError() / 1000) == 6) return "CMS Error " + (getLastError() % 1000);
    else return "Error: unknown";
  }

  public boolean isOk()
  {
    return (getLastError() == OK);
  }

  protected ModemGateway getGateway()
  {
    return this.gateway;
  }

  protected void setGateway(ModemGateway myGateway)
  {
    this.gateway = myGateway;
  }

  protected boolean isConnected()
  {
    return this.connected;
  }

  protected void setConnected(boolean myConnected)
  {
    this.connected = myConnected;
  }

  protected boolean isDataReceived()
  {
    return this.dataReceived;
  }

  protected void setDataReceived(boolean myDataReceived)
  {
    this.dataReceived = myDataReceived;
  }

  protected CharQueue getCharQueue()
  {
    return this.charQueue;
  }

  protected void setCharQueue(CharQueue myCharQueue)
  {
    this.charQueue = myCharQueue;
  }

  protected Object getSYNCReader()
  {
    return this.SYNC_Reader;
  }

  protected void setSYNCReader(Object reader)
  {
    this.SYNC_Reader = reader;
  }

  protected Object getSYNCCommander()
  {
    return this.SYNC_Commander;
  }

  protected void setSYNCCommander(Object commander)
  {
    this.SYNC_Commander = commander;
  }

  protected Object getSYNCInboundReader()
  {
    return this.SYNC_InboundReader;
  }

  protected void setSYNCInboundReader(Object inbMessage)
  {
    this.SYNC_InboundReader = inbMessage;
  }

  protected KeepAlive getKeepAlive()
  {
    return this.keepAlive;
  }

  protected void setKeepAlive(KeepAlive myKeepAlive)
  {
    this.keepAlive = myKeepAlive;
  }

  protected AsyncNotifier getAsyncNotifier()
  {
    return this.asyncNotifier;
  }

  protected void setAsyncNotifier(AsyncNotifier myAsyncNotifier)
  {
    this.asyncNotifier = myAsyncNotifier;
  }

  protected AsyncMessageProcessor getAsyncMessageProcessor()
  {
    return this.asyncMessageProcessor;
  }

  protected void setAsyncMessageProcessor(AsyncMessageProcessor myAsyncMessageProcessor)
  {
    this.asyncMessageProcessor = myAsyncMessageProcessor;
  }

  protected CNMIEmulatorProcessor getCnmiEmulationProcessor()
  {
    return this.cnmiEmulationProcessor;
  }

  protected void setCnmiEmulationProcessor(CNMIEmulatorProcessor myCnmiEmulationProcessor)
  {
    this.cnmiEmulationProcessor = myCnmiEmulationProcessor;
  }

  protected ModemReader getModemReader()
  {
    return this.modemReader;
  }

  protected void setModemReader(ModemReader myModemReader)
  {
    this.modemReader = myModemReader;
  }
}
TOP

Related Classes of org.smslib.modem.AModemDriver$CNMIEmulatorProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.