Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync libcontroller master #963

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions webots_ros2_driver/webots/src/controller/c/robot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 <extern> 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 <extern> controllers, retrying for another %d seconds...\n",
50 - retry);
} else
fprintf(stderr, "%s, retrying for another %d seconds...\n", error_message, 50 - retry);
}
Expand Down
Loading