package eu.hgross.blaubot.ethernet;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import eu.hgross.blaubot.core.AbstractBlaubotConnection;
import eu.hgross.blaubot.core.IBlaubotDevice;
import eu.hgross.blaubot.util.Log;
/**
* Connection implementation for Ethernet.
*
* TODO: introduce a super class AbstractEthernetConnection that uses an input and outputstream
*
* @author Henning Gross {@literal (mail.to@henning-gross.de)}
*
*/
public class BlaubotEthernetConnection extends AbstractBlaubotConnection {
private static final String LOG_TAG = "BlaubotEthernetConnection";
private Socket socket;
private IBlaubotDevice device;
private DataInputStream dataInputStream;
/**
* @param device the remote device abstraction
* @param clientSocket a connected socket to the remote device
*/
public BlaubotEthernetConnection(IBlaubotDevice device, Socket clientSocket) {
setUp(device, clientSocket);
}
private void setUp(IBlaubotDevice device, Socket clientSocket) {
this.socket = clientSocket;
this.device = device;
try {
this.dataInputStream = new DataInputStream(clientSocket.getInputStream());
} catch (IOException e) {
throw new RuntimeException("Could not get InputStream from clientSocket. A socket handed to the constructor has to be connected!");
}
}
private volatile boolean notifiedDisconnect = false;
@Override
protected void notifyDisconnected() {
synchronized (this) {
if (notifiedDisconnect) {
return;
}
notifiedDisconnect = true;
}
super.notifyDisconnected();
}
@Override
public void disconnect() {
if(Log.logDebugMessages()) {
//Log.d(LOG_TAG, "Disconnecting BlaubotEthernetConnection " + this + " ...");
}
try {
socket.close();
} catch (IOException e) {
Log.e(LOG_TAG, "Failed to close socket", e);
}
this.notifyDisconnected();
}
@Override
public boolean isConnected() {
return socket.isConnected() && !socket.isClosed();
}
@Override
public IBlaubotDevice getRemoteDevice() {
return device;
}
private void handleSocketException(IOException e) throws SocketTimeoutException, IOException {
if(Log.logWarningMessages()) {
Log.w(LOG_TAG, "Got socket exception", e);
}
if(!(e instanceof SocketTimeoutException)) {
this.disconnect();
}
throw e;
}
@Override
public int read() throws SocketTimeoutException, IOException {
try {
return this.socket.getInputStream().read();
} catch (IOException e) {
this.handleSocketException(e);
return -1; // will never get here
}
}
@Override
public int read(byte[] b) throws SocketTimeoutException, IOException {
try {
return this.socket.getInputStream().read(b);
} catch (IOException e) {
this.handleSocketException(e);
return -1; // will never get here
}
}
@Override
public int read(byte[] buffer, int byteOffset, int byteCount) throws SocketTimeoutException, IOException {
try {
return this.socket.getInputStream().read(buffer, byteOffset, byteCount);
} catch (IOException e) {
this.handleSocketException(e);
return -1; // will never get here
}
}
@Override
public void write(int b) throws SocketTimeoutException, IOException {
try {
this.socket.getOutputStream().write(b);
} catch (IOException e) {
this.handleSocketException(e);
}
}
@Override
public void write(byte[] bytes) throws SocketTimeoutException, IOException {
try {
this.socket.getOutputStream().write(bytes);
} catch (IOException e) {
this.handleSocketException(e);
}
}
@Override
public void write(byte[] b, int off, int len) throws SocketTimeoutException, IOException {
try {
this.socket.getOutputStream().write(b,off,len);
} catch (IOException e) {
this.handleSocketException(e);
}
}
@Override
public void readFully(byte[] buffer) throws SocketTimeoutException, IOException {
try {
dataInputStream.readFully(buffer);
} catch (IOException e) {
handleSocketException(e);
}
}
@Override
public void readFully(byte[] buffer, int offset, int byteCount) throws SocketTimeoutException, IOException {
try {
dataInputStream.readFully(buffer, offset, byteCount);
} catch (IOException e) {
handleSocketException(e);
}
}
@Override
public String toString() {
return "BlaubotEthernetConnection [socket=" + socket + ", device=" + device + "]";
}
}