package call;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.List;
import call.SocketUtil.RequestType;
public abstract class AbstractClient extends AbstractId {
private final RequestType request;
protected Socket socket;
protected Contact contact;
protected List<String> headers;
public AbstractClient(String host, int port, RequestType request) throws IOException {
this.request = request;
init(host, port);
}
public AbstractClient(Contact contact, RequestType request) throws IOException {
this.request = request;
init(contact.getHost(), contact.getPort());
}
public AbstractClient(Contact contact, Socket socket, List<String> headers, RequestType request) {
this.request = request;
this.contact = contact;
this.socket = socket;
this.headers = headers;
}
private void init(String host, int port) throws IOException {
try {
connect(host, port);
} catch (UnknownHostException | SocketTimeoutException | SocketException e) {
throw e;
} catch (IOException e) {
e.printStackTrace();
throw new UnknownHostException("No open port: " + host);
}
}
private void connect(String host, int port) throws IOException {
// open socket
this.socket = openSocket(host, port);
socket.setReuseAddress(true);
socket.setTcpNoDelay(true);
// write and read headers
SocketUtil.writeHeaders(socket.getOutputStream(), request);
InputStream instream = socket.getInputStream();
this.headers = SocketUtil.readHeaders(instream);
// create contact
host = socket.getInetAddress().getCanonicalHostName();
final String user = SocketUtil.getHeaderValue(headers, "User");
this.contact = new Contact(host, port, user);
// handle request
socket.setSoTimeout(Config.SOCKET_READ_TIMEOUT);
if (!request.equals(RequestType.Status) && !request.equals(RequestType.Ping)) {
Util.log(this, "Connected (Client).");
}
}
protected Socket openSocket(String host, int port) throws IOException {
SocketAddress addr = new InetSocketAddress(host, port);
Socket socket = new Socket();
socket.connect(addr, Config.SOCKET_CONNECT_TIMEOUT);
return socket;
}
public void close() {
try {
socket.close();
} catch (IOException e) {}
}
@Override
public abstract String getId();
public Contact getContact() {
return contact;
}
public Socket getSocket() {
return socket;
}
public RequestType getRequest() {
return request;
}
public List<String> getHeaders() {
return headers;
}
}