/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine 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. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.net;
import totalcross.io.Stream;
import totalcross.sys.*;
public class Socket4D extends Stream
{
Object socketRef;
public int readTimeout = DEFAULT_READ_TIMEOUT;
public int writeTimeout = DEFAULT_WRITE_TIMEOUT;
boolean dontFinalize;
private String host;
private int port;
public static final int DEFAULT_OPEN_TIMEOUT = 2000;
public static final int DEFAULT_READ_TIMEOUT = 5000;
public static final int DEFAULT_WRITE_TIMEOUT = 2000;
native void socketCreate(final String host, final int port, final int timeout,
final boolean noLinger);
native private void nativeClose() throws totalcross.io.IOException;
native private int readWriteBytes(byte buf[], int start, int count, boolean isRead)
throws totalcross.io.IOException;
protected Socket4D()
{
}
public Socket4D(String host, int port)
throws totalcross.net.UnknownHostException, totalcross.io.IOException
{
this(host, port, DEFAULT_OPEN_TIMEOUT, null);
}
public Socket4D(String host, int port, int timeout)
throws totalcross.net.UnknownHostException, totalcross.io.IOException
{
this(host, port, timeout, null);
}
public Socket4D(String host, int port, int timeout, boolean noLinger) throws totalcross.net.UnknownHostException, totalcross.io.IOException
{
this(host, port, timeout, "nolinger="+noLinger);
}
public Socket4D(String host, int port, int timeout, String params)
throws totalcross.net.UnknownHostException, totalcross.io.IOException
{
if (port < 0 || port > 65535)
throw new java.lang.IllegalArgumentException("Invalid value for argument 'port': " + port);
if (timeout < 0)
throw new java.lang.IllegalArgumentException("Invalid value for argument 'timeout': " + timeout);
boolean noLinger = params != null && params.toLowerCase().indexOf("nolinger=true") >= 0;
this.host = host;
this.port = port;
socketCreate(host, port, timeout, noLinger);
ConnectionManager4D.openConnections.put(this, this); //flsobral@tc123_20: register the newly created connection.
}
public void close() throws totalcross.io.IOException
{
if (socketRef == null)
throw new totalcross.io.IOException("The socket is already closed.");
nativeClose();
ConnectionManager4D.openConnections.remove(this); //flsobral@tc123_20: unregister the connection after closing it.
}
public int readBytes(byte buf[], int start, int count) throws totalcross.io.IOException
{
if (socketRef == null)
throw new totalcross.io.IOException("The socket is closed.");
if (buf == null)
throw new NullPointerException();
if (start < 0 || count < 0 || start + count > buf.length)
throw new IndexOutOfBoundsException();
if (count == 0)
return 0;
return readWriteBytes(buf, start, count, true);
}
public int readBytes(byte buf[]) throws totalcross.io.IOException
{
if (socketRef == null)
throw new totalcross.io.IOException("The socket is closed.");
if (buf == null)
throw new java.lang.NullPointerException();
if (buf.length == 0)
return 0;
return readWriteBytes(buf, 0, buf.length, true);
}
public int writeBytes(byte buf[], int start, int count) throws totalcross.io.IOException
{
if (socketRef == null)
throw new totalcross.io.IOException("The socket is closed.");
if (buf == null)
throw new NullPointerException();
if (start < 0 || count < 0 || start + count > buf.length)
throw new IndexOutOfBoundsException();
if (count == 0)
return 0;
return readWriteBytes(buf, start, count, false);
}
private byte[] rlbuf;
public String readLine() throws totalcross.io.IOException
{
if (socketRef == null)
throw new totalcross.io.IOException("The socket is closed.");
if (rlbuf == null) // guich@tc123_31: no longer static and initialized on first use
rlbuf = new byte[256];
byte[] buf = rlbuf;
int pos = 0;
int r;
while ((r = readBytes(buf, pos, 1)) == 1)
{
if (buf[pos] == '\n') // guich@tc123_47
{
if (pos > 0 && buf[pos-1] == '\r') // cut last \r
pos--;
// note that pos must be same of length, otherwise the String will be constructed with one less character
break;
}
if (++pos == buf.length) // reached buffer size?
{
byte[] temp = new byte[buf.length+256];
Vm.arrayCopy(buf, 0, temp, 0, pos);
rlbuf = buf = temp;
}
}
return (pos > 0 || r == 1) ? new String(buf, 0, pos) : null; // brunosoares@582_11 - charConverter is already used
}
protected void finalize()
{
try
{
close();
}
catch (totalcross.io.IOException e)
{
}
}
public String getHost()
{
return host;
}
public int getPort()
{
return port;
}
}