package javaforce.voip;
/** SIP TCP Transport
*
* Client needs to only connect to one endpoint.
*
* @author pquiring
*
* Created : Jan 29, 2014
*/
import java.net.*;
import java.io.*;
import javaforce.*;
public class SIPTCPTransportClient implements SIPTransport {
protected boolean connected = false;
protected Socket socket;
protected OutputStream os;
protected InputStream is;
protected InetAddress host;
protected int port;
public String getName() { return "TCP"; }
public boolean open(int localport) {
try {
socket = new Socket();
socket.setSoLinger(true, 0); //allow to reuse socket again without waiting
socket.bind(new InetSocketAddress(InetAddress.getLocalHost(), localport));
} catch (Exception e) {
JFLog.log(e);
return false;
}
return true;
}
public boolean close() {
connected = false;
try {
if (socket != null) {
socket.close();
socket = null;
}
} catch (Exception e) {
JFLog.log(e);
}
return true;
}
public boolean send(byte[] data, int off, int len, InetAddress host, int port) {
try {
if (!connected) {
connect(host, port);
}
os.write(data, off, len);
os.flush();
} catch (Exception e) {
JFLog.log(e);
return false;
}
return true;
}
private byte extra[] = null;
private int detectLength(byte data[], int off, int len) {
for(int a=0;a<len-3;a++) {
if (
(data[off+a+0] == '\r') &&
(data[off+a+1] == '\n') &&
(data[off+a+2] == '\r') &&
(data[off+a+3] == '\n')
) {
return a+4;
}
}
return -1;
}
public boolean receive(SIP.Packet packet) {
try {
if (is == null) {
packet.length = 0;
JF.sleep(100); //wait for first send()
return false;
}
if (extra != null) {
System.arraycopy(extra, 0, packet.data, 0, extra.length);
packet.length = extra.length;
extra = null;
} else {
packet.length = is.read(packet.data);
}
int plen, tlen;
do {
//detect end of packet (double \r\n)
plen = detectLength(packet.data, 0, packet.length);
if (plen == -1) {
//not enough read (frag?)
packet.length += is.read(packet.data, packet.length, packet.data.length - packet.length);
}
} while (plen == -1);
tlen = plen;
//now find Content-Length:
String msg[] = new String(packet.data, 0, plen).split("\r\n");
String clenstr = SIP.getHeader("Content-Length:", msg);
if (clenstr == null) SIP.getHeader("l:", msg);
if (clenstr != null) {
int clen = JF.atoi(clenstr);
tlen += clen;
}
while (packet.length < tlen) {
//not enough read (frag?)
packet.length += is.read(packet.data, packet.length, packet.data.length - packet.length);
}
if (packet.length > tlen) {
//extra read (from next packet)
extra = new byte[packet.length - tlen];
System.arraycopy(packet.data, tlen, extra, 0, packet.length - tlen);
packet.length = tlen;
}
//host and port never change
packet.host = host.getHostAddress();
packet.port = port;
} catch (Exception e) {
if (connected) JFLog.log(e);
return false;
}
return true;
}
protected void connect(InetAddress host, int port) throws Exception {
this.host = host;
this.port = port;
socket.connect(new InetSocketAddress(host, port), 5000);
os = socket.getOutputStream();
is = socket.getInputStream();
connected = true;
}
}