{"action":"created","comment":{"url":"https://api.github.com/repos/netty/netty/pulls/comments/73778086","id":73778086,"diff_hunk":"@@ -49,29 +53,87 @@ public void encodeRecord(DnsRecord record, ByteBuf out) throws Exception {\n             encodeQuestion((DnsQuestion) record, out);\n         } else if (record instanceof DnsPtrRecord) {\n             encodePtrRecord((DnsPtrRecord) record, out);\n+        } else if (record instanceof DnsOptEcsRecord) {\n+            encodeOptEcsRecord((DnsOptEcsRecord) record, out);\n+        } else if (record instanceof DnsOptPseudoRecord) {\n+            encodeOptPseudoRecord((DnsOptPseudoRecord) record, out);\n         } else if (record instanceof DnsRawRecord) {\n             encodeRawRecord((DnsRawRecord) record, out);\n         } else {\n             throw new UnsupportedMessageTypeException(StringUtil.simpleClassName(record));\n         }\n     }\n \n-    private void encodePtrRecord(DnsPtrRecord record, ByteBuf out) throws Exception {\n+    private void encodeRecord0(DnsRecord record, ByteBuf out) throws Exception {\n         encodeName(record.name(), out);\n-\n         out.writeShort(record.type().intValue());\n         out.writeShort(record.dnsClass());\n         out.writeInt((int) record.timeToLive());\n+    }\n \n+    private void encodePtrRecord(DnsPtrRecord record, ByteBuf out) throws Exception {\n+        encodeRecord0(record, out);\n         encodeName(record.hostname(), out);\n     }\n \n-    private void encodeRawRecord(DnsRawRecord record, ByteBuf out) throws Exception {\n-        encodeName(record.name(), out);\n+    private void encodeOptPseudoRecord(DnsOptPseudoRecord record, ByteBuf out) throws Exception {\n+        encodeRecord0(record, out);\n+        out.writeShort(0);\n+    }\n \n-        out.writeShort(record.type().intValue());\n-        out.writeShort(record.dnsClass());\n-        out.writeInt((int) record.timeToLive());\n+    private void encodeOptEcsRecord(DnsOptEcsRecord record, ByteBuf out) throws Exception {\n+        encodeRecord0(record, out);\n+\n+        int sourcePrefixLength = record.sourcePrefixLength();\n+        int scopePrefixLength = record.scopePrefixLength();\n+        int lowOrderBitsToPreserve = sourcePrefixLength & PREFIX_MASK;\n+        InetAddress address = record.address();\n+\n+        byte[] bytes = address.getAddress();\n+        int addressBits = bytes.length * Byte.SIZE;\n+        if (addressBits < sourcePrefixLength || sourcePrefixLength < 0) {\n+            throw new IllegalArgumentException(sourcePrefixLength + \": \"\n+                    + sourcePrefixLength + \" (expected: 0 >= \" + addressBits + ')');\n+        }\n+\n+        // See http://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml\n+        final short addressNumber = (short) InternetProtocolFamily.familyOf(address).addressNumber();\n+        int payloadLength = calculateEcsAddressLength(sourcePrefixLength, lowOrderBitsToPreserve);\n+\n+        int fullpayloadLength = 2 // OPTION-CODE\n+                + 2 // OPTION-LENGTH\n+                + 2 // FAMILY\n+                + 1 // SOURCE PREFIX-LENGTH\n+                + 1 // SCOPE PREFIX-LENGTH\n+                + payloadLength; //  ADDRESS...\n+\n+        out.writeShort(fullpayloadLength);\n+        out.writeShort(8); // This is the defined type for ECS.\n+\n+        out.writeShort(fullpayloadLength - 4); // Not include OPTION-CODE and OPTION-LENGTH\n+        out.writeShort(addressNumber);\n+        out.writeByte(sourcePrefixLength);\n+        out.writeByte(scopePrefixLength); // Must be 0 in queries.\n+\n+        if (lowOrderBitsToPreserve > 0) {\n+            int bytesLength = payloadLength - 1;\n+            out.writeBytes(bytes, 0, bytesLength);\n+\n+            // Pad the leftover of the last byte with zeros.\n+            out.writeByte(padWithZeros(bytes[bytesLength], lowOrderBitsToPreserve));\n+        } else {\n+            // The sourcePrefixLength align with Byte so just copy in the bytes directly.\n+            out.writeBytes(bytes, 0, payloadLength);\n+        }\n+    }\n+\n+    // Package-Private for testing\n+    static int calculateEcsAddressLength(int sourcePrefixLength, int lowOrderBitsToPreserve) {\n+        return sourcePrefixLength / Byte.SIZE + (lowOrderBitsToPreserve != 0 ? 1 : 0);","path":"codec-dns/src/main/java/io/netty/handler/codec/dns/DefaultDnsRecordEncoder.java","position":109,"original_position":109,"commit_id":"797e8c1f357df6a4e428e6006e368a54c1ebcc2a","original_commit_id":"797e8c1f357df6a4e428e6006e368a54c1ebcc2a","user":{"login":"Scottmitch","id":7562868,"avatar_url":"https://avatars.githubusercontent.com/u/7562868?v=3","gravatar_id":"","url":"https://api.github.com/users/Scottmitch","html_url":"https://github.com/Scottmitch","followers_url":"https://api.github.com/users/Scottmitch/followers","following_url":"https://api.github.com/users/Scottmitch/following{/other_user}","gists_url":"https://api.github.com/users/Scottmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/Scottmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Scottmitch/subscriptions","organizations_url":"https://api.github.com/users/Scottmitch/orgs","repos_url":"https://api.github.com/users/Scottmitch/repos","events_url":"https://api.github.com/users/Scottmitch/events{/privacy}","received_events_url":"https://api.github.com/users/Scottmitch/received_events","type":"User","site_admin":false},"body":"nit: `sourcePrefixLength >>> 3 /* sourcePrefixLength / Byte.SIZE */`","created_at":"2016-08-06T01:21:21Z","updated_at":"2016-08-06T01:21:21Z","html_url":"https://github.com/netty/netty/pull/5614#discussion_r73778086","pull_request_url":"https://api.github.com/repos/netty/netty/pulls/5614","_links":{"self":{"href":"https://api.github.com/repos/netty/netty/pulls/comments/73778086"},"html":{"href":"https://github.com/netty/netty/pull/5614#discussion_r73778086"},"pull_request":{"href":"https://api.github.com/repos/netty/netty/pulls/5614"}}},"pull_request":{"url":"https://api.github.com/repos/netty/netty/pulls/5614","id":79530321,"html_url":"https://github.com/netty/netty/pull/5614","diff_url":"https://github.com/netty/netty/pull/5614.diff","patch_url":"https://github.com/netty/netty/pull/5614.patch","issue_url":"https://api.github.com/repos/netty/netty/issues/5614","number":5614,"state":"open","locked":false,"title":"Add support for Client Subnet in DNS Queries (RFC7871)","user":{"login":"normanmaurer","id":439362,"avatar_url":"https://avatars.githubusercontent.com/u/439362?v=3","gravatar_id":"","url":"https://api.github.com/users/normanmaurer","html_url":"https://github.com/normanmaurer","followers_url":"https://api.github.com/users/normanmaurer/followers","following_url":"https://api.github.com/users/normanmaurer/following{/other_user}","gists_url":"https://api.github.com/users/normanmaurer/gists{/gist_id}","starred_url":"https://api.github.com/users/normanmaurer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/normanmaurer/subscriptions","organizations_url":"https://api.github.com/users/normanmaurer/orgs","repos_url":"https://api.github.com/users/normanmaurer/repos","events_url":"https://api.github.com/users/normanmaurer/events{/privacy}","received_events_url":"https://api.github.com/users/normanmaurer/received_events","type":"User","site_admin":false},"body":"Motivation:\r\n\r\nRFC7871 defines an extension which allows to request responses for a given subset.\r\n\r\nModifications:\r\n\r\n- Add DnsOptPseudoRrRecord which can act as base class for extensions based on EDNS(0) as defined in RFC6891\r\n- Add DnsOptEcsRecord to support the Client Subnet in DNS Queries extension\r\n- Add tests\r\n\r\nResult:\r\n\r\nClient Subnet in DNS Queries extension is now supported.","created_at":"2016-08-01T08:19:45Z","updated_at":"2016-08-06T01:21:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"13dd2a400888a2f1ab596e0db31022e28c607071","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/netty/netty/pulls/5614/commits","review_comments_url":"https://api.github.com/repos/netty/netty/pulls/5614/comments","review_comment_url":"https://api.github.com/repos/netty/netty/pulls/comments{/number}","comments_url":"https://api.github.com/repos/netty/netty/issues/5614/comments","statuses_url":"https://api.github.com/repos/netty/netty/statuses/797e8c1f357df6a4e428e6006e368a54c1ebcc2a","head":{"label":"netty:dns_rcs","ref":"dns_rcs","sha":"797e8c1f357df6a4e428e6006e368a54c1ebcc2a","user":{"login":"netty","id":473791,"avatar_url":"https://avatars.githubusercontent.com/u/473791?v=3","gravatar_id":"","url":"https://api.github.com/users/netty","html_url":"https://github.com/netty","followers_url":"https://api.github.com/users/netty/followers","following_url":"https://api.github.com/users/netty/following{/other_user}","gists_url":"https://api.github.com/users/netty/gists{/gist_id}","starred_url":"https://api.github.com/users/netty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/netty/subscriptions","organizations_url":"https://api.github.com/users/netty/orgs","repos_url":"https://api.github.com/users/netty/repos","events_url":"https://api.github.com/users/netty/events{/privacy}","received_events_url":"https://api.github.com/users/netty/received_events","type":"Organization","site_admin":false},"repo":{"id":1064563,"name":"netty","full_name":"netty/netty","owner":{"login":"netty","id":473791,"avatar_url":"https://avatars.githubusercontent.com/u/473791?v=3","gravatar_id":"","url":"https://api.github.com/users/netty","html_url":"https://github.com/netty","followers_url":"https://api.github.com/users/netty/followers","following_url":"https://api.github.com/users/netty/following{/other_user}","gists_url":"https://api.github.com/users/netty/gists{/gist_id}","starred_url":"https://api.github.com/users/netty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/netty/subscriptions","organizations_url":"https://api.github.com/users/netty/orgs","repos_url":"https://api.github.com/users/netty/repos","events_url":"https://api.github.com/users/netty/events{/privacy}","received_events_url":"https://api.github.com/users/netty/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/netty/netty","description":"Netty project - an event-driven asynchronous network application framework","fork":false,"url":"https://api.github.com/repos/netty/netty","forks_url":"https://api.github.com/repos/netty/netty/forks","keys_url":"https://api.github.com/repos/netty/netty/keys{/key_id}","collaborators_url":"https://api.github.com/repos/netty/netty/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/netty/netty/teams","hooks_url":"https://api.github.com/repos/netty/netty/hooks","issue_events_url":"https://api.github.com/repos/netty/netty/issues/events{/number}","events_url":"https://api.github.com/repos/netty/netty/events","assignees_url":"https://api.github.com/repos/netty/netty/assignees{/user}","branches_url":"https://api.github.com/repos/netty/netty/branches{/branch}","tags_url":"https://api.github.com/repos/netty/netty/tags","blobs_url":"https://api.github.com/repos/netty/netty/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/netty/netty/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/netty/netty/git/refs{/sha}","trees_url":"https://api.github.com/repos/netty/netty/git/trees{/sha}","statuses_url":"https://api.github.com/repos/netty/netty/statuses/{sha}","languages_url":"https://api.github.com/repos/netty/netty/languages","stargazers_url":"https://api.github.com/repos/netty/netty/stargazers","contributors_url":"https://api.github.com/repos/netty/netty/contributors","subscribers_url":"https://api.github.com/repos/netty/netty/subscribers","subscription_url":"https://api.github.com/repos/netty/netty/subscription","commits_url":"https://api.github.com/repos/netty/netty/commits{/sha}","git_commits_url":"https://api.github.com/repos/netty/netty/git/commits{/sha}","comments_url":"https://api.github.com/repos/netty/netty/comments{/number}","issue_comment_url":"https://api.github.com/repos/netty/netty/issues/comments{/number}","contents_url":"https://api.github.com/repos/netty/netty/contents/{+path}","compare_url":"https://api.github.com/repos/netty/netty/compare/{base}...{head}","merges_url":"https://api.github.com/repos/netty/netty/merges","archive_url":"https://api.github.com/repos/netty/netty/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/netty/netty/downloads","issues_url":"https://api.github.com/repos/netty/netty/issues{/number}","pulls_url":"https://api.github.com/repos/netty/netty/pulls{/number}","milestones_url":"https://api.github.com/repos/netty/netty/milestones{/number}","notifications_url":"https://api.github.com/repos/netty/netty/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/netty/netty/labels{/name}","releases_url":"https://api.github.com/repos/netty/netty/releases{/id}","deployments_url":"https://api.github.com/repos/netty/netty/deployments","created_at":"2010-11-09T09:22:21Z","updated_at":"2016-08-05T21:02:11Z","pushed_at":"2016-08-05T19:49:24Z","git_url":"git://github.com/netty/netty.git","ssh_url":"git@github.com:netty/netty.git","clone_url":"https://github.com/netty/netty.git","svn_url":"https://github.com/netty/netty","homepage":"http://netty.io/","size":70356,"stargazers_count":7489,"watchers_count":7489,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3806,"mirror_url":null,"open_issues_count":319,"forks":3806,"open_issues":319,"watchers":7489,"default_branch":"4.1"}},"base":{"label":"netty:4.1","ref":"4.1","sha":"a6dfd08812da2fc14aa048d5742ac077be2e6b3f","user":{"login":"netty","id":473791,"avatar_url":"https://avatars.githubusercontent.com/u/473791?v=3","gravatar_id":"","url":"https://api.github.com/users/netty","html_url":"https://github.com/netty","followers_url":"https://api.github.com/users/netty/followers","following_url":"https://api.github.com/users/netty/following{/other_user}","gists_url":"https://api.github.com/users/netty/gists{/gist_id}","starred_url":"https://api.github.com/users/netty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/netty/subscriptions","organizations_url":"https://api.github.com/users/netty/orgs","repos_url":"https://api.github.com/users/netty/repos","events_url":"https://api.github.com/users/netty/events{/privacy}","received_events_url":"https://api.github.com/users/netty/received_events","type":"Organization","site_admin":false},"repo":{"id":1064563,"name":"netty","full_name":"netty/netty","owner":{"login":"netty","id":473791,"avatar_url":"https://avatars.githubusercontent.com/u/473791?v=3","gravatar_id":"","url":"https://api.github.com/users/netty","html_url":"https://github.com/netty","followers_url":"https://api.github.com/users/netty/followers","following_url":"https://api.github.com/users/netty/following{/other_user}","gists_url":"https://api.github.com/users/netty/gists{/gist_id}","starred_url":"https://api.github.com/users/netty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/netty/subscriptions","organizations_url":"https://api.github.com/users/netty/orgs","repos_url":"https://api.github.com/users/netty/repos","events_url":"https://api.github.com/users/netty/events{/privacy}","received_events_url":"https://api.github.com/users/netty/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/netty/netty","description":"Netty project - an event-driven asynchronous network application framework","fork":false,"url":"https://api.github.com/repos/netty/netty","forks_url":"https://api.github.com/repos/netty/netty/forks","keys_url":"https://api.github.com/repos/netty/netty/keys{/key_id}","collaborators_url":"https://api.github.com/repos/netty/netty/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/netty/netty/teams","hooks_url":"https://api.github.com/repos/netty/netty/hooks","issue_events_url":"https://api.github.com/repos/netty/netty/issues/events{/number}","events_url":"https://api.github.com/repos/netty/netty/events","assignees_url":"https://api.github.com/repos/netty/netty/assignees{/user}","branches_url":"https://api.github.com/repos/netty/netty/branches{/branch}","tags_url":"https://api.github.com/repos/netty/netty/tags","blobs_url":"https://api.github.com/repos/netty/netty/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/netty/netty/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/netty/netty/git/refs{/sha}","trees_url":"https://api.github.com/repos/netty/netty/git/trees{/sha}","statuses_url":"https://api.github.com/repos/netty/netty/statuses/{sha}","languages_url":"https://api.github.com/repos/netty/netty/languages","stargazers_url":"https://api.github.com/repos/netty/netty/stargazers","contributors_url":"https://api.github.com/repos/netty/netty/contributors","subscribers_url":"https://api.github.com/repos/netty/netty/subscribers","subscription_url":"https://api.github.com/repos/netty/netty/subscription","commits_url":"https://api.github.com/repos/netty/netty/commits{/sha}","git_commits_url":"https://api.github.com/repos/netty/netty/git/commits{/sha}","comments_url":"https://api.github.com/repos/netty/netty/comments{/number}","issue_comment_url":"https://api.github.com/repos/netty/netty/issues/comments{/number}","contents_url":"https://api.github.com/repos/netty/netty/contents/{+path}","compare_url":"https://api.github.com/repos/netty/netty/compare/{base}...{head}","merges_url":"https://api.github.com/repos/netty/netty/merges","archive_url":"https://api.github.com/repos/netty/netty/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/netty/netty/downloads","issues_url":"https://api.github.com/repos/netty/netty/issues{/number}","pulls_url":"https://api.github.com/repos/netty/netty/pulls{/number}","milestones_url":"https://api.github.com/repos/netty/netty/milestones{/number}","notifications_url":"https://api.github.com/repos/netty/netty/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/netty/netty/labels{/name}","releases_url":"https://api.github.com/repos/netty/netty/releases{/id}","deployments_url":"https://api.github.com/repos/netty/netty/deployments","created_at":"2010-11-09T09:22:21Z","updated_at":"2016-08-05T21:02:11Z","pushed_at":"2016-08-05T19:49:24Z","git_url":"git://github.com/netty/netty.git","ssh_url":"git@github.com:netty/netty.git","clone_url":"https://github.com/netty/netty.git","svn_url":"https://github.com/netty/netty","homepage":"http://netty.io/","size":70356,"stargazers_count":7489,"watchers_count":7489,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3806,"mirror_url":null,"open_issues_count":319,"forks":3806,"open_issues":319,"watchers":7489,"default_branch":"4.1"}},"_links":{"self":{"href":"https://api.github.com/repos/netty/netty/pulls/5614"},"html":{"href":"https://github.com/netty/netty/pull/5614"},"issue":{"href":"https://api.github.com/repos/netty/netty/issues/5614"},"comments":{"href":"https://api.github.com/repos/netty/netty/issues/5614/comments"},"review_comments":{"href":"https://api.github.com/repos/netty/netty/pulls/5614/comments"},"review_comment":{"href":"https://api.github.com/repos/netty/netty/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/netty/netty/pulls/5614/commits"},"statuses":{"href":"https://api.github.com/repos/netty/netty/statuses/797e8c1f357df6a4e428e6006e368a54c1ebcc2a"}}}}
{"actor":{"display_login":"Scottmitch"}}