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 /plugins
parent06ee121ca368c05dd8765fabd3483b9fa08a8cc2 (diff)
Plugin connection close refactoring
Diffstat (limited to 'plugins')
-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
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;
}
-