blob: 22dea39c37137e880817633fcacfdec7e6fcec2e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 R.Dvorak and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Radek Dvorak - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.qvt.oml.debug.core.vm;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.m2m.qvt.oml.debug.core.app.SocketUtil;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMConnectRequest;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMConnectResponse;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMEvent;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMRequest;
import org.eclipse.m2m.qvt.oml.debug.core.vm.protocol.VMResponse;
class VMRemoteClient {
public static final int CONNECT_ATTEMPTS = 100;
public static final int CONNECT_ATTEMPT_DELAY = 200;
private InetSocketAddress fAddress;
private Socket fRequestSocket;
private ObjectOutputStream fRequestOut;
private ObjectInputStream fResponseIn;
private InputStream fResponseIS;
private Socket fEventSocket;
private int fEventPort;
private ObjectInputStream fEventObjInput;
VMRemoteClient(String host, int requestPort, Monitor monitor) throws IOException {
fAddress = new InetSocketAddress(host, requestPort);
fRequestSocket = connect(fAddress, CONNECT_ATTEMPTS, monitor);
fRequestOut = new ObjectOutputStream(fRequestSocket.getOutputStream());
fResponseIS = fRequestSocket.getInputStream();
VMResponse response = sendRequest(new VMConnectRequest());
if(response instanceof VMConnectResponse) {
VMConnectResponse connectResponse = (VMConnectResponse) response;
fEventPort = connectResponse.getEventPort();
} else {
// FIXME
throw new IOException("No free port for event dispatcher");
}
}
VMEvent readEvent() throws IOException {
if(fEventObjInput == null) {
assert fRequestSocket != null;
InetSocketAddress eventSocketAddress = new InetSocketAddress(fAddress.getAddress(), fEventPort);
int attemptCount = 3;
Socket eventSocket = connect(eventSocketAddress, attemptCount, null);
fEventObjInput = new ObjectInputStream(eventSocket.getInputStream());
}
try {
return (VMEvent) fEventObjInput.readObject();
} catch (ClassNotFoundException e) {
throw new IOException(e.toString());
}
}
VMResponse sendRequest(VMRequest request) throws IOException {
fRequestOut.writeObject(request);
fRequestOut.flush();
try {
if(fResponseIn == null) {
fResponseIn = new ObjectInputStream(fResponseIS);
}
Object readObject = fResponseIn.readObject();
if(readObject instanceof VMResponse == false) {
// FIXME - report invalid response
return VMResponse.createERROR();
}
return (VMResponse) readObject;
} catch (ClassNotFoundException e) {
throw new IOException(e.toString());
}
}
void close() throws IOException {
SocketUtil.close(fRequestOut);
SocketUtil.close(fResponseIn);
SocketUtil.close(fRequestSocket);
SocketUtil.close(fEventObjInput);
SocketUtil.close(fEventSocket);
}
private Socket connect(InetSocketAddress address, int attemptCount, Monitor monitor) throws IOException {
Socket socket = null;
int attempts = attemptCount;
while(attempts-- > 0) {
try {
socket = new Socket(address.getAddress(), address.getPort());
break;
} catch (IOException e) {
if (attempts == 0 || (monitor != null && monitor.isCanceled())) {
throw e;
}
}
try {
// get some sleep and try again
Thread.sleep(CONNECT_ATTEMPT_DELAY);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
assert socket != null;
return socket;
}
}