+
+char *alloc_printf(const char *format, ...)
+{
+ char *string;
+ va_list ap;
+ va_start(ap, format);
+ string = alloc_vprintf(format, ap);
+ va_end(ap);
+ return string;
+}
+
+/* Code must return to the server loop before 1000ms has returned or invoke
+ * this function.
+ *
+ * The GDB connection will time out if it spends >2000ms and you'll get nasty
+ * error messages from GDB:
+ *
+ * Ignoring packet error, continuing...
+ * Reply contains invalid hex digit 116
+ *
+ * While it is possible use "set remotetimeout" to more than the default 2000ms
+ * in GDB, OpenOCD guarantees that it sends keep-alive packages on the
+ * GDB protocol and it is a bug in OpenOCD not to either return to the server
+ * loop or invoke keep_alive() every 1000ms.
+ *
+ * This function will send a keep alive packet if >500ms has passed since last time
+ * it was invoked.
+ *
+ * Note that this function can be invoked often, so it needs to be relatively
+ * fast when invoked more often than every 500ms.
+ *
+ */
+#define KEEP_ALIVE_KICK_TIME_MS 500
+#define KEEP_ALIVE_TIMEOUT_MS 1000
+
+static void gdb_timeout_warning(int64_t delta_time)
+{
+ extern int gdb_actual_connections;
+
+ if (gdb_actual_connections)
+ LOG_WARNING("keep_alive() was not invoked in the "
+ "%d ms timelimit. GDB alive packet not "
+ "sent! (%" PRId64 " ms). Workaround: increase "
+ "\"set remotetimeout\" in GDB",
+ KEEP_ALIVE_TIMEOUT_MS,
+ delta_time);
+ else
+ LOG_DEBUG("keep_alive() was not invoked in the "
+ "%d ms timelimit (%" PRId64 " ms). This may cause "
+ "trouble with GDB connections.",
+ KEEP_ALIVE_TIMEOUT_MS,
+ delta_time);
+}
+
+void keep_alive(void)
+{
+ int64_t current_time = timeval_ms();
+ int64_t delta_time = current_time - last_time;
+
+ if (delta_time > KEEP_ALIVE_TIMEOUT_MS) {
+ last_time = current_time;
+
+ gdb_timeout_warning(delta_time);
+ }
+
+ if (delta_time > KEEP_ALIVE_KICK_TIME_MS) {
+ last_time = current_time;
+
+ /* this will keep the GDB connection alive */
+ server_keep_clients_alive();
+
+ /* DANGER!!!! do not add code to invoke e.g. target event processing,
+ * jim timer processing, etc. it can cause infinite recursion +
+ * jim event callbacks need to happen at a well defined time,
+ * not anywhere keep_alive() is invoked.
+ *
+ * These functions should be invoked at a well defined spot in server.c
+ */
+ }
+}
+
+/* reset keep alive timer without sending message */
+void kept_alive(void)
+{
+ int64_t current_time = timeval_ms();
+
+ int64_t delta_time = current_time - last_time;
+
+ last_time = current_time;
+
+ if (delta_time > KEEP_ALIVE_TIMEOUT_MS)
+ gdb_timeout_warning(delta_time);
+}
+
+/* if we sleep for extended periods of time, we must invoke keep_alive() intermittently */
+void alive_sleep(uint64_t ms)
+{
+ uint64_t nap_time = 10;
+ for (uint64_t i = 0; i < ms; i += nap_time) {
+ uint64_t sleep_a_bit = ms - i;
+ if (sleep_a_bit > nap_time)
+ sleep_a_bit = nap_time;
+
+ usleep(sleep_a_bit * 1000);
+ keep_alive();
+ }
+}
+
+void busy_sleep(uint64_t ms)
+{
+ uint64_t then = timeval_ms();
+ while (timeval_ms() - then < ms) {
+ /*
+ * busy wait
+ */
+ }
+}
+
+/* Maximum size of socket error message retrieved from operation system */
+#define MAX_SOCKET_ERR_MSG_LENGTH 256
+
+/* Provide log message for the last socket error.
+ Uses errno on *nix and WSAGetLastError() on Windows */
+void log_socket_error(const char *socket_desc)
+{
+ int error_code;
+#ifdef _WIN32
+ error_code = WSAGetLastError();
+ char error_message[MAX_SOCKET_ERR_MSG_LENGTH];
+ error_message[0] = '\0';
+ DWORD retval = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0,
+ error_message, MAX_SOCKET_ERR_MSG_LENGTH, NULL);
+ error_message[MAX_SOCKET_ERR_MSG_LENGTH - 1] = '\0';
+ const bool have_message = (retval != 0) && (error_message[0] != '\0');
+ LOG_ERROR("Error on socket '%s': WSAGetLastError==%d%s%s.", socket_desc, error_code,
+ (have_message ? ", message: " : ""),
+ (have_message ? error_message : ""));
+#else
+ error_code = errno;
+ LOG_ERROR("Error on socket '%s': errno==%d, message: %s.", socket_desc, error_code, strerror(error_code));
+#endif
+}
+
+/**
+ * Find the first non-printable character in the char buffer, return a pointer to it.
+ * If no such character exists, return NULL.
+ */
+char *find_nonprint_char(char *buf, unsigned buf_len)
+{
+ for (unsigned int i = 0; i < buf_len; i++) {
+ if (!isprint(buf[i]))
+ return buf + i;
+ }
+ return NULL;
+}