/* ================================================== */
-static unsigned long sequence = 0;
static int max_retries = 2;
static int initial_timeout = 1000;
static int proto_version = PROTO_VERSION_NUMBER;
static int
submit_request(CMD_Request *request, CMD_Reply *reply)
{
- unsigned long tx_sequence;
int bad_length, bad_sequence, bad_header;
int select_status;
int recv_status;
int expected_length;
int command_length;
int padding_length;
+ struct timespec ts_now, ts_start;
struct timeval tv;
- int timeout;
- int n_attempts;
+ int n_attempts, new_attempt;
+ double timeout;
fd_set rdfd, wrfd, exfd;
request->pkt_type = PKT_TYPE_CMD_REQUEST;
request->res1 = 0;
request->res2 = 0;
- tx_sequence = sequence++;
- request->sequence = htonl(tx_sequence);
request->pad1 = 0;
request->pad2 = 0;
- timeout = initial_timeout;
-
n_attempts = 0;
+ new_attempt = 1;
do {
- request->version = proto_version;
- request->attempt = htons(n_attempts);
- command_length = PKL_CommandLength(request);
- padding_length = PKL_CommandPaddingLength(request);
- assert(command_length > 0 && command_length > padding_length);
+ if (new_attempt) {
+ new_attempt = 0;
- /* Zero the padding to avoid sending uninitialized data */
- memset(((char *)request) + command_length - padding_length, 0, padding_length);
+ if (n_attempts > max_retries)
+ return 0;
- if (sock_fd < 0) {
- DEBUG_LOG(LOGF_Client, "No socket to send request");
- return 0;
+ if (gettimeofday(&tv, NULL))
+ return 0;
+
+ UTI_TimevalToTimespec(&tv, &ts_start);
+
+ UTI_GetRandomBytes(&request->sequence, sizeof (request->sequence));
+ request->attempt = htons(n_attempts);
+ request->version = proto_version;
+ command_length = PKL_CommandLength(request);
+ padding_length = PKL_CommandPaddingLength(request);
+ assert(command_length > 0 && command_length > padding_length);
+
+ n_attempts++;
+
+ /* Zero the padding to not send any uninitialized data */
+ memset(((char *)request) + command_length - padding_length, 0, padding_length);
+
+ if (sock_fd < 0) {
+ DEBUG_LOG(LOGF_Client, "No socket to send request");
+ return 0;
+ }
+
+ if (send(sock_fd, (void *)request, command_length, 0) < 0) {
+ DEBUG_LOG(LOGF_Client, "Could not send %d bytes : %s",
+ command_length, strerror(errno));
+ return 0;
+ }
+
+ DEBUG_LOG(LOGF_Client, "Sent %d bytes", command_length);
}
- if (send(sock_fd, (void *)request, command_length, 0) < 0) {
- DEBUG_LOG(LOGF_Client, "Could not send %d bytes : %s",
- command_length, strerror(errno));
+ if (gettimeofday(&tv, NULL))
return 0;
- }
- DEBUG_LOG(LOGF_Client, "Sent %d bytes", command_length);
+ UTI_TimevalToTimespec(&tv, &ts_now);
+
+ /* Check if the clock wasn't stepped back */
+ if (UTI_CompareTimespecs(&ts_now, &ts_start) < 0)
+ ts_start = ts_now;
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = timeout % 1000 * 1000;
- timeout *= 2;
+ timeout = initial_timeout / 1000.0 * (1U << (n_attempts - 1)) -
+ UTI_DiffTimespecsToDouble(&ts_now, &ts_start);
+ UTI_DoubleToTimeval(timeout, &tv);
+ DEBUG_LOG(LOGF_Client, "Timeout %f seconds", timeout);
FD_ZERO(&rdfd);
FD_ZERO(&wrfd);
DEBUG_LOG(LOGF_Client, "select failed : %s", strerror(errno));
} else if (select_status == 0) {
/* Timeout must have elapsed, try a resend? */
- n_attempts ++;
- if (n_attempts > max_retries) {
- return 0;
- }
-
- /* Back to top of loop to do resend */
- continue;
-
+ new_attempt = 1;
} else {
recv_status = recv(sock_fd, (void *)reply, sizeof(CMD_Reply), 0);
/* If we get connrefused here, it suggests the sendto is
going to a dead port */
DEBUG_LOG(LOGF_Client, "Could not receive : %s", strerror(errno));
-
- n_attempts++;
- if (n_attempts > max_retries) {
- return 0;
- }
+ new_attempt = 1;
} else {
DEBUG_LOG(LOGF_Client, "Received %d bytes", recv_status);
expected_length < offsetof(CMD_Reply, data));
if (!bad_length) {
- bad_sequence = (ntohl(reply->sequence) != tx_sequence);
+ bad_sequence = reply->sequence != request->sequence;
} else {
bad_sequence = 0;
}
if (bad_length || bad_sequence) {
- n_attempts++;
- if (n_attempts > max_retries) {
- return 0;
- }
continue;
}
(reply->command != request->command));
if (bad_header) {
- n_attempts++;
- if (n_attempts > max_retries) {
- return 0;
- }
continue;
}
if (proto_version == PROTO_VERSION_NUMBER &&
reply->version == PROTO_VERSION_NUMBER - 1) {
proto_version = PROTO_VERSION_NUMBER - 1;
+ n_attempts--;
+ new_attempt = 1;
continue;
}
#else
#endif
/* Good packet received, print out results */
- DEBUG_LOG(LOGF_Client, "Reply cmd=%d reply=%d stat=%d seq=%d",
- ntohs(reply->command), ntohs(reply->reply), ntohs(reply->status),
- ntohl(reply->sequence));
+ DEBUG_LOG(LOGF_Client, "Reply cmd=%d reply=%d stat=%d",
+ ntohs(reply->command), ntohs(reply->reply), ntohs(reply->status));
break;
}
}