Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions timer/src/org/jeffpiazza/derby/ClientSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ private Element makeRequest(URL url, String method, List<String> headers,
do {
connection = (HttpURLConnection) url.openConnection();

// Log default timeout values before setting them
int defaultConnectTimeout = connection.getConnectTimeout();
int defaultReadTimeout = connection.getReadTimeout();
LogWriter.info("Default timeouts - Connect: " + defaultConnectTimeout + "ms, Read: " + defaultReadTimeout + "ms");
System.err.println(Timestamp.string() + ": Default timeouts - Connect: " + defaultConnectTimeout + "ms, Read: " + defaultReadTimeout + "ms");

// Set timeouts to prevent hanging when server is unresponsive
connection.setConnectTimeout(10000); // 10 seconds to establish connection
connection.setReadTimeout(5000); // 5 seconds to read response

connection.setRequestMethod(method);
connection.addRequestProperty("User-Agent",
"derby-timer.jar/" + Version.get());
Expand Down Expand Up @@ -240,6 +250,16 @@ private JSONObject makeJsonRequest(URL url, String method, List<String> headers,
do {
connection = (HttpURLConnection) url.openConnection();

// Log default timeout values before setting them
int defaultConnectTimeout = connection.getConnectTimeout();
int defaultReadTimeout = connection.getReadTimeout();
LogWriter.info("Default timeouts - Connect: " + defaultConnectTimeout + "ms, Read: " + defaultReadTimeout + "ms");
System.err.println(Timestamp.string() + ": Default timeouts - Connect: " + defaultConnectTimeout + "ms, Read: " + defaultReadTimeout + "ms");

// Set timeouts to prevent hanging when server is unresponsive
connection.setConnectTimeout(10000); // 10 seconds to establish connection
connection.setReadTimeout(5000); // 5 seconds to read response

connection.setRequestMethod(method);
connection.addRequestProperty("User-Agent",
"derby-timer.jar/" + Version.get());
Expand Down
69 changes: 67 additions & 2 deletions timer/src/org/jeffpiazza/derby/HttpTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public class HttpTask implements Runnable {
private RemoteStartCallback remoteStartCallback;
private AssignPortCallback assignPortCallback;
private AssignDeviceCallback assignDeviceCallback;
// Store credentials for automatic re-authentication
private String role;
private String password;

public static final long heartbeatPace = 500; // ms.

Expand Down Expand Up @@ -94,16 +97,18 @@ public void run() {

if (login_ok) {
callback.onLoginSuccess();
HttpTask task = new HttpTask(session);
HttpTask task = new HttpTask(session, role, password);
connector.setHttpTask(task);
task.run();
}
}
}).start();
}

public HttpTask(ClientSession session) {
public HttpTask(ClientSession session, String role, String password) {
this.session = session;
this.role = role;
this.password = password;
this.queue = new ArrayList<Message>();
synchronized (queue) {
queueMessage(new Message.Hello());
Expand Down Expand Up @@ -200,6 +205,44 @@ private static int parseIntOrZero(String attr) {
}
}

// Check if the response indicates "not authorized"
private boolean isNotAuthorized(Element response) {
if (response == null) {
return false;
}
NodeList failures = response.getElementsByTagName("failure");
for (int i = 0; i < failures.getLength(); i++) {
Element failure = (Element) failures.item(i);
String code = failure.getAttribute("code");
if ("notauthorized".equals(code)) {
return true;
}
}
return false;
}

// Attempt to re-authenticate with the server
private boolean reAuthenticate() {
try {
LogWriter.info("Session lost, attempting to re-authenticate...");
System.err.println(Timestamp.string() + ": Session lost, re-authenticating...");
JSONObject login_response = session.login(role, password);
boolean success = ClientSession.wasSuccessful(login_response);
if (success) {
LogWriter.info("Re-authentication successful");
System.err.println(Timestamp.string() + ": Re-authentication successful");
} else {
LogWriter.info("Re-authentication failed");
System.err.println(Timestamp.string() + ": Re-authentication failed");
}
return success;
} catch (IOException e) {
LogWriter.stacktrace(e);
System.err.println(Timestamp.string() + ": Re-authentication error: " + e.getMessage());
return false;
}
}

// HttpTask has a queue for events to send, registers callbacks
// for HEAT-READY(with lane mask) and ABORT. Continually checks
// queue, sending queued events; otherwise sends a HEARTBEAT and
Expand Down Expand Up @@ -253,11 +296,33 @@ public void run() {
response = session.sendTimerMessage(params);
} catch (ClientSession.HttpException he) {
LogWriter.httpResponse(he.getMessage());
// Brief delay before retry to avoid hammering a recovering server
try {
Thread.sleep(1000); // 1 second
} catch (InterruptedException ie) {
}
} catch (Throwable t) {
LogWriter.trace("Unable to send HTTP message " + params);
LogWriter.stacktrace(t);
// Brief delay before retry to avoid hammering a recovering server
try {
Thread.sleep(1000); // 1 second
} catch (InterruptedException ie) {
}
}
}
}

// Check for "not authorized" and attempt re-authentication
if (isNotAuthorized(response)) {
if (reAuthenticate()) {
// Re-authentication successful, retry the message
synchronized (queue) {
queue.add(0, nextMessage); // Put message back at front of queue
}
continue; // Skip to next iteration to retry the message
}
// Re-authentication failed, continue to log the failure below
}

if (ClientSession.wasSuccessful(response)) {
Expand Down