Package threads

Source Code of threads.HttpBindThread

/**
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Library General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package threads;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;
import java.util.Date;

import jabber.presence.*;
import xmlstreamparser.*;
import util.Datas;
import jmc.StanzaReader;
import jmc.MidletEventListener;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

import com.twmacinta.util.MD5;

/**
* Class for transmitting stanzas over http-binding (JEP 124)
* @author G.Bianchi
*
*/
public class HttpBindThread extends Thread implements IWriterThread{

  public static int DEFAULT_WAIT = 30;

  private String httpburl; // url of the HTTB Binding gateway

  private int wait = DEFAULT_WAIT; // max seconds to keep the connection

  private int polling = 5; // max seconds for polling
       
  protected boolean statusSet = false;
  private HttpConnection[] conn = new HttpConnection[2]; //allow exactly 2 connections

  private int defaultConn = 0;

  private long rid = -1; // request id

  private String sid = null; // session id

  private Thread secondThread = null;
 
  private boolean ended = false; // Network error flag

  private boolean busy = false; // Indicates if someone reads packet

  private boolean terminated = false; // Indicates if someone closed

  private StanzaReader stanzaReader;

  private MidletEventListener eventsListener;
 
  private String buffer = ""
 
  /**
   * Constructor
   */
  public HttpBindThread(StanzaReader _stanzaReader, MidletEventListener events) {
    stanzaReader = _stanzaReader;
    eventsListener = events;
    start();
  }

  /**
   * Run Method of the thread
   *
   *
   */
  public void run() {
   
   
    String user = Datas.jid.getLittleJid();
   
    String domain = Datas.hostname;
   
    String addr = Datas.server_name + ":"
        + Datas.port;

    httpburl = "http://"+addr+"/http-bind/";
   
    System.out.println("Connecting..."+httpburl);
   
    try {
      /* Starts session with jabber server */
      initSession(addr, domain, user, Datas.getPassword(),
          "JabberMix", Presence.getPresence(1));
         
    } catch (Exception e) {
      // If any exception throws - terminate connection
      System.out.println(e.getMessage());
     
      ended = true;
    }
    if (ended) {
     
      terminate();
      return;
    }
    System.out.println("Successfully connected with "
        + addr);

    // Calculates string representation of initial user status
 

    if (!ended) {
      stanzaReader.setRosterState();
      //Requests roster items
      writeWithBody("<iq id=\"s3\" type=\"get\">"+ "<query xmlns=\"jabber:iq:roster\"/></iq>");
      readStanzas(0);

    //  writeWithBody("<iq type=\"get\" from=\""+Datas.jid.getFullJid()+"\" to=\""+Datas.hostname+"\" id=\"discoitem1\"><query xmlns=\"http://jabber.org/protocol/disco#items\"/></iq>");
    //  readStanzas(0);

   
    }

 
    defaultConn = 1;
    statusSet = false;
            
                Date last = null;
    while (!ended) {
      // Main loop
      try {
        if (!terminated && !busy) {
         
          Date now = new Date();

         
          if (last != null && (now.getTime() - last.getTime() < (polling*1000))) {
            sleep(((polling * 1000) - (now.getTime() - last.getTime())));
           
          }
         
         
          last = new Date();
          System.out.println("sending [" + last.toString() + "]: "+buffer);
       
          writeWithBody(buffer, 0);
          buffer = "";
         
          readStanzas(0);
          System.out.println("receiving  [" + new Date().toString() + "]");
         

        }
      } catch (Exception e) {
        ended = true;
       
      }
    }
  //  System.out.println("Run: loop ended");

  }



  /**
   * Read stanzas
   * @param connIdx
   */
  private synchronized void readStanzas(int connIdx) {
    HttpNode n = readResponse(connIdx);
    if (n == null)
      return;
    System.out.println("readStanzas: " + n.getChilds());
   
    int s = n.getChilds().size();
    for (int i=0; i<s; i++) {
     
     
      stanzaReader.read(new Node((HttpNode) n.getChilds().elementAt(i)));
    }
  }



  /**
   * reads the next stanza from the given connection
   * @param httpconn
   * @return HttpNode
   */
  private HttpNode readStanza(int connIdx) {
    HttpNode n = readResponse(connIdx);
    int s = n.getChilds().size();
    if (s > 1) {
     
      return (HttpNode) n.getChilds().firstElement();
    } else if (s < 1) {
      //discard empty stanza
      return new HttpNode();
    }
    return n;
  }

  /**
   * reads the next non-empty stanza (blocking)
   *
   * @return HttpNode
   */
  protected HttpNode readStanza() {
    //use default connection
    return readStanza(defaultConn);
  }

  /**
   * reads the returned response with the body element
   *
   * @return HttpNode
   */
  private HttpNode readResponse(int connIdx) {
    busy = true;
 
    HttpNode x = new HttpNode();
    if (ended) {
   
      return null;
    }
    do {
      if (!ended) {
        InputStream is = null;
        try {
          HttpConnection httpconn = conn[connIdx];
          int rc = ((HttpConnection)httpconn).getResponseCode();
          if (rc == 404)
            return null;
             
          if (rc != 200)
          {
            is = httpconn.openInputStream();
            int code;
            while ((code = is.read()) != -1)
              System.out.print((char)code);
            throw new Exception("Exception response code: " + rc);
          }
          is = httpconn.openInputStream();
                 
          x.parse("", is);
   
        } catch (Exception e) {
     
          System.out.println("Exception reading response: " + e.getMessage());
          ended = true;
        } finally {
          try {
            if (is != null)
              is.close();
          } catch (IOException e) {
           
          }
        }
        busy = false;
      }
    } while (x.getName().equals("") && !ended);
 

    return x;
  }

  /**
   * Initialize the session
   *
   *
   */
  protected void initSession(String addr, String domain, String user,
      String pass, String resource, String Status) throws Exception {
    try {
     
      System.out.println("Opening first stream");
   
      generateRequestId(); // create rid

      writeStream("<body content=\"text/xml; charset=utf-8\" to=\""
          + domain
          + "\" hold=\"1\" wait=\""
          + wait
          + "\" rid=\""
          + rid
          + "\" "
          + "xml:lang=\"en\" "
          + ""
          + "route=\"xmpp:" + addr + "\" "
          + "xmlns=\"http://jabber.org/protocol/httpbind\" "    
          +"/>", 0);

      HttpNode x = readResponse(0);
     
      if (!x.getName().equals("body"))
        eventsListener.unauthorizedEvent("Body element missing!");
      sid = x.getAttr("sid");
      System.out.println("Session creation response received: "+x.toString(0));
      if (sid == null || sid.length() == 0) {
        eventsListener.unauthorizedEvent("Session ID not given!");
        throw new Exception("Session ID not given!");
      }
      if (x.getAttr("requests") == null || x.getAttr("requests").equals("1")) {
        eventsListener.unauthorizedEvent("Server supports only polling behaviour!");
        throw new Exception("Server supports only polling behaviour!");
      }
     
      int tmpW = Integer.parseInt(x.getAttr("wait"));
      if (tmpW < wait)
        wait = tmpW;
       
     
      if (x.getAttr("polling") != null) {
        polling =  Integer.parseInt(x.getAttr("polling"));
        polling++;
      }
     
      if (x.getAttr("inactivity").length()>0) {
       int inact=Integer.parseInt(x.getAttr("inactivity"));
       if (inact < wait)
       wait = inact;
       }

      System.out.println("Authenticating: "+x.toString());
     
      x = x.child("features");
      Authenticate(x, user, pass, domain);
     
      writeWithBody("<iq type=\"set\" id=\"bind_1\">"
          + "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
          + "<resource>" + resource + "</resource></bind></iq>");
      System.out.println("Binding resource");
      x = readStanza();
      if (x.getAttr("type").equals("error")) {
        eventsListener.unauthorizedEvent("Error binding resource");
        throw new Exception("Error binding resource");
      }
      writeWithBody("<iq to=\""
          + domain
          + "\" type=\"set\" id=\"sess_1\">"
          + "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/></iq>");
      System.out.println("Opening session");
      x = readStanza();
      if (x.getAttr("type").equals("error")) {
        eventsListener.unauthorizedEvent("Error opening session");
        throw new Exception("Error opening session");
      }
      System.out.println("Session Open!");
    } catch (Exception e) {
     
      eventsListener.unauthorizedEvent(e.getMessage());
      throw new Exception(e.getMessage());
    }
  }


 
    /**
     * Tells the thread to terminate as soon as possible.
     */
  public synchronized void terminate()
  {

   
    wait = DEFAULT_WAIT;
    rid = -1;
    sid = null;
    ended = true;
    terminated = true;
    defaultConn = 0;

    //close open connections
    for (int i = 0; i < conn.length; i++)
    {
      try
      {
        if (conn[i] != null)
          conn[i].close();
      }
      catch (Exception e)
      {
        System.out.println(e.getMessage());
      }
    }
    eventsListener.disconnectedEvent();

    System.out.println("Terminated!");
    }
 
  /**
   * Implements the interface method
   * @param _s
   */
  public synchronized void write(final String _s)
  {
    System.out.println("Writing");
   
    while (secondThread != null && secondThread.isAlive())
    {
      try
      {
        sleep(200);
      }
      catch (InterruptedException e)
      {
      }
   
    }
    secondThread = new Thread()
    {
      public void run()
      {
        writeWithBody(_s, 1);
        readStanzas(defaultConn);
      }
    };
    secondThread.start();
  }

  /**
   * writes the message to the outputsream of the given connection
   * @param mess
   * @param conn
   */
  private void writeWithBody(String mess, int connIdx)  {
    writeStream("<body rid=\"" + (++rid) + "\" sid=\"" + sid + "\" "
        + "xmlns=\"http://jabber.org/protocol/httpbind\">" + mess
        + "</body>", connIdx);
  }

  /*
   * Add the body tag to the message
   *
   *
   */
  protected void writeWithBody(final String mess) {
    //default connection to use when called from outside
    if (defaultConn == 1) {
     
      while (secondThread != null && secondThread.isAlive()) {
        try {
          sleep(200);
        } catch (InterruptedException e) {
        }
       
      }
      secondThread = new Thread() {
        public void run() {
          writeWithBody(mess, defaultConn);
          readStanzas(defaultConn);
        }
      };
      secondThread.start();
    } else {
      writeWithBody(mess, defaultConn);
    }
  }

  /**
   * sends the message, but does not autonmatically include the enclosing body
   * element.
   *
   * @param mess
   */
  private void writeStream(String mess, int connIdx) {
    if (ended) {
      terminate();
      return;
    }
    OutputStream out = null;
    try {
      byte[] bout = unicodeToServer(mess);
      HttpConnection httpconn = (HttpConnection) Connector.open(httpburl);
      conn[connIdx] = httpconn;
     
      if (!httpburl.startsWith("https://")) {
       
        httpconn.setRequestProperty("User-Agent",
            "Profile/MIDP-2.0 Configuration/CLDC-1.1");
       
      }
      httpconn.setRequestMethod("POST");
      httpconn.setRequestProperty("Content-Length", ""
          + bout.length);
      out = httpconn.openOutputStream();
      if (out != null) {
        out.write(bout);
       
      }
      System.out.println("writtenToAir ["+connIdx+"]: " + mess);
    } catch (Exception e) {
      System.out.println("Exception found: " + e.getMessage());
      ended = true;
    } finally {
      try {
        if (out != null)
          out.close();
      } catch (IOException e) {
       
      }
    }
  }

  /**
   * generates a random rid with max. 10 digits.
   * (9007199254740991 limit)
   *
   * @return
   */
  private long generateRequestId() {
    String strRid = "";
    Random r = new Random();
    for (int i = 0; i < 10; i++)
      strRid += "" + r.nextInt(10);
    rid = Long.parseLong(strRid);
 
    return rid;
  }
 
  /**
   * authenticates the user with the most appropriate mechanism
   * @param x  features
   * @param user
   * @param pass
   * @param domain
   * @throws Exception
   */
  protected void Authenticate(HttpNode x, String user, String pass, String domain) throws Exception {



    if (x.child("mechanisms").hasValueOfChild("PLAIN")) {
        // PLAIN authorization
        System.out.println("Using plain authorization");
        String resp = "\0" + user + "\0" + pass;
        writeWithBody("<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\">"
            + MD5.toBase64(resp.getBytes()) + "</auth>");
        System.out.println("Starting PLAIN authorization");
        x = readStanza();
        if (x.getName().equals("failure"))
          throw new Exception("PLAIN authorization error");
    }
    else throw new Exception("Only PLAIN authorization supported");
  }
 
   /**
    * Unicode Support
    * � 2003, 2004 Vidar Holen
    * www.vidarholen.net
    *
    */
    public byte[] unicodeToServer(String s) {
        byte[] b=new byte[strlen(s)];
        char[] a=s.toCharArray();
        int j=0;
        for(int i=0; i<a.length; i++) {
            if(a[i]<0x80) {
                b[j]=(byte)(a[i]);
                j+=1;
            } else if(a[i]<0x800) {
                b[j]=(byte)(0xC0 | (a[i]>>6));
                b[j+1]=(byte)(0x80 | (a[i]&0x3F));
                j+=2;
            } else {
                b[j]=(byte)(0xE0 | (a[i]>>12));
                b[j+1]=(byte)(0x80 | ((a[i]>>6)&0x3F));
                b[j+2]=(byte)(0x80 | (a[i]&0x3F));
                j+=3;
            }
        }

        return b;
    }
   
    /**
     * Find length in bytes of a string, akin to strlen vs wcslen
     *
     * � 2003, 2004 Vidar Holen
      * www.vidarholen.net
     */
    public static int strlen(String s) {
        int n=0;
        char[] a=s.toCharArray();
        for(int i=0; i<a.length; i++) {
            if(a[i]<0x80) n++;
            else if(a[i]<0x800) n+=2;
            else n+=3;
        }
        return n;
    }

 

}
TOP

Related Classes of threads.HttpBindThread

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.