Skip to content
This repository was archived by the owner on Jul 31, 2022. It is now read-only.

Commit 11f4410

Browse files
committed
Implement #53
1 parent d035c4d commit 11f4410

File tree

8 files changed

+457
-32
lines changed

8 files changed

+457
-32
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.kttdevelopment</groupId>
88
<artifactId>simplehttpserver</artifactId>
9-
<version>03.04.03</version>
9+
<version>03.05.00</version>
1010
<packaging>jar</packaging>
1111

1212
<url>https://github.com/Ktt-Development/simplehttpserver</url>

src/main/java/com/kttdevelopment/simplehttpserver/handler/ConnectionThrottler.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
/**
66
* Determines how connections are handled by the {@link ThrottledHandler}.
77
*
8-
* @see ServerThrottler
8+
* @see ThrottledHandler
9+
* @see ExchangeThrottler
10+
* @see ServerExchangeThrottler
911
* @see SessionThrottler
12+
* @see ServerSessionThrottler
1013
* @since 03.03.00
11-
* @version 03.03.00
14+
* @version 03.05.00
1215
* @author Ktt Development
1316
*/
1417
abstract class ConnectionThrottler {
@@ -19,7 +22,9 @@ abstract class ConnectionThrottler {
1922
* @param exchange exchange to process
2023
* @return if exchange was able to be added
2124
*
25+
* @see HttpExchange
2226
* @see #deleteConnection(HttpExchange)
27+
* @see #getMaxConnections(HttpExchange)
2328
* @since 03.03.00
2429
* @author Ktt Development
2530
*/
@@ -30,10 +35,26 @@ abstract class ConnectionThrottler {
3035
*
3136
* @param exchange exchange to process
3237
*
38+
* @see HttpExchange
3339
* @see #addConnection(HttpExchange)
40+
* @see #getMaxConnections(HttpExchange)
3441
* @since 03.03.00
3542
* @author Ktt Development
3643
*/
3744
abstract void deleteConnection(final HttpExchange exchange);
3845

46+
/**
47+
* Returns the maximum number of connections for an exchange. A value of <code>-1</code> means unlimited connections.
48+
*
49+
* @param exchange exchange to process
50+
* @return maximum number of connections allowed
51+
*
52+
* @see HttpExchange
53+
* @see #addConnection(HttpExchange)
54+
* @see #deleteConnection(HttpExchange)
55+
* @since 03.05.00
56+
* @author Ktt Development
57+
*/
58+
abstract int getMaxConnections(final HttpExchange exchange);
59+
3960
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.kttdevelopment.simplehttpserver.handler;
2+
3+
import com.sun.net.httpserver.HttpExchange;
4+
5+
import java.net.InetAddress;
6+
import java.util.Map;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.concurrent.atomic.AtomicBoolean;
9+
import java.util.concurrent.atomic.AtomicInteger;
10+
11+
/**
12+
* Limits connections per address to the server.
13+
*
14+
* @see HttpExchange
15+
* @see ThrottledHandler
16+
* @see ServerThrottler
17+
* @see SessionThrottler
18+
* @since 03.05.00
19+
* @version 03.05.00
20+
* @author Ktt Development
21+
*/
22+
public class ExchangeThrottler extends ConnectionThrottler {
23+
24+
private final Map<InetAddress,AtomicInteger> connections = new ConcurrentHashMap<>();
25+
26+
@Override
27+
final boolean addConnection(final HttpExchange exchange){
28+
final InetAddress address = exchange.getRemoteAddress().getAddress();
29+
final int maxConn = getMaxConnections(exchange);
30+
31+
if(!connections.containsKey(address))
32+
connections.put(address,new AtomicInteger(0));
33+
34+
final AtomicInteger conn = connections.get(address);
35+
36+
if(maxConn < 0){
37+
conn.incrementAndGet();
38+
return true;
39+
}else{
40+
final AtomicBoolean added = new AtomicBoolean(false);
41+
conn.updateAndGet(operand -> {
42+
if(operand < maxConn) added.set(true);
43+
return operand < maxConn ? operand + 1 : operand;
44+
});
45+
return added.get();
46+
}
47+
}
48+
49+
@Override
50+
final void deleteConnection(final HttpExchange exchange){
51+
final InetAddress address = exchange.getRemoteAddress().getAddress();
52+
if(connections.containsKey(address))
53+
connections.get(address).decrementAndGet();
54+
}
55+
56+
@Override
57+
int getMaxConnections(final HttpExchange exchange){
58+
return -1;
59+
}
60+
61+
@Override
62+
public String toString(){
63+
final StringBuilder OUT = new StringBuilder();
64+
65+
OUT.append("ExchangeThrottler") .append('{');
66+
OUT.append("connections") .append('=') .append(connections.toString());
67+
OUT.append('}');
68+
69+
return OUT.toString();
70+
}
71+
72+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.kttdevelopment.simplehttpserver.handler;
2+
3+
import com.sun.net.httpserver.HttpExchange;
4+
5+
import java.net.InetAddress;
6+
import java.util.Map;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.concurrent.atomic.AtomicBoolean;
9+
import java.util.concurrent.atomic.AtomicInteger;
10+
11+
/**
12+
* Limits connections per address to the server and total server connections.
13+
*
14+
* @see HttpExchange
15+
* @see ThrottledHandler
16+
* @see ExchangeThrottler
17+
* @since 03.05.00
18+
* @version 03.05.00
19+
* @author Ktt Development
20+
*/
21+
public class ServerExchangeThrottler extends ConnectionThrottler {
22+
23+
private final Map<InetAddress, AtomicInteger> connections = new ConcurrentHashMap<>();
24+
25+
private final AtomicInteger uConn = new AtomicInteger(0);
26+
private final AtomicInteger uConnMax = new AtomicInteger(0);
27+
28+
@Override
29+
final boolean addConnection(final HttpExchange exchange){
30+
final InetAddress address = exchange.getRemoteAddress().getAddress();
31+
final int maxConn = getMaxConnections(exchange);
32+
33+
if(!connections.containsKey(address))
34+
connections.put(address,new AtomicInteger(0));
35+
36+
final AtomicInteger conn = connections.get(address);
37+
final boolean exempt = canIgnoreConnectionLimit(exchange);
38+
39+
if(maxConn < 0){
40+
if(!exempt){
41+
synchronized(this){
42+
final int umax = uConnMax.get();
43+
if(umax < 0 || uConn.get() < umax){
44+
conn.incrementAndGet();
45+
uConn.incrementAndGet();
46+
return true;
47+
}
48+
return false;
49+
}
50+
}else{
51+
conn.incrementAndGet();
52+
return true;
53+
}
54+
}else{
55+
if(!exempt){
56+
synchronized(this){
57+
final int umax = uConnMax.get();
58+
if(conn.get() < maxConn && (umax < 0 || uConn.get() < umax)){
59+
conn.incrementAndGet();
60+
uConn.incrementAndGet();
61+
return true;
62+
}
63+
return false;
64+
}
65+
}else{
66+
final AtomicBoolean added = new AtomicBoolean(false);
67+
conn.updateAndGet(operand -> {
68+
if(operand < maxConn) added.set(true);
69+
return operand < maxConn ? operand + 1 : operand;
70+
});
71+
return added.get();
72+
}
73+
}
74+
}
75+
76+
@Override
77+
final void deleteConnection(final HttpExchange exchange){
78+
final InetAddress address = exchange.getRemoteAddress().getAddress();
79+
if(connections.containsKey(address)){
80+
connections.get(address).decrementAndGet();
81+
if(!canIgnoreConnectionLimit(exchange))
82+
uConn.decrementAndGet();
83+
}
84+
}
85+
86+
@Override
87+
int getMaxConnections(final HttpExchange exchange){
88+
return -1;
89+
}
90+
91+
/**
92+
* Returns if an exchange is exempt from the server connection limit only.
93+
*
94+
* @param exchange exchange to process
95+
* @return if exchange ignores server connection limit
96+
*
97+
* @see HttpExchange
98+
* @since 03.05.00
99+
* @author Ktt Development
100+
*/
101+
boolean canIgnoreConnectionLimit(final HttpExchange exchange){
102+
return false;
103+
}
104+
105+
/**
106+
* Sets the maximum number of connections the server can have. A value of <code>-1</code> means unlimited connections.
107+
*
108+
* @param connections maximum number of connections allowed on the server
109+
*
110+
* @see #getMaxConnections(HttpExchange)
111+
* @since 03.05.00
112+
* @author Ktt Development
113+
*/
114+
public synchronized final void setMaxServerConnections(final int connections){
115+
uConnMax.set(connections);
116+
}
117+
118+
/**
119+
* Returns the maximum number of connections the server can have.
120+
*
121+
* @return maximum number of connections allowed on th server
122+
*
123+
* @see #setMaxServerConnections(int)
124+
* @since 03.05.00
125+
* @author Ktt Development
126+
*/
127+
public synchronized final int getMaxServerConnections(){
128+
return uConnMax.get();
129+
}
130+
131+
}

0 commit comments

Comments
 (0)