/* Copyright (c) 2008 Bluendo S.r.L.
* See about.html for details about license.
*
* $Id: BaseChannel.java 1577 2009-06-15 14:38:27Z luca $
*/
package it.yup.transport;
// #debug
import it.yup.util.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
//#ifdef TLS
import org.bouncycastle.crypto.tls.TlsOuputStream;
//#endif
// #ifdef COMPRESSION
import com.jcraft.jzlib.ZOutputStream;
// #endif
public abstract class BaseChannel {
/** The outputStream to the server. */
protected OutputStream outputStream = null;
/** The inputStream form the server. */
protected InputStream inputStream = null;
/** Indicating the network transport that implements this BaseHTTPConnection. Derived classes muts set this*/
public String transportType = null;
/** outgoing packets */
protected Vector packets = new Vector();
/** The sender thread */
protected Sender sender = null;
/*
* The number of sent bytes over the socket
*/
public static int bytes_sent = 0;
/*
* The number of received bytes over the socket
*/
public static int bytes_received = 0;
/*
* A flag used to enable or disable compression
*/
/**
* Asynchronous data sender on a connection.
* It starts a thread that synchronizes on the packets Vector. In order to send a packet queue it into
* the packets queue and call notify.
*
*/
protected class Sender extends Thread {
private BaseChannel channel;
public boolean exiting = false;
public Sender(BaseChannel channel) {
this.channel = channel;
}
public void run() {
byte[] pkt = null;
while (!this.exiting) {
// wait until we've packets
synchronized (channel.packets) {
while (channel.packets.size() == 0) {
try {
if (this.exiting) { return; }
// #mdebug
Logger
.log(
"Sender: waiting for packets to send. Data: ",
Logger.DEBUG);
// #enddebug
channel.packets.wait();
/* Also if we have nothing to send, check the socket
* This may be useful for... */
if (!channel.pollAlive()) {
// #debug
Logger.log("send exited");
return;
}
} catch (InterruptedException e) {
}
}
// There is something to send, send the packet
pkt = (byte[]) channel.packets.firstElement();
channel.packets.removeElementAt(0);
}
if (pkt == null) {
/* safety check */
continue;
}
try {
// #debug
Logger.log("[SEND] " + new String(pkt));
// #ifndef BXMPP
channel.outputStream.write(pkt);
channel.outputStream.flush();
// #ifdef COMPRESSION
if (channel.outputStream instanceof ZOutputStream) {
BaseChannel.bytes_sent = (int) ((ZOutputStream) channel.outputStream)
.getTotalOut();
}
else {
// #ifndef TLS
BaseChannel.bytes_sent += pkt.length;
// #endif
// #ifdef TLS
if (channel.outputStream instanceof TlsOuputStream == false) {
BaseChannel.bytes_sent += pkt.length;
} else if (channel.outputStream instanceof TlsOuputStream == true) {
BaseChannel.bytes_sent = SocketChannel.handler
.getBytes_sent();
}
// #endif
}
// #endif
// #ifndef COMPRESSION
bytes_sent += pkt.length;
// #endif
// #endif
} catch (IOException e) {
// #debug
Logger.log("[SEND] IOException:" + e.getMessage());
close();
}
}
// #debug
Logger.log("Sender: exiting", Logger.DEBUG);
}
}
/** open this channel */
public abstract void open();
/** close this channel */
public abstract void close();
/**
* Send a packet
* @param packetToSend
*/
public abstract void sendContent(byte[] packetToSend);
/** @return true is the channel is open */
public abstract boolean isOpen();
/** Called for each tick of the server */
protected boolean pollAlive() {
return true;
}
}