blob: 4e839905cd98372ad76bcbb1602f39f28970402f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2018 Willink Transformations 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:
* R.Dvorak and others - QVTo debugger framework
* E.D.Willink - revised API for OCL debugger framework
*******************************************************************************/
package org.eclipse.ocl.examples.debug.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.jdt.annotation.NonNull;
import org.eclipse.ocl.examples.debug.vm.core.VMDebugCore;
import org.eclipse.ocl.examples.debug.vm.event.VMEvent;
import org.eclipse.ocl.examples.debug.vm.request.VMConnectRequest;
import org.eclipse.ocl.examples.debug.vm.request.VMRequest;
import org.eclipse.ocl.examples.debug.vm.response.VMConnectResponse;
import org.eclipse.ocl.examples.debug.vm.response.VMResponse;
import org.eclipse.ocl.examples.debug.vm.utils.SocketUtil;
class VMRemoteClient {
public static final int CONNECT_ATTEMPTS = 100;
public static final int CONNECT_ATTEMPT_DELAY = 200;
protected final @NonNull VMDebugCore debugCore;
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(@NonNull VMDebugCore debugCore, String host, int requestPort, Monitor monitor) throws IOException {
this.debugCore = debugCore;
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 socketUtil = new SocketUtil(debugCore);
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;
}
}