From 2bed84cfc3eff7b86986012be3e9d57b4f6aae5f Mon Sep 17 00:00:00 2001
From: Dmitry Ilyin <dima@doty.ru>
Date: Thu, 4 Nov 2021 13:42:37 +0300
Subject: [PATCH] Improve xmdp output

---
 general/package/xmdp/src/netip.c | 42 +++++++++++++++++++++++---------
 general/package/xmdp/src/netip.h |  8 +++++-
 general/package/xmdp/src/xmdp.c  | 34 +++++++++++++++++---------
 3 files changed, 59 insertions(+), 25 deletions(-)

diff --git a/general/package/xmdp/src/netip.c b/general/package/xmdp/src/netip.c
index 8572ae0b..69267e1f 100644
--- a/general/package/xmdp/src/netip.c
+++ b/general/package/xmdp/src/netip.c
@@ -4,8 +4,10 @@
 #include <string.h>
 
 #include <arpa/inet.h>
+#include <fcntl.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
+#include <unistd.h>
 
 #include "cjson/cJSON.h"
 #include "netip.h"
@@ -43,8 +45,9 @@ typedef union netip_pkt {
 #define NETIP_HSIZE sizeof(netip_preabmle_t)
 #define NETIP_MAX_JSON sizeof(resp) - NETIP_HSIZE - 1
 
-bool netip_connect(const char *addr, uint16_t port) {
-  bool res = true;
+enum ConnectStatus netip_connect(const char *addr, uint16_t port) {
+  bool res = CONNECT_OK;
+  cJSON *json = NULL;
 
   int s = socket(AF_INET, SOCK_STREAM, 0);
   if (s == -1)
@@ -55,8 +58,22 @@ bool netip_connect(const char *addr, uint16_t port) {
   srv.sin_family = AF_INET;
   srv.sin_port = htons(port);
 
-  if (connect(s, (struct sockaddr *)&srv, sizeof(srv)) < 0)
-    return false;
+  const int flags = fcntl(s, F_GETFL, 0);
+  fcntl(s, F_SETFL, flags | O_NONBLOCK);
+  (void)connect(s, (struct sockaddr *)&srv, sizeof(srv));
+
+  fd_set fdset;
+  FD_ZERO(&fdset);
+  FD_SET(s, &fdset);
+  struct timeval tv = {
+      .tv_sec = 2, /* 2 second timeout */
+  };
+
+  if (select(s + 1, NULL, &fdset, NULL, &tv) != 1) {
+    res = CONNECT_ERR;
+    goto quit;
+  }
+  fcntl(s, F_SETFL, flags);
 
   netip_pkt_t msg;
   memset(&msg.header, 0, sizeof(msg.header));
@@ -69,29 +86,30 @@ bool netip_connect(const char *addr, uint16_t port) {
   msg.header.len_data = sizeof(default_login);
 
   if (send(s, &msg, sizeof(default_login) + NETIP_HSIZE, 0) < 0) {
-    puts("Send failed");
-    return false;
+    return CONNECT_ERR;
   }
 
   if (recv(s, &msg, sizeof(msg), 0) <= NETIP_HSIZE) {
     puts("recv failed");
   }
 
-  cJSON *json = cJSON_Parse(msg.header.data);
+  json = cJSON_Parse(msg.header.data);
   if (!json) {
     const char *error_ptr = cJSON_GetErrorPtr();
     if (error_ptr != NULL) {
       fprintf(stderr, "Error before: %s\n", error_ptr);
     }
-    res = false;
-    goto skip_loop;
+    res = CONNECT_ERR;
+    goto quit;
   }
   const int retval = get_json_intval(json, "Ret", 0);
   if (retval != RESULT_OK)
-    return false;
+    return CONNECT_PWDREQ;
 
-skip_loop:
-  cJSON_Delete(json);
+quit:
+  if (json)
+    cJSON_Delete(json);
+  close(s);
 
   return res;
 }
diff --git a/general/package/xmdp/src/netip.h b/general/package/xmdp/src/netip.h
index b702384d..55fef381 100644
--- a/general/package/xmdp/src/netip.h
+++ b/general/package/xmdp/src/netip.h
@@ -1,6 +1,12 @@
 #ifndef NETIP_H
 #define NETIP_H
 
-bool netip_connect(const char* addr, uint16_t port);
+enum ConnectStatus {
+  CONNECT_OK,
+  CONNECT_ERR,
+  CONNECT_PWDREQ,
+};
+
+enum ConnectStatus netip_connect(const char *addr, uint16_t port);
 
 #endif /* NETIP_H */
diff --git a/general/package/xmdp/src/xmdp.c b/general/package/xmdp/src/xmdp.c
index 2a79dbaf..3cc8f545 100644
--- a/general/package/xmdp/src/xmdp.c
+++ b/general/package/xmdp/src/xmdp.c
@@ -26,6 +26,18 @@ const char brpkt[] =
     "\x00\x00\x00\x00";
 static const char *Reset = "\x1b[0m";
 static const char *FgRed = "\x1b[31m";
+static const char *FgBrightRed = "\033[31;1m";
+
+static const char *color(enum ConnectStatus status) {
+  switch (status) {
+  case CONNECT_OK:
+    return FgRed;
+  case CONNECT_ERR:
+    return FgBrightRed;
+  default:
+    return "";
+  }
+}
 
 // get sockaddr, IPv4 or IPv6:
 void *get_in_addr(struct sockaddr *sa) {
@@ -175,7 +187,7 @@ int main() {
       ipaddr_from32bit(abuf, sizeof abuf, host_ip);
       host_ip = abuf;
     }
-    bool netip_ok = netip_connect(host_ip, netip_port);
+    enum ConnectStatus netip_conn = netip_connect(host_ip, netip_port);
 
     char verstr[128] = {0};
     if (strlen(version)) {
@@ -191,23 +203,21 @@ int main() {
         version++;
       }
 
-      if (strlen(builddt)) {
-        const char *end;
-        if ((end = strchr(builddt, ' '))) {
-          strcat(verstr + strlen(verstr), " (");
-          snprintf(verstr + strlen(verstr),
-                   MIN(sizeof(verstr) - strlen(verstr), end - builddt + 1),
-                   "%s", builddt);
-          strcat(verstr + strlen(verstr), ")");
-        }
+      if (strlen(builddt) == 19 && builddt[10] == ' ') {
+        const char *end = builddt + 10;
+        strcat(verstr + strlen(verstr), " (");
+        snprintf(verstr + strlen(verstr),
+                 MIN(sizeof(verstr) - strlen(verstr), end - builddt + 1), "%s",
+                 builddt);
+        strcat(verstr + strlen(verstr), ")");
       }
     }
 
-    printf("%s%s\t%s\t%s %s, %s", netip_ok ? FgRed : "", host_ip, mac,
+    printf("%s%s\t%s\t%s %s, %s", color(netip_conn), host_ip, mac,
            chan_num > 1 ? "DVR" : "IPC", sn, hostname);
     if (strlen(verstr))
       printf("\t%s", verstr);
-    printf("%s\n", netip_ok ? Reset : "");
+    printf("%s\n", *color(netip_conn) ? Reset : "");
 
   skip_loop: