Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
0020ffe2
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0020ffe2
编写于
8月 07, 2017
作者:
I
igerasim
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8182125: Improve reliability of DNS lookups
Reviewed-by: chegar, rriggs, dfuchs
上级
bac6a91a
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
324 addition
and
46 deletion
+324
-46
src/share/classes/com/sun/jndi/dns/DNSDatagramSocketFactory.java
...re/classes/com/sun/jndi/dns/DNSDatagramSocketFactory.java
+246
-0
src/share/classes/com/sun/jndi/dns/DnsClient.java
src/share/classes/com/sun/jndi/dns/DnsClient.java
+49
-44
src/share/classes/com/sun/jndi/dns/ResourceRecord.java
src/share/classes/com/sun/jndi/dns/ResourceRecord.java
+29
-2
未找到文件。
src/share/classes/com/sun/jndi/dns/DNSDatagramSocketFactory.java
0 → 100644
浏览文件 @
0020ffe2
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
com.sun.jndi.dns
;
import
java.io.IOException
;
import
java.net.DatagramSocket
;
import
java.net.ProtocolFamily
;
import
java.net.SocketException
;
import
java.net.InetSocketAddress
;
import
java.nio.channels.DatagramChannel
;
import
java.util.Objects
;
import
java.util.Random
;
class
DNSDatagramSocketFactory
{
static
final
int
DEVIATION
=
3
;
static
final
int
THRESHOLD
=
6
;
static
final
int
BIT_DEVIATION
=
2
;
static
final
int
HISTORY
=
32
;
static
final
int
MAX_RANDOM_TRIES
=
5
;
/**
* The dynamic allocation port range (aka ephemeral ports), as configured
* on the system. Use nested class for lazy evaluation.
*/
static
final
class
EphemeralPortRange
{
private
EphemeralPortRange
()
{}
static
final
int
LOWER
=
sun
.
net
.
PortConfig
.
getLower
();
static
final
int
UPPER
=
sun
.
net
.
PortConfig
.
getUpper
();
static
final
int
RANGE
=
UPPER
-
LOWER
+
1
;
}
// Records a subset of max {@code capacity} previously used ports
static
final
class
PortHistory
{
final
int
capacity
;
final
int
[]
ports
;
final
Random
random
;
int
index
;
PortHistory
(
int
capacity
,
Random
random
)
{
this
.
random
=
random
;
this
.
capacity
=
capacity
;
this
.
ports
=
new
int
[
capacity
];
}
// returns true if the history contains the specified port.
public
boolean
contains
(
int
port
)
{
int
p
=
0
;
for
(
int
i
=
0
;
i
<
capacity
;
i
++)
{
if
((
p
=
ports
[
i
])
==
0
||
p
==
port
)
break
;
}
return
p
==
port
;
}
// Adds the port to the history - doesn't check whether the port
// is already present. Always adds the port and always return true.
public
boolean
add
(
int
port
)
{
if
(
ports
[
index
]
!=
0
)
{
// at max capacity
// remove one port at random and store the new port there
ports
[
random
.
nextInt
(
capacity
)]
=
port
;
}
else
{
// there's a free slot
ports
[
index
]
=
port
;
}
if
(++
index
==
capacity
)
index
=
0
;
return
true
;
}
// Adds the port to the history if not already present.
// Return true if the port was added, false if the port was already
// present.
public
boolean
offer
(
int
port
)
{
if
(
contains
(
port
))
return
false
;
else
return
add
(
port
);
}
}
int
lastport
=
0
;
int
suitablePortCount
;
int
unsuitablePortCount
;
final
ProtocolFamily
family
;
// null (default) means dual stack
final
int
thresholdCount
;
// decision point
final
int
deviation
;
final
Random
random
;
final
PortHistory
history
;
DNSDatagramSocketFactory
()
{
this
(
new
Random
());
}
DNSDatagramSocketFactory
(
Random
random
)
{
this
(
Objects
.
requireNonNull
(
random
),
null
,
DEVIATION
,
THRESHOLD
);
}
DNSDatagramSocketFactory
(
Random
random
,
ProtocolFamily
family
,
int
deviation
,
int
threshold
)
{
this
.
random
=
Objects
.
requireNonNull
(
random
);
this
.
history
=
new
PortHistory
(
HISTORY
,
random
);
this
.
family
=
family
;
this
.
deviation
=
Math
.
max
(
1
,
deviation
);
this
.
thresholdCount
=
Math
.
max
(
2
,
threshold
);
}
/**
* Opens a datagram socket listening to the wildcard address on a
* random port. If the underlying OS supports UDP port randomization
* out of the box (if binding a socket to port 0 binds it to a random
* port) then the underlying OS implementation is used. Otherwise, this
* method will allocate and bind a socket on a randomly selected ephemeral
* port in the dynamic range.
* @return A new DatagramSocket bound to a random port.
* @throws SocketException if the socket cannot be created.
*/
public
synchronized
DatagramSocket
open
()
throws
SocketException
{
int
lastseen
=
lastport
;
DatagramSocket
s
;
boolean
thresholdCrossed
=
unsuitablePortCount
>
thresholdCount
;
if
(
thresholdCrossed
)
{
// Underlying stack does not support random UDP port out of the box.
// Use our own algorithm to allocate a random UDP port
s
=
openRandom
();
if
(
s
!=
null
)
return
s
;
// couldn't allocate a random port: reset all counters and fall
// through.
unsuitablePortCount
=
0
;
suitablePortCount
=
0
;
lastseen
=
0
;
}
// Allocate an ephemeral port (port 0)
s
=
openDefault
();
lastport
=
s
.
getLocalPort
();
if
(
lastseen
==
0
)
{
history
.
offer
(
lastport
);
return
s
;
}
thresholdCrossed
=
suitablePortCount
>
thresholdCount
;
boolean
farEnough
=
Integer
.
bitCount
(
lastseen
^
lastport
)
>
BIT_DEVIATION
&&
Math
.
abs
(
lastport
-
lastseen
)
>
deviation
;
boolean
recycled
=
history
.
contains
(
lastport
);
boolean
suitable
=
(
thresholdCrossed
||
farEnough
&&
!
recycled
);
if
(
suitable
&&
!
recycled
)
history
.
add
(
lastport
);
if
(
suitable
)
{
if
(!
thresholdCrossed
)
{
suitablePortCount
++;
}
else
if
(!
farEnough
||
recycled
)
{
unsuitablePortCount
=
1
;
suitablePortCount
=
thresholdCount
/
2
;
}
// Either the underlying stack supports random UDP port allocation,
// or the new port is sufficiently distant from last port to make
// it look like it is. Let's use it.
return
s
;
}
// Undecided... the new port was too close. Let's allocate a random
// port using our own algorithm
assert
!
thresholdCrossed
;
DatagramSocket
ss
=
openRandom
();
if
(
ss
==
null
)
return
s
;
unsuitablePortCount
++;
s
.
close
();
return
ss
;
}
private
DatagramSocket
openDefault
()
throws
SocketException
{
if
(
family
!=
null
)
{
try
{
DatagramChannel
c
=
DatagramChannel
.
open
(
family
);
try
{
DatagramSocket
s
=
c
.
socket
();
s
.
bind
(
null
);
return
s
;
}
catch
(
Throwable
x
)
{
c
.
close
();
throw
x
;
}
}
catch
(
SocketException
x
)
{
throw
x
;
}
catch
(
IOException
x
)
{
SocketException
e
=
new
SocketException
(
x
.
getMessage
());
e
.
initCause
(
x
);
throw
e
;
}
}
return
new
DatagramSocket
();
}
synchronized
boolean
isUsingNativePortRandomization
()
{
return
unsuitablePortCount
<=
thresholdCount
&&
suitablePortCount
>
thresholdCount
;
}
synchronized
boolean
isUsingJavaPortRandomization
()
{
return
unsuitablePortCount
>
thresholdCount
;
}
synchronized
boolean
isUndecided
()
{
return
!
isUsingJavaPortRandomization
()
&&
!
isUsingNativePortRandomization
();
}
private
DatagramSocket
openRandom
()
{
int
maxtries
=
MAX_RANDOM_TRIES
;
while
(
maxtries
--
>
0
)
{
int
port
=
EphemeralPortRange
.
LOWER
+
random
.
nextInt
(
EphemeralPortRange
.
RANGE
);
try
{
if
(
family
!=
null
)
{
DatagramChannel
c
=
DatagramChannel
.
open
(
family
);
try
{
DatagramSocket
s
=
c
.
socket
();
s
.
bind
(
new
InetSocketAddress
(
port
));
return
s
;
}
catch
(
Throwable
x
)
{
c
.
close
();
throw
x
;
}
}
return
new
DatagramSocket
(
port
);
}
catch
(
IOException
x
)
{
// try again until maxtries == 0;
}
}
return
null
;
}
}
src/share/classes/com/sun/jndi/dns/DnsClient.java
浏览文件 @
0020ffe2
...
...
@@ -85,7 +85,9 @@ public class DnsClient {
private
int
timeout
;
// initial timeout on UDP queries in ms
private
int
retries
;
// number of UDP retries
private
DatagramSocket
udpSocket
;
private
final
Object
udpSocketLock
=
new
Object
();
private
static
final
DNSDatagramSocketFactory
factory
=
new
DNSDatagramSocketFactory
(
random
);
// Requests sent
private
Map
<
Integer
,
ResourceRecord
>
reqs
;
...
...
@@ -105,14 +107,6 @@ public class DnsClient {
throws
NamingException
{
this
.
timeout
=
timeout
;
this
.
retries
=
retries
;
try
{
udpSocket
=
new
DatagramSocket
();
}
catch
(
java
.
net
.
SocketException
e
)
{
NamingException
ne
=
new
ConfigurationException
();
ne
.
setRootCause
(
e
);
throw
ne
;
}
this
.
servers
=
new
InetAddress
[
servers
.
length
];
serverPorts
=
new
int
[
servers
.
length
];
...
...
@@ -142,6 +136,16 @@ public class DnsClient {
resps
=
Collections
.
synchronizedMap
(
new
HashMap
<
Integer
,
byte
[]>());
}
DatagramSocket
getDatagramSocket
()
throws
NamingException
{
try
{
return
factory
.
open
();
}
catch
(
java
.
net
.
SocketException
e
)
{
NamingException
ne
=
new
ConfigurationException
();
ne
.
setRootCause
(
e
);
throw
ne
;
}
}
protected
void
finalize
()
{
close
();
}
...
...
@@ -150,7 +154,6 @@ public class DnsClient {
private
Object
queuesLock
=
new
Object
();
public
void
close
()
{
udpSocket
.
close
();
synchronized
(
queuesLock
)
{
reqs
.
clear
();
resps
.
clear
();
...
...
@@ -392,7 +395,8 @@ public class DnsClient {
int
minTimeout
=
50
;
// msec after which there are no retries.
synchronized
(
udpSocket
)
{
synchronized
(
udpSocketLock
)
{
try
(
DatagramSocket
udpSocket
=
getDatagramSocket
())
{
DatagramPacket
opkt
=
new
DatagramPacket
(
pkt
.
getData
(),
pkt
.
length
(),
server
,
port
);
DatagramPacket
ipkt
=
new
DatagramPacket
(
new
byte
[
8000
],
8000
);
...
...
@@ -431,6 +435,7 @@ public class DnsClient {
return
null
;
// no matching packet received within the timeout
}
}
}
/*
* Sends a TCP query, and returns the first DNS message in the response.
...
...
src/share/classes/com/sun/jndi/dns/ResourceRecord.java
浏览文件 @
0020ffe2
/*
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
7
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -355,8 +355,19 @@ public class ResourceRecord {
pos
+=
typeAndLen
;
}
else
if
((
typeAndLen
&
0xC0
)
==
0xC0
)
{
// name compression
++
level
;
endPos
=
pos
+
2
;
// cater for the case where the name pointed to is itself
// compressed: we don't want endPos to be reset by the second
// compression level.
int
ppos
=
pos
;
if
(
endPos
==
-
1
)
endPos
=
pos
+
2
;
pos
=
getUShort
(
pos
)
&
0x3FFF
;
if
(
debug
)
{
dprint
(
"decode: name compression at "
+
ppos
+
" -> "
+
pos
+
" endPos="
+
endPos
);
assert
endPos
>
0
;
assert
pos
<
ppos
;
assert
pos
>=
Header
.
HEADER_SIZE
;
}
}
else
throw
new
IOException
(
"Invalid label type: "
+
typeAndLen
);
}
...
...
@@ -405,6 +416,11 @@ public class ResourceRecord {
}
}
// Unknown RR type/class
if
(
debug
)
{
dprint
(
"Unknown RR type for RR data: "
+
rrtype
+
" rdlen="
+
rdlen
+
", pos="
+
pos
+
", msglen="
+
msg
.
length
+
", remaining="
+
(
msg
.
length
-
pos
));
}
byte
[]
rd
=
new
byte
[
rdlen
];
System
.
arraycopy
(
msg
,
pos
,
rd
,
0
,
rdlen
);
return
rd
;
...
...
@@ -613,4 +629,15 @@ public class ResourceRecord {
return
buf
.
toString
();
}
//-------------------------------------------------------------------------
private
static
final
boolean
debug
=
false
;
private
static
void
dprint
(
String
mess
)
{
if
(
debug
)
{
System
.
err
.
println
(
"DNS: "
+
mess
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录