From f52f4778ebbfbe51ae7bd9371fc3e3a1d57c09ca Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:07:08 +0100 Subject: [PATCH] Update SCP with connect session calls --- libipm/scp.c | 154 +++++++++++++++++++++++++++++++++ libipm/scp.h | 65 ++++++++++++++ libipm/scp_application_types.c | 28 ++++++ libipm/scp_application_types.h | 34 +++++++- 4 files changed, 280 insertions(+), 1 deletion(-) diff --git a/libipm/scp.c b/libipm/scp.c index 0e96a192..298d526c 100644 --- a/libipm/scp.c +++ b/libipm/scp.c @@ -53,6 +53,9 @@ msgno_to_str(unsigned short n) (n == E_SCP_CREATE_SESSION_REQUEST) ? "SCP_CREATE_SESSION_REQUEST" : (n == E_SCP_CREATE_SESSION_RESPONSE) ? "SCP_CREATE_SESSION_RESPONSE" : + (n == E_SCP_CONNECT_SESSION_REQUEST) ? "SCP_CONNECT_SESSION_REQUEST" : + (n == E_SCP_CONNECT_SESSION_RESPONSE) ? "SCP_CONNECT_SESSION_RESPONSE" : + (n == E_SCP_LIST_SESSIONS_REQUEST) ? "SCP_LIST_SESSIONS_REQUEST" : (n == E_SCP_LIST_SESSIONS_RESPONSE) ? "SCP_LIST_SESSIONS_RESPONSE" : @@ -519,6 +522,157 @@ scp_get_create_session_response(struct trans *trans, /*****************************************************************************/ +int +scp_send_connect_session_request(struct trans *trans, + const struct guid *guid, + unsigned int flags) +{ + struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; + + return libipm_msg_out_simple_send( + trans, + (int)E_SCP_CONNECT_SESSION_REQUEST, + "Bu", &guid_descriptor, flags); +} + +/*****************************************************************************/ + +int +scp_get_connect_session_request(struct trans *trans, + struct guid *guid, + unsigned int *flags) +{ + struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; + /* Intermediate values */ + uint32_t i_flags; + + int rv = libipm_msg_in_parse( trans, "Bu", &guid_descriptor, &i_flags); + + if (rv == 0) + { + *flags = i_flags; + } + + return rv; +} + +/*****************************************************************************/ + +int +scp_send_connect_session_response(struct trans *trans, + enum scp_sconnect_status status, + int display_fd, + int chan_fd) +{ + int rv = libipm_msg_out_init( + trans, (int)E_SCP_CONNECT_SESSION_RESPONSE, + "i", status); + // Send the display file descriptor, guarded by a boolean + if (rv == 0) + { + if (display_fd >= 0) + { + rv = libipm_msg_out_append( + trans, "bh", 1, display_fd); + } + else + { + rv = libipm_msg_out_append(trans, "b", 0); + } + } + + // Send the chansrv file descriptor, guarded by a boolean + if (rv == 0) + { + if (chan_fd >= 0) + { + rv = libipm_msg_out_append( + trans, "bh", 1, chan_fd); + } + else + { + rv = libipm_msg_out_append(trans, "b", 0); + } + } + + if (rv == 0) + { + libipm_msg_out_mark_end(trans); + if (trans_force_write(trans) != 0) + { + rv = E_LI_TRANSPORT_ERROR; + } + } + + return rv; +} + +/*****************************************************************************/ + +int +scp_get_connect_session_response(struct trans *trans, + enum scp_sconnect_status *status, + int *display_fd, + int *chan_fd) +{ + int fd_present; + int got_display_fd = 0; + int got_chan_fd = 0; + + /* Intermediate values */ + int32_t i_status; + int rv = libipm_msg_in_parse( trans, "i", &i_status); + + // Read the X11 file descriptor + if (rv == 0 && libipm_msg_in_parse(trans, "b", &fd_present) == 0) + { + if (!fd_present) + { + // Caller didn't send display_fd + *display_fd = -1; + } + else + { + got_display_fd = (libipm_msg_in_parse(trans, "h", display_fd) == 0); + } + } + + // Read the chansrv file descriptor + if (rv == 0 && libipm_msg_in_parse(trans, "b", &fd_present) == 0) + { + if (!fd_present) + { + // Caller didn't send chan_fd + *chan_fd = -1; + } + else + { + got_chan_fd = (libipm_msg_in_parse(trans, "h", chan_fd) == 0); + } + } + + // If we've failed, close any file descriptors we've parsed so far + if (rv != 0) + { + if (got_display_fd) + { + g_file_close(*display_fd); + } + if (got_chan_fd) + { + g_file_close(*chan_fd); + } + } + else + { + *status = (enum scp_sconnect_status)i_status; + } + + return rv; +} + +/*****************************************************************************/ + int scp_send_list_sessions_request(struct trans *trans) { diff --git a/libipm/scp.h b/libipm/scp.h index 1ec51e82..fb68d0b8 100644 --- a/libipm/scp.h +++ b/libipm/scp.h @@ -56,6 +56,9 @@ enum scp_msg_code E_SCP_CREATE_SESSION_REQUEST, E_SCP_CREATE_SESSION_RESPONSE, + E_SCP_CONNECT_SESSION_REQUEST, + E_SCP_CONNECT_SESSION_RESPONSE, + E_SCP_LIST_SESSIONS_REQUEST, E_SCP_LIST_SESSIONS_RESPONSE, @@ -413,6 +416,68 @@ scp_get_create_session_response(struct trans *trans, int *display, struct guid *guid); +/** + * Send an E_SCP_CONNECT_SESSION_REQUEST (SCP client) + * + * @param trans SCP transport + * @param guid Session guid + * @param flags Flags which affect the returned FDs + * @return != 0 for error + * + * Server replies with E_SCP_CONNECT_SESSION_RESPONSE + */ +int +scp_send_connect_session_request(struct trans *trans, + const struct guid *guid, + unsigned int flags); + + +/** + * Parse an incoming E_SCP_CONNECT_SESSION_REQUEST (SCP server) + * + * @param trans SCP transport + * @param[out] guid Session guid + * @param[out] flags Flags which affect the returned FDs + * @return != 0 for error + */ +int +scp_get_connect_session_request(struct trans *trans, + struct guid *guid, + unsigned int *flags); + +/** + * Send an E_SCP_CONNECT_SESSION_RESPONSE (SCP server) + * + * @param trans SCP transport + * @param status Status of connection request + * @param display_fd File descriptor for display server + * @param chan_fd File descriptor for chansrv, or -1 for no chansrv + * + * @return != 0 for error + */ +int +scp_send_connect_session_response(struct trans *trans, + enum scp_sconnect_status status, + int display_fd, + int chan_fd); + + +/** + * Parse an incoming E_SCP_CONNECT_SESSION_RESPONSE (SCP client) + * + * @param trans SCP transport + * @param[out] status Status of connection request + * @param[out] display_fd File descriptor for display server + * @param[out] chan_fd File descriptor for chansrv, or -1 for no chansrv + * + * @return != 0 for error + */ +int +scp_get_connect_session_response(struct trans *trans, + enum scp_sconnect_status *status, + int *display_fd, + int *chan_fd); + /** * Send an E_SCP_LIST_SESSIONS_REQUEST (SCP client) * diff --git a/libipm/scp_application_types.c b/libipm/scp_application_types.c index f09fba01..5250d811 100644 --- a/libipm/scp_application_types.c +++ b/libipm/scp_application_types.c @@ -85,3 +85,31 @@ scp_screate_status_to_str(enum scp_screate_status n, return buff; } + +/*****************************************************************************/ +const char * +scp_sconnect_status_to_str(enum scp_sconnect_status n, + char *buff, unsigned int buff_size) +{ + const char *str = + (n == E_SCP_SCONNECT_OK) ? "OK" : + (n == E_SCP_SCONNECT_NOT_LOGGED_IN) ? "Connection is not logged in" : + (n == E_SCP_SCONNECT_NO_SUCH_GUID) ? "No such session for this user" : + (n == E_SCP_SCONNECT_NO_MEMORY) ? "No memory for connection" : + (n == E_SCP_SCONNECT_SERVER_FAIL) ? "Can't connect to X server" : + (n == E_SCP_SCONNECT_GENERAL_ERROR) ? "General session connection error" : + + /* Default */ NULL; + + if (str == NULL) + { + g_snprintf(buff, buff_size, "[session connection error code #%d]", + (int)n); + } + else + { + g_snprintf(buff, buff_size, "%s", str); + } + + return buff; +} diff --git a/libipm/scp_application_types.h b/libipm/scp_application_types.h index 1e1698b7..1c5630dd 100644 --- a/libipm/scp_application_types.h +++ b/libipm/scp_application_types.h @@ -114,6 +114,39 @@ const char * scp_screate_status_to_str(enum scp_screate_status n, char *buff, unsigned int buff_size); +/* + * Flags passed to scp_send_connect_session_request() + */ + +/** + * Set this to get an FD for chansrv + */ +#define E_SCP_SCONNECT_FLAG_NEED_CHANSRV (1<<0) + +/** + * Status of a session connection request + */ +enum scp_sconnect_status +{ + E_SCP_SCONNECT_OK = 0, ///< Session created + E_SCP_SCONNECT_NOT_LOGGED_IN, ///< Connection is not logged in + E_SCP_SCONNECT_NO_SUCH_GUID, ///< GUID does not exist for this user + E_SCP_SCONNECT_NO_MEMORY, ///< Memory allocation failure + E_SCP_SCONNECT_SERVER_FAIL, ///< Can't connect to X server + E_SCP_SCONNECT_GENERAL_ERROR ///< An unspecific error has occurred +}; + +/** + * Convert an scp_session connection code to a readable string for output + * @param n Message code + * @param buff to contain string + * @param buff_size length of buff + * @return buff is returned for convenience. + */ +const char * +scp_sconnect_status_to_str(enum scp_sconnect_status n, + char *buff, unsigned int buff_size); + /** * Status of an list sessions message */ @@ -158,5 +191,4 @@ enum scp_create_sockdir_status E_SCP_CS_OTHER_ERROR }; - #endif /* SCP_APPLICATION_TYPES_H */