1 package com.ericsson.research.transport.ws.spi;
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 import java.io.IOException;
37 import java.io.OutputStream;
38
39 import com.ericsson.research.transport.ws.WSException;
40 import com.ericsson.research.transport.ws.WSSecurityContext;
41 import com.ericsson.research.transport.ws.WSURI;
42
43 public abstract class WSAbstractProtocol extends WSAbstractProtocolWrapper implements WSConstants {
44
45 public static final int HANDSHAKING = 0;
46 public static final int OPEN = 1;
47 public static final int CLOSING = 2;
48 public static final int CLOSED = 3;
49
50 protected int state = HANDSHAKING;
51
52 protected WSAbstractHandshake handshake;
53 protected byte[] buf = empty;
54 protected WSAbstractFrame currentFrame;
55
56 protected boolean client;
57
58 protected String host;
59 protected String resource;
60 protected int port;
61 protected String origin;
62 protected String location;
63 protected String protocol;
64 protected final WSSecurityContext securityContext;
65
66 protected WSAbstractProtocolWrapper wrapper;
67
68 public WSAbstractProtocol(WSURI uri, WSSecurityContext securityContext) {
69 host = uri.getHost();
70 origin = "http://"+host;
71 port = uri.getPort();
72 resource = uri.getPath();
73 client = true;
74 this.securityContext = securityContext;
75 }
76
77 public WSAbstractProtocol(WSSecurityContext securityContext) {
78 this.securityContext = securityContext;
79 }
80
81 protected void setWrapper(WSAbstractProtocolWrapper wrapper) {
82 this.wrapper = wrapper;
83 }
84
85 public String getState() {
86 switch (state) {
87 case HANDSHAKING:
88 return "HANDSHAKING";
89 case OPEN:
90 return "OPEN";
91 case CLOSING:
92 return "CLOSING";
93 case CLOSED:
94 return "CLOSED";
95 }
96 return "UKNOWN";
97 }
98
99 public synchronized void close() {
100 if (state == CLOSED || state == CLOSING)
101 return;
102 state = CLOSING;
103 forceClose();
104 }
105
106 public void forceClose() {
107 wrapper.forceClose();
108 }
109
110 public OutputStream getRawOutput() throws IOException {
111 return wrapper.getRawOutput();
112 }
113
114 public void notifyConnected() {
115 try {
116 if(client)
117 getHandshake().sendHandshake(getRawOutput());
118 } catch(IOException e) {
119 notifyError(e);
120 }
121 }
122
123 public void notifyDisconnected() {
124 state = CLOSED;
125 wrapper.notifyClose();
126 }
127
128 public void notifySocketData(byte[] data, int length) {
129 try {
130 if(length == 0)
131 return;
132 byte[] newbuf = new byte[buf.length + length];
133 if(buf.length > 0)
134 System.arraycopy(buf, 0, newbuf, 0, buf.length);
135 System.arraycopy(data, 0, newbuf, buf.length, length);
136 buf = newbuf;
137 int read;
138 do {
139 if(state == HANDSHAKING)
140 read = getHandshake().deserialize(buf, buf.length);
141 else {
142 if(currentFrame == null)
143 currentFrame = createEmptyFrame();
144 read = currentFrame.deserialize(buf, buf.length);
145 }
146 if(read > 0) {
147 if(read == buf.length) {
148 buf = empty;
149 read = 0;
150 } else {
151 newbuf = new byte[buf.length - read];
152 System.arraycopy(buf, read, newbuf, 0, newbuf.length);
153 buf = newbuf;
154 }
155 if(state == HANDSHAKING) {
156
157
158
159 WSAbstractProtocol newProtocol = getHandshake().protocol;
160 wrapper.setProtocol(newProtocol);
161 if(!client)
162 getHandshake().sendResponse();
163 newProtocol.state = OPEN;
164 newProtocol.wrapper.notifyOpen(newProtocol.wrapper);
165 if(read > 0 && newProtocol != this) {
166 newProtocol.wrapper.notifySocketData(buf, buf.length);
167 return;
168 }
169 } else {
170 dispatchFrame(currentFrame);
171 currentFrame = null;
172 }
173 }
174 } while(read > 0);
175 } catch(Exception e) {
176 notifyError(e);
177 }
178 }
179
180 protected abstract WSAbstractHandshake getHandshake();
181 protected abstract WSAbstractFrame createEmptyFrame();
182 protected abstract void dispatchFrame(WSAbstractFrame frame) throws IOException, WSException;
183
184 }