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

Commit 670f94d

Browse files
authored
Merge pull request #55 from Ktt-Development/throttler-update
Add ExchangeThrottler, ServerExchangeThrottler, ServerSessionThrottler
2 parents c7ce5ba + b41c414 commit 670f94d

File tree

7 files changed

+540
-37
lines changed

7 files changed

+540
-37
lines changed

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+
public abstract int getMaxConnections(final HttpExchange exchange);
59+
3960
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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 ServerExchangeThrottler
17+
* @see SessionThrottler
18+
* @see ServerSessionThrottler
19+
* @since 03.05.00
20+
* @version 03.05.00
21+
* @author Ktt Development
22+
*/
23+
public class ExchangeThrottler extends ConnectionThrottler {
24+
25+
private final Map<InetAddress,AtomicInteger> connections = new ConcurrentHashMap<>();
26+
27+
/**
28+
* Creates a throttler with limits on each exchange.
29+
*
30+
* @since 03.05.00
31+
* @author Ktt Development
32+
*/
33+
public ExchangeThrottler(){ }
34+
35+
@Override
36+
final boolean addConnection(final HttpExchange exchange){
37+
final InetAddress address = exchange.getRemoteAddress().getAddress();
38+
final int maxConn = getMaxConnections(exchange);
39+
40+
if(!connections.containsKey(address))
41+
connections.put(address,new AtomicInteger(0));
42+
43+
final AtomicInteger conn = connections.get(address);
44+
45+
if(maxConn < 0){
46+
conn.incrementAndGet();
47+
return true;
48+
}else{
49+
final AtomicBoolean added = new AtomicBoolean(false);
50+
conn.updateAndGet(operand -> {
51+
if(operand < maxConn) added.set(true);
52+
return operand < maxConn ? operand + 1 : operand;
53+
});
54+
return added.get();
55+
}
56+
}
57+
58+
@Override
59+
final void deleteConnection(final HttpExchange exchange){
60+
final InetAddress address = exchange.getRemoteAddress().getAddress();
61+
if(connections.containsKey(address))
62+
connections.get(address).decrementAndGet();
63+
}
64+
65+
@Override
66+
public int getMaxConnections(final HttpExchange exchange){
67+
return -1;
68+
}
69+
70+
@Override
71+
public String toString(){
72+
return
73+
"Exchange Throttler" + '{' +
74+
"connections" + '=' + connections.toString() +
75+
'}';
76+
}
77+
78+
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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+
* @see SessionThrottler
18+
* @see ServerSessionThrottler
19+
* @since 03.05.00
20+
* @version 03.05.00
21+
* @author Ktt Development
22+
*/
23+
public class ServerExchangeThrottler extends ConnectionThrottler {
24+
25+
private final Map<InetAddress, AtomicInteger> connections = new ConcurrentHashMap<>();
26+
27+
private final AtomicInteger uConn = new AtomicInteger(0);
28+
private final AtomicInteger uConnMax = new AtomicInteger(-1);
29+
30+
/**
31+
* Creates a throttler with connection limits on user and total connections.
32+
*
33+
* @since 03.05.00
34+
* @author Ktt Development
35+
*/
36+
public ServerExchangeThrottler(){ }
37+
38+
/**
39+
* Creates a throttler with connection limits on user and total connections.
40+
*
41+
* @param maxConnections maximum allowed server connections
42+
*
43+
* @since 03.05.00
44+
* @author Ktt Development
45+
*/
46+
public ServerExchangeThrottler(final int maxConnections){
47+
uConnMax.set(maxConnections);
48+
}
49+
50+
@Override
51+
final boolean addConnection(final HttpExchange exchange){
52+
final InetAddress address = exchange.getRemoteAddress().getAddress();
53+
final int maxConn = getMaxConnections(exchange);
54+
55+
if(!connections.containsKey(address))
56+
connections.put(address,new AtomicInteger(0));
57+
58+
final AtomicInteger conn = connections.get(address);
59+
final boolean exempt = canIgnoreConnectionLimit(exchange);
60+
61+
if(maxConn < 0){
62+
if(!exempt){
63+
synchronized(this){
64+
final int umax = uConnMax.get();
65+
if(umax < 0 || uConn.get() < umax){
66+
conn.incrementAndGet();
67+
uConn.incrementAndGet();
68+
return true;
69+
}
70+
return false;
71+
}
72+
}else{
73+
conn.incrementAndGet();
74+
return true;
75+
}
76+
}else{
77+
if(!exempt){
78+
synchronized(this){
79+
final int umax = uConnMax.get();
80+
if(conn.get() < maxConn && (umax < 0 || uConn.get() < umax)){
81+
conn.incrementAndGet();
82+
uConn.incrementAndGet();
83+
return true;
84+
}
85+
return false;
86+
}
87+
}else{
88+
final AtomicBoolean added = new AtomicBoolean(false);
89+
conn.updateAndGet(operand -> {
90+
if(operand < maxConn) added.set(true);
91+
return operand < maxConn ? operand + 1 : operand;
92+
});
93+
return added.get();
94+
}
95+
}
96+
}
97+
98+
@Override
99+
final void deleteConnection(final HttpExchange exchange){
100+
final InetAddress address = exchange.getRemoteAddress().getAddress();
101+
if(connections.containsKey(address)){
102+
connections.get(address).decrementAndGet();
103+
if(!canIgnoreConnectionLimit(exchange))
104+
uConn.decrementAndGet();
105+
}
106+
}
107+
108+
@Override
109+
public int getMaxConnections(final HttpExchange exchange){
110+
return -1;
111+
}
112+
113+
/**
114+
* Returns if an exchange is exempt from the server connection limit only.
115+
*
116+
* @param exchange exchange to process
117+
* @return if exchange ignores server connection limit
118+
*
119+
* @see HttpExchange
120+
* @since 03.05.00
121+
* @author Ktt Development
122+
*/
123+
public boolean canIgnoreConnectionLimit(final HttpExchange exchange){
124+
return false;
125+
}
126+
127+
/**
128+
* Sets the maximum number of connections the server can have. A value of <code>-1</code> means unlimited connections.
129+
*
130+
* @param connections maximum number of connections allowed on the server
131+
*
132+
* @see #getMaxConnections(HttpExchange)
133+
* @since 03.05.00
134+
* @author Ktt Development
135+
*/
136+
public synchronized final void setMaxServerConnections(final int connections){
137+
uConnMax.set(connections);
138+
}
139+
140+
/**
141+
* Returns the maximum number of connections the server can have.
142+
*
143+
* @return maximum number of connections allowed on th server
144+
*
145+
* @see #setMaxServerConnections(int)
146+
* @since 03.05.00
147+
* @author Ktt Development
148+
*/
149+
public synchronized final int getMaxServerConnections(){
150+
return uConnMax.get();
151+
}
152+
153+
@Override
154+
public String toString(){
155+
return
156+
"ServerExchangeThrottler" + '{' +
157+
"connections" + '=' + connections.toString() + ", " +
158+
"userConnections" + '=' + uConn + ", " +
159+
"userConnectionsMax" + '=' + uConnMax +
160+
'}';
161+
}
162+
163+
}

0 commit comments

Comments
 (0)