-
Notifications
You must be signed in to change notification settings - Fork 0
/
Main.java
118 lines (99 loc) · 5.37 KB
/
Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package javachr.examples.webserver;
import javachr.RuleApplicator;
import javachr.SimpleRuleApplicator;
import javachr.constraints.Constraint;
import javachr.rules.Propagation;
import javachr.rules.Rule;
import javachr.rules.Simplification;
import javachr.rules.head.Head;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Logger;
public class Main {
public static final int PORT = 8080;
public static final Logger LOG = Logger.getLogger("ServerLog");
public static void main(String[] args) throws IOException {
// Accept connection (ONLY ACCEPTS ONE!)
Rule acceptConnection = new Simplification("Accept Connection", Head.ofType(ServerSocket.class))
.body((head, newConstraints) -> { // Add connection constraint if connection incoming.
try {
Socket conn = ((ServerSocket) head[0].get()).accept();
if (conn != null){
newConstraints.add(new Constraint<>(new Connection(conn)));
LOG.info("New connection opened");
}
} catch (IOException e) {
// Don't log; it just tells that accept timed out
}
newConstraints.add(head[0]);
});
// Receive some bytes
Rule readFromConnection = new Propagation("Read from connection", Head.ofType(Connection.class))
.guard(head -> ((Connection) head[0].get()).hasReceivedBytes())
.body(((head, newConstraints) -> {
LOG.info("Read from connection");
((Connection) head[0].get()).readAll();
LOG.info("Read complete");
}));
// Kick incomplete corrupt messages
Rule kickIncomplete = new Simplification("Kick incomplete", Head.ofType(Connection.class))
.guard(head -> !((Connection) head[0].get()).isMessageComplete())
.body((head, newConstraints) -> ((Connection) head[0].get()).close());
// Parse request, kick it if invalid, otherwise create HTTP Request object
Rule parseRequest = new Simplification("Parse request", Head.ofType(Connection.class))
.guard(head -> ((Connection) head[0].get()).isMessageComplete())
.body((head, newConstraints) -> {
Connection connection = (Connection) head[0].get();
HTTP_Request request = connection.getRequest();
newConstraints.add(new Constraint<>(request));
LOG.info("Got request: \n" + connection.getRequest().toString());
});
// Remove invalid requests
Rule kickRequest = new Simplification("Kick request", Head.ofType(HTTP_Request.class))
.guard(head -> ! ((HTTP_Request) head[0].get()).isValid())
.body((head, newConstraints) -> {
LOG.warning("Got invalid request!");
try {
((HTTP_Request) head[0].get()).getSender().close();
} catch (IOException e) {
e.printStackTrace();
}
});
// Create response object
Rule createResponse = new Simplification("Create response", Head.ofType(HTTP_Request.class))
.body((head, newConstraints) -> {
HTTP_Request request = (HTTP_Request) head[0].get();
HTTP_Response response = request.getResponse();
newConstraints.add(new Constraint<>(response));
LOG.info("Created response: " + response.toString().split("\r\n")[0]);
});
// Send response
Rule sendResponse = new Simplification("Send response", Head.ofType(HTTP_Response.class))
.body((head, newConstraints) -> {
HTTP_Response response = (HTTP_Response) head[0].get();
assert !response.getSender().isClosed();
try (Socket client = response.getSender();
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream())) {
out.write(response.getResponse());
LOG.info("Response sent successfully!");
} catch (IOException e) {
LOG.warning("Sending response failed: " + e);
e.printStackTrace();
}
});
LOG.info("Start server on port " + PORT + " ...");
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
serverSocket.setSoTimeout(10); // makes accept() block only 10ms
RuleApplicator solver = new SimpleRuleApplicator(readFromConnection,
parseRequest,
kickIncomplete,
createResponse,
kickRequest,
sendResponse,
acceptConnection);
solver.execute(serverSocket);
}
}
}