{"action":"created","comment":{"url":"https://api.github.com/repos/jenkinsci/remoting/pulls/comments/74017037","id":74017037,"diff_hunk":"@@ -0,0 +1,286 @@\n+/*\n+ * The MIT License\n+ *\n+ * Copyright (c) 2016, CloudBees, Inc.\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be included in\n+ * all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ * THE SOFTWARE.\n+ */\n+package hudson.remoting;\n+\n+import java.io.IOException;\n+import java.io.ObjectOutputStream;\n+import java.nio.ByteBuffer;\n+import java.util.Arrays;\n+import java.util.logging.Level;\n+import java.util.logging.Logger;\n+import javax.annotation.Nonnull;\n+import org.jenkinsci.remoting.util.ByteBufferQueue;\n+import org.jenkinsci.remoting.util.ByteBufferQueueOutputStream;\n+import org.jenkinsci.remoting.util.FastByteBufferQueueInputStream;\n+import org.jenkinsci.remoting.util.IOUtils;\n+\n+/**\n+ * A {@link CommandTransport} that uses {@link ByteBuffer} rather than {@link byte[]}.\n+ *\n+ * @since FIXME\n+ */\n+public abstract class AbstractByteBufferCommandTransport extends CommandTransport {\n+\n+    /**\n+     * Our logger.\n+     */\n+    private static final Logger LOGGER = Logger.getLogger(AbstractByteBufferCommandTransport.class.getName());\n+    /**\n+     * The {@link #readState} when waiting for a frame header.\n+     */\n+    private static final int READ_STATE_NEED_HEADER = 0;\n+    /**\n+     * The {@link #readState} when waiting for the remaining byte of a frame header.\n+     */\n+    private static final int READ_STATE_MORE_HEADER = 1;\n+    /**\n+     * The {@link #readState} when waiting for {@link #readFrameRemaining} more bytes of frame body.\n+     */\n+    private static final int READ_STATE_FRAME_BODY = 2;\n+    /**\n+     * The {@link #readState} when a whole command has been read.\n+     */\n+    private static final int READ_STATE_COMMAND_READY = 3;\n+    /**\n+     * Our channel.\n+     */\n+    protected Channel channel;\n+    /**\n+     * The chunk header buffer.\n+     */\n+    private final ByteBuffer writeChunkHeader = ByteBuffer.allocate(2);\n+    /**\n+     * The transport frame size.\n+     */\n+    private int transportFrameSize = 8192;\n+    /**\n+     * The chunk body.\n+     */\n+    private ByteBuffer writeChunkBody = ByteBuffer.allocate(transportFrameSize);\n+    /**\n+     * The delegate, this is required as we cannot access some of the methods of {@link ChunkHeader} outside of the\n+     * remoting module.\n+     */\n+    private CommandReceiver receiver;\n+    /**\n+     * The queue of data that has been received and is waiting to be processed.\n+     */\n+    private final ByteBufferQueue receiveQueue = new ByteBufferQueue(transportFrameSize);\n+    /**\n+     * Internal tracking of the read state. We use primitive field rather than an enum to enhance data locality\n+     */\n+    private int readState;\n+    /**\n+     * When {@link #readState} is {@link #READ_STATE_FRAME_BODY} this is the number of remaining bytes in the current\n+     * frame.\n+     */\n+    private int readFrameRemaining;\n+    /**\n+     * When {@link #readState} is {@link #READ_STATE_MORE_HEADER} this is the first byte of the header,\n+     * when {@link #READ_STATE_FRAME_BODY} this is the {@link ChunkHeader#parse(int, int)} parsed header.\n+     */\n+    private int readFrameHeader;\n+    /**\n+     * The offset in {@link #readCommandSizes} holding the current command length.\n+     */\n+    private int readCommandIndex = 0;\n+    /**\n+     * The command lengths read in so far. Normally we just use index 0 but there is the case where some commands\n+     * may have arrived prior to {@link #setup(Channel, CommandReceiver)} in which case we just have to buffer all\n+     * the commands we get and parse them later.\n+     */\n+    private int[] readCommandSizes = new int[16];\n+    /**\n+     * The queue used to stage output.\n+     */\n+    private ByteBufferQueue sendStaging = new ByteBufferQueue(transportFrameSize);\n+\n+    /**\n+     * Write the packet.\n+     *\n+     * @param header the header to write.\n+     * @param data   the data to write.\n+     * @throws IOException if the data could not be written.\n+     */\n+    protected abstract void write(ByteBuffer header, ByteBuffer data) throws IOException;","path":"src/main/java/hudson/remoting/AbstractByteBufferCommandTransport.java","position":126,"original_position":126,"commit_id":"debffeeea965afd02a0124e38640df6066c0e084","original_commit_id":"debffeeea965afd02a0124e38640df6066c0e084","user":{"login":"oleg-nenashev","id":3000480,"avatar_url":"https://avatars.githubusercontent.com/u/3000480?v=3","gravatar_id":"","url":"https://api.github.com/users/oleg-nenashev","html_url":"https://github.com/oleg-nenashev","followers_url":"https://api.github.com/users/oleg-nenashev/followers","following_url":"https://api.github.com/users/oleg-nenashev/following{/other_user}","gists_url":"https://api.github.com/users/oleg-nenashev/gists{/gist_id}","starred_url":"https://api.github.com/users/oleg-nenashev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleg-nenashev/subscriptions","organizations_url":"https://api.github.com/users/oleg-nenashev/orgs","repos_url":"https://api.github.com/users/oleg-nenashev/repos","events_url":"https://api.github.com/users/oleg-nenashev/events{/privacy}","received_events_url":"https://api.github.com/users/oleg-nenashev/received_events","type":"User","site_admin":false},"body":"So InterruptedException is not an option here? The API is not symmetric then, and this command transport may be not so good for sync protocols","created_at":"2016-08-09T08:22:45Z","updated_at":"2016-08-09T08:22:45Z","html_url":"https://github.com/jenkinsci/remoting/pull/92#discussion_r74017037","pull_request_url":"https://api.github.com/repos/jenkinsci/remoting/pulls/92","_links":{"self":{"href":"https://api.github.com/repos/jenkinsci/remoting/pulls/comments/74017037"},"html":{"href":"https://github.com/jenkinsci/remoting/pull/92#discussion_r74017037"},"pull_request":{"href":"https://api.github.com/repos/jenkinsci/remoting/pulls/92"}}},"pull_request":{"url":"https://api.github.com/repos/jenkinsci/remoting/pulls/92","id":79050780,"html_url":"https://github.com/jenkinsci/remoting/pull/92","diff_url":"https://github.com/jenkinsci/remoting/pull/92.diff","patch_url":"https://github.com/jenkinsci/remoting/pull/92.patch","issue_url":"https://api.github.com/repos/jenkinsci/remoting/issues/92","number":92,"state":"open","locked":false,"title":"[JENKINS-36871] JNLPProtocol4","user":{"login":"stephenc","id":209336,"avatar_url":"https://avatars.githubusercontent.com/u/209336?v=3","gravatar_id":"","url":"https://api.github.com/users/stephenc","html_url":"https://github.com/stephenc","followers_url":"https://api.github.com/users/stephenc/followers","following_url":"https://api.github.com/users/stephenc/following{/other_user}","gists_url":"https://api.github.com/users/stephenc/gists{/gist_id}","starred_url":"https://api.github.com/users/stephenc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephenc/subscriptions","organizations_url":"https://api.github.com/users/stephenc/orgs","repos_url":"https://api.github.com/users/stephenc/repos","events_url":"https://api.github.com/users/stephenc/events{/privacy}","received_events_url":"https://api.github.com/users/stephenc/received_events","type":"User","site_admin":false},"body":"This is a JNLP protocol that uses TLS upgrade over the plaintext socket before exchanging any connection secrets and allows for end-to-end security leveraging the TLS certificates on the Jenkins master HTTPS end-point where the master is using TLS on the web UI.\r\n\r\nInitial measurements show that the TLS encryption using SSLEngine coupled with the ByteBuffer backed NIO implementation does not seem to have any negative performance impact. Additionally the new NIO implementation shows significantly better scalability and performance due to the offloading of I/O processing to the worker threads (this was necessary for to use SSLEngine, but a nice side-effect when compared with the previous NIO implementation (i.e. JNLPProtocol2) which does the actual I/O processing on the selector thread and thus can cause excessive transport delays when the selector thread becomes overloaded)\r\n\r\nSee [JENKINS-36871](https://issues.jenkins-ci.org/browse/JENKINS-36871) for the tracking issue.\r\n\r\nThis code is being contributed to the Jenkins Community by CloudBees, Inc. (though some of this code was work developed by me in personal time, but I am contributing that to the Jenkins Community anyway)\r\n\r\nWork in progress while I complete our internal process for all the files required to be released.","created_at":"2016-07-27T15:59:01Z","updated_at":"2016-08-09T08:22:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"90db5508e255e01a57c28021084f496dd682a2cd","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/jenkinsci/remoting/pulls/92/commits","review_comments_url":"https://api.github.com/repos/jenkinsci/remoting/pulls/92/comments","review_comment_url":"https://api.github.com/repos/jenkinsci/remoting/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jenkinsci/remoting/issues/92/comments","statuses_url":"https://api.github.com/repos/jenkinsci/remoting/statuses/debffeeea965afd02a0124e38640df6066c0e084","head":{"label":"jenkinsci:jenkins-36871","ref":"jenkins-36871","sha":"debffeeea965afd02a0124e38640df6066c0e084","user":{"login":"jenkinsci","id":107424,"avatar_url":"https://avatars.githubusercontent.com/u/107424?v=3","gravatar_id":"","url":"https://api.github.com/users/jenkinsci","html_url":"https://github.com/jenkinsci","followers_url":"https://api.github.com/users/jenkinsci/followers","following_url":"https://api.github.com/users/jenkinsci/following{/other_user}","gists_url":"https://api.github.com/users/jenkinsci/gists{/gist_id}","starred_url":"https://api.github.com/users/jenkinsci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jenkinsci/subscriptions","organizations_url":"https://api.github.com/users/jenkinsci/orgs","repos_url":"https://api.github.com/users/jenkinsci/repos","events_url":"https://api.github.com/users/jenkinsci/events{/privacy}","received_events_url":"https://api.github.com/users/jenkinsci/received_events","type":"Organization","site_admin":false},"repo":{"id":2040168,"name":"remoting","full_name":"jenkinsci/remoting","owner":{"login":"jenkinsci","id":107424,"avatar_url":"https://avatars.githubusercontent.com/u/107424?v=3","gravatar_id":"","url":"https://api.github.com/users/jenkinsci","html_url":"https://github.com/jenkinsci","followers_url":"https://api.github.com/users/jenkinsci/followers","following_url":"https://api.github.com/users/jenkinsci/following{/other_user}","gists_url":"https://api.github.com/users/jenkinsci/gists{/gist_id}","starred_url":"https://api.github.com/users/jenkinsci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jenkinsci/subscriptions","organizations_url":"https://api.github.com/users/jenkinsci/orgs","repos_url":"https://api.github.com/users/jenkinsci/repos","events_url":"https://api.github.com/users/jenkinsci/events{/privacy}","received_events_url":"https://api.github.com/users/jenkinsci/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jenkinsci/remoting","description":"Jenkins remoting module","fork":false,"url":"https://api.github.com/repos/jenkinsci/remoting","forks_url":"https://api.github.com/repos/jenkinsci/remoting/forks","keys_url":"https://api.github.com/repos/jenkinsci/remoting/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jenkinsci/remoting/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jenkinsci/remoting/teams","hooks_url":"https://api.github.com/repos/jenkinsci/remoting/hooks","issue_events_url":"https://api.github.com/repos/jenkinsci/remoting/issues/events{/number}","events_url":"https://api.github.com/repos/jenkinsci/remoting/events","assignees_url":"https://api.github.com/repos/jenkinsci/remoting/assignees{/user}","branches_url":"https://api.github.com/repos/jenkinsci/remoting/branches{/branch}","tags_url":"https://api.github.com/repos/jenkinsci/remoting/tags","blobs_url":"https://api.github.com/repos/jenkinsci/remoting/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jenkinsci/remoting/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jenkinsci/remoting/git/refs{/sha}","trees_url":"https://api.github.com/repos/jenkinsci/remoting/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jenkinsci/remoting/statuses/{sha}","languages_url":"https://api.github.com/repos/jenkinsci/remoting/languages","stargazers_url":"https://api.github.com/repos/jenkinsci/remoting/stargazers","contributors_url":"https://api.github.com/repos/jenkinsci/remoting/contributors","subscribers_url":"https://api.github.com/repos/jenkinsci/remoting/subscribers","subscription_url":"https://api.github.com/repos/jenkinsci/remoting/subscription","commits_url":"https://api.github.com/repos/jenkinsci/remoting/commits{/sha}","git_commits_url":"https://api.github.com/repos/jenkinsci/remoting/git/commits{/sha}","comments_url":"https://api.github.com/repos/jenkinsci/remoting/comments{/number}","issue_comment_url":"https://api.github.com/repos/jenkinsci/remoting/issues/comments{/number}","contents_url":"https://api.github.com/repos/jenkinsci/remoting/contents/{+path}","compare_url":"https://api.github.com/repos/jenkinsci/remoting/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jenkinsci/remoting/merges","archive_url":"https://api.github.com/repos/jenkinsci/remoting/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jenkinsci/remoting/downloads","issues_url":"https://api.github.com/repos/jenkinsci/remoting/issues{/number}","pulls_url":"https://api.github.com/repos/jenkinsci/remoting/pulls{/number}","milestones_url":"https://api.github.com/repos/jenkinsci/remoting/milestones{/number}","notifications_url":"https://api.github.com/repos/jenkinsci/remoting/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jenkinsci/remoting/labels{/name}","releases_url":"https://api.github.com/repos/jenkinsci/remoting/releases{/id}","deployments_url":"https://api.github.com/repos/jenkinsci/remoting/deployments","created_at":"2011-07-13T05:06:16Z","updated_at":"2016-08-08T19:47:25Z","pushed_at":"2016-08-08T15:25:36Z","git_url":"git://github.com/jenkinsci/remoting.git","ssh_url":"git@github.com:jenkinsci/remoting.git","clone_url":"https://github.com/jenkinsci/remoting.git","svn_url":"https://github.com/jenkinsci/remoting","homepage":"http://jenkins-ci.org/","size":3014,"stargazers_count":43,"watchers_count":43,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":74,"mirror_url":null,"open_issues_count":6,"forks":74,"open_issues":6,"watchers":43,"default_branch":"master"}},"base":{"label":"jenkinsci:master","ref":"master","sha":"4f8bf8eb9765dab1bccce5e3819f7f4cd7113f63","user":{"login":"jenkinsci","id":107424,"avatar_url":"https://avatars.githubusercontent.com/u/107424?v=3","gravatar_id":"","url":"https://api.github.com/users/jenkinsci","html_url":"https://github.com/jenkinsci","followers_url":"https://api.github.com/users/jenkinsci/followers","following_url":"https://api.github.com/users/jenkinsci/following{/other_user}","gists_url":"https://api.github.com/users/jenkinsci/gists{/gist_id}","starred_url":"https://api.github.com/users/jenkinsci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jenkinsci/subscriptions","organizations_url":"https://api.github.com/users/jenkinsci/orgs","repos_url":"https://api.github.com/users/jenkinsci/repos","events_url":"https://api.github.com/users/jenkinsci/events{/privacy}","received_events_url":"https://api.github.com/users/jenkinsci/received_events","type":"Organization","site_admin":false},"repo":{"id":2040168,"name":"remoting","full_name":"jenkinsci/remoting","owner":{"login":"jenkinsci","id":107424,"avatar_url":"https://avatars.githubusercontent.com/u/107424?v=3","gravatar_id":"","url":"https://api.github.com/users/jenkinsci","html_url":"https://github.com/jenkinsci","followers_url":"https://api.github.com/users/jenkinsci/followers","following_url":"https://api.github.com/users/jenkinsci/following{/other_user}","gists_url":"https://api.github.com/users/jenkinsci/gists{/gist_id}","starred_url":"https://api.github.com/users/jenkinsci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jenkinsci/subscriptions","organizations_url":"https://api.github.com/users/jenkinsci/orgs","repos_url":"https://api.github.com/users/jenkinsci/repos","events_url":"https://api.github.com/users/jenkinsci/events{/privacy}","received_events_url":"https://api.github.com/users/jenkinsci/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jenkinsci/remoting","description":"Jenkins remoting module","fork":false,"url":"https://api.github.com/repos/jenkinsci/remoting","forks_url":"https://api.github.com/repos/jenkinsci/remoting/forks","keys_url":"https://api.github.com/repos/jenkinsci/remoting/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jenkinsci/remoting/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jenkinsci/remoting/teams","hooks_url":"https://api.github.com/repos/jenkinsci/remoting/hooks","issue_events_url":"https://api.github.com/repos/jenkinsci/remoting/issues/events{/number}","events_url":"https://api.github.com/repos/jenkinsci/remoting/events","assignees_url":"https://api.github.com/repos/jenkinsci/remoting/assignees{/user}","branches_url":"https://api.github.com/repos/jenkinsci/remoting/branches{/branch}","tags_url":"https://api.github.com/repos/jenkinsci/remoting/tags","blobs_url":"https://api.github.com/repos/jenkinsci/remoting/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jenkinsci/remoting/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jenkinsci/remoting/git/refs{/sha}","trees_url":"https://api.github.com/repos/jenkinsci/remoting/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jenkinsci/remoting/statuses/{sha}","languages_url":"https://api.github.com/repos/jenkinsci/remoting/languages","stargazers_url":"https://api.github.com/repos/jenkinsci/remoting/stargazers","contributors_url":"https://api.github.com/repos/jenkinsci/remoting/contributors","subscribers_url":"https://api.github.com/repos/jenkinsci/remoting/subscribers","subscription_url":"https://api.github.com/repos/jenkinsci/remoting/subscription","commits_url":"https://api.github.com/repos/jenkinsci/remoting/commits{/sha}","git_commits_url":"https://api.github.com/repos/jenkinsci/remoting/git/commits{/sha}","comments_url":"https://api.github.com/repos/jenkinsci/remoting/comments{/number}","issue_comment_url":"https://api.github.com/repos/jenkinsci/remoting/issues/comments{/number}","contents_url":"https://api.github.com/repos/jenkinsci/remoting/contents/{+path}","compare_url":"https://api.github.com/repos/jenkinsci/remoting/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jenkinsci/remoting/merges","archive_url":"https://api.github.com/repos/jenkinsci/remoting/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jenkinsci/remoting/downloads","issues_url":"https://api.github.com/repos/jenkinsci/remoting/issues{/number}","pulls_url":"https://api.github.com/repos/jenkinsci/remoting/pulls{/number}","milestones_url":"https://api.github.com/repos/jenkinsci/remoting/milestones{/number}","notifications_url":"https://api.github.com/repos/jenkinsci/remoting/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jenkinsci/remoting/labels{/name}","releases_url":"https://api.github.com/repos/jenkinsci/remoting/releases{/id}","deployments_url":"https://api.github.com/repos/jenkinsci/remoting/deployments","created_at":"2011-07-13T05:06:16Z","updated_at":"2016-08-08T19:47:25Z","pushed_at":"2016-08-08T15:25:36Z","git_url":"git://github.com/jenkinsci/remoting.git","ssh_url":"git@github.com:jenkinsci/remoting.git","clone_url":"https://github.com/jenkinsci/remoting.git","svn_url":"https://github.com/jenkinsci/remoting","homepage":"http://jenkins-ci.org/","size":3014,"stargazers_count":43,"watchers_count":43,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":74,"mirror_url":null,"open_issues_count":6,"forks":74,"open_issues":6,"watchers":43,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jenkinsci/remoting/pulls/92"},"html":{"href":"https://github.com/jenkinsci/remoting/pull/92"},"issue":{"href":"https://api.github.com/repos/jenkinsci/remoting/issues/92"},"comments":{"href":"https://api.github.com/repos/jenkinsci/remoting/issues/92/comments"},"review_comments":{"href":"https://api.github.com/repos/jenkinsci/remoting/pulls/92/comments"},"review_comment":{"href":"https://api.github.com/repos/jenkinsci/remoting/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jenkinsci/remoting/pulls/92/commits"},"statuses":{"href":"https://api.github.com/repos/jenkinsci/remoting/statuses/debffeeea965afd02a0124e38640df6066c0e084"}}}}
{"actor":{"display_login":"oleg-nenashev"}}