diff --git a/webots_ros2_driver/webots/src/controller/c/robot.c b/webots_ros2_driver/webots/src/controller/c/robot.c index 8b32ca8c1..50616de66 100644 --- a/webots_ros2_driver/webots/src/controller/c/robot.c +++ b/webots_ros2_driver/webots/src/controller/c/robot.c @@ -1081,21 +1081,33 @@ static void wb_robot_cleanup_devices() { } } -static char *encode_robot_name(const char *robot_name) { +static char *encode_robot_name(const char *robot_name, int chars_used) { if (!robot_name) return NULL; char *encoded_name = percent_encode(robot_name); int length = strlen(encoded_name); // the robot name is used to connect to the libController and in this process there are indirect - // limitations such as QLocalServer only accepting strings up to 106 characters for server names, - // for these reasons if the robot name is bigger than an arbitrary length, a hashed version is used instead - if (length > 70) { // note: this threshold should be the same as in WbRobot.cpp + // limitations such as QLocalServer only accepting strings up to 91 characters long for server names + // on some platforms. + // Since the server name also contains the tmp path and that includes the user's username and, + // in the case of a Snap, the user's home directory, we need to limit the length of the encoded + // robot name based on the tmp path. If it is longer than that, then we compute a hashed version + // of the name and use as much of it as we can. If that would be less than 4 chars, we try to use + // 4 chars and hope we are on a platform where QLocalServer accepts longer names. 4 chars makes the + // chance of a name collision 1/65536. + // Note: It is critical that the same logic is used in WbRobot.cpp + int max_name_length = 91 - chars_used; + if (max_name_length < 4) + max_name_length = 4; + // Round down to the next multiple of 2 because it makes the code easier. + max_name_length = max_name_length / 2 * 2; + if (length > max_name_length) { char hash[21]; - char *output = malloc(41); + char *output = malloc(max_name_length + 1); SHA1(hash, encoded_name, length); free(encoded_name); - for (size_t i = 0; i < 20; i++) + for (size_t i = 0; i < max_name_length / 2 && i < 20; i++) sprintf((output + (2 * i)), "%02x", hash[i] & 0xff); return output; } @@ -1104,10 +1116,12 @@ static char *encode_robot_name(const char *robot_name) { } static char *compute_socket_filename(char *error_buffer) { - char *robot_name = encode_robot_name(wbu_system_getenv("WEBOTS_ROBOT_NAME")); const char *WEBOTS_INSTANCE_PATH = wbu_system_webots_instance_path(true); + char *robot_name = NULL; + const char *WEBOTS_ROBOT_NAME = wbu_system_getenv("WEBOTS_ROBOT_NAME"); char *socket_filename; - if (robot_name && robot_name[0] && WEBOTS_INSTANCE_PATH && WEBOTS_INSTANCE_PATH[0]) { + if (WEBOTS_ROBOT_NAME && WEBOTS_ROBOT_NAME[0] && WEBOTS_INSTANCE_PATH && WEBOTS_INSTANCE_PATH[0]) { + robot_name = encode_robot_name(WEBOTS_ROBOT_NAME, strlen(WEBOTS_INSTANCE_PATH) + strlen("ipc//intern")); #ifndef _WIN32 const int length = strlen(WEBOTS_INSTANCE_PATH) + strlen(robot_name) + 15; // "%sintern/%s/socket" socket_filename = malloc(length); @@ -1267,7 +1281,7 @@ static char *compute_socket_filename(char *error_buffer) { free(robot_name); const char *sub_string = strstr(&WEBOTS_CONTROLLER_URL[6], "/"); - robot_name = encode_robot_name(sub_string ? sub_string + 1 : NULL); + robot_name = encode_robot_name(sub_string ? sub_string + 1 : NULL, strlen(ipc_folder) + strlen("//extern")); if (robot_name) { #ifndef _WIN32 // socket file name is like: folder + robot_name + "/extern" @@ -1370,7 +1384,7 @@ static void compute_remote_info(char **host, int *port, char **robot_name) { snprintf(*host, host_length, "%s", &WEBOTS_CONTROLLER_URL[6]); sscanf(url_suffix, ":%d", port); const char *rn = strstr(url_suffix, "/"); - *robot_name = rn != NULL ? encode_robot_name(rn + 1) : NULL; + *robot_name = rn != NULL ? encode_robot_name(rn + 1, 0) : NULL; } int wb_robot_init() { // API initialization @@ -1462,11 +1476,11 @@ int wb_robot_init() { // API initialization retry -= 5; fprintf(stderr, "%s, pending until loading is done...\n", error_message); } else if (socket_filename) { + fprintf(stderr, + "The specified robot (at %s) is not in the list of robots with controllers, retrying for another %d " + "seconds...\n", + socket_filename, 50 - retry); free(socket_filename); - fprintf( - stderr, - "The specified robot is not in the list of robots with controllers, retrying for another %d seconds...\n", - 50 - retry); } else fprintf(stderr, "%s, retrying for another %d seconds...\n", error_message, 50 - retry); }