Boolean lIsSecure = false;
Long lSecNum1 = null;
Long lSecNum2 = null;
byte[] lSecKeyResp = new byte[8];
Map lRes = new FastMap();
int lReqLen = aReq.length;
String lRequest = "";
try {
lRequest = new String(aReq, "US-ASCII");
} catch (Exception ex) {
// TODO: add exception handling
}
if (lRequest.indexOf("policy-file-request") >= 0) { // "<policy-file-request/>"
lRes.put("policy-file-request", lRequest);
return lRes;
}
lIsSecure = (lRequest.indexOf("Sec-WebSocket") > 0);
if (lIsSecure) {
lReqLen -= 8;
for (int i = 0; i < 8; i++) {
lSecKey3[i] = aReq[lReqLen + i];
}
}
// now parse header for correct handshake....
// get host....
int lPos = lRequest.indexOf("Host:");
lPos += 6;
lHost = lRequest.substring(lPos);
lPos = lHost.indexOf("\r\n");
lHost = lHost.substring(0, lPos);
// get origin....
lPos = lRequest.indexOf("Origin:");
lPos += 8;
lOrigin = lRequest.substring(lPos);
lPos = lOrigin.indexOf("\r\n");
lOrigin = lOrigin.substring(0, lPos);
// get path....
lPos = lRequest.indexOf("GET");
lPos += 4;
lPath = lRequest.substring(lPos);
lPos = lPath.indexOf("HTTP");
lPath = lPath.substring(0, lPos - 1);
lLocation = "ws://" + lHost + lPath;
// the following section implements the sec-key process in WebSocket
// Draft 76
/*
* To prove that the handshake was received, the server has to take
* three pieces of information and combine them to form a response. The
* first two pieces of information come from the |Sec-WebSocket-Key1|
* and |Sec-WebSocket-Key2| fields in the client handshake.
*
* Sec-WebSocket-Key1: 18x 6]8vM;54 *(5: { U1]8 z [ 8
* Sec-WebSocket-Key2: 1_ tx7X d < nw 334J702) 7]o}` 0
*
* For each of these fields, the server has to take the digits from the
* value to obtain a number (in this case 1868545188 and 1733470270
* respectively), then divide that number by the number of spaces
* characters in the value (in this case 12 and 10) to obtain a 32-bit
* number (155712099 and 173347027). These two resulting numbers are
* then used in the server handshake, as described below.
*/
lPos = lRequest.indexOf("Sec-WebSocket-Key1:");
if (lPos > 0) {
lPos += 20;
lSecKey1 = lRequest.substring(lPos);
lPos = lSecKey1.indexOf("\r\n");
lSecKey1 = lSecKey1.substring(0, lPos);
lSecNum1 = calcSecKeyNum(lSecKey1);
// log.debug("Sec-WebSocket-Key1:" + secKey1 + " => " + secNum1);
}
lPos = lRequest.indexOf("Sec-WebSocket-Key2:");
if (lPos > 0) {
lPos += 20;
lSecKey2 = lRequest.substring(lPos);
lPos = lSecKey2.indexOf("\r\n");
lSecKey2 = lSecKey2.substring(0, lPos);
lSecNum2 = calcSecKeyNum(lSecKey2);
// log.debug("Sec-WebSocket-Key2:" + secKey2 + " => " + secNum2);
}
/*
* The third piece of information is given after the fields, in the last
* eight bytes of the handshake, expressed here as they would be seen if
* interpreted as ASCII: Tm[K T2u The concatenation of the number
* obtained from processing the |Sec- WebSocket-Key1| field, expressed
* as a big-endian 32 bit number, the number obtained from processing
* the |Sec-WebSocket-Key2| field, again expressed as a big-endian 32
* bit number, and finally the eight bytes at the end of the handshake,
* form a 128 bit string whose MD5 sum is then used by the server to
* prove that it read the handshake.
*/
if (lSecNum1 != null && lSecNum2 != null) {
// log.debug("Sec-WebSocket-Key3:" + new String(secKey3, "UTF-8"));
BigInteger sec1 = new BigInteger(lSecNum1.toString());
BigInteger sec2 = new BigInteger(lSecNum2.toString());
// concatenate 3 parts secNum1 + secNum2 + secKey (16 Bytes)
byte[] l128Bit = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] lTmp;
int lOfs;
lTmp = sec1.toByteArray();
int lIdx = lTmp.length;
int lCnt = 0;
while(lIdx > 0 && lCnt < 4) {
lIdx--;
lCnt++;
l128Bit[4 - lCnt] = lTmp[lIdx];
}
lTmp = sec2.toByteArray();
lIdx = lTmp.length;
lCnt = 0;
while(lIdx > 0 && lCnt < 4) {
lIdx--;
lCnt++;
l128Bit[8 - lCnt] = lTmp[lIdx];
}
lTmp = lSecKey3;
System.arraycopy(lSecKey3, 0, l128Bit, 8, 8);
/*
// TODO: replace by arraycopy
for (int i = 0; i < 8; i++) {
l128Bit[i + 8] = lTmp[i];
}
*/
// build md5 sum of this new 128 byte string
try {
MessageDigest md = MessageDigest.getInstance("MD5");
lSecKeyResp = md.digest(l128Bit);
} catch (Exception ex) {
// log.error("getMD5: " + ex.getMessage());
}
}
lRes.put("path", lPath);
lRes.put("host", lHost);
lRes.put("origin", lOrigin);
lRes.put("location", lLocation);
lRes.put("secKey1", lSecKey1);
lRes.put("secKey2", lSecKey2);
lRes.put("isSecure", lIsSecure);
lRes.put("secKeyResponse", lSecKeyResp);
return lRes;
}