-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEchoLineReadWriteHandler.java
More file actions
165 lines (125 loc) · 4.17 KB
/
EchoLineReadWriteHandler.java
File metadata and controls
165 lines (125 loc) · 4.17 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import java.nio.*;
import java.nio.channels.*;
import java.io.IOException;
public class EchoLineReadWriteHandler implements IReadWriteHandler {
private ByteBuffer inBuffer;
private ByteBuffer outBuffer;
private boolean requestComplete;
private boolean responseReady;
private boolean responseSent;
private boolean channelClosed;
private StringBuffer request;
// private enum State {
// READ_REQUEST, REQUEST_COMPLETE, GENERATING_RESPONSE, RESPONSE_READY,
// RESPONSE_SENT
// }
// private State state;
public EchoLineReadWriteHandler() {
inBuffer = ByteBuffer.allocate(4096);
outBuffer = ByteBuffer.allocate(4096);
// initial state
requestComplete = false;
responseReady = false;
responseSent = false;
channelClosed = false;
request = new StringBuffer(4096);
}
public int getInitOps() {
return SelectionKey.OP_READ;
}
public void handleException() {
}
public void handleRead(SelectionKey key) throws IOException {
// a connection is ready to be read
Debug.DEBUG("->handleRead");
if (requestComplete) { // this call should not happen, ignore
return;
}
// process data
processInBuffer(key);
// update state
updateState(key);
Debug.DEBUG("handleRead->");
} // end of handleRead
private void updateState(SelectionKey key) throws IOException {
Debug.DEBUG("->Update dispatcher.");
if (channelClosed)
return;
/*
* if (responseSent) { Debug.DEBUG(
* "***Response sent; shutdown connection"); client.close();
* dispatcher.deregisterSelection(sk); channelClosed = true; return; }
*/
int nextState = key.interestOps();
if (requestComplete) {
nextState = nextState & ~SelectionKey.OP_READ;
Debug.DEBUG("New state: -Read since request parsed complete");
} else {
nextState = nextState | SelectionKey.OP_READ;
Debug.DEBUG("New state: +Read to continue to read");
}
if (responseReady) {
if (!responseSent) {
nextState = nextState | SelectionKey.OP_WRITE;
Debug.DEBUG("New state: +Write since response ready but not done sent");
} else {
nextState = nextState & ~SelectionKey.OP_WRITE;
Debug.DEBUG("New state: -Write since response ready and sent");
}
}
key.interestOps(nextState);
}
public void handleWrite(SelectionKey key) throws IOException {
Debug.DEBUG("->handleWrite");
// process data
SocketChannel client = (SocketChannel) key.channel();
Debug.DEBUG("handleWrite: Write data to connection " + client + "; from buffer " + outBuffer);
int writeBytes = client.write(outBuffer);
Debug.DEBUG("handleWrite: write " + writeBytes + " bytes; after write " + outBuffer);
if (responseReady && (outBuffer.remaining() == 0)) {
responseSent = true;
Debug.DEBUG("handleWrite: responseSent");
}
// update state
updateState(key);
// try {Thread.sleep(5000);} catch (InterruptedException e) {}
Debug.DEBUG("handleWrite->");
} // end of handleWrite
private void processInBuffer(SelectionKey key) throws IOException {
Debug.DEBUG("processInBuffer");
SocketChannel client = (SocketChannel) key.channel();
int readBytes = client.read(inBuffer);
Debug.DEBUG("handleRead: Read data from connection " + client + " for " + readBytes + " byte(s); to buffer "
+ inBuffer);
if (readBytes == -1) { // end of stream
requestComplete = true;
Debug.DEBUG("handleRead: readBytes == -1");
} else {
inBuffer.flip(); // read input
// outBuffer = ByteBuffer.allocate( inBuffer.remaining() );
while (!requestComplete && inBuffer.hasRemaining() && request.length() < request.capacity()) {
char ch = (char) inBuffer.get();
Debug.DEBUG("Ch: " + ch);
request.append(ch);
if (ch == '\r' || ch == '\n') {
requestComplete = true;
// client.shutdownInput();
Debug.DEBUG("handleRead: find terminating chars");
} // end if
} // end of while
}
inBuffer.clear(); // we do not keep things in the inBuffer
if (requestComplete) {
generateResponse();
}
} // end of process input
private void generateResponse() {
for (int i = 0; i < request.length(); i++) {
char ch = (char) request.charAt(i);
ch = Character.toUpperCase(ch);
outBuffer.put((byte) ch);
}
outBuffer.flip();
responseReady = true;
} // end of generate response
}