/*
* Socket.java
*
* Created on 4 Февраль 2009 г., 15:11
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package protocol.xmpp;
import com.jcraft.jzlib.*;
import jimm.JimmException;
import jimm.modules.*;
import protocol.net.TcpSocket;
import java.util.Vector;
/**
*
* @author Vladimir Krukov
*/
final class Socket implements Runnable {
private TcpSocket socket = new TcpSocket();
private volatile boolean connected;
private byte[] inputBuffer = new byte[1024];
private int inputBufferLength = 0;
public int inputBufferIndex = 0;
// #sijapp cond.if modules_ZLIB is "true" #
private ZInputStream zIn;
private ZOutputStream zOut;
private boolean compressed;
private boolean secured;
// #sijapp cond.end #
private final Vector<Object> read = new Vector<Object>();
/**
* Creates a new instance of Socket
*/
public Socket() {
}
// #sijapp cond.if modules_ZLIB is "true" #
public void startCompression() {
zIn = new ZInputStream(socket);
zOut = new ZOutputStream(socket, JZlib.Z_DEFAULT_COMPRESSION);
zOut.setFlushMode(JZlib.Z_SYNC_FLUSH);
compressed = true;
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.println("zlib is working");
// #sijapp cond.end #
}
public void startTls(String host) {
socket.startTls(host);
secured = true;
}
// #sijapp cond.end #
public boolean isConnected() {
return connected;
}
public void connectTo(String url) throws JimmException {
System.out.println("url: " + url);
socket.connectTo(url);
connected = true;
}
private int read(byte[] data) throws JimmException {
// #sijapp cond.if modules_ZLIB is "true" #
if (compressed) {
int bRead = zIn.read(data);
if (-1 == bRead) {
throw new JimmException(120, 13);
}
return bRead;
}
// #sijapp cond.end #
int bRead = socket.read(data, 0, data.length);
if (-1 == bRead) {
throw new JimmException(120, 12);
}
return bRead;
}
public void write(byte[] data) throws JimmException {
// #sijapp cond.if modules_ZLIB is "true" #
if (compressed) {
zOut.write(data);
zOut.flush();
return;
}
// #sijapp cond.end #
socket.write(data, 0, data.length);
socket.flush();
}
public void close() {
connected = false;
// #sijapp cond.if modules_ZLIB is "true" #
try {
zIn.close();
zOut.close();
} catch (Exception ignored) {
}
// #sijapp cond.end #
socket.close();
inputBufferLength = 0;
inputBufferIndex = 0;
}
public void sleep(long ms) {
try {
Thread.sleep(ms);
} catch (Exception ignored) {
}
}
private void fillBuffer() throws JimmException {
inputBufferIndex = 0;
inputBufferLength = read(inputBuffer);
while (0 == inputBufferLength) {
sleep(100);
inputBufferLength = read(inputBuffer);
}
}
private byte readByte() throws JimmException {
if (inputBufferIndex >= inputBufferLength) {
fillBuffer();
}
return inputBuffer[inputBufferIndex++];
}
char readChar() throws JimmException {
try {
byte bt = readByte();
if (0 <= bt) {
return (char)bt;
}
if ((bt & 0xE0) == 0xC0) {
byte bt2 = readByte();
return (char)(((bt & 0x3F) << 6) | (bt2 & 0x3F));
} else if ((bt & 0xF0) == 0xE0) {
byte bt2 = readByte();
byte bt3 = readByte();
return (char)(((bt & 0x1F) << 12) | ((bt2 & 0x3F) << 6) | (bt3 & 0x3F));
} else {
int seqLen = 0;
if ((bt & 0xF8) == 0xF0) seqLen = 3;
else if ((bt & 0xFC) == 0xF8) seqLen = 4;
else if ((bt & 0xFE) == 0xFC) seqLen = 5;
for (; 0 < seqLen; --seqLen) {
readByte();
}
return '?';
}
} catch (JimmException e) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.panic("readChar je ", e);
// #sijapp cond.end #
throw e;
} catch (Exception e) {
// #sijapp cond.if modules_DEBUGLOG is "true" #
DebugLog.panic("readChar e ", e);
// #sijapp cond.end #
throw new JimmException(120, 7);
}
}
boolean isSecured() {
return secured;
}
private Object readObject() throws JimmException {
Object readObject = null;
while (connected && null == readObject) {
readObject = XmlNode.parse(this);
if (null == readObject) sleep(100);
}
return readObject;
}
@Override
public void run() {
Object readObject;
while (connected) {
try {
readObject = readObject();
} catch (JimmException e) {
readObject = e;
}
if (null != readObject) {
synchronized (read) {
read.addElement(readObject);
}
}
}
}
public XmlNode readNode(boolean wait) throws JimmException {
Object readObject = null;
if (wait) {
readObject = readObject();
} else {
synchronized (read) {
if (0 < read.size()) {
readObject = read.elementAt(0);
read.removeElementAt(0);
}
}
}
if (readObject instanceof JimmException) throw (JimmException) readObject;
return (XmlNode) readObject;
}
public void start() {
new Thread(this).start();
}
}