diff --git a/core/src/main/java/hudson/cli/CLIAction.java b/core/src/main/java/hudson/cli/CLIAction.java index d42e974452..31d4700e4c 100644 --- a/core/src/main/java/hudson/cli/CLIAction.java +++ b/core/src/main/java/hudson/cli/CLIAction.java @@ -136,7 +136,7 @@ public class CLIAction implements UnprotectedRootAction, StaplerProxy { } } - private void doClose() { + private void doClose() throws IOException { close(); } diff --git a/core/src/main/java/hudson/slaves/SlaveComputer.java b/core/src/main/java/hudson/slaves/SlaveComputer.java index a2e7d91958..0f8b925535 100644 --- a/core/src/main/java/hudson/slaves/SlaveComputer.java +++ b/core/src/main/java/hudson/slaves/SlaveComputer.java @@ -921,7 +921,7 @@ public class SlaveComputer extends Computer { if (c != null) { try { c.close(); - } catch (IOException e) { + } catch (Exception e) { logger.log(Level.SEVERE, "Failed to terminate channel to " + getDisplayName(), e); } Listeners.notify(ComputerListener.class, true, l -> l.onOffline(this, offlineCause)); diff --git a/core/src/main/java/jenkins/agents/WebSocketAgents.java b/core/src/main/java/jenkins/agents/WebSocketAgents.java index 4c4451b974..f3953106da 100644 --- a/core/src/main/java/jenkins/agents/WebSocketAgents.java +++ b/core/src/main/java/jenkins/agents/WebSocketAgents.java @@ -27,6 +27,7 @@ package jenkins.agents; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.ExtensionList; +import hudson.Util; import hudson.model.Computer; import hudson.model.InvisibleAction; import hudson.model.UnprotectedRootAction; @@ -89,16 +90,24 @@ public final class WebSocketAgents extends InvisibleAction implements Unprotecte state.setRemoteEndpointDescription(req.getRemoteAddr()); state.fireBeforeProperties(); LOGGER.fine(() -> "connecting " + agent); - // TODO or just pass all request headers? Map properties = new HashMap<>(); properties.put(JnlpConnectionState.CLIENT_NAME_KEY, agent); properties.put(JnlpConnectionState.SECRET_KEY, secret); + String unsafeCookie = req.getHeader(Engine.WEBSOCKET_COOKIE_HEADER); + String cookie; + if (unsafeCookie != null) { + // This will blow up if the client sent us a malformed cookie. + cookie = Util.toHexString(Util.fromHexString(unsafeCookie)); + } else { + cookie = JnlpAgentReceiver.generateCookie(); + } + properties.put(JnlpConnectionState.COOKIE_KEY, cookie); state.fireAfterProperties(Collections.unmodifiableMap(properties)); Capability remoteCapability = Capability.fromASCII(remoteCapabilityStr); LOGGER.fine(() -> "received " + remoteCapability); rsp.setHeader(Capability.KEY, new Capability().toASCII()); rsp.setHeader(Engine.REMOTING_MINIMUM_VERSION_HEADER, RemotingVersionInfo.getMinimumSupportedVersion().toString()); - rsp.setHeader(JnlpConnectionState.COOKIE_KEY, JnlpAgentReceiver.generateCookie()); // TODO figure out what this is for, if anything + rsp.setHeader(Engine.WEBSOCKET_COOKIE_HEADER, cookie); return WebSockets.upgrade(new Session(state, agent, remoteCapability)); } diff --git a/core/src/main/java/jenkins/websocket/WebSocketEcho.java b/core/src/main/java/jenkins/websocket/WebSocketEcho.java index 6b370bba5f..b1576690ba 100644 --- a/core/src/main/java/jenkins/websocket/WebSocketEcho.java +++ b/core/src/main/java/jenkins/websocket/WebSocketEcho.java @@ -27,6 +27,7 @@ package jenkins.websocket; import hudson.Extension; import hudson.model.InvisibleAction; import hudson.model.RootAction; +import java.io.IOException; import java.nio.ByteBuffer; import jenkins.model.Jenkins; import org.kohsuke.accmod.Restricted; @@ -46,12 +47,12 @@ public class WebSocketEcho extends InvisibleAction implements RootAction { Jenkins.get().checkPermission(Jenkins.ADMINISTER); return WebSockets.upgrade(new WebSocketSession() { @Override - protected void text(String message) { + protected void text(String message) throws IOException { sendText("hello " + message); } @Override - protected void binary(byte[] payload, int offset, int len) { + protected void binary(byte[] payload, int offset, int len) throws IOException { ByteBuffer data = ByteBuffer.allocate(len); for (int i = 0; i < len; i++) { byte b = payload[offset + i]; diff --git a/core/src/main/java/jenkins/websocket/WebSocketSession.java b/core/src/main/java/jenkins/websocket/WebSocketSession.java index 4eb36ed4e1..341be5ea71 100644 --- a/core/src/main/java/jenkins/websocket/WebSocketSession.java +++ b/core/src/main/java/jenkins/websocket/WebSocketSession.java @@ -24,6 +24,7 @@ package jenkins.websocket; +import java.io.IOException; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.util.concurrent.Future; @@ -114,45 +115,45 @@ public abstract class WebSocketSession { LOGGER.log(Level.WARNING, "unhandled WebSocket service error", cause); } - protected void binary(byte[] payload, int offset, int len) { + protected void binary(byte[] payload, int offset, int len) throws IOException { LOGGER.warning("unexpected binary frame"); } - protected void text(String message) { + protected void text(String message) throws IOException { LOGGER.warning("unexpected text frame"); } @SuppressWarnings("unchecked") - protected final Future sendBinary(ByteBuffer data) { + protected final Future sendBinary(ByteBuffer data) throws IOException { try { return (Future) remoteEndpoint.getClass().getMethod("sendBytesByFuture", ByteBuffer.class).invoke(remoteEndpoint, data); } catch (Exception x) { - throw new RuntimeException(x); + throw new IOException(x); } } - protected final void sendBinary(ByteBuffer partialByte, boolean isLast) { + protected final void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException { try { remoteEndpoint.getClass().getMethod("sendPartialBytes", ByteBuffer.class, boolean.class).invoke(remoteEndpoint, partialByte, isLast); } catch (Exception x) { - throw new RuntimeException(x); + throw new IOException(x); } } @SuppressWarnings("unchecked") - protected final Future sendText(String text) { + protected final Future sendText(String text) throws IOException { try { return (Future) remoteEndpoint.getClass().getMethod("sendStringByFuture", String.class).invoke(remoteEndpoint, text); } catch (Exception x) { - throw new RuntimeException(x); + throw new IOException(x); } } - protected final void close() { + protected final void close() throws IOException { try { session.getClass().getMethod("close").invoke(session); } catch (Exception x) { - throw new RuntimeException(x); + throw new IOException(x); } } diff --git a/pom.xml b/pom.xml index 8f922fe534..3d0aac43f8 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,7 @@ THE SOFTWARE. https://www.jenkins.io/changelog - 4.14 + 3025.vf64a_a_3da_6b_55 3.14