/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* src/com/vodafone360/people/VODAFONE.LICENSE.txt or
* http://github.com/360/360-Engine-for-Android
* See the License for the specific language governing permissions and
* limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each file and
* include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the fields
* enclosed by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved.
* Use is subject to license terms.
*/
package com.vodafone360.people.service.transport.tcp;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;
import com.vodafone360.people.datatypes.AuthSessionHolder;
import com.vodafone360.people.engine.login.LoginEngine;
import com.vodafone360.people.service.io.rpg.RpgHeader;
import com.vodafone360.people.service.io.rpg.RpgMessageTypes;
import com.vodafone360.people.service.transport.http.HttpConnectionThread;
import com.vodafone360.people.service.utils.hessian.HessianEncoder;
public class ConnectionTester {
/**
* We wait at least 59 seconds for a response from the server. After that we
* return false.
*/
private static final int MAX_TEST_RESPONSE_WAIT_TIME_MILLIS = 59 * 1000; // 59 seconds
private DataInputStream mIs;
private OutputStream mOs;
public ConnectionTester(InputStream is, OutputStream os) {
mIs = new DataInputStream(is);
mOs = os;
}
/**
* Starts a test by sending a test message to the RPG, which the RPG should
* reply to.
*
* @return True if the test succeeded, false if the RPG did not respond in a
* correct manner.
*/
public boolean runTest() {
if ((null == mIs) || (null == mOs)) {
return false;
}
if (!sendTestMessage()) {
HttpConnectionThread.logE("ConnectionTester.runTest()", "Could not send test message.",
null);
return false;
}
if (!receiveTestResponse()) {
HttpConnectionThread.logE("ConnectionTester.runTest()",
"Did not receive test response.", null);
return false;
}
return true;
}
/**
* Attempts to send a TCP test message (type 101) to the RPG.
*
* @return True if sending happened without any exceptions false otherwise.
*/
private boolean sendTestMessage() {
try {
HttpConnectionThread.logI("ConnectionTester.sentTestMessage()", "Sending TCP test request...");
byte[] payload = getConnectionTestHessianPayload();
mOs.write(payload);
} catch (IOException ioe) {
return false;
} catch (Exception e) {
return false;
} finally {
mOs = null; // clear reference
}
return true;
}
/**
* Attempts to read any valid RPG response (even if it is not the requested TCP test
* response)
*
* @return True if we were able to receive an RPG response, otherwise false will
* be returned.
*/
private boolean receiveTestResponse() {
int waitingTimeMillis = 0;
try {
// wait until we have bytes available or we have waited for MAX_WAIT_TIME_MILLIS
while (mIs.available() <= 0) {
if (waitingTimeMillis <= MAX_TEST_RESPONSE_WAIT_TIME_MILLIS) {
try {
Thread.sleep(200);
waitingTimeMillis += 200;
} catch (InterruptedException ie) {
}
} else {
return false; // we timed out waiting for bytes
}
}
} catch (IOException ioe) {
return false;
} finally {
mIs = null; // clear reference
}
HttpConnectionThread.logI("ConnectionTester.receiveTestResponse()", "Connection test successful!!");
return true;
}
/**
* Returns a byte-array containing the data needed for sending a connection
* test to the RPG.
*
* @throws IOException If there was an exception serializing the hash map to
* a hessian byte array.
* @return A byte array representing the connection test request.
*/
private byte[] getConnectionTestHessianPayload() throws IOException {
// hash table for parameters to Hessian encode
final Hashtable<String, Object> ht = new Hashtable<String, Object>();
final AuthSessionHolder auth = LoginEngine.getSession();
ht.put("userid", auth.userID);
// do Hessian encoding
final byte[] payload = HessianEncoder.createHessianByteArray("", ht);
payload[1] = (byte)1;
payload[2] = (byte)0;
final int reqLength = RpgHeader.HEADER_LENGTH + payload.length;
final RpgHeader rpgHeader = new RpgHeader();
rpgHeader.setPayloadLength(payload.length);
rpgHeader.setReqType(RpgMessageTypes.RPG_TCP_CONNECTION_TEST);
final byte[] rpgMsg = new byte[reqLength];
System.arraycopy(rpgHeader.createHeader(), 0, rpgMsg, 0, RpgHeader.HEADER_LENGTH);
if (null != payload) {
System.arraycopy(payload, 0, rpgMsg, RpgHeader.HEADER_LENGTH, payload.length);
}
return rpgMsg;
}
}