Hi
On Thu, Sep 17, 2015 at 12:23 PM, Marc-André Lureau <marcandre.lureau@xxxxxxxxx> wrote:
Only way to connect multiple drives, is if you restart the service,
because the drives will disconnect, after restarting guest.
I will add a disconnect function to the quit function in the service,
so that if uou disable, or restart teh service, the drive will be unmapped
Hi
On Thu, Aug 27, 2015 at 6:25 PM, Lukas Venhoda <lvenhoda@xxxxxxxxxx> wrote:
> Try to connect to shared folder automatically on Windows.
>
> On each loop of run_service(), spawn a thread, that waits for 5 seconds.
> If read_thread() returns, it means, that sharing is not yet connected,
> and the map_drive thread is cancelled, and joined back to main thread.
>
> If the map_drive thread is NOT cancelled, it enumerates free drive
> letters, and maps shared folder to highest possible (from Z: to A:).
>
> If all drive letters are already assigned, stop the service.
Could you explain in the commit message why you need the thread ?
How about this commit message?
"Try to connect to shared folder automatically on Windows.
When client is connected, and sharing is enabled, map_drive is called.
It enumerates free drive letters, and maps shared folder to highest possible,
from (Z:) to (A:). If all drive letters are already assigned, stops the service.
map_drive needs to be called only after, the read_thread blocks.
If it is called before, the mapping fails.
In order to call it only after read_thread blocks, we spawn a thread,
that waits for 5 seconds, before actually calling map_drive.
If read_thread() returns, it means, that sharing is not yet connected,
and the map_drive thread is cancelled.
We spawn this thread on each loop of run_service(), and join it back
into main_thread, after main loop ends."
"Try to connect to shared folder automatically on Windows.
When client is connected, and sharing is enabled, map_drive is called.
It enumerates free drive letters, and maps shared folder to highest possible,
from (Z:) to (A:). If all drive letters are already assigned, stops the service.
map_drive needs to be called only after, the read_thread blocks.
If it is called before, the mapping fails.
In order to call it only after read_thread blocks, we spawn a thread,
that waits for 5 seconds, before actually calling map_drive.
If read_thread() returns, it means, that sharing is not yet connected,
and the map_drive thread is cancelled.
We spawn this thread on each loop of run_service(), and join it back
into main_thread, after main loop ends."
How do you prevent from having multiple drive pointing to the spice folder?
Currently, I don't.
Only way to connect multiple drives, is if you restart the service,
because the drives will disconnect, after restarting guest.
I will add a disconnect function to the quit function in the service,
so that if uou disable, or restart teh service, the drive will be unmapped
It looks like this would fail if the guest is started without client
> ---
> Changes since RFC:
> - Calling WNetAddConnection2() blindly was slow and caause many threads to spawn.
> - Now only call it once, when it is sure, that it will connect.
> - Now connects to a * drive, instead of always Z:
> - Thread is now spawned and joined every time run_service() is called.
> ---
> Makefile.am | 4 +++
> spice/spice-webdavd.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 80 insertions(+)
>
> diff --git a/Makefile.am b/Makefile.am
> index 485417b..df9a73e 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -87,6 +87,10 @@ spice_webdavd_LDADD = \
> $(PIE_LDFLAGS) \
> $(NULL)
>
> +if OS_WIN32
> +spice_webdavd_LDADD += -lnetapi32 -lmpr
> +endif
> +
> deps.txt:
> $(AM_V_GEN)rpm -qa | grep $(host_os) | sort | unix2dos > $@
>
> diff --git a/spice/spice-webdavd.c b/spice/spice-webdavd.c
> index f9c5cf1..3940f1c 100644
> --- a/spice/spice-webdavd.c
> +++ b/spice/spice-webdavd.c
> @@ -737,11 +737,81 @@ open_mux_path (const char *path)
> mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream));
> }
>
> +#ifdef G_OS_WIN32
> +static gchar
> +get_free_drive_letter(void)
> +{
> + const guint32 max_mask = 1 << 25;
> + guint32 drives;
> + guint32 mask;
> + gint i;
> +
> + drives = GetLogicalDrives ();
> +
> + for (i = 0; i < 26; i++)
> + {
> + mask = max_mask >> i;
> + if ((drives & mask) == 0)
> + return 'Z' - i;
> + }
> +
> + return 0;
> +}
> +
> +static gpointer
> +map_drive(gpointer user_data)
> +{
> + GCancellable * cancel_map = user_data;
> + gchar drive_letter;
> + gchar local_name[3];
> + gchar remote_name[] = "http://localhost:9843/";
> + NETRESOURCE net_resource;
> + guint32 retval;
> + gint i;
> +
> + for (i = 0; i < 5; ++i)
> + {
> + if (g_cancellable_is_cancelled (cancel_map))
> + return NULL;
> + else
> + g_usleep (G_USEC_PER_SEC);
> + }
connected (or not sharing folder).
I'm not sure I follow.
This is supposed to return NULL precisely, if the client is not connected,
or not sharing folder. Windows webdavd will loop and call run_service(),
until sharing is enabled, which will then NOT cancel this function,
and we map the drive.
or not sharing folder. Windows webdavd will loop and call run_service(),
until sharing is enabled, which will then NOT cancel this function,
and we map the drive.
> _______________________________________________
> +
> + if ((drive_letter = get_free_drive_letter ()) == 0)
> + g_error ("all drive letters already assigned.");
> +
> + local_name[0] = drive_letter;
> + local_name[1] = ':';
> + local_name[2] = 0;
> +
> + net_resource.dwType = RESOURCETYPE_DISK;
> + net_resource.lpLocalName = local_name;
> + net_resource.lpRemoteName = remote_name;
> + net_resource.lpProvider = NULL;
> +
> + retval = WNetAddConnection2 (&net_resource, NULL, NULL, CONNECT_TEMPORARY);
> +
> + if (retval == NO_ERROR)
> + g_debug ("map_drive ok");
> + else if (retval == ERROR_ALREADY_ASSIGNED)
> + g_debug ("map_drive already asigned");
> + else
> + g_error ("map_drive error %d", retval);
> +
> + return NULL;
> +}
> +#endif
> +
> static void
> run_service (void)
> {
> g_debug ("Run service");
>
> +#ifdef G_OS_WIN32
> + GCancellable * cancel_map = g_cancellable_new ();
> + GThread * map_drive_thread = g_thread_new ("map-drive-thread", map_drive, cancel_map);
> +#endif
> +
> g_socket_service_start (socket_service);
>
> cancel = g_cancellable_new ();
> @@ -775,6 +845,12 @@ run_service (void)
> g_main_loop_run (loop);
> g_main_loop_unref (loop);
>
> +#ifdef G_OS_WIN32
> + g_cancellable_cancel (cancel_map);
> + g_thread_join(map_drive_thread);
> + g_print ("map-drive-thread joined\n");
> +#endif
> +
> g_cancellable_cancel (cancel);
>
> g_clear_object (&mux_istream);
> --
> 2.4.3
>
> Spice-devel mailing list
> Spice-devel@xxxxxxxxxxxxxxxxxxxxx
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
--
Marc-André Lureau
Lukas Venhoda
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel