├── .git-blame-ignore-revs
├── .github
├── FUNDING.yml
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ └── cd.yml
├── .gitignore
├── .mvn
├── extensions.xml
├── jvm.config
└── maven.config
├── CHANGELOG-2.x.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Jenkinsfile
├── LICENSE.md
├── NOTICE
├── README.md
├── TODO.txt
├── docs
├── class-loading.md
├── close.md
├── configuration.md
├── inbound-agent.md
├── jenkins-specifics.md
├── logging.md
├── no_proxy.md
├── protocol-stack.dot
├── protocol-stack.svg
├── protocols.md
├── remoting-kafka-architecture.png
├── tcpAgentStatus.png
├── troubleshooting.md
└── workDir.md
├── pom.xml
└── src
├── assembly
├── agent-load-test.xml
└── agent-load-test
│ ├── LICENSE.md
│ ├── NOTICE
│ ├── README.md
│ ├── agent-load-test
│ └── agent-load-test.bat
├── filter
└── resources
│ ├── hudson
│ └── remoting
│ │ └── hudson-version.properties
│ └── jenkins
│ └── remoting
│ └── jenkins-version.properties
├── main
└── java
│ ├── hudson
│ └── remoting
│ │ ├── AbstractByteArrayCommandTransport.java
│ │ ├── AbstractByteBufferCommandTransport.java
│ │ ├── AbstractSynchronousByteArrayCommandTransport.java
│ │ ├── AsyncFutureImpl.java
│ │ ├── Asynchronous.java
│ │ ├── AtmostOneThreadExecutor.java
│ │ ├── Base64.java
│ │ ├── BinarySafeStream.java
│ │ ├── Callable.java
│ │ ├── CallableDecoratorAdapter.java
│ │ ├── CallableDecoratorList.java
│ │ ├── CallableFilter.java
│ │ ├── Capability.java
│ │ ├── Channel.java
│ │ ├── ChannelBuilder.java
│ │ ├── ChannelClosedException.java
│ │ ├── ChannelProperty.java
│ │ ├── Checksum.java
│ │ ├── ChunkHeader.java
│ │ ├── ChunkedCommandTransport.java
│ │ ├── ChunkedInputStream.java
│ │ ├── ChunkedOutputStream.java
│ │ ├── ClassFilter.java
│ │ ├── ClassLoaderHolder.java
│ │ ├── ClassicCommandTransport.java
│ │ ├── Command.java
│ │ ├── CommandTransport.java
│ │ ├── DaemonThreadFactory.java
│ │ ├── DelegatingCallable.java
│ │ ├── DelegatingExecutorService.java
│ │ ├── DiagnosedStreamCorruptionException.java
│ │ ├── DumbClassLoaderBridge.java
│ │ ├── Engine.java
│ │ ├── EngineListener.java
│ │ ├── EngineListenerAdapter.java
│ │ ├── EngineListenerSplitter.java
│ │ ├── ErrorPropagatingOutputStream.java
│ │ ├── ExportTable.java
│ │ ├── FastPipedInputStream.java
│ │ ├── FastPipedOutputStream.java
│ │ ├── FileSystemJarCache.java
│ │ ├── FlightRecorderInputStream.java
│ │ ├── Future.java
│ │ ├── FutureAdapter.java
│ │ ├── GCCommand.java
│ │ ├── HexDump.java
│ │ ├── IChannel.java
│ │ ├── IReadResolve.java
│ │ ├── ImportedClassLoaderTable.java
│ │ ├── InitializeJarCacheMain.java
│ │ ├── InterceptingExecutorService.java
│ │ ├── InternalCallable.java
│ │ ├── JarCache.java
│ │ ├── JarCacheSupport.java
│ │ ├── JarLoader.java
│ │ ├── JarLoaderImpl.java
│ │ ├── JarURLValidator.java
│ │ ├── Launcher.java
│ │ ├── LocalChannel.java
│ │ ├── MimicException.java
│ │ ├── MultiClassLoaderSerializer.java
│ │ ├── NamingThreadFactory.java
│ │ ├── NoProxyEvaluator.java
│ │ ├── ObjectInputStreamEx.java
│ │ ├── PingThread.java
│ │ ├── Pipe.java
│ │ ├── PipeWindow.java
│ │ ├── PipeWriter.java
│ │ ├── PreloadJarTask.java
│ │ ├── PreloadJarTask2.java
│ │ ├── ProxyException.java
│ │ ├── ProxyInputStream.java
│ │ ├── ProxyOutputStream.java
│ │ ├── ProxyWriter.java
│ │ ├── RemoteClassLoader.java
│ │ ├── RemoteInputStream.java
│ │ ├── RemoteInvocationHandler.java
│ │ ├── RemoteOutputStream.java
│ │ ├── RemoteWriter.java
│ │ ├── RemotingSystemException.java
│ │ ├── Request.java
│ │ ├── RequestAbortedException.java
│ │ ├── RequiredRoleCheckerWrapper.java
│ │ ├── ResourceImageBoth.java
│ │ ├── ResourceImageDirect.java
│ │ ├── ResourceImageInJar.java
│ │ ├── ResourceImageRef.java
│ │ ├── Response.java
│ │ ├── SingleLaneExecutorService.java
│ │ ├── SocketChannelStream.java
│ │ ├── SocketInputStream.java
│ │ ├── SocketOutputStream.java
│ │ ├── StandardOutputStream.java
│ │ ├── SynchronousCommandTransport.java
│ │ ├── SynchronousExecutorService.java
│ │ ├── TeeOutputStream.java
│ │ ├── URLDeserializationHelper.java
│ │ ├── URLish.java
│ │ ├── UnexportCommand.java
│ │ ├── UserRequest.java
│ │ ├── Util.java
│ │ ├── VirtualChannel.java
│ │ ├── Which.java
│ │ ├── forward
│ │ ├── CopyThread.java
│ │ ├── Forwarder.java
│ │ ├── ForwarderFactory.java
│ │ ├── ListeningPort.java
│ │ ├── PortForwarder.java
│ │ └── package-info.java
│ │ ├── jnlp
│ │ ├── Main.java
│ │ └── package-info.java
│ │ └── package-info.java
│ └── org
│ └── jenkinsci
│ └── remoting
│ ├── CallableDecorator.java
│ ├── ChannelStateException.java
│ ├── DurationOptionHandler.java
│ ├── Role.java
│ ├── RoleChecker.java
│ ├── RoleSensitive.java
│ ├── SerializableOnlyOverRemoting.java
│ ├── engine
│ ├── HostPort.java
│ ├── Jnlp4ConnectionState.java
│ ├── JnlpAgentEndpoint.java
│ ├── JnlpAgentEndpointConfigurator.java
│ ├── JnlpAgentEndpointResolver.java
│ ├── JnlpClientDatabase.java
│ ├── JnlpConnectionState.java
│ ├── JnlpConnectionStateListener.java
│ ├── JnlpEndpointResolver.java
│ ├── JnlpProtocol4Handler.java
│ ├── JnlpProtocol4ProxyHandler.java
│ ├── JnlpProtocolHandler.java
│ ├── JnlpProtocolHandlerFactory.java
│ └── WorkDirManager.java
│ ├── nio
│ ├── Closeables.java
│ ├── FifoBuffer.java
│ ├── NioChannelBuilder.java
│ ├── NioChannelHub.java
│ ├── SelectableFileChannelFactory.java
│ └── SelectorThreadOnly.java
│ ├── org
│ └── apache
│ │ └── commons
│ │ ├── net
│ │ └── util
│ │ │ └── SubnetUtils.java
│ │ └── validator
│ │ └── routines
│ │ ├── InetAddressValidator.java
│ │ └── RegexValidator.java
│ ├── protocol
│ ├── ApplicationLayer.java
│ ├── FilterLayer.java
│ ├── IOHub.java
│ ├── IOHubReadyListener.java
│ ├── IOHubRegistrationCallback.java
│ ├── IOHubRegistrationFutureAdapterImpl.java
│ ├── NetworkLayer.java
│ ├── ProtocolLayer.java
│ ├── ProtocolStack.java
│ ├── cert
│ │ ├── BlindTrustX509ExtendedTrustManager.java
│ │ ├── DelegatingX509ExtendedTrustManager.java
│ │ ├── PublicKeyMatchingX509ExtendedTrustManager.java
│ │ └── ValidityCheckingX509ExtendedTrustManager.java
│ └── impl
│ │ ├── AckFilterLayer.java
│ │ ├── AgentProtocolClientFilterLayer.java
│ │ ├── BIONetworkLayer.java
│ │ ├── ChannelApplicationLayer.java
│ │ ├── ConnectionHeaders.java
│ │ ├── ConnectionHeadersFilterLayer.java
│ │ ├── ConnectionRefusalException.java
│ │ ├── NIONetworkLayer.java
│ │ ├── PermanentConnectionRefusalException.java
│ │ └── SSLEngineFilterLayer.java
│ └── util
│ ├── AnonymousClassWarnings.java
│ ├── ByteBufferPool.java
│ ├── ByteBufferQueue.java
│ ├── ByteBufferQueueInputStream.java
│ ├── ByteBufferQueueOutputStream.java
│ ├── ByteBufferUtils.java
│ ├── DirectByteBufferPool.java
│ ├── DurationFormatter.java
│ ├── DurationStyle.java
│ ├── ExecutorServiceUtils.java
│ ├── FastByteBufferQueueInputStream.java
│ ├── IOUtils.java
│ ├── KeyUtils.java
│ ├── ListenableFuture.java
│ ├── LoggingChannelListener.java
│ ├── PathUtils.java
│ ├── SettableFuture.java
│ ├── ThrowableUtils.java
│ ├── VersionNumber.java
│ └── https
│ ├── NoCheckHostnameVerifier.java
│ └── NoCheckTrustManager.java
├── spotbugs
└── excludesFilter.xml
└── test
├── java
├── JarCertDump.java
├── OISInterception.java
├── TrafficAnalyzer.java
├── hudson
│ └── remoting
│ │ ├── AbstractNioChannelRunner.java
│ │ ├── BinarySafeStreamTest.java
│ │ ├── CallableBase.java
│ │ ├── ChannelFilterTest.java
│ │ ├── ChannelRunner.java
│ │ ├── ChannelRunners.java
│ │ ├── ChannelTest.java
│ │ ├── ChecksumTest.java
│ │ ├── ChunkedInputStreamTest.java
│ │ ├── ClassFilterTest.java
│ │ ├── ClassRemoting2Test.java
│ │ ├── ClassRemotingTest.java
│ │ ├── Copier.java
│ │ ├── DeadRemoteOutputStreamTest.java
│ │ ├── DefaultClassFilterTest.java
│ │ ├── DiagnosedStreamCorruptionExceptionTest.java
│ │ ├── DualSideChannelRunner.java
│ │ ├── DummyClassLoader.java
│ │ ├── DummyClassLoaderTest.java
│ │ ├── EngineTest.java
│ │ ├── ExportTableTest.java
│ │ ├── FileSystemJarCacheTest.java
│ │ ├── FlightRecorderInputStreamTest.java
│ │ ├── ForkEBCDICRunner.java
│ │ ├── ForkRunner.java
│ │ ├── HexDumpTest.java
│ │ ├── InProcessCompatibilityRunner.java
│ │ ├── InProcessRunner.java
│ │ ├── LauncherTest.java
│ │ ├── NioPipeRunner.java
│ │ ├── NioSocketRunner.java
│ │ ├── NoProxyEvaluatorTest.java
│ │ ├── NonSerializableExceptionTest.java
│ │ ├── PipeTest.java
│ │ ├── PipeWriterTest.java
│ │ ├── PipeWriterTestChecker.java
│ │ ├── PrefetchTest.java
│ │ ├── PrefetchingTest.java
│ │ ├── ProxyExceptionTest.java
│ │ ├── ProxyWriterTest.java
│ │ ├── RegExpBenchmark.java
│ │ ├── RemoteInputStreamTest.java
│ │ ├── RemoteInvocationHandlerTest.java
│ │ ├── SimpleTest.java
│ │ ├── SingleLaneExecutorServiceTest.java
│ │ ├── TeeOutputStreamTest.java
│ │ ├── TestCallable.java
│ │ ├── TestLinkage.java
│ │ ├── TestStaticGetResources.java
│ │ ├── TestStaticResourceReference.java
│ │ ├── TrafficAnalyzer.java
│ │ ├── URLDeserializatinHelperTest.java
│ │ ├── WithRunner.java
│ │ ├── pipe
│ │ ├── RandomWorkload.java
│ │ └── Workload.java
│ │ ├── throughput
│ │ ├── DumbReceiver.java
│ │ ├── DumbSender.java
│ │ ├── Receiver.java
│ │ └── Sender.java
│ │ └── util
│ │ └── GCTask.java
└── org
│ └── jenkinsci
│ └── remoting
│ ├── engine
│ ├── HandlerLoopbackLoadStress.java
│ ├── HostPortTest.java
│ ├── JnlpAgentEndpointResolverTest.java
│ ├── JnlpProtocolHandlerTest.java
│ ├── PropertiesStringMatcher.java
│ ├── WorkDirManagerRule.java
│ └── WorkDirManagerTest.java
│ ├── nio
│ ├── FifoBufferTest.java
│ ├── FlushEveryByteStream.java
│ ├── Main.java
│ ├── SocketClientMain.java
│ └── SocketServerMain.java
│ ├── org
│ └── apache
│ │ └── commons
│ │ ├── net
│ │ └── util
│ │ │ └── SubnetUtilsTest.java
│ │ └── validator
│ │ └── routines
│ │ ├── InetAddressValidatorTest.java
│ │ └── RegexValidatorTest.java
│ ├── protocol
│ ├── IOBufferMatcher.java
│ ├── IOBufferMatcherLayer.java
│ ├── IOHubRule.java
│ ├── IOHubTest.java
│ ├── NetworkLayerFactory.java
│ ├── ProtocolStackImplTest.java
│ ├── ProtocolStackLoopbackLoadStress.java
│ ├── ProtocolStackTest.java
│ ├── Repeat.java
│ ├── RepeatRule.java
│ ├── cert
│ │ ├── BlindTrustX509ExtendedTrustManagerTest.java
│ │ ├── DHKeyPairRule.java
│ │ ├── DSAKeyPairRule.java
│ │ ├── ECKeyPairRule.java
│ │ ├── KeyPairRule.java
│ │ ├── PublicKeyMatchingX509ExtendedTrustManagerTest.java
│ │ ├── RSAKeyPairRule.java
│ │ ├── SSLContextRule.java
│ │ ├── ValidityCheckingX509ExtendedTrustManagerTest.java
│ │ └── X509CertificateRule.java
│ └── impl
│ │ ├── AckFilterLayerTest.java
│ │ ├── BatchSendBufferingFilterLayer.java
│ │ ├── ConnectionHeadersFilterLayerTest.java
│ │ ├── ConnectionHeadersTest.java
│ │ ├── HoldFilterLayer.java
│ │ ├── NetworkLayerTest.java
│ │ ├── NoOpFilterLayer.java
│ │ ├── SSLEngineFilterLayerTest.java
│ │ └── SequentialSender.java
│ └── util
│ ├── ByteBufferQueueInputStreamTest.java
│ ├── ByteBufferQueueOutputStreamTest.java
│ ├── ByteBufferQueueTest.java
│ ├── DurationFormatterTest.java
│ ├── DurationStyleTest.java
│ ├── FastByteBufferQueueInputStreamTest.java
│ ├── SettableFutureTest.java
│ └── VersionNumberTest.java
└── resources
└── hudson
└── remoting
├── embedded_doctype.jnlp
├── lol.jnlp
├── note.dtd
├── test.jnlp
├── xxe_file.jnlp
└── xxe_http.jnlp
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # .git-blame-ignore-revs
2 | # Format repository with Spotless (#751)
3 | 3ea58fc6d3356698eb8b14210135149b8f1e6018
4 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | community_bridge: jenkins
2 | custom: ["https://jenkins.io/donate/#why-donate"]
3 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: maven
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
8 | - package-ecosystem: github-actions
9 | directory: /
10 | schedule:
11 | interval: weekly
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | _extends: .github
2 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yml:
--------------------------------------------------------------------------------
1 | # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins
2 |
3 | name: cd
4 | on:
5 | workflow_dispatch:
6 | check_run:
7 | types:
8 | - completed
9 |
10 | jobs:
11 | maven-cd:
12 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
13 | secrets:
14 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
15 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | *.ipr
3 | *.iws
4 | .idea
5 | target
6 | /.classpath
7 | /.project
8 | /.settings
9 | .fbExcludeFilterFile
10 |
--------------------------------------------------------------------------------
/.mvn/extensions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | io.jenkins.tools.incrementals
4 | git-changelist-maven-extension
5 | 1.8
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.mvn/jvm.config:
--------------------------------------------------------------------------------
1 | -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:+TieredCompilation -XX:TieredStopAtLevel=1
--------------------------------------------------------------------------------
/.mvn/maven.config:
--------------------------------------------------------------------------------
1 | -Pconsume-incrementals
2 | -Pmight-produce-incrementals
3 | -Dchangelist.format=%d.v%s
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing
2 | =====
3 |
4 | Remoting library follows the common contribution rules/recommendations in the Jenkins project.
5 | These recommendations are available [here](https://wiki.jenkins-ci.org/display/JENKINS/Beginners+Guide+to+Contributing).
6 |
7 | ### Proposing changes
8 |
9 | * Create pull requests (PRs) against the master branch.
10 | * Bug fixes or performance improvements may be a subject for backporting to Remoting 2.x.
11 | If you need it, please mention it in the pull request or JIRA ticket.
12 |
13 | ### Q&A
14 |
15 | Use the [Jenkins developer mailing list](https://groups.google.com/g/jenkinsci-dev) to sync-up with remoting developers.
16 | In the case of the mailing list, it's a good practice to CC maintainers directly.
17 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | /*
2 | * While this is not a plugin, it is much simpler to reuse the pipeline code for CI. This allows for
3 | * easy Linux/Windows testing and produces incrementals. The only feature that relates to plugins is
4 | * allowing one to test against multiple Jenkins versions.
5 | */
6 | buildPlugin(timeout: 20, useContainerAgent: true, configurations: [
7 | [platform: 'linux', jdk: 21],
8 | [platform: 'windows', jdk: 17],
9 | ])
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License
2 | ===============
3 |
4 | Copyright (c) 2004-2016, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer, Stephen Connolly, and others
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Jenkins Remoting
2 | Copyright (c) 2004-2016, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer, Stephen Connolly, and others
3 |
4 | This product includes software developed at
5 | The Apache Software Foundation (http://www.apache.org/).
6 |
--------------------------------------------------------------------------------
/TODO.txt:
--------------------------------------------------------------------------------
1 | - client needs to send a break between commands
2 | -> ... which means the remoting core needs to be chunking aware, and therefore
3 | AbstractByteArrayCommandTransport can just use one ObjectOutputStream per command
4 |
5 | - server doesn't echo back CloseCommand correctly because it's using single SelectableChannel
6 | and ChannelPair.closeRead() closes the writer before stuff gets sent.
7 | Half close needs to be handled properly
8 |
9 | Phase 2:
10 | Socket connecting NioChannelHub to thread-driven Channel inside the same process
11 |
12 | Phase 3:
13 | process-based channel client connected to NioChannelHub
14 |
15 | Phase 3:
16 | client-side NioChannelHub
17 |
18 | TODOs:
19 | - multi-threaded acceptors?
20 | =======
21 | Prefetch branch TODO before merge
22 |
23 | - constant pool analyzer must be shaded & rebundled
24 | - some classes should be traversed more deeply
25 | - base class and interfaces (this might be easy enough)
26 | - types used in static fields
27 |
28 | - ClassLoader oracles
29 | - for creating a smarter remote classloader clone
30 | built on top of ClassLoader -> IClassLoader translation service
31 | & jar transfer service
32 |
33 | - if jar is still loading, fall back to fetch2
34 |
--------------------------------------------------------------------------------
/docs/close.md:
--------------------------------------------------------------------------------
1 | # Shutdown sequence of a Channel
2 | A `Channel` builds on top of two uni-directional stream of bytes that can be independently closed, like a TCP socket.
3 |
4 | ## Orderly shutdown
5 | The orderly shutdown of a channel goes through a sequence somewhat like
6 | [a termination of a TCP socket](http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination).
7 |
8 | The shutdown sequence starts by the `Channel.close()` call, which sends out a `CloseCommand` (equivalent of TCP FIN.)
9 | The receiver marks that, sends out its own `CloseCommand` in response. The initiator receives and executes this,
10 | successfully closing down both directions of the streams.
11 |
12 | A `CloseCommand` is always the last command on a stream. This sender uses `outClosed` field to track if it has
13 | already sent out the `CloseCommand`. When it sends out the command, the field is set to non-null. Likewise,
14 | the receiver uses `inClosed` field to track whether it has received a `CloseCommand`.
15 |
16 |
17 | ## Unorderly shutdown
18 | A termination can be also initiated by the reader side noticing that the sender no longer exists.
19 | This depends on the ability of the underlying transport to detect that, which can take long time
20 | to detect this situation (for example, it is possible to kill one end of a TCP socket in such
21 | a way that the other side will block forever.)
22 |
23 | Anyway, when the reader end determines that the sender is gone (such as EOF of a socket), it immediately
24 | gets to the `Channel.terminate()` method, which declares both directions of the streams dead, and
25 | generally behaves as if it has received a `CloseCommand`, except that it doesn't send one out since
26 | the transport is assumed to be dead.
27 |
28 | (TODO: now that I'm writing about it, I feel like it should try to send out `CloseCommand`, because
29 | one side noticing that the connection is bad doesn't mean the other side notices it right away.)
--------------------------------------------------------------------------------
/docs/jenkins-specifics.md:
--------------------------------------------------------------------------------
1 | Jenkins specifics
2 | =====
3 |
4 | This page contains information about use-cases specific to Jenkins.
5 |
6 | NOTE: The page is under construction
--------------------------------------------------------------------------------
/docs/no_proxy.md:
--------------------------------------------------------------------------------
1 | # NO_PROXY Environment Variable
2 |
3 | This optional setting provides a way to specify one or more hosts where the connection should not be proxied.
4 | Similar settings are available in many applications. Unfortunately, there is no standard specification across the different implementations.
5 | Each one defines its own syntax and supported capabilities.
6 |
7 | Remoting provides an implementation that is similar to a number of other applications and systems. Its simple rules provide
8 | sufficient power and flexibility for many needs.
9 |
10 | Rules:
11 | 1. Environment variable may be named `NO_PROXY` or `no_proxy`.
12 | 1. Different specification pieces may be separated by a comma (`,`) or a pipe (`|`).
13 | 1. Each piece may specify an IP address, a network, or a host / domain.
14 | 1. An IP address may be IPv4 or IPv6.
15 | 1. An IPv6 address may be expressed in full or compressed form.
16 | 1. A network is expressed in CIDR notation, for example, `192.168.17.0/24`.
17 | 1. Localhost and loopback addresses are not proxied by default.
18 | 1. All subdomains matching a domain or host are not proxied.
19 | 1. A `NO_PROXY` setting of `jenkins.io` matches `repo.jenkins.io`, `sub.sub.jenkins.io`, and `jenkins.io`. It also matches `myjenkins.io`.
20 | 1. The following forms are identical: `jenkins.io`, `.jenkins.io`, and `*.jenkins.io`.
21 | 1. All other notations are ignored.
22 |
23 | ## History
24 |
25 | The exact implementation has changed in different remoting versions. The 3.28 release of Remoting clarified and expanded a
26 | number of these capabilities. All specifications that worked prior to 3.28 should still work. Enhancements added at 3.28
27 | include environment variable capitalization, pipe separation, compressed
28 | IPv6 form, networks, and simple hostnames or root domains. The [Changelog](../CHANGELOG.md) provides information on some of the prior changes.
29 |
--------------------------------------------------------------------------------
/docs/protocol-stack.dot:
--------------------------------------------------------------------------------
1 | digraph g {
2 | rankdir=LR;
3 | node [shape=record];
4 | null1 [label="null"];
5 | network [label=" nextRecv| BIONetworkLayer| nextSend"];
6 | filter1 [label=" nextRecv| AgentProtocolClientFilterLayer| nextSend"];
7 | filter2 [label=" nextRecv| AckFilterLayer| nextSend"];
8 | filter3 [label=" nextRecv| SSLEngineFilterLayer| nextSend"];
9 | filter4 [label=" nextRecv| ConnectionHeadersFilterLayer| nextSend"];
10 | application [label=" nextRecv| ChannelApplicationLayer| nextSend"];
11 | null2 [label="null"];
12 | network:f2 -> null1;
13 | network:f0 -> filter1:f1;
14 | filter1:f0 -> filter2:f1;
15 | filter1:f2 -> network:f1;
16 | filter2:f0 -> filter3:f1;
17 | filter2:f2 -> filter1:f1;
18 | filter3:f0 -> filter4:f1;
19 | filter3:f2 -> filter2:f1;
20 | filter4:f0 -> application:f1;
21 | filter4:f2 -> filter3:f1;
22 | application:f0 -> null2;
23 | application:f2 -> filter4:f1;
24 | }
25 |
--------------------------------------------------------------------------------
/docs/protocols.md:
--------------------------------------------------------------------------------
1 | Remoting protocols
2 | ====
3 |
4 | The Remoting library provides APIs which allow custom communication protocols to be implemented.
5 |
6 | This section describes only the protocols available within the remoting library.
7 |
8 | ## Active protocols
9 |
10 | This section lists all actively maintained protocols offered in Remoting.
11 | There may be other actively maintained protocols in other Jenkins and 3rd-party components.
12 |
13 | ### JNLP4-connect
14 |
15 | * Introduced in: Remoting 3.0, [JENKINS-36871](https://issues.jenkins-ci.org/browse/JENKINS-36871)
16 |
17 | This protocol uses the SSLEngine provided by the Java Cryptography Architecture
18 | to perform a TLS upgrade of the plaintext connection before any connection secrets are exchanged.
19 | The subsequent connection is then secured using TLS.
20 |
21 | The encryption algorithms and cyphers used by the SSLEngine when using Oracle JDK 1.8
22 | are described in [Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8](http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html))
23 | If stronger algorithms are needed (for example, AES with 256-bit keys), the [JCE Unlimited Strength Jurisdiction Policy Files](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
24 | can be obtained on Oracle website and installed in the JDK/JRE.
25 |
26 |
27 | Protocol uses non-blocking I/O wherever possible which removes the performance bottleneck of the JNLP3-connect protocol.
28 |
29 | The protocol stack starts with the network layer, proceeds to an arbitrary number of filter layers, and ends with the application layer.
30 | It is represented as a doubly-linked list:
31 |
32 | 
33 |
34 | ### WebSocket
35 |
36 | * Introduced in: Remoting version 4.0, [JEP-222](https://jenkins.io/jep/222)
37 | * At initial release, this protocol is considered a beta release and has not yet undergone extensive testing.
38 |
39 | Uses WebSocket over an HTTP(S) port to handle handshakes, encryption, framing, etc.
40 |
41 | ## Plugin protocols
42 |
43 | ### Remoting Kafka Plugin
44 |
45 | * [Remoting Kafka Plugin](https://github.com/jenkinsci/remoting-kafka-plugin) uses Kafka as fault-tolerant communication layer to support command invocation between Jenkins controller and agent.
46 | * The plugin gets rid of current direct TCP connection between controller and agent.
47 | * More info can be found in the technical [documentation](https://github.com/jenkinsci/remoting-kafka-plugin/blob/master/docs/DOCUMENTATION.md) of the plugin.
48 |
--------------------------------------------------------------------------------
/docs/remoting-kafka-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/remoting/1d80543ebaf27c64e3641d6a67993a13ca9cd7f6/docs/remoting-kafka-architecture.png
--------------------------------------------------------------------------------
/docs/tcpAgentStatus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenkinsci/remoting/1d80543ebaf27c64e3641d6a67993a13ca9cd7f6/docs/tcpAgentStatus.png
--------------------------------------------------------------------------------
/docs/troubleshooting.md:
--------------------------------------------------------------------------------
1 | Troubleshooting Remoting issues
2 | ====
3 |
4 | This page provides information about common remoting issues and the ways allowing to triangulate and solve them.
5 | In particular cases the page provides references to external resources.
6 |
7 | NOTE: The page is under construction
--------------------------------------------------------------------------------
/docs/workDir.md:
--------------------------------------------------------------------------------
1 | Remoting Work directory
2 | ===
3 |
4 | In Remoting work directory is an internal data storage, which may be used by Remoting to store caches, logs and other metadata.
5 |
6 | Remoting work directory is available starting from Remoting `3.8`, which is available in [Jenkins 2.68](https://jenkins.io/changelog/#v2.68)).
7 | Before this version there was no working directory concept in the library itself;
8 | all operations were managed by library users (e.g. Jenkins agent workspaces).
9 |
10 | ### Before Remoting 3.8 (Jenkins 2.68)
11 |
12 | * There is no work directory management in Remoting itself
13 | * Logs are not being persisted to the disk unless `-agentLog` option is specified
14 | * JAR Cache is being stored in `${user.home}/.jenkins` unless `-jarCache` option is specified
15 |
16 | ### After Remoting 3.8 (Jenkins 2.68)
17 |
18 | Due to compatibility reasons, Remoting retains the legacy behavior by default.
19 | Work directory can be enabled using the `-workDir` option in CLI.
20 |
21 | Once the option is enabled, Remoting starts using the following structure:
22 |
23 | ```
24 | ${WORKDIR}
25 | |_ ${INTERNAL_DIR} - defined by '-internalDir', 'remoting' by default
26 | |_ jarCache - JAR Cache
27 | |_ logs - Remoting logs
28 | |_ ... - Other directories contributed by library users
29 | ```
30 |
31 | Structure of the `logs` directory depends on the logging settings.
32 | See [this page](logging.md) for more information.
33 |
34 | ### Migrating to work directories in Jenkins
35 |
36 | :exclamation: Remoting does not perform migration from the previous structure,
37 | because it cannot identify potential external users of the data.
38 |
39 | Once the `-workDir` flag is enabled in Remoting, admins are expected to do the following:
40 |
41 | 1. Remove the `${user.home}/.jenkins` directory if there is no other Remoting instances running under the same user.
42 | 2. Consider upgrading configurations of agents in order to enable Work Directories
43 | * SSH agents can be configured in agent settings.
44 | * JNLP agents should be started with the `-workDir` parameter.
45 | * See [JENKINS-44108](https://issues.jenkins-ci.org/browse/JENKINS-44108) for more information about changes in Jenkins plugins, which enable work directories by default.
46 |
--------------------------------------------------------------------------------
/src/assembly/agent-load-test.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 | agent-load-test
6 |
7 | tar.gz
8 | zip
9 |
10 | false
11 |
12 |
13 | /repo
14 | true
15 | true
16 | test
17 |
18 |
19 |
20 |
21 | ${project.basedir}/src/assembly/agent-load-test
22 | bin
23 |
24 | agent-load-test
25 |
26 | 0755
27 | true
28 |
29 |
30 | ${project.basedir}/src/assembly/agent-load-test
31 | bin
32 |
33 | agent-load-test.bat
34 |
35 | true
36 |
37 |
38 | ${project.basedir}/src/assembly/agent-load-test
39 | ./
40 |
41 | agent-load-test*
42 |
43 | true
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/assembly/agent-load-test/NOTICE:
--------------------------------------------------------------------------------
1 | Jenkins Remoting
2 | Copyright (c) 2004-2016, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer, Stephen Connolly, and others
3 |
4 | This product includes software developed at
5 | The Apache Software Foundation (http://www.apache.org/).
6 |
7 | Apache Ant
8 | Copyright 1999-2012 The Apache Software Foundation
9 |
10 | The task is based on code Copyright (c) 2002, Landmark
11 | Graphics Corp that has been kindly donated to the Apache Software
12 | Foundation.
13 |
14 | Apache Commons IO
15 | Copyright 2002-2012 The Apache Software Foundation
16 |
17 | Objenesis
18 | Copyright 2006-2013 Joe Walnes, Henri Tremblay, Leonardo Mesquita
19 |
20 | Mockito license - MIT.
21 |
22 | Cglib - Apache License 2.0
23 | ASM - BSD license
24 |
25 | Mockito all distribution:
26 |
27 | Objenesis - MIT license
28 | Hamcrest - BSD license
29 |
--------------------------------------------------------------------------------
/src/assembly/agent-load-test/README.md:
--------------------------------------------------------------------------------
1 | Jenkins Remoting Agent Load Tester
2 | ==================================
3 |
4 | This is a test utility to determine the capacity limits of your Jenkins controller.
5 | Using this utility, you can fire up a remoting server that accepts a number of
6 | loopback connections in order to see what load the JNLP remoting protocols
7 | produce on your server.
8 |
9 | To get a comparable set of measures you can run the following commands:
10 |
11 | * Unix systems
12 |
13 | bin/agent-load-test --protocol JNLP2-connect --warmup 60 --collect 60 --stats stats.csv
14 | bin/agent-load-test --protocol JNLP2-connect --warmup 60 --collect 60 --stats stats.csv --bio
15 | bin/agent-load-test --protocol JNLP3-connect --warmup 60 --collect 60 --stats stats.csv --bio
16 | bin/agent-load-test --protocol JNLP4-connect --warmup 60 --collect 60 --stats stats.csv
17 | bin/agent-load-test --protocol JNLP4-connect --warmup 60 --collect 60 --stats stats.csv --bio
18 | bin/agent-load-test --protocol JNLP4-plaintext --warmup 60 --collect 60 --stats stats.csv
19 | bin/agent-load-test --protocol JNLP4-plaintext --warmup 60 --collect 60 --stats stats.csv --bio
20 |
21 | * Windows systems
22 |
23 | bin\agent-load-test --protocol JNLP2-connect --warmup 60 --collect 60 --stats stats.csv
24 | bin\agent-load-test --protocol JNLP2-connect --warmup 60 --collect 60 --stats stats.csv --bio
25 | bin\agent-load-test --protocol JNLP3-connect --warmup 60 --collect 60 --stats stats.csv --bio
26 | bin\agent-load-test --protocol JNLP4-connect --warmup 60 --collect 60 --stats stats.csv
27 | bin\agent-load-test --protocol JNLP4-connect --warmup 60 --collect 60 --stats stats.csv --bio
28 | bin\agent-load-test --protocol JNLP4-plaintext --warmup 60 --collect 60 --stats stats.csv
29 | bin\agent-load-test --protocol JNLP4-plaintext --warmup 60 --collect 60 --stats stats.csv --bio
30 |
--------------------------------------------------------------------------------
/src/filter/resources/hudson/remoting/hudson-version.properties:
--------------------------------------------------------------------------------
1 | version=${build.version}
--------------------------------------------------------------------------------
/src/filter/resources/jenkins/remoting/jenkins-version.properties:
--------------------------------------------------------------------------------
1 | version=${build.version}
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/AbstractSynchronousByteArrayCommandTransport.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.ObjectOutputStream;
6 | import org.jenkinsci.remoting.util.AnonymousClassWarnings;
7 |
8 | /**
9 | * {@link SynchronousCommandTransport} that works with {@code byte[]} instead of command object.
10 | *
11 | * This base class hides away some of the {@link Command} serialization details. One less thing
12 | * for transport implementers to worry about.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | * @since 2.13
16 | */
17 | public abstract class AbstractSynchronousByteArrayCommandTransport extends SynchronousCommandTransport {
18 | /**
19 | * Read a byte[] from the underlying transport for the given channel.
20 | */
21 | public abstract byte[] readBlock(Channel channel) throws IOException, ClassNotFoundException;
22 |
23 | /**
24 | * Writes a byte[] to the transport.
25 | *
26 | * The block boundary is significant. A transport needs to ensure that that the same byte[] is
27 | * read by the peer through {@link #readBlock(Channel)} (unlike TCP, where a single write can
28 | * be split into multiple read()s on the other side.)
29 | */
30 | public abstract void writeBlock(Channel channel, byte[] payload) throws IOException;
31 |
32 | @Override
33 | public Command read() throws IOException, ClassNotFoundException {
34 | byte[] block = readBlock(channel);
35 | return Command.readFrom(channel, block);
36 | }
37 |
38 | @Override
39 | public void write(Command cmd, boolean last) throws IOException {
40 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
41 | try (ObjectOutputStream oos = AnonymousClassWarnings.checkingObjectOutputStream(baos)) {
42 | cmd.writeTo(channel, oos);
43 | }
44 | byte[] block = baos.toByteArray();
45 | channel.notifyWrite(cmd, block.length);
46 | writeBlock(channel, block);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/Asynchronous.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * Used on a method in a remotable exported interface to designate
11 | * that the call is made asynchronously. The call will be issued,
12 | * but the caller will return without waiting for the return value
13 | * to come back from the other side.
14 | *
15 | * The signature of the method must return void.
16 | *
17 | *
18 | * interface Foo {
19 | * void bar();
20 | * @Asynchronous
21 | * void zot();
22 | * }
23 | *
24 | * Foo foo = getSomeRemoteReferenceToFoo();
25 | * // this invocation calls a remote method, wait for that to complete,
26 | * // then return.
27 | * foo.bar();
28 | * // this invocation returns immediately after the request to execute a remote method
29 | * // is sent to the other side. There's no ordering guarantee as to when
30 | * // this method actually gets executed. For example, if you invoke two async
31 | * // calls, they may execute in the reverse order.
32 | * foo.zot();
33 | *
27 | */
28 | V call(java.util.concurrent.Callable callable) throws Exception;
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ChannelClosedException.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.CheckForNull;
4 | import edu.umd.cs.findbugs.annotations.NonNull;
5 | import org.jenkinsci.remoting.ChannelStateException;
6 |
7 | /**
8 | * Indicates that the channel is already closed or being closed.
9 | *
10 | * @author Kohsuke Kawaguchi
11 | */
12 | public class ChannelClosedException extends ChannelStateException {
13 | /**
14 | * @deprecated
15 | * Use {@link #ChannelClosedException(Throwable)} or {@link #ChannelClosedException(String, Throwable)}.
16 | * This constructor will not include cause of the termination.
17 | */
18 | @Deprecated
19 | public ChannelClosedException() {
20 | this(null, "channel is already closed", null);
21 | }
22 |
23 | /**
24 | * @deprecated Use {@link #ChannelClosedException(Channel, Throwable)}
25 | */
26 | @Deprecated
27 | public ChannelClosedException(Throwable cause) {
28 | this((Channel) null, cause);
29 | }
30 |
31 | /**
32 | * Constructor.
33 | * @param channel Reference to the channel. {@code null} if the channel is unknown.
34 | * @param cause Cause
35 | * @since 3.15
36 | */
37 | public ChannelClosedException(@CheckForNull Channel channel, @CheckForNull Throwable cause) {
38 | super(channel, "channel is already closed", cause);
39 | }
40 |
41 | /**
42 | * Constructor.
43 | *
44 | * @param message Message
45 | * @param cause Cause of the channel close/termination.
46 | * May be {@code null} if it cannot be determined when the exception is constructed.
47 | * @since 3.11
48 | * @deprecated Use {@link #ChannelClosedException(Channel, String, Throwable)}
49 | */
50 | @Deprecated
51 | public ChannelClosedException(@NonNull String message, @CheckForNull Throwable cause) {
52 | this(null, message, cause);
53 | }
54 |
55 | /**
56 | * Constructor.
57 | *
58 | * @param channel Reference to the channel. {@code null} if the channel is unknown.
59 | * @param message Message
60 | * @param cause Cause of the channel close/termination.
61 | * May be {@code null} if it cannot be determined when the exception is constructed.
62 | * @since 3.15
63 | */
64 | public ChannelClosedException(
65 | @CheckForNull Channel channel, @NonNull String message, @CheckForNull Throwable cause) {
66 | super(channel, message, cause);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ChannelProperty.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2010, InfraDNA, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package hudson.remoting;
26 |
27 | import java.io.Serializable;
28 |
29 | /**
30 | * A convenient key type for {@link Channel#getProperty(Object)} and {@link Channel#setProperty(Object, Object)}
31 | *
32 | * @author Kohsuke Kawaguchi
33 | */
34 | public class ChannelProperty implements Serializable {
35 | public final Class type;
36 | public final String displayName;
37 |
38 | public ChannelProperty(Class type, String displayName) {
39 | this.type = type;
40 | this.displayName = displayName;
41 | }
42 |
43 | private static final long serialVersionUID = 1L;
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ChunkHeader.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.nio.ByteBuffer;
4 | import org.jenkinsci.remoting.util.ByteBufferQueue;
5 |
6 | /**
7 | * Parsing of the chunk header.
8 | *
9 | *
10 | * The header is {@link #SIZE} bytes, in the network order. The first bit designates whether this chunk
11 | * is the last chunk (0 if this is the last chunk), and the remaining 15 bits designate the
12 | * length of the chunk as unsigned number.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | */
16 | public class ChunkHeader {
17 |
18 | public static final int SIZE = 2;
19 |
20 | public static int read(ByteBuffer buf) {
21 | return parse(buf.get(), buf.get());
22 | }
23 |
24 | public static int peek(ByteBuffer buf) {
25 | return peek(buf, 0);
26 | }
27 |
28 | public static int peek(ByteBuffer buf, int pos) {
29 | return parse(buf.get(pos), buf.get(pos + 1));
30 | }
31 |
32 | public static int parse(byte[] buf) {
33 | return parse(buf, 0);
34 | }
35 |
36 | public static int parse(byte[] buf, int pos) {
37 | return parse(buf[pos], buf[pos + 1]);
38 | }
39 |
40 | public static int parse(int b1, int b2) {
41 | return ((b1 & 0xFF) << 8) | (b2 & 0xFF);
42 | }
43 |
44 | public static boolean isLast(int header) {
45 | return (header & 0x8000) == 0;
46 | }
47 |
48 | public static int length(int header) {
49 | return header & 0x7FFF;
50 | }
51 |
52 | public static void write(ByteBuffer buf, int length, boolean hasMore) {
53 | buf.put((byte) ((hasMore ? 0x80 : 0) | (length >> 8)));
54 | buf.put((byte) length);
55 | }
56 |
57 | public static void write(ByteBufferQueue buf, int length, boolean hasMore) {
58 | buf.put((byte) ((hasMore ? 0x80 : 0) | (length >> 8)));
59 | buf.put((byte) length);
60 | }
61 |
62 | public static byte[] pack(int length, boolean hasMore) {
63 | byte[] header = new byte[SIZE];
64 | header[0] = (byte) ((hasMore ? 0x80 : 0) | (length >> 8));
65 | header[1] = (byte) (length);
66 | return header;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ChunkedCommandTransport.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.OutputStream;
7 |
8 | /**
9 | * A variation of {@link ClassicCommandTransport} that uses the chunked encoding.
10 | *
11 | * @author Kohsuke Kawaguchi
12 | */
13 | class ChunkedCommandTransport extends AbstractSynchronousByteArrayCommandTransport {
14 | private final Capability remoteCapability;
15 |
16 | private final ChunkedInputStream in;
17 | private final ChunkedOutputStream out;
18 |
19 | /**
20 | * See {@link CommandTransport#getUnderlyingStream()}
21 | */
22 | private final OutputStream rawOut;
23 |
24 | /*package*/ ChunkedCommandTransport(
25 | Capability remoteCapability, InputStream in, OutputStream out, OutputStream rawOut) {
26 | this.remoteCapability = remoteCapability;
27 | this.in = new ChunkedInputStream(in);
28 | this.out = new ChunkedOutputStream(8192, out);
29 | this.rawOut = rawOut;
30 | }
31 |
32 | @Override
33 | public Capability getRemoteCapability() throws IOException {
34 | return remoteCapability;
35 | }
36 |
37 | @Override
38 | public byte[] readBlock(Channel channel) throws IOException, ClassNotFoundException {
39 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
40 | in.readUntilBreak(baos);
41 | return baos.toByteArray();
42 | }
43 |
44 | @Override
45 | public void writeBlock(Channel channel, byte[] payload) throws IOException {
46 | out.write(payload);
47 | out.sendBreak();
48 | }
49 |
50 | @Override
51 | public void closeWrite() throws IOException {
52 | out.close();
53 | }
54 |
55 | @Override
56 | public void closeRead() throws IOException {
57 | in.close();
58 | }
59 |
60 | @Override
61 | OutputStream getUnderlyingStream() {
62 | return rawOut;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ClassLoaderHolder.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.CheckForNull;
4 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
5 | import java.io.IOException;
6 | import java.io.ObjectInputStream;
7 | import java.io.ObjectOutputStream;
8 | import org.jenkinsci.remoting.SerializableOnlyOverRemoting;
9 |
10 | /**
11 | * Remoting-aware holder of {@link ClassLoader} that replaces ClassLoader by its {@link RemoteClassLoader}.
12 | *
13 | * @author Kohsuke Kawaguchi
14 | * @since 2.12
15 | */
16 | public class ClassLoaderHolder implements SerializableOnlyOverRemoting {
17 |
18 | @CheckForNull
19 | private transient ClassLoader classLoader;
20 |
21 | public ClassLoaderHolder(@CheckForNull ClassLoader classLoader) {
22 | this.classLoader = classLoader;
23 | }
24 |
25 | public ClassLoaderHolder() {}
26 |
27 | @CheckForNull
28 | public ClassLoader get() {
29 | return classLoader;
30 | }
31 |
32 | public void set(@CheckForNull ClassLoader classLoader) {
33 | this.classLoader = classLoader;
34 | }
35 |
36 | @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT", justification = "TODO needs triage")
37 | private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
38 | RemoteClassLoader.IClassLoader proxy = (RemoteClassLoader.IClassLoader) ois.readObject();
39 | classLoader = proxy == null
40 | ? null
41 | : getChannelForSerialization().importedClassLoaders.get(proxy);
42 | }
43 |
44 | @SuppressFBWarnings(
45 | value = "DMI_NONSERIALIZABLE_OBJECT_WRITTEN",
46 | justification = "RemoteClassLoader.export() produces a serializable wrapper class")
47 | private void writeObject(ObjectOutputStream oos) throws IOException {
48 | if (classLoader == null) {
49 | oos.writeObject(null);
50 | } else {
51 | RemoteClassLoader.IClassLoader proxy = RemoteClassLoader.export(classLoader, getChannelForSerialization());
52 | oos.writeObject(proxy);
53 | }
54 | }
55 |
56 | private static final long serialVersionUID = 1L;
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/DaemonThreadFactory.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import java.util.concurrent.ThreadFactory;
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 |
8 | /**
9 | * @author Kohsuke Kawaguchi
10 | */
11 | public class DaemonThreadFactory implements ThreadFactory {
12 | private static final Logger LOGGER = Logger.getLogger(DaemonThreadFactory.class.getName());
13 |
14 | @Override
15 | public Thread newThread(@NonNull Runnable r) {
16 | Thread thread = new Thread(r);
17 | thread.setDaemon(true);
18 | thread.setUncaughtExceptionHandler(
19 | (t, e) -> LOGGER.log(Level.SEVERE, e, () -> "Unhandled exception in thread " + t));
20 | return thread;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/DiagnosedStreamCorruptionException.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
5 | import java.io.PrintWriter;
6 | import java.io.StreamCorruptedException;
7 | import java.io.StringWriter;
8 |
9 | /**
10 | * Signals a {@link StreamCorruptedException} with some additional diagnostic information.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | */
14 | public class DiagnosedStreamCorruptionException extends StreamCorruptedException {
15 | private final Exception diagnoseFailure;
16 |
17 | @NonNull
18 | private final byte[] readBack;
19 |
20 | @NonNull
21 | private final byte[] readAhead;
22 |
23 | DiagnosedStreamCorruptionException(
24 | Exception cause, Exception diagnoseFailure, @NonNull byte[] readBack, @NonNull byte[] readAhead) {
25 | initCause(cause);
26 | this.diagnoseFailure = diagnoseFailure;
27 | this.readBack = readBack;
28 | this.readAhead = readAhead;
29 | }
30 |
31 | public Exception getDiagnoseFailure() {
32 | return diagnoseFailure;
33 | }
34 |
35 | @NonNull
36 | public byte[] getReadBack() {
37 | return readBack.clone();
38 | }
39 |
40 | @NonNull
41 | public byte[] getReadAhead() {
42 | return readAhead.clone();
43 | }
44 |
45 | @Override
46 | @SuppressFBWarnings(
47 | value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE",
48 | justification = "Used for diagnosing stream corruption between agent and server.")
49 | public String toString() {
50 | StringBuilder buf = new StringBuilder();
51 | buf.append(super.toString()).append("\n");
52 | buf.append("Read back: ").append(HexDump.toHex(readBack)).append('\n');
53 | buf.append("Read ahead: ").append(HexDump.toHex(readAhead));
54 | if (diagnoseFailure != null) {
55 | StringWriter w = new StringWriter();
56 | PrintWriter p = new PrintWriter(w);
57 | diagnoseFailure.printStackTrace(p);
58 | p.flush();
59 |
60 | buf.append("\nDiagnosis problem:\n ");
61 | buf.append(w.toString().trim().replace("\n", "\n "));
62 | }
63 | return buf.toString();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/EngineListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import javax.swing.SwingUtilities;
27 |
28 | /**
29 | * Receives status notification from {@link Engine}.
30 | *
31 | *
32 | * The callback will be invoked on a non-GUI thread, so if the implementation
33 | * wants to touch Swing, {@link SwingUtilities#invokeLater(Runnable)} would be needed.
34 | *
35 | *
36 | * To implement this interface outside this module, extend from {@link EngineListenerAdapter}
37 | * instead to protect against method additions in the future.
38 | *
39 | * @author Kohsuke Kawaguchi
40 | */
41 | public interface EngineListener {
42 | /**
43 | * Status message that indicates the progress of the operation.
44 | */
45 | void status(String msg);
46 |
47 | /**
48 | * Status message, with additional stack trace that indicates an error that was recovered.
49 | */
50 | void status(String msg, Throwable t);
51 |
52 | /**
53 | * Fatal error that's non recoverable.
54 | */
55 | void error(Throwable t);
56 |
57 | /**
58 | * Called when a connection is terminated.
59 | */
60 | void onDisconnect();
61 |
62 | /**
63 | * Called when a re-connection is about to be attempted.
64 | * @since 2.0
65 | */
66 | void onReconnect();
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/EngineListenerAdapter.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | /**
4 | * Adapter class for {@link EngineListener} to shield subtypes from future callback additions.
5 | *
6 | * @author Kohsuke Kawaguchi
7 | * @since 2.36
8 | */
9 | public abstract class EngineListenerAdapter implements EngineListener {
10 | @Override
11 | public void status(String msg) {}
12 |
13 | @Override
14 | public void status(String msg, Throwable t) {}
15 |
16 | @Override
17 | public void error(Throwable t) {}
18 |
19 | @Override
20 | public void onDisconnect() {}
21 |
22 | @Override
23 | public void onReconnect() {}
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/EngineListenerSplitter.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.util.List;
4 | import java.util.concurrent.CopyOnWriteArrayList;
5 |
6 | /**
7 | * {@link EngineListener} that distributes callbacks.
8 | *
9 | * @author Kohsuke Kawaguchi
10 | * @since 2.36
11 | */
12 | public class EngineListenerSplitter implements EngineListener {
13 | protected final List listeners = new CopyOnWriteArrayList<>();
14 |
15 | public void add(EngineListener el) {
16 | listeners.add(el);
17 | }
18 |
19 | public void remove(EngineListener el) {
20 | listeners.remove(el);
21 | }
22 |
23 | @Override
24 | public void status(String msg) {
25 | for (EngineListener l : listeners) {
26 | l.status(msg);
27 | }
28 | }
29 |
30 | @Override
31 | public void status(String msg, Throwable t) {
32 | for (EngineListener l : listeners) {
33 | l.status(msg, t);
34 | }
35 | }
36 |
37 | @Override
38 | public void error(Throwable t) {
39 | for (EngineListener l : listeners) {
40 | l.error(t);
41 | }
42 | }
43 |
44 | @Override
45 | public void onDisconnect() {
46 | for (EngineListener l : listeners) {
47 | l.onDisconnect();
48 | }
49 | }
50 |
51 | @Override
52 | public void onReconnect() {
53 | for (EngineListener l : listeners) {
54 | l.onReconnect();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ErrorPropagatingOutputStream.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.CheckForNull;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.OutputStream;
7 |
8 | /**
9 | * {@link OutputStream} that's connected to an {@link InputStream} somewhere,
10 | * which provides ability to have {@link InputStream} report an error.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | * @since 2.35
14 | */
15 | public interface ErrorPropagatingOutputStream {
16 | /**
17 | * Closes the stream and causes the reading {@link InputStream} to report an error.
18 | *
19 | *
20 | * This method is somewhat like {@link OutputStream#close()},
21 | * in that it signals the end of a stream. In addition to what the close method does,
22 | * this method will cause the {@link InputStream#read()}
23 | * method (or any other overloaded versions) to throw an
24 | * {@link IOException} with the given throwable as the cause.
25 | *
26 | *
27 | * {@link InputStream} will report an error only after all the data that has written
28 | * before is read. IOW, the error will not magically jump over the data that was written.
29 | *
30 | *
31 | * This is useful to propagate error over a pipe. If used over
32 | * a channel with the remoting library that doesn't yet support this,
33 | * or if the {@link OutputStream} isn't connecting to an {@link InputStream},
34 | * this method behaves exactly like {@link OutputStream#close()}.
35 | *
36 | *
37 | * If {@link OutputStream} is already closed or error state is
38 | * set, this method will be no-op.
39 | *
40 | * @param e
41 | * if null, this method behaves exactly like {@link OutputStream#close()}
42 | */
43 | void error(@CheckForNull Throwable e) throws IOException;
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/Future.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
27 |
28 | // TODO: This Future should be actually deprecated, because it may confuse API users
29 | /**
30 | * Alias to {@link Future}.
31 | *
32 | *
33 | * This alias is defined so that retro-translation won't affect
34 | * the publicly committed signature of the API.
35 | *
36 | * @author Kohsuke Kawaguchi
37 | */
38 | @SuppressFBWarnings(
39 | value = "NM_SAME_SIMPLE_NAME_AS_INTERFACE",
40 | justification = "This class is just an alias, but this alias is a part of public API")
41 | public interface Future extends java.util.concurrent.Future {}
42 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/FutureAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import edu.umd.cs.findbugs.annotations.NonNull;
27 | import java.util.concurrent.ExecutionException;
28 | import java.util.concurrent.TimeUnit;
29 | import java.util.concurrent.TimeoutException;
30 |
31 | /**
32 | * {@link Future} that converts the return type.
33 | *
34 | * @author Kohsuke Kawaguchi
35 | */
36 | abstract class FutureAdapter implements Future {
37 | protected final Future core;
38 |
39 | protected FutureAdapter(Future core) {
40 | this.core = core;
41 | }
42 |
43 | @Override
44 | public boolean cancel(boolean mayInterruptIfRunning) {
45 | return core.cancel(mayInterruptIfRunning);
46 | }
47 |
48 | @Override
49 | public boolean isCancelled() {
50 | return core.isCancelled();
51 | }
52 |
53 | @Override
54 | public boolean isDone() {
55 | return core.isDone();
56 | }
57 |
58 | @Override
59 | public X get() throws InterruptedException, ExecutionException {
60 | return adapt(core.get());
61 | }
62 |
63 | @Override
64 | public X get(long timeout, @NonNull TimeUnit unit)
65 | throws InterruptedException, ExecutionException, TimeoutException {
66 | return adapt(core.get(timeout, unit));
67 | }
68 |
69 | protected abstract X adapt(Y y) throws ExecutionException;
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/GCCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
27 |
28 | /**
29 | * Performs GC.
30 | *
31 | * @author Kohsuke Kawaguchi
32 | */
33 | class GCCommand extends Command {
34 | @Override
35 | @SuppressFBWarnings(value = "DM_GC", justification = "TODO needs triage")
36 | protected void execute(Channel channel) {
37 | System.gc();
38 | }
39 |
40 | @Override
41 | public String toString() {
42 | return "GC";
43 | }
44 |
45 | private static final long serialVersionUID = 1L;
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/HexDump.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | /**
4 | * @author Kohsuke Kawaguchi
5 | */
6 | public class HexDump {
7 | private static final String CODE = "0123456789abcdef";
8 |
9 | public static String toHex(byte[] buf) {
10 | return toHex(buf, 0, buf.length);
11 | }
12 |
13 | public static String toHex(byte[] buf, int start, int len) {
14 | StringBuilder r = new StringBuilder(len * 2);
15 | boolean inText = false;
16 | for (int i = 0; i < len; i++) {
17 | byte b = buf[start + i];
18 | if (b >= 0x20 && b <= 0x7e) {
19 | if (!inText) {
20 | inText = true;
21 | r.append('\'');
22 | }
23 | r.append((char) b);
24 | } else {
25 | if (inText) {
26 | r.append("' ");
27 | inText = false;
28 | }
29 | r.append("0x");
30 | r.append(CODE.charAt((b >> 4) & 15));
31 | r.append(CODE.charAt(b & 15));
32 | if (i < len - 1) {
33 | if (b == 10) {
34 | r.append('\n');
35 | } else {
36 | r.append(' ');
37 | }
38 | }
39 | }
40 | }
41 | if (inText) {
42 | r.append('\'');
43 | }
44 | return r.toString();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/IChannel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | /**
27 | * Internally used to mark methods on {@link Channel} that are exported to remote.
28 | *
29 | *
30 | * Behaviors of the methods are explained in {@link Channel}.
31 | *
32 | * @author Kohsuke Kawaguchi
33 | */
34 | interface IChannel {
35 | Object getProperty(Object key);
36 |
37 | Object waitForProperty(Object key) throws InterruptedException;
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/IReadResolve.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import java.io.ObjectStreamException;
27 |
28 | /**
29 | * Used internally in the remoting code to have the proxy object
30 | * implement readResolve.
31 | *
32 | * @author Kohsuke Kawaguchi
33 | */
34 | public interface IReadResolve {
35 | Object readResolve() throws ObjectStreamException;
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/InitializeJarCacheMain.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 | import java.io.File;
5 | import java.io.FilenameFilter;
6 | import java.io.IOException;
7 | import java.nio.file.Files;
8 | import java.nio.file.StandardCopyOption;
9 |
10 | /**
11 | * Takes a directory of jars and populates them into the given jar cache
12 | * directory with the correct hash names.
13 | *
14 | *
Ideally this class should exist outside hudson.remoting but unfortunately
15 | * it needs access to package-private methods in hudson.remoting.
16 | *
17 | * @author Akshay Dayal
18 | */
19 | public class InitializeJarCacheMain {
20 |
21 | private static final FilenameFilter JAR_FILE_FILTER = (dir, name) -> name.endsWith(".jar");
22 |
23 | /**
24 | * Requires 2 parameters:
25 | *
26 | *
The source jar directory.
27 | *
The jar cache directory.
28 | *
29 | */
30 | @SuppressFBWarnings(
31 | value = "PATH_TRAVERSAL_IN",
32 | justification =
33 | "These file values are provided by users with sufficient administrative permissions to run this utility program.")
34 | public static void main(String[] argv) throws Exception {
35 | if (argv.length != 2) {
36 | throw new IllegalArgumentException("Usage: java -cp agent.jar hudson.remoting.InitializeJarCacheMain "
37 | + "");
38 | }
39 |
40 | File sourceJarDir = new File(argv[0]);
41 | File jarCacheDir = new File(argv[1]);
42 | FileSystemJarCache jarCache = new FileSystemJarCache(jarCacheDir, false);
43 |
44 | File[] jars = sourceJarDir.listFiles(JAR_FILE_FILTER);
45 | if (jars == null) {
46 | throw new IOException("Cannot list JAR files in " + sourceJarDir);
47 | }
48 | for (File jar : jars) {
49 | Checksum checksum = Checksum.forFile(jar);
50 | File newJarLocation = jarCache.map(checksum.sum1, checksum.sum2);
51 |
52 | Files.createDirectories(newJarLocation.getParentFile().toPath());
53 | Files.copy(jar.toPath(), newJarLocation.toPath(), StandardCopyOption.REPLACE_EXISTING);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/InternalCallable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2021, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import org.jenkinsci.remoting.RoleChecker;
27 | import org.kohsuke.accmod.Restricted;
28 | import org.kohsuke.accmod.restrictions.NoExternalUse;
29 |
30 | /**
31 | * For remoting internal use only: {@link Callable}s implement
32 | * this marker interface to be allowed to bypass the required role check of
33 | * {@link RequiredRoleCheckerWrapper}, as the application-defined
34 | * roles are unknown to remoting.
35 | * Callables defined in Jenkins need to extend {@code MasterToSlaveCallable} or
36 | * (rarely) {@code SlaveToMasterCallable}, or (almost never) implement
37 | * their own role checks.
38 | *
39 | * @since TODO
40 | */
41 | @Restricted(NoExternalUse.class)
42 | /* package */ interface InternalCallable extends Callable {
43 | @Override
44 | default void checkRoles(RoleChecker checker) throws SecurityException {
45 | // no-op
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/JarCache.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.net.URL;
7 | import java.util.concurrent.CompletableFuture;
8 |
9 | /**
10 | * Jar file cache.
11 | *
12 | *
13 | * The remoting library supports local jar file caching for the efficiency in remote class loading.
14 | * The cache stores jar files sent by the other side, and identifies jars with MD5 checksums that uniquely
15 | * identifies its content.
16 | *
17 | * This allows the cache to be reused by future channel sessions or other concurrent channel sessions.
18 | *
19 | * @author Kohsuke Kawaguchi
20 | * @since 2.24
21 | */
22 | public abstract class JarCache {
23 |
24 | /**
25 | * Default JAR cache location for disabled workspace Manager.
26 | */
27 | public static final File DEFAULT_NOWS_JAR_CACHE_LOCATION =
28 | new File(System.getProperty("user.home"), ".jenkins/cache/jars");
29 |
30 | // TODO: replace by checked exception
31 | /**
32 | * Gets a default value for {@link FileSystemJarCache} to be initialized on agents.
33 | * @return Created JAR Cache
34 | * @throws IOException Default JAR Cache location cannot be initialized
35 | */
36 | @NonNull
37 | /*package*/ static JarCache getDefault() throws IOException {
38 | try {
39 | return new FileSystemJarCache(DEFAULT_NOWS_JAR_CACHE_LOCATION, true);
40 | } catch (IllegalArgumentException ex) {
41 | throw new IOException("Failed to initialize the default JAR Cache location", ex);
42 | }
43 | }
44 |
45 | /**
46 | * Looks up the jar in cache, and if not found, use {@link JarLoader} to retrieve it
47 | * from the other side.
48 | *
49 | *
50 | * This method must be concurrency-safe.
51 | *
52 | * @param channel
53 | * Channel that needs this jar file.
54 | * @return
55 | * URL of the jar file.
56 | */
57 | @NonNull
58 | public abstract CompletableFuture resolve(@NonNull Channel channel, long sum1, long sum2)
59 | throws IOException, InterruptedException;
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/JarLoader.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 |
6 | /**
7 | * Remoting interface to allow the other side to retrieve a jar file
8 | * from the checksum advertised in {@link ResourceImageInJar}.
9 | *
10 | *
11 | * {@link Channel} exposes this as {@linkplain Channel#getRemoteProperty(Object) a remote property}
12 | * under the key {@link #OURS}, then once retrieved we store it in a local property under {@link #THEIRS}.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | * @since 2.24
16 | */
17 | public interface JarLoader {
18 | /**
19 | * Retrieve the jar file image.
20 | *
21 | * This method is called by the other side to receive the jar file. This call implicitly
22 | * has the effect of {@link #notifyJarPresence(long, long)}
23 | *
24 | * @param sink
25 | * This stream receives the jar file.
26 | *
27 | * @throws InterruptedException
28 | * Since this is a remote call, if the calling thread gets interrupted while waiting for the completion
29 | * of the call, this exception will be thrown.
30 | */
31 | void writeJarTo(long sum1, long sum2, OutputStream sink) throws IOException, InterruptedException;
32 |
33 | /**
34 | * Called by the other side to notify that they already own the jar file of the given checksum.
35 | *
36 | * This allows this side to send {@link ResourceImageRef} smartly by avoiding unnecessary
37 | * image transport.
38 | */
39 | @Asynchronous
40 | void notifyJarPresence(long sum1, long sum2);
41 |
42 | /**
43 | * @param sums
44 | * Array of even length. sums[2i] and sumes[2i+1] are paired up and interpreted as one checksum.
45 | */
46 | @Asynchronous
47 | void notifyJarPresence(long[] sums);
48 |
49 | /**
50 | * Used by the local side to see if the jar file of the given checksum is already present
51 | * on the other side. Used to decide if the class file image gets sent to the remote or not.
52 | */
53 | boolean isPresentOnRemote(Checksum sum);
54 |
55 | String OURS = JarLoader.class.getName() + ".ours";
56 | ChannelProperty THEIRS = new ChannelProperty<>(JarLoader.class, "their JarLoader");
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/JarURLValidator.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.io.IOException;
4 | import java.net.URL;
5 |
6 | /**
7 | * Validate a URL attempted to be read by the remote end (agent side).
8 | *
9 | * @deprecated Do not use, intended as a temporary workaround only.
10 | */
11 | // TODO Remove once we no longer require compatibility with remoting before 2024-08.
12 | @Deprecated
13 | public interface JarURLValidator {
14 | void validate(URL url) throws IOException;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/MimicException.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import edu.umd.cs.findbugs.annotations.Nullable;
5 | import org.kohsuke.accmod.Restricted;
6 | import org.kohsuke.accmod.restrictions.DoNotUse;
7 |
8 | /**
9 | * Exception that prints like the specified exception.
10 | *
11 | * This is used to carry the diagnostic information to the other side of the channel
12 | * in situations where we cannot use class remoting.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | * @see Capability#hasMimicException()
16 | * @deprecated Use {@link ProxyException} instead.
17 | */
18 | @Deprecated
19 | @Restricted(DoNotUse.class)
20 | class MimicException extends Exception {
21 | private final String className;
22 |
23 | MimicException(Throwable cause) {
24 | super(cause.getMessage());
25 | className = cause.getClass().getName();
26 | setStackTrace(cause.getStackTrace());
27 |
28 | if (cause.getCause() != null) {
29 | initCause(new MimicException(cause.getCause()));
30 | }
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | String s = className;
36 | String message = getLocalizedMessage();
37 | return (message != null) ? (s + ": " + message) : s;
38 | }
39 |
40 | @Nullable
41 | public static Throwable make(@NonNull Channel ch, @Nullable Throwable cause) {
42 | if (cause == null) {
43 | return null;
44 | }
45 |
46 | // make sure the remoting layer of the other end supports this
47 | if (ch.remoteCapability.hasMimicException()) {
48 | return new MimicException(cause);
49 | } else {
50 | return cause;
51 | }
52 | }
53 |
54 | private static final long serialVersionUID = 1L;
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/NamingThreadFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright 2013 Jesse Glick.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package hudson.remoting;
26 |
27 | import edu.umd.cs.findbugs.annotations.NonNull;
28 | import java.util.concurrent.Executors;
29 | import java.util.concurrent.ThreadFactory;
30 | import java.util.concurrent.atomic.AtomicInteger;
31 |
32 | /**
33 | * Thread factory that sets thread name so we know who is responsible for so many threads being created.
34 | * @since 2.52
35 | */
36 | public class NamingThreadFactory implements ThreadFactory {
37 | private final AtomicInteger threadNum = new AtomicInteger();
38 | private final ThreadFactory delegate;
39 | private final String name;
40 |
41 | /**
42 | * Creates a new naming factory.
43 | * @param delegate a baseline factory, such as {@link Executors#defaultThreadFactory} or {@link DaemonThreadFactory}
44 | * @param name an identifier to be used in thread names; might be e.g. your {@link Class#getSimpleName}
45 | */
46 | public NamingThreadFactory(ThreadFactory delegate, String name) {
47 | this.delegate = delegate;
48 | this.name = name;
49 | }
50 |
51 | @Override
52 | public Thread newThread(@NonNull Runnable r) {
53 | Thread result = delegate.newThread(r);
54 | result.setName(String.format("%s [#%d]", name, threadNum.incrementAndGet()));
55 | return result;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/RemotingSystemException.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | /**
4 | * Remote proxy uses this exception to signal the exception thrown
5 | * by the remoting layer and not by the application code that was invoked remotely.
6 | *
7 | *
8 | * The use of this exception triggers the caller to wrap a thrown exception to
9 | * add the stack trace that includes the call site information, making
10 | * the debugging easier
11 | *
12 | *
13 | * @author Kohsuke Kawaguchi
14 | */
15 | class RemotingSystemException extends RuntimeException {
16 | RemotingSystemException(Throwable cause) {
17 | super(cause);
18 | }
19 |
20 | RemotingSystemException(String message, Throwable cause) {
21 | super(message, cause);
22 | }
23 |
24 | private static final long serialVersionUID = 1L;
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/RequestAbortedException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | /**
27 | * Signals that the communication is aborted and thus
28 | * the pending {@link Request} will never recover its {@link Response}.
29 | *
30 | * @author Kohsuke Kawaguchi
31 | */
32 | // this was added before RemotingSystemException. Going forward, it's probably
33 | // unnecessary to define specific subtypes of RemotingSystemException
34 | public class RequestAbortedException extends RemotingSystemException {
35 | public RequestAbortedException(Throwable cause) {
36 | super(cause);
37 | }
38 |
39 | private static final long serialVersionUID = 238929914783987425L;
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/RequiredRoleCheckerWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2021, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import edu.umd.cs.findbugs.annotations.NonNull;
27 | import java.util.Collection;
28 | import org.jenkinsci.remoting.Role;
29 | import org.jenkinsci.remoting.RoleChecker;
30 | import org.jenkinsci.remoting.RoleSensitive;
31 |
32 | /**
33 | * Implementation that can tell whether a {@code #check} method was invoked.
34 | */
35 | /* package-private */ class RequiredRoleCheckerWrapper extends RoleChecker {
36 | private boolean checked;
37 |
38 | private RoleChecker roleChecker;
39 |
40 | public RequiredRoleCheckerWrapper(RoleChecker roleChecker) {
41 | this.roleChecker = roleChecker;
42 | }
43 |
44 | @Override
45 | public void check(@NonNull RoleSensitive subject, Role... expected) throws SecurityException {
46 | checked = true;
47 | roleChecker.check(subject, expected);
48 | }
49 |
50 | @Override
51 | public void check(@NonNull RoleSensitive subject, @NonNull Role expected) throws SecurityException {
52 | checked = true;
53 | roleChecker.check(subject, expected);
54 | }
55 |
56 | @Override
57 | public void check(@NonNull RoleSensitive subject, @NonNull Collection expected) throws SecurityException {
58 | checked = true;
59 | roleChecker.check(subject, expected);
60 | }
61 |
62 | public boolean isChecked() {
63 | return checked;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ResourceImageBoth.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import java.io.IOException;
5 | import java.net.URL;
6 | import java.util.concurrent.Future;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | /**
11 | * @author Kohsuke Kawaguchi
12 | */
13 | class ResourceImageBoth extends ResourceImageDirect {
14 | final long sum1, sum2;
15 |
16 | public ResourceImageBoth(URL resource, Checksum sum) throws IOException {
17 | super(resource);
18 | this.sum1 = sum.sum1;
19 | this.sum2 = sum.sum2;
20 | }
21 |
22 | @Override
23 | Future resolve(Channel channel, String resourcePath) throws IOException, InterruptedException {
24 | initiateJarRetrieval(channel);
25 | return super.resolve(channel, resourcePath);
26 | }
27 |
28 | @Override
29 | Future resolveURL(Channel channel, String resourcePath) throws IOException, InterruptedException {
30 | Future f = initiateJarRetrieval(channel);
31 | if (f.isDone()) { // prefer using the jar URL if the stuff is already available
32 | return new ResourceImageInJar(sum1, sum2, null).resolveURL(channel, resourcePath);
33 | } else {
34 | return super.resolveURL(channel, resourcePath);
35 | }
36 | }
37 |
38 | /**
39 | * Starts JAR retrieval over the channel.
40 | *
41 | * @param channel Channel instance
42 | * @return Future object. In the case of error the diagnostics info will be sent to {@link #LOGGER}.
43 | */
44 | @NonNull
45 | private Future initiateJarRetrieval(@NonNull Channel channel) throws IOException, InterruptedException {
46 | JarCache c = channel.getJarCache();
47 | if (c == null) {
48 | throw new IOException(
49 | "Failed to initiate retrieval. JAR Cache is disabled for the channel " + channel.getName());
50 | }
51 |
52 | try {
53 | return c.resolve(channel, sum1, sum2);
54 | } catch (IOException e) {
55 | LOGGER.log(Level.WARNING, "Failed to initiate retrieval", e);
56 | throw e;
57 | } catch (InterruptedException e) {
58 | LOGGER.log(Level.WARNING, "Failed to initiate retrieval", e);
59 | Thread.currentThread().interrupt(); // process the interrupt later
60 | throw e;
61 | }
62 | }
63 |
64 | private static final long serialVersionUID = 1L;
65 |
66 | private static final Logger LOGGER = Logger.getLogger(ResourceImageBoth.class.getName());
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ResourceImageDirect.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 | import java.io.IOException;
5 | import java.net.URL;
6 | import java.util.concurrent.CompletableFuture;
7 | import java.util.concurrent.Future;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | /**
12 | * {@link ResourceImageRef} that directly encapsulates the resource as {@code byte[]}.
13 | *
14 | *
15 | * This is used when {@link ResourceImageInJar} cannot be used because we couldn't identify the jar file.
16 | *
17 | * @author Kohsuke Kawaguchi
18 | */
19 | @SuppressFBWarnings(
20 | value = "URLCONNECTION_SSRF_FD",
21 | justification = "Used by the agent as part of jar cache management.")
22 | class ResourceImageDirect extends ResourceImageRef {
23 | /**
24 | * The actual resource.
25 | */
26 | private final byte[] payload;
27 |
28 | ResourceImageDirect(byte[] payload) {
29 | this.payload = payload;
30 | }
31 |
32 | ResourceImageDirect(URL resource) throws IOException {
33 | this(Util.readFully(resource.openStream()));
34 | }
35 |
36 | @Override
37 | Future resolve(Channel channel, String resourcePath) throws IOException, InterruptedException {
38 | LOGGER.log(Level.FINE, resourcePath + " image is direct");
39 | return CompletableFuture.completedFuture(payload);
40 | }
41 |
42 | @Override
43 | Future resolveURL(Channel channel, String resourcePath) throws IOException, InterruptedException {
44 | return CompletableFuture.completedFuture(URLish.from(Util.makeResource(resourcePath, payload)));
45 | }
46 |
47 | private static final Logger LOGGER = Logger.getLogger(ResourceImageDirect.class.getName());
48 |
49 | private static final long serialVersionUID = 1L;
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/ResourceImageRef.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.io.IOException;
4 | import java.io.Serializable;
5 | import java.util.concurrent.Future;
6 |
7 | /**
8 | * Wire protocol data representation that encapsulates the access to a resource inside a {@link ClassLoader}.
9 | *
10 | *
11 | * We support two kinds of references. One {@linkplain ResourceImageInJar points to a resource inside a jar},
12 | * and the other {@linkplain ResourceImageDirect directly contains the byte[] image}.
13 | *
14 | *
15 | * Subtypes need to be available on both sides of the channel, so it's package protected.
16 | *
17 | * @author Kohsuke Kawaguchi
18 | */
19 | /*package*/ abstract class ResourceImageRef implements Serializable {
20 | /**
21 | * Obtains the a resource file byte image.
22 | *
23 | * @param channel
24 | * The channel object as the context.
25 | * @param resourcePath
26 | * Fully qualified name of the resource being retrieved, that doesn't start with '/',
27 | * such as 'java/lang/String.class' Identical to the name parameter in {@link ClassLoader#getResource(String)}.
28 | *
29 | * This parameter must be the same name you used to retrieve {@link RemoteClassLoader.ClassReference}.
30 | *
31 | * One {@link ResourceImageRef} represents a single resource, and that resource name
32 | * is specified when you retrieve {@link RemoteClassLoader.ClassReference}. Therefore from pure abstraction
33 | * point of view, this information is redundant. However, specifying that information reduces
34 | * the amount of state {@link ResourceImageRef}s need to carry around, which helps reduce
35 | * the bandwidth consumption.
36 | */
37 | /*package*/ abstract Future resolve(Channel channel, String resourcePath)
38 | throws IOException, InterruptedException;
39 |
40 | /**
41 | * Returns an URL that points to this resource.
42 | *
43 | * This may require creating a temporary file.
44 | */
45 | /*package*/ abstract Future resolveURL(Channel channel, String resourcePath)
46 | throws IOException, InterruptedException;
47 |
48 | private static final long serialVersionUID = 1L;
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/SocketInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import java.io.FilterInputStream;
27 | import java.io.IOException;
28 | import java.io.InputStream;
29 | import java.net.Socket;
30 |
31 | /**
32 | * {@link InputStream} connected to socket.
33 | *
34 | *
13 | * Thie indirection on {@link URL} allows us to make sure that URLs backed by temporary files
14 | * actually do exist before we use them.
15 | *
16 | * @author Kohsuke Kawaguchi
17 | */
18 | abstract class URLish {
19 | private URLish() {}
20 |
21 | /**
22 | * Converts URLish to the standard {@link URL} type.
23 | * @return URL or {@code null} if the target destination is known to be non-existent.
24 | * @throws MalformedURLException URL cannot be constructed
25 | */
26 | @CheckForNull
27 | abstract URL toURL() throws MalformedURLException;
28 |
29 | @NonNull
30 | static URLish from(@NonNull final URL url) {
31 |
32 | return new URLish() {
33 | @Override
34 | @NonNull
35 | URL toURL() {
36 | return url;
37 | }
38 | };
39 | }
40 |
41 | @NonNull
42 | static URLish from(@NonNull final File f) {
43 | return new URLish() {
44 | @Override
45 | URL toURL() throws MalformedURLException {
46 | // be defensive against external factors that might have deleted this file, since we use /tmp
47 | // see http://www.nabble.com/Surefire-reports-tt17554215.html
48 | if (f.exists()) {
49 | return f.toURI().toURL();
50 | }
51 | return null;
52 | }
53 | };
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/UnexportCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import edu.umd.cs.findbugs.annotations.CheckForNull;
27 |
28 | /**
29 | * {@link Command} that unexports an object.
30 | * @author Kohsuke Kawaguchi
31 | */
32 | public class UnexportCommand extends Command {
33 | private final int oid;
34 |
35 | UnexportCommand(int oid, @CheckForNull Throwable cause) {
36 | this.oid = oid;
37 | chainCause(cause);
38 | }
39 |
40 | /**
41 | * @deprecated Use {@link #UnexportCommand(int, Throwable)}
42 | */
43 | @Deprecated
44 | public UnexportCommand(int oid) {
45 | this(oid, null);
46 | }
47 |
48 | @Override
49 | protected void execute(Channel channel) {
50 | channel.unexport(oid, createdAt);
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return "Unexport";
56 | }
57 |
58 | private static final long serialVersionUID = 1L;
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/forward/CopyThread.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting.forward;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.OutputStream;
6 | import java.util.logging.Level;
7 | import java.util.logging.Logger;
8 |
9 | /**
10 | * Copies a stream and close them at EOF.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | */
14 | final class CopyThread extends Thread {
15 | private static final Logger LOGGER = Logger.getLogger(CopyThread.class.getName());
16 | private final InputStream in;
17 | private final OutputStream out;
18 |
19 | /**
20 | * Callers are responsible for closing the input and output streams.
21 | */
22 | public CopyThread(String threadName, InputStream in, OutputStream out, Runnable termination) {
23 | this(threadName, in, out, termination, 5);
24 | }
25 |
26 | private CopyThread(String threadName, InputStream in, OutputStream out, Runnable termination, int remainingTries) {
27 | super(threadName);
28 | this.in = in;
29 | this.out = out;
30 | setUncaughtExceptionHandler((t, e) -> {
31 | if (remainingTries > 0) {
32 | LOGGER.log(Level.WARNING, e, () -> "Uncaught exception in CopyThread " + t + ", retrying copy");
33 | new CopyThread(threadName, in, out, termination, remainingTries - 1).start();
34 | } else {
35 | LOGGER.log(Level.SEVERE, e, () -> "Uncaught exception in CopyThread " + t + ", out of retries");
36 | termination.run();
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | public void run() {
43 | try {
44 | byte[] buf = new byte[8192];
45 | int len;
46 | while ((len = in.read(buf)) > 0) {
47 | out.write(buf, 0, len);
48 | }
49 | } catch (IOException e) {
50 | LOGGER.log(Level.WARNING, e, () -> "Exception while copying in thread: " + getName());
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/forward/Forwarder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting.forward;
25 |
26 | import java.io.IOException;
27 | import java.io.OutputStream;
28 | import java.io.Serializable;
29 |
30 | /**
31 | * Abstracts away how the forwarding is set up.
32 | *
33 | * @author Kohsuke Kawaguchi
34 | */
35 | public interface Forwarder extends Serializable {
36 | /**
37 | * Establishes a port forwarding connection and returns
38 | * the writer end.
39 | *
40 | * @param out
41 | * The writer end to the initiator. The callee will
42 | * start a thread that writes to this.
43 | */
44 | OutputStream connect(OutputStream out) throws IOException;
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/forward/ListeningPort.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting.forward;
2 |
3 | import java.io.Closeable;
4 | import java.io.IOException;
5 |
6 | /**
7 | * Represents a listening port that forwards a connection
8 | * via port forwarding.
9 | *
10 | * @author Kohsuke Kawaguchi
11 | */
12 | public interface ListeningPort extends Closeable {
13 | /**
14 | * TCP/IP port that is listening.
15 | */
16 | int getPort();
17 |
18 | /**
19 | * Shuts down the port forwarding by removing the server socket.
20 | * Connections that are already established will not be affected
21 | * by this operation.
22 | */
23 | @Override
24 | void close() throws IOException;
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/forward/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * TCP port forwarding over {@code hudson.remoting}.
3 | */
4 | package hudson.remoting.forward;
5 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/jnlp/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting.jnlp;
25 |
26 | import hudson.remoting.Launcher;
27 | import java.io.IOException;
28 | import org.kohsuke.args4j.CmdLineException;
29 |
30 | /**
31 | * Previous entry point to pseudo-JNLP agent.
32 | *
33 | *
See also {@code jenkins-agent.jnlp.jelly} in the core.
34 | *
35 | * @author Kohsuke Kawaguchi
36 | * @deprecated use {@link Launcher}
37 | */
38 | @Deprecated
39 | public class Main extends Launcher {
40 |
41 | private static volatile boolean deprecationWarningLogged;
42 |
43 | public static void main(String... args) throws IOException, InterruptedException {
44 | logDeprecation();
45 | Launcher.main(args);
46 | }
47 |
48 | @Override
49 | public void run() throws CmdLineException, IOException, InterruptedException {
50 | logDeprecation();
51 | super.run();
52 | }
53 |
54 | private static void logDeprecation() {
55 | if (deprecationWarningLogged) {
56 | return;
57 | }
58 | System.err.println(
59 | "WARNING: Using deprecated entrypoint \"java -cp agent.jar hudson.remoting.jnlp.Main\". Use \"java -jar agent.jar\" instead.");
60 | deprecationWarningLogged = true;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/jnlp/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | /**
25 | * Code for launching the remote agent through JNLP.
26 | *
27 | *
28 | * This involves in getting the connection parameters through command line,
29 | * which is provided from {@code jenkins-agent.jnlp.jelly} file in the core.
30 | */
31 | package hudson.remoting.jnlp;
32 |
--------------------------------------------------------------------------------
/src/main/java/hudson/remoting/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | /**
25 | * Remoting infrastructure for Hudson.
26 | *
27 | *
28 | * Code in this package is used for running a part of a program in agents.
29 | * If you are new to this package, start from {@link hudson.remoting.Channel}.
30 | */
31 | package hudson.remoting;
32 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/CallableDecorator.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.remoting;
2 |
3 | import hudson.remoting.Callable;
4 | import hudson.remoting.Channel;
5 |
6 | /**
7 | * Decorator on {@code Callable.call()} to filter the execution.
8 | *
9 | * @author Kohsuke Kawaguchi
10 | * @see Channel#addLocalExecutionInterceptor(CallableDecorator)
11 | */
12 | public abstract class CallableDecorator {
13 | /**
14 | * Used to decorate everything that executes in the channel as a result of a request from the other side,
15 | * such as RPC executions on exported objects, user-provided {@link Callable} execution, pipe write, and so on.
16 | */
17 | public V call(java.util.concurrent.Callable callable) throws Exception {
18 | return callable.call();
19 | }
20 |
21 | /**
22 | * Used to specifically decorate user-provided {@link Callable} execution.
23 | *
24 | * Unlike {@link #call(java.util.concurrent.Callable)}, this method provides an opportunity
25 | * to inspect the actual {@link Callable} object given to {@link Channel#call(Callable)}
26 | * from the other side, whereas {@link #call(java.util.concurrent.Callable)} only
27 | * provides an opaque blob that itself may wrap the actual user-given operations.
28 | *
29 | * @param op
30 | * The original callable object given to {@link Channel#call(Callable)}.
31 | * @param stem
32 | * Computation that represents the invocation of {@code op} as well as any additional decoration done by other
33 | * {@link CallableDecorator}s.
34 | * @return
35 | * Returns the a decorated {@link Callable} that represents the decorated computation,
36 | * which normally executes some pre-processing, then delegates to the {@code stem}, then performs some cleanup.
37 | *
38 | * If there's nothing to filter, return {@code stem}.
39 | * @throws RuntimeException
40 | * Any exception thrown from this method will be propagated to the other side as if the execution of
41 | * the callable had failed with this exception.
42 | */
43 | public Callable userRequest(Callable op, Callable stem) {
44 | return stem;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/DurationOptionHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2024, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting;
25 |
26 | import java.time.Duration;
27 | import org.jenkinsci.remoting.util.DurationFormatter;
28 | import org.jenkinsci.remoting.util.DurationStyle;
29 | import org.kohsuke.accmod.Restricted;
30 | import org.kohsuke.accmod.restrictions.NoExternalUse;
31 | import org.kohsuke.args4j.CmdLineException;
32 | import org.kohsuke.args4j.CmdLineParser;
33 | import org.kohsuke.args4j.OptionDef;
34 | import org.kohsuke.args4j.spi.OptionHandler;
35 | import org.kohsuke.args4j.spi.Parameters;
36 | import org.kohsuke.args4j.spi.Setter;
37 |
38 | /**
39 | * Parses a string like 1s, 2m, 3h, 4d into a {@link Duration}.
40 | */
41 | @Restricted(NoExternalUse.class)
42 | public class DurationOptionHandler extends OptionHandler {
43 | public DurationOptionHandler(CmdLineParser parser, OptionDef option, Setter super Duration> setter) {
44 | super(parser, option, setter);
45 | }
46 |
47 | @Override
48 | public int parseArguments(Parameters params) throws CmdLineException {
49 | setter.addValue(DurationStyle.detectAndParse(params.getParameter(0)));
50 | return 1;
51 | }
52 |
53 | @Override
54 | public String getDefaultMetaVariable() {
55 | return "DURATION";
56 | }
57 |
58 | @Override
59 | protected String print(Duration v) {
60 | return DurationFormatter.format(v);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/RoleChecker.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.remoting;
2 |
3 | import edu.umd.cs.findbugs.annotations.NonNull;
4 | import hudson.remoting.Callable;
5 | import hudson.remoting.ChannelBuilder;
6 | import java.util.Arrays;
7 | import java.util.Collection;
8 | import java.util.Set;
9 |
10 | /**
11 | * Verifies that the callable is getting run on the intended recipient.
12 | *
13 | * @author Kohsuke Kawaguchi
14 | * @see ChannelBuilder#withRoleChecker(RoleChecker)
15 | * @since 2.47
16 | */
17 | public abstract class RoleChecker {
18 | /**
19 | * Called from {@link RoleSensitive#checkRoles(RoleChecker)} to ensure that this side of the channel
20 | * is willing to execute {@link Callable}s that expects one of the given roles on their intended recipients.
21 | *
If you think you need to implement {@link RoleSensitive#checkRoles} please reread that method’s Javadoc.
22 | *
23 | * Normally, each side of the channel has a fixed set of roles (say {@code actualRoles}),
24 | * and the implementation would be {@code actualRoles.containsAll(roles)}.
25 | *
26 | * @param subject
27 | * Object whose role we are checking right now. Useful context information when reporting an error.
28 | * @param expected
29 | * The current JVM that executes the callable should have one of these roles.
30 | * Never empty nor null.
31 | * @throws SecurityException
32 | * Any exception thrown will prevent the callable from getting executed, but we recommend
33 | * {@link SecurityException}
34 | */
35 | public abstract void check(@NonNull RoleSensitive subject, @NonNull Collection expected)
36 | throws SecurityException;
37 |
38 | public void check(@NonNull RoleSensitive subject, @NonNull Role expected) throws SecurityException {
39 | check(subject, Set.of(expected));
40 | }
41 |
42 | public void check(@NonNull RoleSensitive subject, Role... expected) throws SecurityException {
43 | check(subject, Arrays.asList(expected));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/RoleSensitive.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.remoting;
2 |
3 | import hudson.remoting.Callable;
4 | import java.util.Collection;
5 |
6 | /**
7 | * Used by {@link Callable}-like objects to designate the intended recipient of the callable,
8 | * to help verify callables are running in JVMs that it is intended to run.
9 | *
10 | *
11 | * This interface is defined separately from {@link Callable} so that other callable-like interfaces
12 | * can reuse this.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | * @see RoleChecker
16 | * @since 2.47
17 | */
18 | public interface RoleSensitive {
19 | /**
20 | * Verifies the roles expected by this callable by invoking {@link RoleChecker#check(RoleSensitive, Collection)}
21 | * method (or its variants), to provide an opportunity for {@link RoleChecker} to reject this object.
22 | *
Do not implement this method unless you know what you are doing.
23 | * If you have a Jenkins {@link Callable} or {@code FileCallable}, use the standard abstract base classes instead,
24 | * such as {@code MasterToSlaveCallable}, {@code MasterToSlaveFileCallable}, {@code NotReallyRoleSensitiveCallable}, etc.
25 | * See this document for details.
26 | *
27 | * If the method returns normally, the check has passed.
28 | *
29 | * @throws SecurityException
30 | * If there's a mismatch in the expected roles and the actual roles that should prevent
31 | * the execution of this callable.
32 | *
33 | * @throws AbstractMethodError
34 | * In the history of this library, this interface was added rather later, so there's lots of
35 | * {@link Callable}s out there that do not implement this method.
36 | * For this reason, code that calls this method should be prepared to
37 | * receive {@link AbstractMethodError}, and treat that as if the invocation of
38 | * {@code checker.check(this,Role.UNKNOWN)} has happened.
39 | */
40 | void checkRoles(RoleChecker checker) throws SecurityException;
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/engine/HostPort.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.remoting.engine;
2 |
3 | class HostPort {
4 |
5 | private static final int PORT_MIN = 0;
6 | private static final int PORT_MAX = (1 << 16) - 1;
7 |
8 | private String host;
9 | private int port;
10 |
11 | public HostPort(String value) {
12 | splitHostPort(value, null, 0);
13 | }
14 |
15 | public HostPort(String value, String defaultHost, int defaultPort) {
16 | splitHostPort(value, defaultHost, defaultPort);
17 | }
18 |
19 | private void splitHostPort(String value, String defaultHost, int defaultPort) {
20 | String hostPortValue = value.trim();
21 | if (hostPortValue.charAt(0) == '[') {
22 | extractIPv6(hostPortValue);
23 | return;
24 | }
25 | int portSeparator = hostPortValue.lastIndexOf(':');
26 | if (portSeparator < 0) {
27 | throw new IllegalArgumentException("Invalid HOST:PORT value: " + value);
28 | }
29 | String hostValue = hostPortValue.substring(0, portSeparator).trim();
30 | host = !hostValue.isEmpty() ? hostValue : defaultHost;
31 | String portString = hostPortValue.substring(portSeparator + 1).trim();
32 | if (!portString.isEmpty()) {
33 | port = Integer.parseInt(portString);
34 | if (port <= PORT_MIN || port > PORT_MAX) {
35 | throw new IllegalArgumentException(
36 | "Port " + value + " out of valid range [" + PORT_MIN + ", " + PORT_MAX + ")");
37 | }
38 | } else {
39 | port = defaultPort;
40 | }
41 | }
42 |
43 | private void extractIPv6(String hostPortValue) {
44 | int endBracket = hostPortValue.indexOf(']');
45 | if (endBracket < 2) {
46 | throw new IllegalArgumentException("Invalid IPv6 value.");
47 | }
48 | host = hostPortValue.substring(1, endBracket).trim();
49 | int portSeparator = hostPortValue.lastIndexOf(':');
50 | if (portSeparator < endBracket) {
51 | throw new IllegalArgumentException("Missing port.");
52 | }
53 | port = Integer.parseInt(hostPortValue.substring(portSeparator + 1).trim());
54 | }
55 |
56 | public String getHost() {
57 | return host;
58 | }
59 |
60 | public int getPort() {
61 | return port;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/engine/JnlpEndpointResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2019, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.engine;
25 |
26 | import java.io.IOException;
27 | import java.security.KeyFactory;
28 | import java.security.NoSuchAlgorithmException;
29 | import java.security.interfaces.RSAPublicKey;
30 | import java.security.spec.InvalidKeySpecException;
31 | import java.security.spec.X509EncodedKeySpec;
32 | import java.util.Base64;
33 |
34 | public abstract class JnlpEndpointResolver {
35 |
36 | public abstract JnlpAgentEndpoint resolve() throws IOException;
37 |
38 | public abstract void waitForReady() throws InterruptedException;
39 |
40 | protected RSAPublicKey getIdentity(String base64EncodedIdentity) throws InvalidKeySpecException {
41 | if (base64EncodedIdentity == null) {
42 | return null;
43 | }
44 | try {
45 | byte[] encodedKey = Base64.getDecoder().decode(base64EncodedIdentity);
46 | if (encodedKey == null) {
47 | return null;
48 | }
49 | X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedKey);
50 | KeyFactory kf = KeyFactory.getInstance("RSA");
51 | return (RSAPublicKey) kf.generatePublic(spec);
52 | } catch (NoSuchAlgorithmException e) {
53 | throw new IllegalStateException(
54 | "The Java Language Specification mandates RSA as a supported algorithm.", e);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/nio/Closeables.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.remoting.nio;
2 |
3 | import java.io.Closeable;
4 | import java.io.IOException;
5 | import java.net.Socket;
6 | import java.nio.channels.SelectableChannel;
7 | import java.nio.channels.SocketChannel;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | /**
12 | * Creates {@link Closeable} that does socket half-close.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | */
16 | class Closeables {
17 | public static Closeable input(SelectableChannel ch) {
18 | if (ch instanceof SocketChannel) {
19 | final SocketChannel s = (SocketChannel) ch;
20 | return () -> {
21 | try {
22 | s.socket().shutdownInput();
23 | } catch (IOException e) {
24 | // at least as of Java7u55, shutdownInput fails if the socket
25 | // is already closed or half-closed, as opposed to be a no-op.
26 | // so let's just ignore close error altogether
27 | LOGGER.log(Level.FINE, "Failed to close " + s, e);
28 | }
29 | maybeClose(s);
30 | };
31 | } else {
32 | return ch;
33 | }
34 | }
35 |
36 | public static Closeable output(SelectableChannel ch) {
37 | if (ch instanceof SocketChannel) {
38 | final SocketChannel s = (SocketChannel) ch;
39 | return () -> {
40 | try {
41 | s.socket().shutdownOutput();
42 | } catch (IOException e) {
43 | // see the discussion in try/catch block around shutdownInput above
44 | LOGGER.log(Level.FINE, "Failed to close " + s, e);
45 | }
46 | maybeClose(s);
47 | };
48 | } else {
49 | return ch;
50 | }
51 | }
52 |
53 | /**
54 | * If both direction is closed, close the whole thing.
55 | */
56 | private static void maybeClose(SocketChannel sc) throws IOException {
57 | Socket s = sc.socket();
58 | if (s.isInputShutdown() && s.isOutputShutdown()) {
59 | s.close();
60 | sc.close();
61 | }
62 | }
63 |
64 | private static final Logger LOGGER = Logger.getLogger(Closeables.class.getName());
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/nio/SelectorThreadOnly.java:
--------------------------------------------------------------------------------
1 | package org.jenkinsci.remoting.nio;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Marks the methods that can be only executed by the NIO selector thread.
10 | *
11 | *
Rules
12 | *
13 | *
If the base method has this annotation, all the overriding methods must have this.
14 | *
Only the caller that's marked as {@link SelectorThreadOnly} can call these methods.
15 | *
16 | *
17 | * @author Kohsuke Kawaguchi
18 | */
19 | @Target(ElementType.METHOD)
20 | @Retention(RetentionPolicy.SOURCE)
21 | @interface SelectorThreadOnly {}
22 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/protocol/IOHubRegistrationCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, CloudBees, Inc., Stephen Connolly
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.protocol;
25 |
26 | import java.nio.channels.ClosedChannelException;
27 | import java.nio.channels.SelectableChannel;
28 | import java.nio.channels.SelectionKey;
29 |
30 | /**
31 | * Callback to be notified when a call to
32 | * {@link IOHub#register(SelectableChannel, IOHubReadyListener, boolean, boolean, boolean, boolean, IOHubRegistrationCallback)} has completed registration.
33 | *
34 | * @since 3.0
35 | */
36 | public interface IOHubRegistrationCallback {
37 |
38 | /**
39 | * Notification callback that the {@link SelectableChannel} has been successfully registered.
40 | *
41 | * @param selectionKey the {@link SelectionKey} that the {@link SelectableChannel} was registered as.
42 | */
43 | void onRegistered(SelectionKey selectionKey);
44 |
45 | /**
46 | * Notification callback that the {@link SelectableChannel} was closed by the time the registration request was
47 | * processed.
48 | *
49 | * @param e the {@link ClosedChannelException} that was thrown when the registration request was attempted.
50 | */
51 | void onClosedChannel(ClosedChannelException e);
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/protocol/IOHubRegistrationFutureAdapterImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, CloudBees, Inc., Stephen Connolly
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.protocol;
25 |
26 | import hudson.remoting.Future;
27 | import java.nio.channels.ClosedChannelException;
28 | import java.nio.channels.SelectionKey;
29 | import org.jenkinsci.remoting.util.SettableFuture;
30 |
31 | /**
32 | * Converts the {@link IOHubRegistrationCallback} pattern into a {@link Future}.
33 | *
34 | * @since 3.0
35 | */
36 | class IOHubRegistrationFutureAdapterImpl implements IOHubRegistrationCallback {
37 | /**
38 | * The future.
39 | */
40 | private final SettableFuture future = SettableFuture.create();
41 |
42 | /**
43 | * {@inheritDoc}
44 | */
45 | @Override
46 | public void onRegistered(SelectionKey selectionKey) {
47 | future.set(selectionKey);
48 | }
49 |
50 | /**
51 | * {@inheritDoc}
52 | */
53 | @Override
54 | public void onClosedChannel(ClosedChannelException e) {
55 | future.setException(e);
56 | }
57 |
58 | /**
59 | * Gets the future.
60 | *
61 | * @return the future.
62 | */
63 | public SettableFuture getFuture() {
64 | return future;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/protocol/impl/PermanentConnectionRefusalException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, Stephen Connolly, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.protocol.impl;
25 |
26 | /**
27 | * An exception to flag that the connection has been rejected and no further connection attempts should be made.
28 | * @deprecated Does not actually do what it claims; only affects logging levels.
29 | * @since 3.0
30 | */
31 | @Deprecated
32 | public class PermanentConnectionRefusalException extends ConnectionRefusalException {
33 | public PermanentConnectionRefusalException() {
34 | super();
35 | }
36 |
37 | public PermanentConnectionRefusalException(String message) {
38 | super(message);
39 | }
40 |
41 | public PermanentConnectionRefusalException(String message, Object... args) {
42 | super(message, args);
43 | }
44 |
45 | public PermanentConnectionRefusalException(Throwable cause, String message, Object... args) {
46 | super(cause, message, args);
47 | }
48 |
49 | public PermanentConnectionRefusalException(String message, Throwable cause) {
50 | super(message, cause);
51 | }
52 |
53 | public PermanentConnectionRefusalException(Throwable cause) {
54 | super(cause);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/ByteBufferPool.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.util;
25 |
26 | import java.nio.ByteBuffer;
27 |
28 | /**
29 | * API for a pool of {@link ByteBuffer}s.
30 | */
31 | public interface ByteBufferPool {
32 | /**
33 | * Borrow a buffer from the pool.
34 | *
35 | * @param size The minimum size and initial limit of the buffer.
36 | * @return the buffer.
37 | */
38 | ByteBuffer acquire(int size);
39 |
40 | /**
41 | * Returns a buffer to the pool.
42 | *
43 | * @param buffer the buffer.
44 | */
45 | void release(ByteBuffer buffer);
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/ByteBufferQueueOutputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.util;
25 |
26 | import edu.umd.cs.findbugs.annotations.NonNull;
27 | import java.io.IOException;
28 | import java.io.OutputStream;
29 |
30 | /**
31 | * An {@link OutputStream} backed by a {@link ByteBufferQueue}.
32 | *
33 | * @since 3.0
34 | */
35 | public class ByteBufferQueueOutputStream extends OutputStream {
36 |
37 | /**
38 | * The backing queue.
39 | */
40 | private final ByteBufferQueue queue;
41 |
42 | /**
43 | * Creates a new instance.
44 | *
45 | * @param queue the backing queue.
46 | */
47 | public ByteBufferQueueOutputStream(ByteBufferQueue queue) {
48 | this.queue = queue;
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | */
54 | @Override
55 | public void write(int b) throws IOException {
56 | queue.put((byte) b);
57 | }
58 |
59 | /**
60 | * {@inheritDoc}
61 | */
62 | @Override
63 | public void write(@NonNull byte[] b, int off, int len) throws IOException {
64 | queue.put(b, off, len);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/IOUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.util;
25 |
26 | import java.io.Closeable;
27 | import java.io.IOException;
28 | import org.kohsuke.accmod.Restricted;
29 | import org.kohsuke.accmod.restrictions.NoExternalUse;
30 |
31 | /**
32 | * I/O related utility methods. Included to minimize external dependencies of the remoting library.
33 | *
34 | * @since 3.0
35 | */
36 | @Restricted(NoExternalUse.class)
37 | public class IOUtils {
38 |
39 | /**
40 | * Utility class.
41 | */
42 | private IOUtils() {
43 | throw new IllegalAccessError("Utility class");
44 | }
45 |
46 | /**
47 | * Unconditionally close a Closeable.
48 | *
49 | * @param closeable the object to close, may be null or already closed
50 | * @since 3.0
51 | */
52 | public static void closeQuietly(Closeable closeable) {
53 | try {
54 | if (closeable != null) {
55 | closeable.close();
56 | }
57 | } catch (IOException ioe) {
58 | // ignore
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/PathUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * The MIT License
4 | *
5 | * Copyright (c) 2017 CloudBees, Inc.
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | *
25 | */
26 |
27 | package org.jenkinsci.remoting.util;
28 |
29 | import edu.umd.cs.findbugs.annotations.NonNull;
30 | import java.io.File;
31 | import java.io.IOException;
32 | import java.nio.file.InvalidPathException;
33 | import java.nio.file.Path;
34 | import org.kohsuke.accmod.Restricted;
35 | import org.kohsuke.accmod.restrictions.NoExternalUse;
36 |
37 | /**
38 | * Utilities for {@link Path} handling.
39 | */
40 | @Restricted(NoExternalUse.class)
41 | public class PathUtils {
42 |
43 | private PathUtils() {}
44 |
45 | /**
46 | * Converts {@link File} to {@link Path} and checks runtime exceptions.
47 | * @param file File
48 | * @return Resulting path
49 | * @throws IOException Conversion error caused by {@link InvalidPathException}
50 | * @since 3.14
51 | */
52 | @NonNull
53 | @Restricted(NoExternalUse.class)
54 | public static Path fileToPath(@NonNull File file) throws IOException {
55 | try {
56 | return file.toPath();
57 | } catch (InvalidPathException ex) {
58 | throw new IOException(ex);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/ThrowableUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2016, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package org.jenkinsci.remoting.util;
25 |
26 | import edu.umd.cs.findbugs.annotations.CheckForNull;
27 |
28 | /**
29 | * Utility methods to help when working with {@link Throwable} instances.
30 | *
31 | * @since 3.0
32 | */
33 | public class ThrowableUtils {
34 |
35 | /**
36 | * This is a utility class, prevent accidental instance creation.
37 | */
38 | private ThrowableUtils() {
39 | throw new IllegalAccessError("Utility class");
40 | }
41 |
42 | /**
43 | * Allows building a chain of exceptions.
44 | *
45 | * @param e1 The first exception (or {@code null}).
46 | * @param e2 The second exception (or {@code null}).
47 | * @param The widened return type.
48 | * @param The type of first exception.
49 | * @param The type of second exception.
50 | * @return The first exception with the second added as a suppressed exception or the closest approximation to that.
51 | */
52 | @CheckForNull
53 | public static T chain(@CheckForNull T1 e1, @CheckForNull T2 e2) {
54 | if (e1 == null) {
55 | return e2;
56 | }
57 | if (e2 == null) {
58 | return e1;
59 | }
60 | e1.addSuppressed(e2);
61 | return e1;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/https/NoCheckHostnameVerifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * The MIT License
4 | *
5 | * Copyright (c) 2017 CloudBees, Inc.
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | *
25 | */
26 |
27 | package org.jenkinsci.remoting.util.https;
28 |
29 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
30 | import javax.net.ssl.HostnameVerifier;
31 | import javax.net.ssl.SSLSession;
32 | import org.kohsuke.accmod.Restricted;
33 | import org.kohsuke.accmod.restrictions.NoExternalUse;
34 |
35 | /**
36 | * Hostname verifier, which accepts any hostname.
37 | */
38 | @Restricted(NoExternalUse.class)
39 | @SuppressFBWarnings(value = "WEAK_HOSTNAME_VERIFIER", justification = "User set parameter to skip verifier.")
40 | public class NoCheckHostnameVerifier implements HostnameVerifier {
41 |
42 | @Override
43 | public boolean verify(String s, SSLSession sslSession) {
44 | return true;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/jenkinsci/remoting/util/https/NoCheckTrustManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * The MIT License
4 | *
5 | * Copyright (c) 2016- CloudBees, Inc.
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | *
25 | */
26 |
27 | package org.jenkinsci.remoting.util.https;
28 |
29 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
30 | import java.security.cert.X509Certificate;
31 | import javax.net.ssl.X509TrustManager;
32 | import org.kohsuke.accmod.Restricted;
33 | import org.kohsuke.accmod.restrictions.NoExternalUse;
34 |
35 | /**
36 | * {@link X509TrustManager} that performs no check at all.
37 | */
38 | @Restricted(NoExternalUse.class)
39 | @SuppressFBWarnings(value = "WEAK_TRUST_MANAGER", justification = "User set parameter to skip verifier.")
40 | public class NoCheckTrustManager implements X509TrustManager {
41 | @Override
42 | public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {}
43 |
44 | @Override
45 | public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {}
46 |
47 | @Override
48 | public X509Certificate[] getAcceptedIssuers() {
49 | return new X509Certificate[0];
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/test/java/JarCertDump.java:
--------------------------------------------------------------------------------
1 | import java.io.File;
2 | import java.io.IOException;
3 | import java.nio.charset.StandardCharsets;
4 | import java.security.cert.Certificate;
5 | import java.util.jar.JarEntry;
6 | import java.util.jar.JarFile;
7 | import org.apache.commons.io.IOUtils;
8 |
9 | /**
10 | * Tool to parse the certificate chain in the jar file.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | */
14 | public class JarCertDump {
15 | public static void main(String[] args) throws IOException {
16 | try (JarFile j = new JarFile(new File(args[0]))) {
17 | JarEntry je = j.getJarEntry("hudson/remoting/Channel.class");
18 | if (je == null) {
19 | throw new IllegalArgumentException();
20 | }
21 | IOUtils.readLines(j.getInputStream(je), StandardCharsets.UTF_8);
22 | for (Certificate c : je.getCertificates()) {
23 | System.out.println("################# Certificate #################");
24 | System.out.println(c);
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/OISInterception.java:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayInputStream;
2 | import java.io.ByteArrayOutputStream;
3 | import java.io.IOException;
4 | import java.io.ObjectInputStream;
5 | import java.io.ObjectOutputStream;
6 | import java.io.ObjectStreamClass;
7 | import java.util.Set;
8 |
9 | /**
10 | * Experimenting with inspecting stream contents as it is read.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | */
14 | public class OISInterception {
15 | public static void main(String[] args) throws Exception {
16 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
17 | try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
18 | oos.writeObject(Set.of("foo"));
19 | }
20 |
21 | ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())) {
22 | @Override
23 | protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
24 | ObjectStreamClass d = super.readClassDescriptor();
25 | // this can be used to filter out classes
26 | System.out.println(d.getName());
27 | return d;
28 | }
29 | };
30 |
31 | System.out.println(ois.readObject());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/TrafficAnalyzer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * See {@link hudson.remoting.TrafficAnalyzer}. This entry point makes it easier to
3 | * invoke the tool.
4 | *
5 | * @author Kohsuke Kawaguchi
6 | */
7 | public class TrafficAnalyzer {
8 | public static void main(String[] args) throws Exception {
9 | hudson.remoting.TrafficAnalyzer.main(args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/java/hudson/remoting/AbstractNioChannelRunner.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.util.concurrent.ExecutorService;
4 | import java.util.concurrent.Executors;
5 | import org.jenkinsci.remoting.nio.NioChannelHub;
6 |
7 | /**
8 | * @author Kohsuke Kawaguchi
9 | */
10 | public abstract class AbstractNioChannelRunner implements DualSideChannelRunner {
11 | protected ExecutorService executor = Executors.newCachedThreadPool();
12 | protected NioChannelHub nio;
13 | /**
14 | * failure occurred in the other {@link Channel}.
15 | */
16 | protected Throwable failure;
17 |
18 | protected Channel south;
19 |
20 | @Override
21 | public void stop(Channel channel) throws Exception {
22 | channel.close();
23 | channel.join();
24 |
25 | System.out.println("north completed");
26 |
27 | // we initiate the shutdown from north, so by the time it closes south should be all closed, too
28 | /* TODO passes reliably on Java 7 but often fails on Java 8
29 | assertTrue(south.isInClosed());
30 | assertTrue(south.isOutClosed());
31 | */
32 |
33 | nio.close();
34 | executor.shutdown();
35 |
36 | if (failure != null) {
37 | throw new AssertionError(failure); // report a failure in the south side
38 | }
39 | }
40 |
41 | @Override
42 | public Channel getOtherSide() {
43 | return south;
44 | }
45 |
46 | @Override
47 | public String toString() {
48 | return getName();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/hudson/remoting/CallableBase.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import org.jenkinsci.remoting.Role;
4 | import org.jenkinsci.remoting.RoleChecker;
5 |
6 | /**
7 | * @author Kohsuke Kawaguchi
8 | */
9 | public abstract class CallableBase implements Callable {
10 | @Override
11 | public void checkRoles(RoleChecker checker) throws SecurityException {
12 | checker.check(this, ROLE);
13 | }
14 |
15 | public static final Role ROLE = new Role("test callable");
16 | private static final long serialVersionUID = 1L;
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/java/hudson/remoting/ChannelRunners.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | import java.util.stream.Stream;
4 |
5 | public final class ChannelRunners {
6 | public static final String PROVIDER_METHOD = "hudson.remoting.ChannelRunners#provider";
7 |
8 | private ChannelRunners() {}
9 |
10 | @SuppressWarnings("unused") // used by JUnit
11 | public static Stream provider() {
12 | return Stream.of(
13 | new InProcessRunner(),
14 | new NioSocketRunner(),
15 | new NioPipeRunner(),
16 | new InProcessCompatibilityRunner(),
17 | new ForkRunner(),
18 | new ForkEBCDICRunner());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/hudson/remoting/Copier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.io.OutputStream;
29 |
30 | /**
31 | * Thread that copies a stream.
32 | *
33 | * @author Kohsuke Kawaguchi
34 | */
35 | class Copier extends Thread {
36 | private final InputStream in;
37 | private final OutputStream out;
38 |
39 | public Copier(String threadName, InputStream in, OutputStream out) {
40 | super(threadName);
41 | this.in = in;
42 | this.out = out;
43 | }
44 |
45 | @Override
46 | public void run() {
47 | try {
48 | byte[] buf = new byte[8192];
49 | int len;
50 | while ((len = in.read(buf)) > 0) {
51 | out.write(buf, 0, len);
52 | }
53 | in.close();
54 | } catch (IOException e) {
55 | // TODO: what to do?
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/hudson/remoting/DualSideChannelRunner.java:
--------------------------------------------------------------------------------
1 | package hudson.remoting;
2 |
3 | /**
4 | * Subset of {@link ChannelRunner} that provides in-memory access
5 | * to the other side, not just this side returned by {@link #start()}
6 | *
7 | * @author Kohsuke Kawaguchi
8 | */
9 | public interface DualSideChannelRunner extends ChannelRunner {
10 | Channel getOtherSide();
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/java/hudson/remoting/DummyClassLoaderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package hudson.remoting;
25 |
26 | import static org.junit.jupiter.api.Assertions.assertTrue;
27 |
28 | import org.junit.jupiter.api.Test;
29 |
30 | /**
31 | * @author Kohsuke Kawaguchi
32 | */
33 | public class DummyClassLoaderTest {
34 | @Test
35 | public void testLoad() throws Throwable {
36 | Callable