Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package dealers-choice for openSUSE:Factory 
checked in at 2026-04-30 20:26:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dealers-choice (Old)
 and      /work/SRC/openSUSE:Factory/.dealers-choice.new.30200 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dealers-choice"

Thu Apr 30 20:26:27 2026 rev:12 rq:1350047 version:0.0.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/dealers-choice/dealers-choice.changes    
2026-04-25 21:38:57.729666532 +0200
+++ /work/SRC/openSUSE:Factory/.dealers-choice.new.30200/dealers-choice.changes 
2026-04-30 20:27:35.547929534 +0200
@@ -1,0 +2,6 @@
+Wed Apr 29 16:28:23 UTC 2026 - Andy Alt <[email protected]>
+
+- Add 0001-server-skip-buffered-MSG_PING_RESPONSE-at-game-start.patch
+  (fixes s390x build / pool/dealers-choice/pulls/1#issuecomment-135113)
+
+-------------------------------------------------------------------

New:
----
  0001-server-skip-buffered-MSG_PING_RESPONSE-at-game-start.patch

----------(New B)----------
  New:
- Add 0001-server-skip-buffered-MSG_PING_RESPONSE-at-game-start.patch
  (fixes s390x build / pool/dealers-choice/pulls/1#issuecomment-135113)
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dealers-choice.spec ++++++
--- /var/tmp/diff_new_pack.qbpLdd/_old  2026-04-30 20:27:36.103952354 +0200
+++ /var/tmp/diff_new_pack.qbpLdd/_new  2026-04-30 20:27:36.107952518 +0200
@@ -24,6 +24,7 @@
 Group:          Amusements/Games/Board/Card
 URL:            https://dealer-s-choice.github.io/
 Source:         
https://github.com/Dealer-s-Choice/dealers-choice/releases/download/v%{version}/%{name}-%{version}.tar.xz
+Patch0:         0001-server-skip-buffered-MSG_PING_RESPONSE-at-game-start.patch
 
 BuildRequires:  fdupes
 BuildRequires:  gcc-c++
@@ -48,7 +49,7 @@
 %lang_package
 
 %prep
-%autosetup -n %{name}-%{version}
+%autosetup -n %{name}-%{version} -p1
 
 %build
 %meson \

++++++ 0001-server-skip-buffered-MSG_PING_RESPONSE-at-game-start.patch ++++++
>From ae6c21eaf5b309e9af39b5c5179d17b9cca7cc65 Mon Sep 17 00:00:00 2001
From: andy5995 <[email protected]>
Date: Tue, 28 Apr 2026 16:22:45 -0500
Subject: [PATCH] server: skip buffered MSG_PING_RESPONSE at game start

Ping requests are only sent in the lobby loop, but on slow or emulated
hardware (e.g. s390x under QEMU) the client's ping response can still
be sitting in the TCP socket buffer when the game begins.
recv_turn_player_msg and handle_draw now loop past MSG_PING_RESPONSE
frames instead of treating them as a protocol error, which was causing
an "Unrecognised opcode 0x0005" log and a spurious disconnection.

---
diff --git a/src/server.c b/src/server.c
index e975a8a..1461c00 100644
--- a/src/server.c
+++ b/src/server.c
@@ -449,45 +449,50 @@ static ETurnMsg_t recv_turn_player_msg(TCPsocket sock, 
PlayerActionMsg_t *out_ac
                                        uint16_t *out_kb_opcode, int8_t 
*out_target_id) {
   /* All client messages now use the standard length-prefix framing:
    *   [size:4 BE][opcode:2 BE][payload...] where size = 2 + len(payload). */
-  uint32_t size_net = 0;
-  if (recv_all_tcp(sock, &size_net, sizeof(size_net)) <= 0)
-    return TURN_MSG_DISCONNECT;
+  for (;;) {
+    uint32_t size_net = 0;
+    if (recv_all_tcp(sock, &size_net, sizeof(size_net)) <= 0)
+      return TURN_MSG_DISCONNECT;
 
-  uint32_t size = SDL_SwapBE32(size_net);
-  if (size < 2 || size > 16) {
-    fprintf(stderr, "[recv_turn_player_msg] Invalid message size: %u\n", size);
-    return TURN_MSG_DISCONNECT;
-  }
+    uint32_t size = SDL_SwapBE32(size_net);
+    if (size < 2 || size > 16) {
+      fprintf(stderr, "[recv_turn_player_msg] Invalid message size: %u\n", 
size);
+      return TURN_MSG_DISCONNECT;
+    }
 
-  uint8_t buf[16];
-  if (recv_all_tcp(sock, buf, size) <= 0)
-    return TURN_MSG_DISCONNECT;
+    uint8_t buf[16];
+    if (recv_all_tcp(sock, buf, size) <= 0)
+      return TURN_MSG_DISCONNECT;
 
-  uint16_t opcode_be;
-  memcpy(&opcode_be, buf, sizeof(opcode_be));
-  uint16_t opcode = SDL_SwapBE16(opcode_be);
+    uint16_t opcode_be;
+    memcpy(&opcode_be, buf, sizeof(opcode_be));
+    uint16_t opcode = SDL_SwapBE16(opcode_be);
 
-  if (opcode == MSG_PLAYER_ACTION) {
-    if (size < 7)
-      return TURN_MSG_DISCONNECT;
-    out_action->action = buf[2];
-    out_action->amount = ((uint32_t)buf[3] << 24) | ((uint32_t)buf[4] << 16) |
-                         ((uint32_t)buf[5] << 8) | (uint32_t)buf[6];
-    verbose_printf("Received action %u with amount %" PRIu32 "\n", 
out_action->action,
-                   out_action->amount);
-    return TURN_MSG_ACTION;
-  }
+    if (opcode == MSG_PING_RESPONSE)
+      continue;
 
-  if (opcode == MSG_KICK_PLAYER || opcode == MSG_BAN_PLAYER) {
-    if (size < 3)
-      return TURN_MSG_DISCONNECT;
-    *out_kb_opcode = opcode;
-    *out_target_id = (int8_t)buf[2];
-    return TURN_MSG_KICK_BAN;
-  }
+    if (opcode == MSG_PLAYER_ACTION) {
+      if (size < 7)
+        return TURN_MSG_DISCONNECT;
+      out_action->action = buf[2];
+      out_action->amount = ((uint32_t)buf[3] << 24) | ((uint32_t)buf[4] << 16) 
|
+                           ((uint32_t)buf[5] << 8) | (uint32_t)buf[6];
+      verbose_printf("Received action %u with amount %" PRIu32 "\n", 
out_action->action,
+                     out_action->amount);
+      return TURN_MSG_ACTION;
+    }
+
+    if (opcode == MSG_KICK_PLAYER || opcode == MSG_BAN_PLAYER) {
+      if (size < 3)
+        return TURN_MSG_DISCONNECT;
+      *out_kb_opcode = opcode;
+      *out_target_id = (int8_t)buf[2];
+      return TURN_MSG_KICK_BAN;
+    }
 
-  fprintf(stderr, "[recv_turn_player_msg] Unrecognised opcode 0x%04X\n", 
opcode);
-  return TURN_MSG_DISCONNECT;
+    fprintf(stderr, "[recv_turn_player_msg] Unrecognised opcode 0x%04X\n", 
opcode);
+    return TURN_MSG_DISCONNECT;
+  }
 }
 
 static int send_opcode(TCPsocket sock, const uint16_t opcode) {
@@ -621,66 +626,80 @@ static ELoop_t handle_draw(ArgsBroadcastGameState_t 
*args, TCPsocket sock, const
   }
 
   DrawRequestMsg_t req;
-  uint32_t msg_size = 0;
+  uint8_t buffer[32] = {0};
 
   uint32_t wait_ms = args->game_settings->action_timeout_ms;
   uint32_t start = SDL_GetTicks();
-  while (SDL_GetTicks() - start < wait_ms) {
-    register_new_client(args);
-    int num_ready = SDLNet_CheckSockets(args->socket_set, 10);
-    if (num_ready == -1) {
-      fprintf(stderr, "SDLNet_CheckSockets: %s\n", SDLNet_GetError());
-      return LOOP_ERROR;
-    }
-    if (num_ready > 0) {
-      if (SDLNet_SocketReady(sock)) {
-        uint32_t size_net = 0;
-        if (recv_all_tcp(sock, &size_net, sizeof(size_net)) > 0) {
-          msg_size = SDL_SwapBE32(size_net);
-          break;
+  for (;;) {
+    uint32_t msg_size = 0;
+
+    while (SDL_GetTicks() - start < wait_ms) {
+      register_new_client(args);
+      int num_ready = SDLNet_CheckSockets(args->socket_set, 10);
+      if (num_ready == -1) {
+        fprintf(stderr, "SDLNet_CheckSockets: %s\n", SDLNet_GetError());
+        return LOOP_ERROR;
+      }
+      if (num_ready > 0) {
+        if (SDLNet_SocketReady(sock)) {
+          uint32_t size_net = 0;
+          if (recv_all_tcp(sock, &size_net, sizeof(size_net)) > 0) {
+            msg_size = SDL_SwapBE32(size_net);
+            break;
+          } else {
+            remove_disconnected_player(args, id);
+            broadcast_game_state(args);
+            return LOOP_BREAK;
+          }
         } else {
-          remove_disconnected_player(args, id);
-          broadcast_game_state(args);
-          return LOOP_BREAK;
+          if (handle_disconnections(args))
+            broadcast_game_state(args);
+          if (args->game_state->player_count == 1)
+            return LOOP_BREAK;
         }
-      } else {
-        if (handle_disconnections(args))
-          broadcast_game_state(args);
-        if (args->game_state->player_count == 1)
-          return LOOP_BREAK;
       }
     }
-  }
 
-  if (msg_size == 0) {
-    /* timed out — treat as stand pat, track consecutive timeouts */
-    args->player_timeouts[id]++;
-    const uint8_t m = args->config->action_timeout_max;
-    if (m != 0 && !args->cli_args->disable_timeout && 
args->player_timeouts[id] == m) {
+    if (msg_size == 0) {
+      /* timed out — treat as stand pat, track consecutive timeouts */
+      args->player_timeouts[id]++;
+      const uint8_t m = args->config->action_timeout_max;
+      if (m != 0 && !args->cli_args->disable_timeout && 
args->player_timeouts[id] == m) {
+        remove_disconnected_player(args, id);
+        printf("exceeded timeout threshold (%d): disconnecting %s\n", m,
+               args->game_state->player[id].nick);
+      }
+      return LOOP_CONTINUE;
+    }
+
+    /* Payload buffer must fit both PING_RESPONSE (up to ~12 B) and
+     * MSG_DRAW_REQUEST (exactly 7 B: 2 opcode + 1 count + 4 indices). */
+    if (msg_size < 2 || msg_size > sizeof(buffer)) {
+      fprintf(stderr, "[handle_draw] Invalid message size: %u\n", msg_size);
+      return LOOP_ERROR;
+    }
+    memset(buffer, 0, sizeof(buffer));
+    if (recv_all_tcp(sock, buffer, msg_size) <= 0) {
       remove_disconnected_player(args, id);
-      printf("exceeded timeout threshold (%d): disconnecting %s\n", m,
-             args->game_state->player[id].nick);
+      broadcast_game_state(args);
+      return LOOP_BREAK;
     }
-    return LOOP_CONTINUE;
-  }
-  args->player_timeouts[id] = 0;
 
-  /* Read the framed payload: [opcode:2][count:1][indices:4] */
-  if (msg_size < 2 || msg_size > 7) {
-    fprintf(stderr, "[handle_draw] Invalid message size: %u\n", msg_size);
-    return LOOP_ERROR;
-  }
-  uint8_t buffer[7] = {0};
-  if (recv_all_tcp(sock, buffer, msg_size) <= 0) {
-    remove_disconnected_player(args, id);
-    broadcast_game_state(args);
-    return LOOP_BREAK;
-  }
+    uint16_t opcode_be;
+    memcpy(&opcode_be, buffer, sizeof(opcode_be));
+    uint16_t opcode = SDL_SwapBE16(opcode_be);
 
-  uint16_t opcode_be;
-  memcpy(&opcode_be, buffer, sizeof(opcode_be));
-  if (SDL_SwapBE16(opcode_be) != MSG_DRAW_REQUEST)
-    return LOOP_ERROR;
+    if (opcode == MSG_PING_RESPONSE)
+      continue;
+
+    if (opcode != MSG_DRAW_REQUEST) {
+      fprintf(stderr, "[handle_draw] Unrecognised opcode 0x%04X\n", opcode);
+      return LOOP_ERROR;
+    }
+
+    args->player_timeouts[id] = 0;
+    break;
+  }
 
   uint8_t count = buffer[2];
   if (count > MAX_DISCARDS)
-- 
2.53.0

Reply via email to