Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Panozzo <giovanni@panozzo.it>2019-10-27 23:41:37 +0300
committerGiovanni Panozzo <giovanni@panozzo.it>2019-11-01 11:11:27 +0300
commitb5a875e043148d7d72c3681042efa31304f2bba9 (patch)
tree93783842c633d81301259f3015a150b47063fb60
parent06ee121ca368c05dd8765fabd3483b9fa08a8cc2 (diff)
Plugin connection close refactoring
-rw-r--r--plugins/nx/nx_plugin.c14
-rw-r--r--plugins/rdp/rdp_channels.c2
-rw-r--r--plugins/rdp/rdp_cliprdr.c2
-rw-r--r--plugins/rdp/rdp_event.c5
-rw-r--r--plugins/rdp/rdp_plugin.c246
-rw-r--r--plugins/rdp/rdp_plugin.h17
-rw-r--r--plugins/spice/spice_plugin.c4
-rw-r--r--plugins/st/st_plugin.c6
-rw-r--r--plugins/vnc/vnc_plugin.c17
-rw-r--r--plugins/xdmcp/xdmcp_plugin.c9
-rw-r--r--src/include/remmina/plugin.h10
-rw-r--r--src/rcw.c16
-rw-r--r--src/remmina_file.c4
-rw-r--r--src/remmina_file.h2
-rw-r--r--src/remmina_plugin_manager.c12
-rw-r--r--src/remmina_protocol_widget.c180
-rw-r--r--src/remmina_protocol_widget.h9
-rw-r--r--src/remmina_sftp_plugin.c2
-rw-r--r--src/remmina_ssh_plugin.c6
19 files changed, 362 insertions, 201 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;
}
-
diff --git a/src/include/remmina/plugin.h b/src/include/remmina/plugin.h
index 3c28b86f9..d08abd770 100644
--- a/src/include/remmina/plugin.h
+++ b/src/include/remmina/plugin.h
@@ -165,7 +165,11 @@ typedef struct _RemminaPluginService {
gboolean (* protocol_plugin_start_reverse_tunnel)(RemminaProtocolWidget *gp, gint local_port);
gboolean (* protocol_plugin_start_xport_tunnel)(RemminaProtocolWidget *gp, RemminaXPortTunnelInitFunc init_func);
void (* protocol_plugin_set_display)(RemminaProtocolWidget *gp, gint display);
- gboolean (* protocol_plugin_close_connection)(RemminaProtocolWidget *gp);
+ void (* protocol_plugin_signal_connection_closed)(RemminaProtocolWidget *gp);
+ void (* protocol_plugin_signal_connection_opened)(RemminaProtocolWidget *gp);
+ void (* protocol_plugin_update_align)(RemminaProtocolWidget *gp);
+ void (* protocol_plugin_unlock_dynres)(RemminaProtocolWidget *gp);
+ void (* protocol_plugin_desktop_resize)(RemminaProtocolWidget *gp);
gint (* protocol_plugin_init_authpwd)(RemminaProtocolWidget *gp, RemminaAuthpwdType authpwd_type, gboolean allow_password_saving);
gint (* protocol_plugin_init_authuserpwd)(RemminaProtocolWidget *gp, gboolean want_domain, gboolean allow_password_saving);
gint (* protocol_plugin_init_certificate)(RemminaProtocolWidget *gp, const gchar* subject, const gchar* issuer, const gchar* fingerprint);
@@ -201,7 +205,7 @@ typedef struct _RemminaPluginService {
gchar* (*file_get_secret)(RemminaFile * remminafile, const gchar * setting);
void (* file_set_int)(RemminaFile *remminafile, const gchar *setting, gint value);
gint (* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value);
- void (* file_unsave_password)(RemminaFile *remminafile);
+ void (* file_unsave_passwords)(RemminaFile *remminafile);
void (* pref_set_value)(const gchar *key, const gchar *value);
gchar* (*pref_get_value)(const gchar * key);
@@ -230,5 +234,3 @@ typedef struct _RemminaPluginService {
typedef gboolean (*RemminaPluginEntryFunc) (RemminaPluginService *service);
G_END_DECLS
-
-
diff --git a/src/rcw.c b/src/rcw.c
index 7b6a92678..875c745ba 100644
--- a/src/rcw.c
+++ b/src/rcw.c
@@ -3701,7 +3701,7 @@ void rco_on_disconnect(RemminaProtocolWidget *gp, gpointer data)
RemminaConnectionWindowPriv *priv = cnnobj->cnnwin->priv;
GtkWidget *pparent;
- g_debug("disconnect signal emitted");
+ g_debug("disconnect signal received on RemminaProtocolWidget");
/* Detach the protocol widget from the notebook now, or we risk that a
* window delete will destroy cnnobj->proto before we complete disconnection.
*/
@@ -3729,8 +3729,10 @@ void rco_on_disconnect(RemminaProtocolWidget *gp, gpointer data)
RemminaMessagePanel *mp;
/* Destroy scrolled_contaner (and viewport) and all its children the plugin created
* on it, so they will not receive GUI signals */
- gtk_widget_destroy(cnnobj->scrolled_container);
- cnnobj->scrolled_container = NULL;
+ if (cnnobj->scrolled_container) {
+ gtk_widget_destroy(cnnobj->scrolled_container);
+ cnnobj->scrolled_container = NULL;
+ }
cnnobj->viewport = NULL;
mp = remmina_message_panel_new();
remmina_message_panel_setup_message(mp, remmina_protocol_widget_get_error_message(gp), cb_lasterror_confirmed, gp);
@@ -3829,6 +3831,12 @@ GtkWidget *rcw_open_from_file_full(RemminaFile *remminafile, GCallback disconnec
gint view_mode;
const gchar *msg;
+ if (disconnect_cb) {
+ g_print("disconnect_cb is deprecated inside rcw_open_from_file_full() and should be null");
+ return NULL;
+ }
+
+
/* Create the RemminaConnectionObject */
cnnobj = g_new0(RemminaConnectionObject, 1);
cnnobj->remmina_file = remminafile;
@@ -3913,8 +3921,6 @@ GtkWidget *rcw_open_from_file_full(RemminaFile *remminafile, GCallback disconnec
gtk_widget_show(cnnobj->proto);
g_signal_connect(G_OBJECT(cnnobj->proto), "connect", G_CALLBACK(rco_on_connect), cnnobj);
- if (disconnect_cb)
- *handler = g_signal_connect(G_OBJECT(cnnobj->proto), "disconnect", disconnect_cb, data);
g_signal_connect(G_OBJECT(cnnobj->proto), "disconnect", G_CALLBACK(rco_on_disconnect), NULL);
g_signal_connect(G_OBJECT(cnnobj->proto), "desktop-resize", G_CALLBACK(rco_on_desktop_resize), NULL);
g_signal_connect(G_OBJECT(cnnobj->proto), "update-align", G_CALLBACK(rco_on_update_align), NULL);
diff --git a/src/remmina_file.c b/src/remmina_file.c
index bfce7113a..eefbb3ffc 100644
--- a/src/remmina_file.c
+++ b/src/remmina_file.c
@@ -603,13 +603,13 @@ void remmina_file_delete(const gchar *filename)
remminafile = remmina_file_load(filename);
if (remminafile) {
- remmina_file_unsave_password(remminafile);
+ remmina_file_unsave_passwords(remminafile);
remmina_file_free(remminafile);
}
g_unlink(filename);
}
-void remmina_file_unsave_password(RemminaFile *remminafile)
+void remmina_file_unsave_passwords(RemminaFile *remminafile)
{
/* Delete all saved secrets for this profile */
diff --git a/src/remmina_file.h b/src/remmina_file.h
index 44a559557..01f3914a6 100644
--- a/src/remmina_file.h
+++ b/src/remmina_file.h
@@ -84,7 +84,7 @@ RemminaFile *remmina_file_dup_temp_protocol(RemminaFile *remminafile, const gcha
/* Delete a .remmina file */
void remmina_file_delete(const gchar *filename);
/* Delete a "password" field and save into .remmina file */
-void remmina_file_unsave_password(RemminaFile *remminafile);
+void remmina_file_unsave_passwords(RemminaFile *remminafile);
/* Function used to update the atime and mtime of a given remmina file, partially
* taken from suckless sbase */
gchar *remmina_file_get_datetime(RemminaFile *remminafile);
diff --git a/src/remmina_plugin_manager.c b/src/remmina_plugin_manager.c
index a47b9c5c6..9881ac0df 100644
--- a/src/remmina_plugin_manager.c
+++ b/src/remmina_plugin_manager.c
@@ -183,7 +183,11 @@ RemminaPluginService remmina_plugin_manager_service =
remmina_protocol_widget_start_reverse_tunnel,
remmina_protocol_widget_start_xport_tunnel,
remmina_protocol_widget_set_display,
- remmina_protocol_widget_close_connection,
+ remmina_protocol_widget_signal_connection_closed,
+ remmina_protocol_widget_signal_connection_opened,
+ remmina_protocol_widget_update_align,
+ remmina_protocol_widget_unlock_dynres,
+ remmina_protocol_widget_desktop_resize,
remmina_protocol_widget_panel_authpwd,
remmina_protocol_widget_panel_authuserpwd,
remmina_protocol_widget_panel_new_certificate,
@@ -217,7 +221,7 @@ RemminaPluginService remmina_plugin_manager_service =
remmina_file_get_secret,
remmina_file_set_int,
remmina_file_get_int,
- remmina_file_unsave_password,
+ remmina_file_unsave_passwords,
remmina_pref_set_value,
remmina_pref_get_value,
@@ -555,7 +559,3 @@ gboolean remmina_plugin_manager_is_encrypted_setting(RemminaProtocolPlugin *pp,
return TRUE;
}
-
-
-
-
diff --git a/src/remmina_protocol_widget.c b/src/remmina_protocol_widget.c
index 8a1c27c95..e8fbaedc5 100644
--- a/src/remmina_protocol_widget.c
+++ b/src/remmina_protocol_widget.c
@@ -41,6 +41,8 @@
#include <glib/gi18n.h>
#include <stdlib.h>
+
+
#include "remmina_chat_window.h"
#include "remmina_masterthread_exec.h"
#include "remmina_ext_exec.h"
@@ -56,7 +58,6 @@
#include <gdk/gdkwayland.h>
#endif
-
struct _RemminaProtocolWidgetPriv {
RemminaFile* remmina_file;
@@ -186,28 +187,7 @@ static void remmina_protocol_widget_destroy(RemminaProtocolWidget* gp, gpointer
gp->priv = NULL;
}
-static void remmina_protocol_widget_on_connected(RemminaProtocolWidget* gp, gpointer data)
-{
- TRACE_CALL(__func__);
-#ifdef HAVE_LIBSSH
- if (gp->priv->ssh_tunnel) {
- remmina_ssh_tunnel_cancel_accept(gp->priv->ssh_tunnel);
- }
-#endif
- if (gp->priv->listen_message_panel) {
- rco_destroy_message_panel(gp->cnnobj, gp->priv->listen_message_panel);
- gp->priv->listen_message_panel = NULL;
- }
- if (gp->priv->connect_message_panel) {
- rco_destroy_message_panel(gp->cnnobj, gp->priv->connect_message_panel);
- gp->priv->connect_message_panel = NULL;
- }
-}
-static void remmina_protocol_widget_on_disconnected(RemminaProtocolWidget* gp, gpointer data)
-{
- TRACE_CALL(__func__);
-}
void remmina_protocol_widget_grab_focus(RemminaProtocolWidget* gp)
{
@@ -232,8 +212,6 @@ static void remmina_protocol_widget_init(RemminaProtocolWidget* gp)
gp->priv->closed = TRUE;
g_signal_connect(G_OBJECT(gp), "destroy", G_CALLBACK(remmina_protocol_widget_destroy), NULL);
- g_signal_connect(G_OBJECT(gp), "connect", G_CALLBACK(remmina_protocol_widget_on_connected), NULL);
- g_signal_connect(G_OBJECT(gp), "disconnect", G_CALLBACK(remmina_protocol_widget_on_disconnected), NULL);
}
void remmina_protocol_widget_open_connection_real(gpointer data)
@@ -325,63 +303,131 @@ void remmina_protocol_widget_open_connection(RemminaProtocolWidget* gp)
remmina_protocol_widget_open_connection_real(gp);
}
-gboolean remmina_protocol_widget_close_connection(RemminaProtocolWidget* gp)
+static gboolean conn_closed(RemminaProtocolWidget* gp)
{
- TRACE_CALL(__func__);
- GdkDisplay *display;
-#if GTK_CHECK_VERSION(3, 20, 0)
- GdkSeat *seat;
-#else
- GdkDeviceManager *manager;
-#endif
- GdkDevice *device = NULL;
- gboolean retval;
-
- if (!GTK_IS_WIDGET(gp) || gp->priv->closed)
- return FALSE;
+ /* Close ssh tunnel */
+ #ifdef HAVE_LIBSSH
+ if (gp->priv->ssh_tunnel) {
+ remmina_ssh_tunnel_free(gp->priv->ssh_tunnel);
+ gp->priv->ssh_tunnel = NULL;
+ }
+ #endif
+ /* Exec postcommand */
+ remmina_ext_exec_new(gp->priv->remmina_file, "postcommand");
+ /* Notify listeners (usually rcw) that the connection is closed */
+ g_signal_emit_by_name(G_OBJECT(gp), "disconnect");
+ return G_SOURCE_REMOVE;
+}
+void remmina_protocol_widget_signal_connection_closed(RemminaProtocolWidget* gp)
+{
+ /* Plugin told us that it closed the connection,
+ add async event to main thread to complete our close tasks */
+ TRACE_CALL(__func__);
gp->priv->closed = TRUE;
+ g_idle_add(conn_closed, (gpointer)gp);
+}
- display = gtk_widget_get_display(GTK_WIDGET(gp));
-#if GTK_CHECK_VERSION(3, 20, 0)
- seat = gdk_display_get_default_seat(display);
- device = gdk_seat_get_pointer(seat);
-#else
- manager = gdk_display_get_device_manager(display);
- device = gdk_device_manager_get_client_pointer(manager);
-#endif
- if (device != NULL) {
-#if GTK_CHECK_VERSION(3, 20, 0)
- gdk_seat_ungrab(seat);
-#else
- gdk_device_ungrab(device, GDK_CURRENT_TIME);
+static gboolean conn_opened(RemminaProtocolWidget* gp)
+{
+ TRACE_CALL(__func__);
+#ifdef HAVE_LIBSSH
+ if (gp->priv->ssh_tunnel) {
+ remmina_ssh_tunnel_cancel_accept(gp->priv->ssh_tunnel);
+ }
#endif
+ if (gp->priv->listen_message_panel) {
+ rco_destroy_message_panel(gp->cnnobj, gp->priv->listen_message_panel);
+ gp->priv->listen_message_panel = NULL;
}
+ if (gp->priv->connect_message_panel) {
+ rco_destroy_message_panel(gp->cnnobj, gp->priv->connect_message_panel);
+ gp->priv->connect_message_panel = NULL;
+ }
+ g_signal_emit_by_name(G_OBJECT(gp), "connect");
+ return G_SOURCE_REMOVE;
+}
+
+void remmina_protocol_widget_signal_connection_opened(RemminaProtocolWidget* gp)
+{
+ /* Plugin told us that it closed the connection,
+ add async event to main thread to complete our close tasks */
+ TRACE_CALL(__func__);
+ g_idle_add(conn_opened, (gpointer)gp);
+}
+
+static gboolean update_align(RemminaProtocolWidget* gp)
+{
+ g_signal_emit_by_name(G_OBJECT(gp), "update-align");
+ return G_SOURCE_REMOVE;
+}
+
+void remmina_protocol_widget_update_align(RemminaProtocolWidget* gp)
+{
+ /* Called by the plugin to do updates on rcw */
+ TRACE_CALL(__func__);
+ g_idle_add(update_align, (gpointer)gp);
+}
+
+static gboolean unlock_dynres(RemminaProtocolWidget* gp)
+{
+ g_signal_emit_by_name(G_OBJECT(gp), "unlock-dynres");
+ return G_SOURCE_REMOVE;
+}
+
+void remmina_protocol_widget_unlock_dynres(RemminaProtocolWidget* gp)
+{
+ /* Called by the plugin to do updates on rcw */
+ TRACE_CALL(__func__);
+ g_idle_add(unlock_dynres, (gpointer)gp);
+}
+
+static gboolean desktop_resize(RemminaProtocolWidget* gp)
+{
+ g_signal_emit_by_name(G_OBJECT(gp), "desktop-resize");
+ return G_SOURCE_REMOVE;
+}
+
+void remmina_protocol_widget_desktop_resize(RemminaProtocolWidget* gp)
+{
+ /* Called by the plugin to do updates on rcw */
+ TRACE_CALL(__func__);
+ g_idle_add(desktop_resize, (gpointer)gp);
+}
+
+
+void remmina_protocol_widget_close_connection(RemminaProtocolWidget* gp)
+{
+ TRACE_CALL(__func__);
+
+ /* kindly ask the protocol plugin to close the connection.
+ Nothing else is done here. */
+
+ if (!GTK_IS_WIDGET(gp))
+ return;
if (gp->priv->chat_window) {
gtk_widget_destroy(gp->priv->chat_window);
gp->priv->chat_window = NULL;
}
- if (!gp->priv->plugin || !gp->priv->plugin->close_connection) {
- remmina_protocol_widget_emit_signal(gp, "disconnect");
- return FALSE;
+ if (gp->priv->closed) {
+ /* Connection is already closed by the plugin, but
+ * rcw is asking to close again (usually after an error panel)
+ */
+ g_signal_emit_by_name(G_OBJECT(gp), "disconnect");
+ return;
}
- retval = gp->priv->plugin->close_connection(gp);
+ /* Ask the plugin to close, async.
+ The plugin will emit a "disconnect" signal on gp to call our
+ remmina_protocol_widget_on_disconnected() when done */
+ gp->priv->plugin->close_connection(gp);
-#ifdef HAVE_LIBSSH
- if (gp->priv->ssh_tunnel) {
- remmina_ssh_tunnel_free(gp->priv->ssh_tunnel);
- gp->priv->ssh_tunnel = NULL;
- }
-#endif
-
- /* Exec postcommand before to close the connection */
- remmina_ext_exec_new(gp->priv->remmina_file, "postcommand");
- return retval;
+ return;
}
+
/** Check if the plugin accepts keystrokes.
*/
gboolean remmina_protocol_widget_plugin_receives_keystrokes(RemminaProtocolWidget* gp)
@@ -488,6 +534,9 @@ void remmina_protocol_widget_emit_signal(RemminaProtocolWidget* gp, const gchar*
{
TRACE_CALL(__func__);
+ g_print("Emitting signals should be used from the object itself, not from another object");
+ raise(SIGINT);
+
if ( !remmina_masterthread_exec_is_main_thread() ) {
/* Allow the execution of this function from a non main thread */
RemminaMTExecData *d;
@@ -1756,6 +1805,3 @@ void remmina_protocol_widget_update_remote_resolution(RemminaProtocolWidget* gp)
gp->priv->profile_remote_width = w;
gp->priv->profile_remote_height = h;
}
-
-
-
diff --git a/src/remmina_protocol_widget.h b/src/remmina_protocol_widget.h
index 9b8d87407..566f6d94b 100644
--- a/src/remmina_protocol_widget.h
+++ b/src/remmina_protocol_widget.h
@@ -94,7 +94,12 @@ gboolean remmina_protocol_widget_is_closed(RemminaProtocolWidget *gp);
RemminaFile* remmina_protocol_widget_get_file(RemminaProtocolWidget *gp);
void remmina_protocol_widget_open_connection(RemminaProtocolWidget *gp);
-gboolean remmina_protocol_widget_close_connection(RemminaProtocolWidget *gp);
+void remmina_protocol_widget_close_connection(RemminaProtocolWidget *gp);
+void remmina_protocol_widget_signal_connection_closed(RemminaProtocolWidget *gp);
+void remmina_protocol_widget_signal_connection_opened(RemminaProtocolWidget *gp);
+void remmina_protocol_widget_update_align(RemminaProtocolWidget *gp);
+void remmina_protocol_widget_unlock_dynres(RemminaProtocolWidget *gp);
+void remmina_protocol_widget_desktop_resize(RemminaProtocolWidget *gp);
void remmina_protocol_widget_grab_focus(RemminaProtocolWidget *gp);
const RemminaProtocolFeature* remmina_protocol_widget_get_features(RemminaProtocolWidget *gp);
gboolean remmina_protocol_widget_query_feature_by_type(RemminaProtocolWidget *gp, RemminaProtocolFeatureType type);
@@ -169,5 +174,3 @@ void remmina_protocol_widget_mpdestroy(RemminaConnectionObject *cnnobj, RemminaM
G_END_DECLS
-
-
diff --git a/src/remmina_sftp_plugin.c b/src/remmina_sftp_plugin.c
index 09bcb113b..f16dc9823 100644
--- a/src/remmina_sftp_plugin.c
+++ b/src/remmina_sftp_plugin.c
@@ -177,7 +177,7 @@ remmina_plugin_sftp_main_thread(gpointer data)
}
if (!cont) {
if (sftp) remmina_sftp_free(sftp);
- IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_close_connection, gp);
+ IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_signal_connection_closed, gp);
return NULL;
}
diff --git a/src/remmina_ssh_plugin.c b/src/remmina_ssh_plugin.c
index 15e6fbeb8..e1d6752de 100644
--- a/src/remmina_ssh_plugin.c
+++ b/src/remmina_ssh_plugin.c
@@ -288,7 +288,7 @@ remmina_plugin_ssh_main_thread(gpointer data)
if (remmina_ssh_init_session(REMMINA_SSH(shell)) &&
remmina_ssh_auth(REMMINA_SSH(shell), NULL, gp, remminafile) > 0 &&
remmina_ssh_shell_open(shell, (RemminaSSHExitFunc)
- remmina_plugin_service->protocol_plugin_close_connection, gp))
+ remmina_plugin_service->protocol_plugin_signal_connection_closed, gp))
cont = TRUE;
} else {
/* New SSH Shell connection */
@@ -313,7 +313,7 @@ remmina_plugin_ssh_main_thread(gpointer data)
if (ret <= 0) break;
if (!remmina_ssh_shell_open(shell, (RemminaSSHExitFunc)
- remmina_plugin_service->protocol_plugin_close_connection, gp)) {
+ remmina_plugin_service->protocol_plugin_signal_connection_closed, gp)) {
remmina_plugin_service->protocol_plugin_set_error(gp, "%s", REMMINA_SSH(shell)->error);
break;
}
@@ -328,7 +328,7 @@ remmina_plugin_ssh_main_thread(gpointer data)
}
if (!cont) {
if (shell) remmina_ssh_shell_free(shell);
- IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_close_connection, gp);
+ IDLE_ADD((GSourceFunc)remmina_plugin_service->protocol_plugin_signal_connection_closed, gp);
return NULL;
}