diff options
author | Giovanni Panozzo <giovanni@panozzo.it> | 2019-10-27 23:41:37 +0300 |
---|---|---|
committer | Giovanni Panozzo <giovanni@panozzo.it> | 2019-11-01 11:11:27 +0300 |
commit | b5a875e043148d7d72c3681042efa31304f2bba9 (patch) | |
tree | 93783842c633d81301259f3015a150b47063fb60 /plugins | |
parent | 06ee121ca368c05dd8765fabd3483b9fa08a8cc2 (diff) |
Plugin connection close refactoring
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/nx/nx_plugin.c | 14 | ||||
-rw-r--r-- | plugins/rdp/rdp_channels.c | 2 | ||||
-rw-r--r-- | plugins/rdp/rdp_cliprdr.c | 2 | ||||
-rw-r--r-- | plugins/rdp/rdp_event.c | 5 | ||||
-rw-r--r-- | plugins/rdp/rdp_plugin.c | 246 | ||||
-rw-r--r-- | plugins/rdp/rdp_plugin.h | 17 | ||||
-rw-r--r-- | plugins/spice/spice_plugin.c | 4 | ||||
-rw-r--r-- | plugins/st/st_plugin.c | 6 | ||||
-rw-r--r-- | plugins/vnc/vnc_plugin.c | 17 | ||||
-rw-r--r-- | plugins/xdmcp/xdmcp_plugin.c | 9 |
10 files changed, 213 insertions, 109 deletions
diff --git a/plugins/nx/nx_plugin.c b/plugins/nx/nx_plugin.c index 34f44e037..c16f0bfda 100644 --- a/plugins/nx/nx_plugin.c +++ b/plugins/nx/nx_plugin.c @@ -182,13 +182,13 @@ static void remmina_plugin_nx_remove_window_id(Window window_id) static void remmina_plugin_nx_on_plug_added(GtkSocket *socket, RemminaProtocolWidget *gp) { TRACE_CALL(__func__); - remmina_plugin_nx_service->protocol_plugin_emit_signal(gp, "connect"); + remmina_plugin_nx_service->protocol_plugin_signal_connection_opened(gp); } static void remmina_plugin_nx_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp) { TRACE_CALL(__func__); - remmina_plugin_nx_service->protocol_plugin_close_connection(gp); + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); } gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userdata) @@ -212,7 +212,7 @@ static void remmina_plugin_nx_on_proxy_exit(GPid pid, gint status, gpointer data TRACE_CALL(__func__); RemminaProtocolWidget *gp = (RemminaProtocolWidget*)data; - remmina_plugin_nx_service->protocol_plugin_close_connection(gp); + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); } static int remmina_plugin_nx_dummy_handler(Display *dsp, XErrorEvent *err) @@ -539,11 +539,12 @@ static gboolean remmina_plugin_nx_main(RemminaProtocolWidget *gp) static gpointer remmina_plugin_nx_main_thread(gpointer data) { TRACE_CALL(__func__); + RemminaProtocolWidget *gp = (RemminaProtocolWidget *)data; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); CANCEL_ASYNC - if (!remmina_plugin_nx_main((RemminaProtocolWidget*)data)) { - IDLE_ADD((GSourceFunc)remmina_plugin_nx_service->protocol_plugin_close_connection, data); + if (!remmina_plugin_nx_main(gp)) { + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); } return NULL; } @@ -638,7 +639,7 @@ static gboolean remmina_plugin_nx_close_connection(RemminaProtocolWidget *gp) close(gpdata->event_pipe[0]); close(gpdata->event_pipe[1]); - remmina_plugin_nx_service->protocol_plugin_emit_signal(gp, "disconnect"); + remmina_plugin_nx_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } @@ -795,4 +796,3 @@ remmina_plugin_entry(RemminaPluginService *service) return TRUE; } - diff --git a/plugins/rdp/rdp_channels.c b/plugins/rdp/rdp_channels.c index 60a58db3b..3a750bf8f 100644 --- a/plugins/rdp/rdp_channels.c +++ b/plugins/rdp/rdp_channels.c @@ -74,7 +74,7 @@ void remmina_rdp_OnChannelConnectedEventHandler(rdpContext* context, ChannelConn // "disp" channel connected, save its context pointer rfi->dispcontext = (DispClientContext*)e->pInterface; // Notify rcw to unlock dynres capability - remmina_plugin_service->protocol_plugin_emit_signal(rfi->protocol_widget, "unlock-dynres"); + remmina_plugin_service->protocol_plugin_unlock_dynres(rfi->protocol_widget); // Send monitor layout message here to ask for resize of remote desktop now if (rfi->scale == REMMINA_PROTOCOL_WIDGET_SCALE_MODE_DYNRES) { remmina_rdp_event_send_delayed_monitor_layout(rfi->protocol_widget); diff --git a/plugins/rdp/rdp_cliprdr.c b/plugins/rdp/rdp_cliprdr.c index 464f89a58..62624b206 100644 --- a/plugins/rdp/rdp_cliprdr.c +++ b/plugins/rdp/rdp_cliprdr.c @@ -730,6 +730,8 @@ void remmina_rdp_cliprdr_detach_owner(RemminaProtocolWidget* gp) rfContext* rfi = GET_PLUGIN_DATA(gp); GtkClipboard* gtkClipboard; + if (!rfi || !rfi->drawing_area) return; + gtkClipboard = gtk_widget_get_clipboard(rfi->drawing_area, GDK_SELECTION_CLIPBOARD); if (gtkClipboard && gtk_clipboard_get_owner(gtkClipboard) == (GObject*)gp) { gtk_clipboard_clear(gtkClipboard); diff --git a/plugins/rdp/rdp_event.c b/plugins/rdp/rdp_event.c index 953cf87fc..3842039d4 100644 --- a/plugins/rdp/rdp_event.c +++ b/plugins/rdp/rdp_event.c @@ -949,7 +949,7 @@ void remmina_rdp_event_update_scale(RemminaProtocolWidget* gp) /* In non scaled mode, the plugins forces dimensions of drawing area */ gtk_widget_set_size_request(rfi->drawing_area, width, height); } - remmina_plugin_service->protocol_plugin_emit_signal(gp, "update-align"); + remmina_plugin_service->protocol_plugin_update_align(gp); } static void remmina_rdp_event_connected(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui) @@ -960,13 +960,14 @@ static void remmina_rdp_event_connected(RemminaProtocolWidget* gp, RemminaPlugin gdi = ((rdpContext *)rfi)->gdi; - remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect"); gtk_widget_realize(rfi->drawing_area); remmina_rdp_event_create_cairo_surface(rfi); gtk_widget_queue_draw_area(rfi->drawing_area, 0, 0, gdi->width, gdi->height); remmina_rdp_event_update_scale(gp); + + remmina_plugin_service->protocol_plugin_signal_connection_opened(gp); } static void remmina_rdp_event_reconnect_progress(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* ui) diff --git a/plugins/rdp/rdp_plugin.c b/plugins/rdp/rdp_plugin.c index ca932ab80..3d679ac3b 100644 --- a/plugins/rdp/rdp_plugin.c +++ b/plugins/rdp/rdp_plugin.c @@ -34,6 +34,7 @@ * */ + #define _GNU_SOURCE #include "rdp_plugin.h" @@ -54,6 +55,7 @@ #include <freerdp/client/channels.h> #include <freerdp/client/cmdline.h> #include <freerdp/error.h> +#include <freerdp/event.h> #include <winpr/memory.h> #ifdef HAVE_CUPS @@ -152,6 +154,10 @@ static BOOL rf_process_event_queue(RemminaProtocolWidget *gp) g_free(dcml); } break; + case REMMINA_RDP_EVENT_DISCONNECT: + /* Disconnect requested via GUI (i.e.: tab destroy/close) */ + freerdp_abort_connect(rfi->instance); + break; } g_free(event); @@ -391,7 +397,7 @@ static BOOL rf_desktop_resize(rdpContext *context) ui->event.type = REMMINA_RDP_UI_EVENT_UPDATE_SCALE; remmina_rdp_event_queue_ui_sync_retint(gp, ui); - remmina_plugin_service->protocol_plugin_emit_signal(gp, "desktop-resize"); + remmina_plugin_service->protocol_plugin_desktop_resize(gp); return TRUE; } @@ -499,6 +505,8 @@ static BOOL remmina_rdp_post_connect(freerdp *instance) gp = rfi->protocol_widget; rfi->postconnect_error = REMMINA_POSTCONNECT_ERROR_OK; + rfi->attempt_interactive_authentication = FALSE; // We did authenticate! + rfi->srcBpp = rfi->settings->ColorDepth; if (rfi->settings->RemoteFxCodec == FALSE) @@ -529,7 +537,7 @@ static BOOL remmina_rdp_post_connect(freerdp *instance) return FALSE; } - pointer_cache_register_callbacks(instance->update); + // pointer_cache_register_callbacks(instance->update); instance->update->BeginPaint = rf_begin_paint; instance->update->EndPaint = rf_end_paint; @@ -593,7 +601,6 @@ static BOOL remmina_rdp_authenticate(freerdp *instance, char **username, char ** return True; } else { - rfi->user_cancelled = TRUE; return False; } @@ -638,7 +645,6 @@ static BOOL remmina_rdp_proxy_authenticate(RemminaProtocolWidget *gp) return True; } else { - rfi->user_cancelled = TRUE; return False; } @@ -691,7 +697,6 @@ static BOOL remmina_rdp_gw_authenticate(freerdp *instance, char **username, char return True; } else { - rfi->user_cancelled = TRUE; return False; } @@ -737,6 +742,27 @@ static DWORD remmina_rdp_verify_changed_certificate(freerdp *instance, return 0; } +static void remmina_rdp_post_disconnect(freerdp *instance) +{ + TRACE_CALL(__func__); + rfContext *rfi; + + if (!instance || !instance->context) + return; + + rfi = (rfContext *)instance->context; + + PubSub_UnsubscribeChannelConnected(instance->context->pubSub, + (pChannelConnectedEventHandler)remmina_rdp_OnChannelConnectedEventHandler); + PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub, + (pChannelDisconnectedEventHandler)remmina_rdp_OnChannelDisconnectedEventHandler); + + gdi_free(instance); + + remmina_rdp_clipboard_free(rfi); + +} + static void remmina_rdp_main_loop(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); @@ -746,11 +772,14 @@ static void remmina_rdp_main_loop(RemminaProtocolWidget *gp) gchar buf[100]; rfContext *rfi = GET_PLUGIN_DATA(gp); + while (!freerdp_shall_disconnect(rfi->instance)) { nCount = freerdp_get_event_handles(rfi->instance->context, &handles[0], 64); if (rfi->event_handle) handles[nCount++] = rfi->event_handle; + handles[nCount++] = rfi->instance->context->abortEvent; + if (nCount == 0) { fprintf(stderr, "freerdp_get_event_handles failed\n"); break; @@ -772,6 +801,12 @@ static void remmina_rdp_main_loop(RemminaProtocolWidget *gp) } } + /* Check if a processed event called freerdp_abort_connect() and exit if true */ + if (WaitForSingleObject(rfi->instance->context->abortEvent, 0) == WAIT_OBJECT_0) { + /* Session disconnected by local user action */ + break; + } + if (!freerdp_check_event_handles(rfi->instance->context)) { if (rf_auto_reconnect(rfi)) { /* Reset the possible reason/error which made us doing many reconnection reattempts and continue */ @@ -783,6 +818,8 @@ static void remmina_rdp_main_loop(RemminaProtocolWidget *gp) break; } } + freerdp_disconnect(rfi->instance); + g_debug("RDP client disconnected\n"); } int remmina_rdp_load_static_channel_addin(rdpChannels *channels, rdpSettings *settings, char *name, void *data) @@ -1058,6 +1095,7 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget *gp) remmina_plugin_service->protocol_plugin_set_width(gp, rfi->settings->DesktopWidth); remmina_plugin_service->protocol_plugin_set_height(gp, rfi->settings->DesktopHeight); + if (remmina_plugin_service->file_get_string(remminafile, "username")) rfi->settings->Username = strdup(remmina_plugin_service->file_get_string(remminafile, "username")); @@ -1065,11 +1103,10 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget *gp) rfi->settings->Domain = strdup(remmina_plugin_service->file_get_string(remminafile, "domain")); s = remmina_plugin_service->file_get_string(remminafile, "password"); + if (s) rfi->settings->Password = strdup(s); + + rfi->settings->AutoLogonEnabled = 1; - if (s) { - rfi->settings->Password = strdup(s); - rfi->settings->AutoLogonEnabled = 1; - } /** * Proxy support * Proxy settings are hidden at the moment as an advanced feauture @@ -1436,8 +1473,32 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget *gp) freerdp_device_collection_add(rfi->settings, (RDPDR_DEVICE *)parallel); } + /* If needed, force interactive authentication by deleting all authentication fields, + * forcing libfreerdp to call our callbacks for authentication. + This usually happens from a second attempt of connection, never on the 1st one. */ + if (rfi->attempt_interactive_authentication) { + if (rfi->settings->Username) free(rfi->settings->Username); + rfi->settings->Username = NULL; + if (rfi->settings->Password) free(rfi->settings->Password); + rfi->settings->Password = NULL; + if (rfi->settings->Domain) free(rfi->settings->Domain); + rfi->settings->Domain = NULL; + + if (rfi->settings->GatewayDomain) free(rfi->settings->GatewayDomain); + rfi->settings->GatewayDomain = NULL; + if (rfi->settings->GatewayUsername) free(rfi->settings->GatewayUsername); + rfi->settings->GatewayUsername = NULL; + if (rfi->settings->GatewayPassword) free(rfi->settings->GatewayPassword); + rfi->settings->GatewayPassword = NULL; + rfi->settings->GatewayUseSameCredentials = FALSE; + + } + + gboolean orphaned; + if (!freerdp_connect(rfi->instance)) { - if (!rfi->user_cancelled) { + if (GET_PLUGIN_DATA(rfi->protocol_widget) == NULL) orphaned = True; else orphaned = False; + if (!orphaned) { UINT32 e; e = freerdp_get_last_error(rfi->instance->context); @@ -1448,11 +1509,8 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget *gp) #ifdef FREERDP_ERROR_CONNECT_LOGON_FAILURE case FREERDP_ERROR_CONNECT_LOGON_FAILURE: #endif - remmina_plugin_service->protocol_plugin_set_error(gp, _("Authentication to RDP server %s failed.\nCheck username, password and domain."), - rfi->settings->ServerHostname); - // Invalidate the saved password, so the user will be re-asked at next logon - if (!remmina_rdp_authenticate(rfi->instance, NULL, NULL, NULL)) - remmina_plugin_service->file_unsave_password(remminafile); + /* Logon failure, will retry with interactive authentication */ + rfi->attempt_interactive_authentication = TRUE; break; case STATUS_ACCOUNT_LOCKED_OUT: #ifdef FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT @@ -1540,6 +1598,11 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget *gp) remmina_plugin_service->protocol_plugin_set_error(gp, _("Server %s denied the connection."), rfi->settings->ServerHostname); break; #endif + + case FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS: + rfi->user_cancelled = TRUE; + break; + default: g_printf("libfreerdp returned code is %08X\n", e); remmina_plugin_service->protocol_plugin_set_error(gp, _("Unable to connect to RDP server %s"), rfi->settings->ServerHostname); @@ -1550,11 +1613,77 @@ static gboolean remmina_rdp_main(RemminaProtocolWidget *gp) return FALSE; } - remmina_rdp_main_loop(gp); + if (GET_PLUGIN_DATA(rfi->protocol_widget) == NULL) orphaned = True; else orphaned = False; + if (!orphaned && freerdp_get_last_error(rfi->instance->context) == FREERDP_ERROR_SUCCESS && !rfi->user_cancelled) { + remmina_rdp_main_loop(gp); + } return TRUE; } +static void rfi_uninit(rfContext* rfi) +{ + freerdp *instance; + + instance = rfi->instance; + + if (rfi->remmina_plugin_thread) { + rfi->thread_cancelled = TRUE; // Avoid all rf_queue function to run + pthread_cancel(rfi->remmina_plugin_thread); + if (rfi->remmina_plugin_thread) + pthread_join(rfi->remmina_plugin_thread, NULL); + } + + if (instance) { + if (rfi->connected) { + freerdp_abort_connect(instance); + rfi->connected = False; + } + } + + + if (rfi->rfx_context) { + rfx_context_free(rfi->rfx_context); + rfi->rfx_context = NULL; + } + if (instance) { + RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; + if (pEntryPoints) + IFCALL(pEntryPoints->GlobalUninit); + free(instance->pClientEntryPoints); + freerdp_context_free(instance); /* context is rfContext* rfi */ + freerdp_free(instance); /* This implicitly frees instance->context and rfi is no longer valid */ + } + + +} + +static gboolean complete_cleanup_on_main_thread(gpointer data) +{ + TRACE_CALL(__func__); + + gboolean orphaned; + rfContext *rfi = (rfContext *)data; + RemminaProtocolWidget *gp; + + gp = rfi->protocol_widget; + if (GET_PLUGIN_DATA(gp) == NULL) orphaned = True; else orphaned = False; + + remmina_rdp_cliprdr_detach_owner(gp); + if (!orphaned) remmina_rdp_event_uninit(gp); + + if (!orphaned) g_object_steal_data(G_OBJECT(gp), "plugin-data"); + + rfi_uninit(rfi); + + /* Notify the RemminaProtocolWidget that we closed our connection, and the GUI interface + can be removed */ + if (!orphaned) + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); + + return G_SOURCE_REMOVE; +} + static gpointer remmina_rdp_main_thread(gpointer data) { TRACE_CALL(__func__); @@ -1564,15 +1693,19 @@ static gpointer remmina_rdp_main_thread(gpointer data) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); CANCEL_ASYNC - gp = (RemminaProtocolWidget *)data; + gp = (RemminaProtocolWidget *)data; rfi = GET_PLUGIN_DATA(gp); - remmina_rdp_main(gp); - rfi->thread = 0; + rfi->attempt_interactive_authentication = FALSE; + do { + remmina_rdp_main(gp); + } while(!remmina_plugin_service->protocol_plugin_has_error(gp) && rfi->attempt_interactive_authentication == TRUE && !rfi->user_cancelled); + + rfi->remmina_plugin_thread = 0; + + /* cleanup */ + g_idle_add(complete_cleanup_on_main_thread, (gpointer)rfi); - /* Signal main thread that we closed the connection. But wait 200ms, because we may - * have outstaiding events to process in the meanwhile */ - g_timeout_add(200, ((GSourceFunc)remmina_plugin_service->protocol_plugin_close_connection), gp); return NULL; } @@ -1586,6 +1719,7 @@ static void remmina_rdp_init(RemminaProtocolWidget *gp) instance = freerdp_new(); instance->PreConnect = remmina_rdp_pre_connect; instance->PostConnect = remmina_rdp_post_connect; + instance->PostDisconnect = remmina_rdp_post_disconnect; instance->Authenticate = remmina_rdp_authenticate; instance->GatewayAuthenticate = remmina_rdp_gw_authenticate; instance->VerifyCertificate = remmina_rdp_verify_certificate; @@ -1602,6 +1736,7 @@ static void remmina_rdp_init(RemminaProtocolWidget *gp) rfi->settings = instance->settings; rfi->connected = False; rfi->is_reconnecting = False; + rfi->user_cancelled = FALSE; freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); @@ -1615,11 +1750,11 @@ static gboolean remmina_rdp_open_connection(RemminaProtocolWidget *gp) rfi->scale = remmina_plugin_service->remmina_protocol_widget_get_current_scale_mode(gp); - if (pthread_create(&rfi->thread, NULL, remmina_rdp_main_thread, gp)) { + if (pthread_create(&rfi->remmina_plugin_thread, NULL, remmina_rdp_main_thread, gp)) { remmina_plugin_service->protocol_plugin_set_error(gp, "%s", "Failed to initialize pthread. Falling back to non-thread mode…"); - rfi->thread = 0; + rfi->remmina_plugin_thread = 0; return FALSE; } @@ -1630,64 +1765,27 @@ static gboolean remmina_rdp_open_connection(RemminaProtocolWidget *gp) static gboolean remmina_rdp_close_connection(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); + + RemminaPluginRdpEvent rdp_event = { 0 }; rfContext *rfi = GET_PLUGIN_DATA(gp); - freerdp *instance; if (!remmina_plugin_service->is_main_thread()) g_printf("WARNING: %s called on a subthread, may not work or crash remmina.\n", __func__); - /* Immediately deatch GTK clipboard from this connection */ - remmina_rdp_cliprdr_detach_owner(gp); - - if (freerdp_get_last_error(rfi->instance->context) == 0x10005) - remmina_plugin_service->protocol_plugin_set_error(gp, "Another user connected to the server (%s), forcing the disconnection of the current connection.", rfi->settings->ServerHostname); - instance = rfi->instance; - if (rfi->thread) { - rfi->thread_cancelled = TRUE; // Avoid all rf_queue function to run - pthread_cancel(rfi->thread); - - if (rfi->thread) - pthread_join(rfi->thread, NULL); - } - - if (instance) { - if (rfi->connected) { - //freerdp_disconnect(instance); - freerdp_abort_connect(instance); - rfi->connected = False; - } - } - - if (rfi->hdc) { - gdi_DeleteDC(rfi->hdc); - rfi->hdc = NULL; - } - - remmina_rdp_clipboard_free(rfi); - if (rfi->rfx_context) { - rfx_context_free(rfi->rfx_context); - rfi->rfx_context = NULL; - } - - if (instance) { - gdi_free(instance); - cache_free(instance->context->cache); - instance->context->cache = NULL; - } - - /* Destroy event queue. Pending async events will be discarded. Should we flush it ? */ - remmina_rdp_event_uninit(gp); - - if (instance) { - freerdp_context_free(instance); /* context is rfContext* rfi */ - freerdp_free(instance); /* This implicitly frees instance->context and rfi is no longer valid */ + if (rfi && !rfi->connected) { + /* libfreerdp is attempting to connect, we cannot interrupt our main thread + * in the connect phase. + * So we remove "plugin-data" from gp, so our rfi remains "orphan" + */ + remmina_rdp_event_uninit(gp); + g_object_steal_data(G_OBJECT(gp), "plugin-data"); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); + return FALSE; } - /* Remove instance->context from gp object data to avoid double free */ - g_object_steal_data(G_OBJECT(gp), "plugin-data"); - /* Now let remmina to complete its disconnection tasks */ - remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect"); + rdp_event.type = REMMINA_RDP_EVENT_DISCONNECT; + remmina_rdp_event_event_push(gp, &rdp_event); return FALSE; } diff --git a/plugins/rdp/rdp_plugin.h b/plugins/rdp/rdp_plugin.h index 523c0fa96..de3d3a062 100644 --- a/plugins/rdp/rdp_plugin.h +++ b/plugins/rdp/rdp_plugin.h @@ -111,7 +111,8 @@ typedef enum { REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_LIST, REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_DATA_RESPONSE, REMMINA_RDP_EVENT_TYPE_CLIPBOARD_SEND_CLIENT_FORMAT_DATA_REQUEST, - REMMINA_RDP_EVENT_TYPE_SEND_MONITOR_LAYOUT + REMMINA_RDP_EVENT_TYPE_SEND_MONITOR_LAYOUT, + REMMINA_RDP_EVENT_DISCONNECT } RemminaPluginRdpEventType; struct remmina_plugin_rdp_event { @@ -241,7 +242,8 @@ typedef struct remmina_plugin_rdp_keymap_entry { } RemminaPluginRdpKeymapEntry; struct rf_context { - rdpContext _p; + rdpContext context; + DEFINE_RDP_CLIENT_COMMON(); RemminaProtocolWidget* protocol_widget; @@ -249,7 +251,7 @@ struct rf_context { rdpSettings* settings; freerdp* instance; - pthread_t thread; + pthread_t remmina_plugin_thread; RemminaScaleMode scale; gboolean user_cancelled; gboolean thread_cancelled; @@ -266,6 +268,11 @@ struct rf_context { gboolean connected; gboolean is_reconnecting; + /* orphaned: rf_context has still one or more libfreerdp thread active, + * but no longer maintained by an open RemminaProtocolWidget/tab. + * When the orphaned thread terminates, we must cleanup rf_context. + */ + gboolean orphaned; int reconnect_maxattempts; int reconnect_nattempt; @@ -278,7 +285,6 @@ struct rf_context { guint delayed_monitor_layout_handler; gboolean use_client_keymap; - HGDI_DC hdc; gint srcBpp; GdkDisplay* display; GdkVisual* visual; @@ -304,6 +310,8 @@ struct rf_context { GArray* keymap; /* Array of RemminaPluginRdpKeymapEntry */ + gboolean attempt_interactive_authentication; + enum { REMMINA_POSTCONNECT_ERROR_OK = 0, REMMINA_POSTCONNECT_ERROR_GDI_INIT = 1, REMMINA_POSTCONNECT_ERROR_NO_H264 } postconnect_error; }; @@ -316,4 +324,3 @@ BOOL rf_check_fds(RemminaProtocolWidget* gp); void rf_object_free(RemminaProtocolWidget* gp, RemminaPluginRdpUiObject* obj); void remmina_rdp_event_event_push(RemminaProtocolWidget* gp, const RemminaPluginRdpEvent* e); - diff --git a/plugins/spice/spice_plugin.c b/plugins/spice/spice_plugin.c index 32219fc75..794a503ce 100644 --- a/plugins/spice/spice_plugin.c +++ b/plugins/spice/spice_plugin.c @@ -157,7 +157,7 @@ static gboolean remmina_plugin_spice_close_connection(RemminaProtocolWidget *gp) spice_session_disconnect(gpdata->session); g_object_unref(gpdata->session); gpdata->session = NULL; - remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect"); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); } #ifdef SPICE_GTK_CHECK_VERSION @@ -313,7 +313,7 @@ static void remmina_plugin_spice_display_ready_cb(GObject *display, GParamSpec * gtk_widget_show(GTK_WIDGET(display)); remmina_plugin_service->protocol_plugin_register_hostkey(gp, GTK_WIDGET(display)); - remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect"); + remmina_plugin_service->protocol_plugin_signal_connection_opened(gp); } } diff --git a/plugins/st/st_plugin.c b/plugins/st/st_plugin.c index 1b50e705a..5bcc3d9db 100644 --- a/plugins/st/st_plugin.c +++ b/plugins/st/st_plugin.c @@ -68,7 +68,7 @@ static void remmina_plugin_st_on_plug_added(GtkSocket *socket, RemminaProtocolWi RemminaPluginData *gpdata; gpdata = (RemminaPluginData*) g_object_get_data(G_OBJECT(gp), "plugin-data"); remmina_plugin_service->log_printf("[%s] Plugin plug added on socket %d\n", PLUGIN_NAME, gpdata->socket_id); - remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect"); + remmina_plugin_service->protocol_plugin_signal_connection_opened(gp); return; } @@ -76,7 +76,7 @@ static void remmina_plugin_st_on_plug_removed(GtkSocket *socket, RemminaProtocol { TRACE_CALL(__func__); remmina_plugin_service->log_printf("[%s] Plugin plug removed\n", PLUGIN_NAME); - remmina_plugin_service->protocol_plugin_close_connection(gp); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); } static void remmina_plugin_st_init(RemminaProtocolWidget *gp) @@ -209,7 +209,7 @@ static gboolean remmina_plugin_st_close_connection(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); remmina_plugin_service->log_printf("[%s] Plugin close connection\n", PLUGIN_NAME); - remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect"); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } diff --git a/plugins/vnc/vnc_plugin.c b/plugins/vnc/vnc_plugin.c index 6cf1df80e..08bff2109 100644 --- a/plugins/vnc/vnc_plugin.c +++ b/plugins/vnc/vnc_plugin.c @@ -60,8 +60,6 @@ static const gchar *dot_cursor_xpm[] = #define LOCK_BUFFER(t) if (t) { CANCEL_DEFER } pthread_mutex_lock(&gpdata->buffer_mutex); #define UNLOCK_BUFFER(t) pthread_mutex_unlock(&gpdata->buffer_mutex); if (t) { CANCEL_ASYNC } - - struct onMainThread_cb_data { enum { FUNC_UPDATE_SCALE } func; GtkWidget * widget; @@ -239,7 +237,7 @@ static void remmina_plugin_vnc_update_scale(RemminaProtocolWidget *gp, gboolean /* In non scaled mode, the plugins forces dimensions of drawing area */ gtk_widget_set_size_request(GTK_WIDGET(gpdata->drawing_area), width, height); - remmina_plugin_service->protocol_plugin_emit_signal(gp, "update-align"); + remmina_plugin_service->protocol_plugin_update_align(gp); } gboolean remmina_plugin_vnc_setcursor(RemminaProtocolWidget *gp) @@ -487,7 +485,7 @@ static rfbBool remmina_plugin_vnc_rfb_allocfb(rfbClient *cl) remmina_plugin_vnc_update_scale(gp, scale); /* Notify window of change so that scroll border can be hidden or shown if needed */ - remmina_plugin_service->protocol_plugin_emit_signal(gp, "desktop-resize"); + remmina_plugin_service->protocol_plugin_desktop_resize(gp); /* Refresh the client’s updateRect - bug in xvncclient */ cl->updateRect.w = width; @@ -1027,6 +1025,7 @@ static gboolean remmina_plugin_vnc_incoming_connection(RemminaProtocolWidget *gp return TRUE; } + static gboolean remmina_plugin_vnc_main_loop(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); @@ -1075,7 +1074,7 @@ handle_buffered: if (!HandleRFBServerMessage(cl)) { gpdata->running = FALSE; if (gpdata->connected && !remmina_plugin_service->protocol_plugin_is_closed(gp)) - IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_close_connection, gp); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } } @@ -1220,7 +1219,7 @@ static gboolean remmina_plugin_vnc_main(RemminaProtocolWidget *gp) remmina_plugin_service->protocol_plugin_set_error(gp, "%s", vnc_error); gpdata->running = FALSE; - IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_close_connection, gp); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } @@ -1229,7 +1228,7 @@ static gboolean remmina_plugin_vnc_main(RemminaProtocolWidget *gp) gpdata->client = cl; - remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect"); + remmina_plugin_service->protocol_plugin_signal_connection_opened(gp); if (remmina_plugin_service->file_get_int(remminafile, "disableserverinput", FALSE)) PermitServerInput(cl, 1); @@ -1609,9 +1608,7 @@ static gboolean remmina_plugin_vnc_close_connection_timeout(RemminaProtocolWidge pthread_mutex_destroy(&gpdata->buffer_mutex); - - - remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect"); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } diff --git a/plugins/xdmcp/xdmcp_plugin.c b/plugins/xdmcp/xdmcp_plugin.c index ac8109f07..97f71fc31 100644 --- a/plugins/xdmcp/xdmcp_plugin.c +++ b/plugins/xdmcp/xdmcp_plugin.c @@ -68,14 +68,14 @@ static void remmina_plugin_xdmcp_on_plug_added(GtkSocket *socket, RemminaProtoco TRACE_CALL(__func__); RemminaPluginXdmcpData *gpdata = GET_PLUGIN_DATA(gp); - remmina_plugin_service->protocol_plugin_emit_signal(gp, "connect"); + remmina_plugin_service->protocol_plugin_signal_connection_opened(gp); gpdata->ready = TRUE; } static void remmina_plugin_xdmcp_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp) { TRACE_CALL(__func__); - remmina_plugin_service->protocol_plugin_close_connection(gp); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); } static gboolean remmina_plugin_xdmcp_start_xephyr(RemminaProtocolWidget *gp) @@ -228,7 +228,7 @@ remmina_plugin_xdmcp_main_thread(gpointer data) CANCEL_ASYNC if (!remmina_plugin_xdmcp_main((RemminaProtocolWidget*)data)) { - IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_close_connection, data); + IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_signal_connection_closed, data); } return NULL; } @@ -307,7 +307,7 @@ static gboolean remmina_plugin_xdmcp_close_connection(RemminaProtocolWidget *gp) gpdata->pid = 0; } - remmina_plugin_service->protocol_plugin_emit_signal(gp, "disconnect"); + remmina_plugin_service->protocol_plugin_signal_connection_closed(gp); return FALSE; } @@ -421,4 +421,3 @@ remmina_plugin_entry(RemminaPluginService *service) return TRUE; } - |