Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (8)
......@@ -369,14 +369,14 @@ EXTRA_LTLIBRARIES += libsmbc_plugin.la
libdsm_plugin_la_SOURCES = access/dsm/access.c access/dsm/sd.c access/smb_common.h
libdsm_plugin_la_CFLAGS = $(AM_CFLAGS) $(DSM_CFLAGS)
libdsm_plugin_la_LIBADD = $(DSM_LIBS)
libdsm_plugin_la_LIBADD = $(DSM_LIBS) libvlc_access_cache.la
if HAVE_DSM
access_LTLIBRARIES += libdsm_plugin.la
endif
libsmb2_plugin_la_SOURCES = access/smb2.c
libsmb2_plugin_la_CFLAGS = $(AM_CFLAGS) $(SMB2_CFLAGS)
libsmb2_plugin_la_LIBADD = $(SMB2_LIBS) $(SOCKET_LIBS)
libsmb2_plugin_la_LIBADD = $(SMB2_LIBS) $(SOCKET_LIBS) libvlc_access_cache.la
libsmb2_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
if HAVE_DSM
libsmb2_plugin_la_CFLAGS += $(DSM_CFLAGS) -DHAVE_DSM
......@@ -463,3 +463,10 @@ librist_plugin_la_LIBADD = $(RIST_LIBS) $(SOCKET_LIBS)
librist_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
access_LTLIBRARIES += $(LTLIBrist)
EXTRA_LTLIBRARIES += librist_plugin.la
### TOOLS ###
libvlc_access_cache_la_SOURCES = access/cache.c access/cache.h
libvlc_access_cache_la_LIBADD = $(LTLIBVLCCORE)
libvlc_access_cache_la_LDFLAGS = -static
noinst_LTLIBRARIES += libvlc_access_cache.la
/*****************************************************************************
* cache.c: access cache helper
*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_threads.h>
#include "access/cache.h"
#include <assert.h>
#define VLC_ACCESS_CACHE_TTL VLC_TICK_FROM_SEC(5)
#define VLC_ACCESS_CACHE_MAX_ENTRY 5
void
vlc_access_cache_entry_Delete(struct vlc_access_cache_entry *entry)
{
free(entry->url);
free(entry->username);
entry->free_cb(entry->context);
free(entry);
}
struct vlc_access_cache_entry *
vlc_access_cache_entry_New(void *context, const char *url, const char *username,
void (*free_cb)(void *context))
{
struct vlc_access_cache_entry *entry = malloc(sizeof(*entry));
if (unlikely(entry == NULL))
return NULL;
entry->url = strdup(url);
entry->username = username ? strdup(username) : NULL;
if (!entry->url || (entry->username == NULL) != (username == NULL))
{
free(entry->url);
free(entry);
return NULL;
}
entry->context = context;
entry->free_cb = free_cb;
return entry;
}
static void *
vlc_access_cache_Thread(void *data)
{
struct vlc_access_cache *cache = data;
vlc_mutex_lock(&cache->lock);
while (cache->running)
{
if (!vlc_list_is_empty(&cache->entries))
{
struct vlc_access_cache_entry *entry =
vlc_list_first_entry_or_null(&cache->entries,
struct vlc_access_cache_entry, node);
if (entry->timeout == 0 ||
vlc_cond_timedwait(&cache->cond, &cache->lock, entry->timeout) != 0)
{
vlc_list_remove(&entry->node);
vlc_mutex_unlock(&cache->lock);
vlc_access_cache_entry_Delete(entry);
vlc_mutex_lock(&cache->lock);
}
}
else
vlc_cond_wait(&cache->cond, &cache->lock);
}
vlc_mutex_unlock(&cache->lock);
return NULL;
}
static void
vlc_access_cache_InitOnce(void *data)
{
struct vlc_access_cache *cache = data;
#ifdef VLC_ACCESS_CACHE_CAN_REGISTER
vlc_mutex_lock(&cache->lock);
cache->running = true;
int ret = vlc_clone(&cache->thread, vlc_access_cache_Thread, cache,
VLC_THREAD_PRIORITY_LOW);
if (ret != 0)
cache->running = false;
vlc_mutex_unlock(&cache->lock);
#endif
}
void
vlc_access_cache_Destroy(struct vlc_access_cache *cache)
{
vlc_mutex_lock(&cache->lock);
if (cache->running)
{
cache->running = false;
vlc_cond_signal(&cache->cond);
vlc_mutex_unlock(&cache->lock);
vlc_join(cache->thread, NULL);
}
else
vlc_mutex_unlock(&cache->lock);
struct vlc_access_cache_entry *entry;
vlc_list_foreach(entry, &cache->entries, node)
vlc_access_cache_entry_Delete(entry);
}
void
vlc_access_cache_AddEntry(struct vlc_access_cache *cache,
struct vlc_access_cache_entry *entry)
{
vlc_once(&cache->once, vlc_access_cache_InitOnce, cache);
vlc_mutex_lock(&cache->lock);
if (!cache->running)
{
vlc_mutex_unlock(&cache->lock);
vlc_access_cache_entry_Delete(entry);
return;
}
struct vlc_access_cache_entry *it;
size_t count = 0;
vlc_list_foreach(it, &cache->entries, node)
count++;
if (count >= VLC_ACCESS_CACHE_MAX_ENTRY)
{
/* Too many entries, signal the thread that will delete the first one */
it = vlc_list_first_entry_or_null(&cache->entries,
struct vlc_access_cache_entry, node);
it->timeout = 0;
}
entry->timeout = vlc_tick_now() + VLC_ACCESS_CACHE_TTL;
vlc_list_append(&entry->node, &cache->entries);
vlc_cond_signal(&cache->cond);
vlc_mutex_unlock(&cache->lock);
}
struct vlc_access_cache_entry *
vlc_access_cache_GetEntry(struct vlc_access_cache *cache,
const char *url, const char *username)
{
vlc_once(&cache->once, vlc_access_cache_InitOnce, cache);
vlc_mutex_lock(&cache->lock);
struct vlc_access_cache_entry *it;
vlc_list_foreach(it, &cache->entries, node)
{
if (strcmp(url, it->url) == 0
&& (username == NULL) == (it->username == NULL)
&& (username != NULL ? strcmp(username, it->username) == 0 : true))
{
vlc_list_remove(&it->node);
vlc_cond_signal(&cache->cond);
vlc_mutex_unlock(&cache->lock);
return it;
}
}
vlc_mutex_unlock(&cache->lock);
return NULL;
}
/*****************************************************************************
* cache.h: access cache helper
*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_list.h>
struct vlc_access_cache_entry
{
void *context;
char *url;
char *username;
vlc_tick_t timeout;
void (*free_cb)(void *context);
struct vlc_list node;
};
struct vlc_access_cache
{
vlc_once_t once;
vlc_mutex_t lock;
vlc_cond_t cond;
vlc_thread_t thread;
bool running;
struct vlc_list entries;
};
#define VLC_ACCESS_CACHE_INITIALIZER(name) { \
.once = VLC_STATIC_ONCE, \
.lock = VLC_STATIC_MUTEX, \
.cond = VLC_STATIC_COND, \
.running = false, \
.entries = VLC_LIST_INITIALIZER(&name.entries), \
}
static inline char *
vlc_access_cache_entry_CreateSmbUrl(const char *server, const char *share)
{
char *url;
if (asprintf(&url, "smb://%s/%s", server, share) == -1)
return NULL;
return url;
}
struct vlc_access_cache_entry *
vlc_access_cache_entry_New(void *context, const char *url, const char *username,
void (*free_cb)(void *context));
static inline struct vlc_access_cache_entry *
vlc_access_cache_entry_NewSmb(void *context, const char *server,
const char *share, const char *username,
void (*free_cb)(void *context))
{
char *url = vlc_access_cache_entry_CreateSmbUrl(server, share);
if (url == NULL)
return NULL;
struct vlc_access_cache_entry *entry =
vlc_access_cache_entry_New(context, url, username, free_cb);
free(url);
return entry;
}
void
vlc_access_cache_entry_Delete(struct vlc_access_cache_entry *entry);
void
vlc_access_cache_Destroy(struct vlc_access_cache *cache);
void
vlc_access_cache_AddEntry(struct vlc_access_cache *cache,
struct vlc_access_cache_entry *entry);
struct vlc_access_cache_entry *
vlc_access_cache_GetEntry(struct vlc_access_cache *cache,
const char *url, const char *username);
static inline struct vlc_access_cache_entry *
vlc_access_cache_GetSmbEntry(struct vlc_access_cache *cache,
const char *server, const char *share,
const char *username)
{
char *url = vlc_access_cache_entry_CreateSmbUrl(server, share);
if (url == NULL)
return NULL;
struct vlc_access_cache_entry *entry =
vlc_access_cache_GetEntry(cache, url, username);
free(url);
return entry;
}
#ifdef __has_attribute
#if __has_attribute(destructor)
#define VLC_ACCESS_CACHE_CAN_REGISTER
#endif
#endif
#ifdef VLC_ACCESS_CACHE_CAN_REGISTER
#define VLC_ACCESS_CACHE_REGISTER(name) \
static struct vlc_access_cache name = VLC_ACCESS_CACHE_INITIALIZER(name); \
__attribute__((destructor)) static void vlc_access_cache_destructor_##name(void) \
{ \
vlc_access_cache_Destroy(&name); \
}
#else
#define VLC_ACCESS_CACHE_REGISTER(name) \
static struct vlc_access_cache name = VLC_ACCESS_CACHE_INITIALIZER(name);
#warning "can't register access cache"
#endif
......@@ -51,6 +51,7 @@
#include <bdsm/bdsm.h>
#include "../smb_common.h"
#include "../cache.h"
/*****************************************************************************
* Module descriptor
......@@ -107,6 +108,15 @@ vlc_module_end ()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
struct dsm_cache_context
{
smb_session *session;
smb_tid tid;
};
VLC_ACCESS_CACHE_REGISTER(dsm_cache);
static ssize_t Read( stream_t *, void *, size_t );
static int Seek( stream_t *, uint64_t );
static int Control( stream_t *, int, va_list );
......@@ -133,6 +143,8 @@ typedef struct
smb_fd i_fd; /**< SMB fd for the file we're reading */
smb_tid i_tid; /**< SMB Tree ID we're connected to */
struct vlc_access_cache_entry *cache_entry;
} access_sys_t;
/*****************************************************************************
......@@ -170,18 +182,6 @@ static int Open( vlc_object_t *p_this )
msg_Dbg( p_access, "Session: Host name = %s, ip = %s", p_sys->netbios_name,
inet_ntoa( p_sys->addr ) );
/* Now that we have the required data, let's establish a session */
status = smb_session_connect( p_sys->p_session, p_sys->netbios_name,
p_sys->addr.s_addr, SMB_TRANSPORT_TCP );
if( status != DSM_SUCCESS )
{
msg_Err( p_access, "Unable to connect/negotiate SMB session");
/* FIXME: libdsm wrongly return network error when the server can't
* handle the SMBv1 protocol */
status = DSM_ERROR_GENERIC;
goto error;
}
get_path( p_access );
if( login( p_access ) != VLC_SUCCESS )
......@@ -244,6 +244,7 @@ static int OpenNotForced( vlc_object_t *p_this )
/*****************************************************************************
* Close: free unused data structures
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
stream_t *p_access = (stream_t*)p_this;
......@@ -253,11 +254,12 @@ static void Close( vlc_object_t *p_this )
netbios_ns_destroy( p_sys->p_ns );
if( p_sys->i_fd )
smb_fclose( p_sys->p_session, p_sys->i_fd );
if( p_sys->p_session )
smb_session_destroy( p_sys->p_session );
vlc_UrlClean( &p_sys->url );
free( p_sys->psz_fullpath );
if( p_sys->cache_entry )
vlc_access_cache_AddEntry( &dsm_cache, p_sys->cache_entry );
free( p_sys );
}
......@@ -352,6 +354,14 @@ error:
== NT_STATUS_ACCESS_DENIED ? EACCES : ENOENT;
}
static void
dsm_FreeContext(void *context_)
{
struct dsm_cache_context *context = context_;
smb_session_destroy( context->session );
free( context );
}
/* Performs login with existing credentials and ask the user for new ones on
failure */
static int login( stream_t *p_access )
......@@ -383,6 +393,41 @@ static int login( stream_t *p_access )
}
psz_domain = credential.psz_realm ? credential.psz_realm : p_sys->netbios_name;
struct vlc_access_cache_entry *cache_entry =
vlc_access_cache_GetSmbEntry( &dsm_cache, p_sys->netbios_name, p_sys->psz_share,
credential.psz_username);
if( cache_entry != NULL )
{
struct dsm_cache_context *context = cache_entry->context;
int ret = smb_fopen( context->session, context->tid,
p_sys->psz_path, SMB_MOD_RO, &p_sys->i_fd );
if( ret == DSM_SUCCESS )
{
p_sys->cache_entry = cache_entry;
smb_session_destroy( p_sys->p_session );
p_sys->p_session = context->session;
p_sys->i_tid = context->tid;
i_ret = VLC_SUCCESS;
msg_Dbg( p_access, "re-using old dsm session" );
goto error;
}
}
/* Now that we have the required data, let's establish a session */
int status = smb_session_connect( p_sys->p_session, p_sys->netbios_name,
p_sys->addr.s_addr, SMB_TRANSPORT_TCP );
if( status != DSM_SUCCESS )
{
msg_Err( p_access, "Unable to connect/negotiate SMB session");
/* FIXME: libdsm wrongly return network error when the server can't
* handle the SMBv1 protocol */
goto error;
}
/* Try to authenticate on the remote machine */
int connect_err = smb_connect( p_access, psz_login, psz_password, psz_domain );
if( connect_err == ENOENT )
......@@ -428,6 +473,28 @@ static int login( stream_t *p_access )
if( !b_guest )
vlc_credential_store( &credential, p_access );
if( p_sys->psz_share )
{
struct dsm_cache_context *context = malloc(sizeof(*context));
if( context )
{
context->session = p_sys->p_session;
context->tid = p_sys->i_tid;
p_sys->cache_entry =
vlc_access_cache_entry_NewSmb( context, p_sys->netbios_name,
p_sys->psz_share,
credential.psz_username,
dsm_FreeContext);
}
else
p_sys->cache_entry = NULL;
if( p_sys->cache_entry == NULL )
{
smb_session_destroy( p_sys->p_session );
goto error;
}
}
i_ret = VLC_SUCCESS;
error:
vlc_credential_clean( &credential );
......
......@@ -58,6 +58,7 @@
#endif
#include "smb_common.h"
#include "cache.h"
static int Open(vlc_object_t *);
static void Close(vlc_object_t *);
......@@ -75,6 +76,8 @@ vlc_module_begin()
set_callbacks(Open, Close)
vlc_module_end()
VLC_ACCESS_CACHE_REGISTER(smb2_cache);
struct access_sys
{
struct smb2_context * smb2;
......@@ -85,59 +88,83 @@ struct access_sys
vlc_url_t encoded_url;
bool eof;
bool smb2_connected;
int error_status;
struct vlc_access_cache_entry *cache_entry;
};
struct vlc_smb2_op
{
struct vlc_logger *log;
struct smb2_context *smb2;
int error_status;
bool res_done;
union {
struct
{
size_t len;
} read;
void *data;
} res;
};
static int
smb2_check_status(stream_t *access, int status, const char *psz_func)
#define VLC_SMB2_OP(access, smb2_) { \
.log = access ? vlc_object_logger(access) : NULL, \
.smb2 = smb2_, \
.error_status = access ? ((struct access_sys *)access->p_sys)->error_status : 0, \
.res_done = false, \
};
static inline void
vlc_smb2_op_reset(struct vlc_smb2_op *op, struct smb2_context *smb2)
{
struct access_sys *sys = access->p_sys;
op->res_done = false;
op->smb2 = smb2;
op->error_status = 0;
}
static int
smb2_check_status(struct vlc_smb2_op *op, int status, const char *psz_func)
{
if (status < 0)
{
const char *psz_error = smb2_get_error(sys->smb2);
msg_Warn(access, "%s failed: %d, '%s'", psz_func, status, psz_error);
sys->error_status = status;
const char *psz_error = smb2_get_error(op->smb2);
if (op->log)
vlc_warning(op->log, "%s failed: %d, '%s'", psz_func, status, psz_error);
op->error_status = status;
return -1;
}
else
{
sys->res_done = true;
op->res_done = true;
return 0;
}
}
static void
smb2_set_error(stream_t *access, const char *psz_func, int err)
smb2_set_error(struct vlc_smb2_op *op, const char *psz_func, int err)
{
struct access_sys *sys = access->p_sys;
msg_Err(access, "%s failed: %d, %s", psz_func, err,
smb2_get_error(sys->smb2));
sys->error_status = err;
if (op->log)
vlc_error(op->log, "%s failed: %d, %s", psz_func, err, smb2_get_error(op->smb2));
op->error_status = err;
}
#define VLC_SMB2_CHECK_STATUS(access, status) \
smb2_check_status(access, status, __func__)
#define VLC_SMB2_CHECK_STATUS(op, status) \
smb2_check_status(op, status, __func__)
#define VLC_SMB2_SET_ERROR(access, func, err) \
smb2_set_error(access, func, err)
#define VLC_SMB2_SET_ERROR(op, func, err) \
smb2_set_error(op, func, err)
#define VLC_SMB2_STATUS_DENIED(x) (x == -ECONNREFUSED || x == -EACCES)
static int
vlc_smb2_mainloop(stream_t *access, bool teardown)
vlc_smb2_mainloop(struct vlc_smb2_op *op, bool teardown)
{
#define TEARDOWN_TIMEOUT 250 /* in ms */
struct access_sys *sys = access->p_sys;
int timeout = -1;
int (*poll_func)(struct pollfd *, unsigned, int) = vlc_poll_i11e;
......@@ -146,7 +173,7 @@ vlc_smb2_mainloop(stream_t *access, bool teardown)
* function can override the error_status (from async cbs). Therefore,
* store the original error_status in order to restore it at the end of
* this call (since we want to keep the first and original error status). */
int original_error_status = sys->error_status;
int original_error_status = op->error_status;
if (teardown)
{
......@@ -155,16 +182,15 @@ vlc_smb2_mainloop(stream_t *access, bool teardown)
* timeout to let a chance for a clean teardown. */
timeout = TEARDOWN_TIMEOUT;
poll_func = (void *)poll;
sys->error_status = 0;
op->error_status = 0;
}
sys->res_done = false;
while (sys->error_status == 0 && !sys->res_done)
while (op->error_status == 0 && !op->res_done)
{
int ret, smb2_timeout;
size_t fd_count;
const t_socket *fds = smb2_get_fds(sys->smb2, &fd_count, &smb2_timeout);
int events = smb2_which_events(sys->smb2);
const t_socket *fds = smb2_get_fds(op->smb2, &fd_count, &smb2_timeout);
int events = smb2_which_events(op->smb2);
struct pollfd p_fds[fd_count];
for (size_t i = 0; i < fd_count; ++i)
......@@ -179,7 +205,8 @@ vlc_smb2_mainloop(stream_t *access, bool teardown)
{
if (errno == EINTR)
{
msg_Warn(access, "vlc_poll_i11e interrupted");
if (op->log)
vlc_warning(op->log, "vlc_poll_i11e interrupted");
if (poll_func != (void *) poll)
{
/* Try again with a timeout to let the command complete.
......@@ -189,44 +216,43 @@ vlc_smb2_mainloop(stream_t *access, bool teardown)
poll_func = (void *) poll;
}
else
sys->error_status = -errno;
op->error_status = -errno;
}
else
{
msg_Err(access, "vlc_poll_i11e failed");
sys->error_status = -errno;
if (op->log)
vlc_error(op->log, "vlc_poll_i11e failed");
op->error_status = -errno;
}
}
else if (ret == 0)
{
if (teardown)
sys->error_status = -ETIMEDOUT;
else if (smb2_service_fd(sys->smb2, -1, 0) < 0)
VLC_SMB2_SET_ERROR(access, "smb2_service", 1);
op->error_status = -ETIMEDOUT;
else if (smb2_service_fd(op->smb2, -1, 0) < 0)
VLC_SMB2_SET_ERROR(op, "smb2_service", 1);
}
else
{
for (size_t i = 0; i < fd_count; ++i)
{
if (p_fds[i].revents
&& smb2_service_fd(sys->smb2, p_fds[i].fd, p_fds[i].revents) < 0)
VLC_SMB2_SET_ERROR(access, "smb2_service", 1);
&& smb2_service_fd(op->smb2, p_fds[i].fd, p_fds[i].revents) < 0)
VLC_SMB2_SET_ERROR(op, "smb2_service", 1);
}
}
}
int ret = sys->error_status == 0 ? 0 : -1;
int ret = op->error_status == 0 ? 0 : -1;
if (original_error_status != 0)
sys->error_status = original_error_status;
op->error_status = original_error_status;
return ret;
}
#define VLC_SMB2_GENERIC_CB() \
VLC_UNUSED(smb2); \
stream_t *access = private_data; \
struct access_sys *sys = access->p_sys; \
assert(sys->smb2 == smb2); \
if (VLC_SMB2_CHECK_STATUS(access, status)) \
struct vlc_smb2_op *op = private_data; \
assert(op->smb2 == smb2); (void) smb2; \
if (VLC_SMB2_CHECK_STATUS(op, status)) \
return
static void
......@@ -244,10 +270,7 @@ smb2_read_cb(struct smb2_context *smb2, int status, void *data,
VLC_UNUSED(data);
VLC_SMB2_GENERIC_CB();
if (status == 0)
sys->eof = true;
else
sys->res.read.len = status;
op->res.read.len = status;
}
static ssize_t
......@@ -267,18 +290,26 @@ FileRead(stream_t *access, void *buf, size_t len)
if (len > 262144)
len = 262144;
sys->res.read.len = 0;
struct vlc_smb2_op op = VLC_SMB2_OP(access, sys->smb2);
op.res.read.len = 0;
if (smb2_read_async(sys->smb2, sys->smb2fh, buf, len,
smb2_read_cb, access) < 0)
smb2_read_cb, &op) < 0)
{
VLC_SMB2_SET_ERROR(access, "smb2_read_async", 1);
VLC_SMB2_SET_ERROR(&op, "smb2_read_async", 1);
return -1;
}
if (vlc_smb2_mainloop(access, false) < 0)
if (vlc_smb2_mainloop(&op, false) < 0)
{
sys->error_status = op.error_status;
return -1;
}
if (op.res.read.len == 0)
sys->eof = true;
return sys->res.read.len;
return op.res.read.len;
}
static int
......@@ -289,9 +320,12 @@ FileSeek(stream_t *access, uint64_t i_pos)
if (sys->error_status != 0)
return VLC_EGENERIC;
if (smb2_lseek(sys->smb2, sys->smb2fh, i_pos, SEEK_SET, NULL) < 0)
struct vlc_smb2_op op = VLC_SMB2_OP(access, sys->smb2);
if (smb2_lseek(op.smb2, sys->smb2fh, i_pos, SEEK_SET, NULL) < 0)
{
VLC_SMB2_SET_ERROR(access, "smb2_seek_async", 1);
VLC_SMB2_SET_ERROR(&op, "smb2_seek_async", 1);
sys->error_status = op.error_status;
return VLC_EGENERIC;
}
sys->eof = false;
......@@ -463,49 +497,32 @@ ShareEnum(stream_t *access, input_item_node_t *p_node)
}
static int
vlc_smb2_close_fh(stream_t *access)
vlc_smb2_close_fh(stream_t *access, struct smb2_context *smb2,
struct smb2fh *smb2fh)
{
struct access_sys *sys = access->p_sys;
struct vlc_smb2_op op = VLC_SMB2_OP(access, smb2);
assert(sys->smb2fh);
if (smb2_close_async(sys->smb2, sys->smb2fh, smb2_generic_cb, access) < 0)
if (smb2_close_async(smb2, smb2fh, smb2_generic_cb, &op) < 0)
{
VLC_SMB2_SET_ERROR(access, "smb2_close_async", 1);
VLC_SMB2_SET_ERROR(&op, "smb2_close_async", 1);
return -1;
}
sys->smb2fh = NULL;
return vlc_smb2_mainloop(access, true);
return vlc_smb2_mainloop(&op, true);
}
static int
vlc_smb2_disconnect_share(stream_t *access)
vlc_smb2_disconnect_share(stream_t *access, struct smb2_context *smb2)
{
struct access_sys *sys = access->p_sys;
if (!sys->smb2_connected)
return 0;
struct vlc_smb2_op op = VLC_SMB2_OP(access, smb2);
if (smb2_disconnect_share_async(sys->smb2, smb2_generic_cb, access) < 0)
if (smb2_disconnect_share_async(smb2, smb2_generic_cb, &op) < 0)
{
VLC_SMB2_SET_ERROR(access, "smb2_connect_share_async", 1);
VLC_SMB2_SET_ERROR(&op, "smb2_connect_share_async", 1);
return -1;
}
int ret = vlc_smb2_mainloop(access, true);
sys->smb2_connected = false;
return ret;
}
static void
smb2_opendir_cb(struct smb2_context *smb2, int status, void *data,
void *private_data)
{
VLC_SMB2_GENERIC_CB();
sys->smb2dir = data;
return vlc_smb2_mainloop(&op, true);
}
static void
......@@ -514,16 +531,7 @@ smb2_open_cb(struct smb2_context *smb2, int status, void *data,
{
VLC_SMB2_GENERIC_CB();
sys->smb2fh = data;
}
static void
smb2_share_enum_cb(struct smb2_context *smb2, int status, void *data,
void *private_data)
{
VLC_SMB2_GENERIC_CB();
sys->share_enum = data;
op->res.data = data;
}
static void
......@@ -559,8 +567,84 @@ vlc_smb2_print_addr(stream_t *access)
}
static int
vlc_smb2_open_share(stream_t *access, const char *url,
const vlc_credential *credential)
vlc_smb2_open_share(stream_t *access, struct smb2_context *smb2,
struct smb2_url *smb2_url, bool do_enum)
{
struct access_sys *sys = access->p_sys;
struct smb2_stat_64 smb2_stat;
struct vlc_smb2_op op = VLC_SMB2_OP(access, smb2);
int ret;
if (do_enum)
ret = smb2_share_enum_async(smb2, smb2_open_cb, &op);
else
{
if (smb2_stat_async(smb2, smb2_url->path, &smb2_stat,
smb2_generic_cb, &op) < 0)
VLC_SMB2_SET_ERROR(&op, "smb2_stat_async", 1);
if (vlc_smb2_mainloop(&op, false) != 0)
goto error;
if (smb2_stat.smb2_type == SMB2_TYPE_FILE)
{
vlc_smb2_op_reset(&op, smb2);
sys->smb2_size = smb2_stat.smb2_size;
ret = smb2_open_async(smb2, smb2_url->path, O_RDONLY,
smb2_open_cb, &op);
}
else if (smb2_stat.smb2_type == SMB2_TYPE_DIRECTORY)
{
vlc_smb2_op_reset(&op, smb2);
ret = smb2_opendir_async(smb2, smb2_url->path, smb2_open_cb, &op);
}
else
{
msg_Err(access, "smb2_stat_cb: file type not handled");
op.error_status = 1;
goto error;
}
}
if (ret < 0)
{
VLC_SMB2_SET_ERROR(&op, "smb2_open*_async", 1);
goto error;
}
if (vlc_smb2_mainloop(&op, false) != 0)
goto error;
if (do_enum)
sys->share_enum = op.res.data;
else if (smb2_stat.smb2_type == SMB2_TYPE_FILE)
sys->smb2fh = op.res.data;
else if (smb2_stat.smb2_type == SMB2_TYPE_DIRECTORY)
sys->smb2dir = op.res.data;
else
vlc_assert_unreachable();
return 0;
error:
sys->error_status = op.error_status;
return -1;
}
static void
vlc_smb2_FreeContext(void *context)
{
struct smb2_context *smb2 = context;
vlc_smb2_disconnect_share(NULL, smb2);
smb2_destroy_context(smb2);
}
static int
vlc_smb2_connect_open_share(stream_t *access, const char *url,
const vlc_credential *credential)
{
struct access_sys *sys = access->p_sys;
......@@ -570,7 +654,7 @@ vlc_smb2_open_share(stream_t *access, const char *url,
if (sys->smb2 == NULL)
{
msg_Err(access, "smb2_init_context failed");
goto error;
return -1;
}
smb2_url = smb2_parse_url(sys->smb2, url);
......@@ -592,70 +676,72 @@ vlc_smb2_open_share(stream_t *access, const char *url,
password = NULL;
}
struct vlc_access_cache_entry *cache_entry =
vlc_access_cache_GetSmbEntry(&smb2_cache, smb2_url->server, share,
credential->psz_username);
if (cache_entry != NULL)
{
int err = vlc_smb2_open_share(access, cache_entry->context, smb2_url, do_enum);
if (err == 0)
{
smb2_destroy_context(sys->smb2);
sys->smb2 = cache_entry->context;
sys->smb2_connected = true;
sys->cache_entry = cache_entry;
smb2_destroy_url(smb2_url);
msg_Dbg(access, "re-using old smb2 session");
return 0;
}
}
smb2_set_security_mode(sys->smb2, SMB2_NEGOTIATE_SIGNING_ENABLED);
smb2_set_password(sys->smb2, password);
smb2_set_domain(sys->smb2, domain ? domain : "");
struct vlc_smb2_op op = VLC_SMB2_OP(access, sys->smb2);
int err = smb2_connect_share_async(sys->smb2, smb2_url->server, share,
username, smb2_generic_cb, access);
username, smb2_generic_cb, &op);
if (err < 0)
{
VLC_SMB2_SET_ERROR(access, "smb2_connect_share_async", err);
VLC_SMB2_SET_ERROR(&op, "smb2_connect_share_async", err);
sys->error_status = op.error_status;
goto error;
}
if (vlc_smb2_mainloop(access, false) != 0)
if (vlc_smb2_mainloop(&op, false) != 0)
{
sys->error_status = op.error_status;
goto error;
}
sys->smb2_connected = true;
vlc_smb2_print_addr(access);
int ret;
if (do_enum)
ret = smb2_share_enum_async(sys->smb2, smb2_share_enum_cb, access);
else
{
struct smb2_stat_64 smb2_stat;
if (smb2_stat_async(sys->smb2, smb2_url->path, &smb2_stat,
smb2_generic_cb, access) < 0)
VLC_SMB2_SET_ERROR(access, "smb2_stat_async", 1);
if (vlc_smb2_mainloop(access, false) != 0)
goto error;
if (smb2_stat.smb2_type == SMB2_TYPE_FILE)
{
sys->smb2_size = smb2_stat.smb2_size;
ret = smb2_open_async(sys->smb2, smb2_url->path, O_RDONLY,
smb2_open_cb, access);
}
else if (smb2_stat.smb2_type == SMB2_TYPE_DIRECTORY)
ret = smb2_opendir_async(sys->smb2, smb2_url->path,
smb2_opendir_cb, access);
else
{
msg_Err(access, "smb2_stat_cb: file type not handled");
sys->error_status = 1;
goto error;
}
}
if (ret < 0)
{
VLC_SMB2_SET_ERROR(access, "smb2_open*_async", 1);
err = vlc_smb2_open_share(access, sys->smb2, smb2_url, do_enum);
if (err < 0)
goto error;
}
if (vlc_smb2_mainloop(access, false) != 0)
sys->cache_entry = vlc_access_cache_entry_NewSmb(sys->smb2, smb2_url->server, share,
credential->psz_username,
vlc_smb2_FreeContext);
if (sys->cache_entry == NULL)
goto error;
smb2_destroy_url(smb2_url);
return 0;
error:
if (smb2_url != NULL)
smb2_destroy_url(smb2_url);
if (sys->smb2 != NULL)
{
vlc_smb2_disconnect_share(access);
if (sys->smb2_connected)
{
vlc_smb2_disconnect_share(access, sys->smb2);
sys->smb2_connected = false;
}
smb2_destroy_context(sys->smb2);
sys->smb2 = NULL;
}
......@@ -755,7 +841,7 @@ Open(vlc_object_t *p_obj)
* keystore/user interaction) */
vlc_credential_get(&credential, access, "smb-user", "smb-pwd", NULL,
NULL);
ret = vlc_smb2_open_share(access, url, &credential);
ret = vlc_smb2_connect_open_share(access, url, &credential);
while (ret == -1
&& (!sys->error_status || VLC_SMB2_STATUS_DENIED(sys->error_status))
......@@ -764,7 +850,7 @@ Open(vlc_object_t *p_obj)
sys->encoded_url.psz_host))
{
sys->error_status = 0;
ret = vlc_smb2_open_share(access, url, &credential);
ret = vlc_smb2_connect_open_share(access, url, &credential);
}
free(resolved_host);
free(url);
......@@ -832,7 +918,7 @@ Close(vlc_object_t *p_obj)
struct access_sys *sys = access->p_sys;
if (sys->smb2fh != NULL)
vlc_smb2_close_fh(access);
vlc_smb2_close_fh(access, sys->smb2, sys->smb2fh);
else if (sys->smb2dir != NULL)
smb2_closedir(sys->smb2, sys->smb2dir);
else if (sys->share_enum != NULL)
......@@ -840,8 +926,9 @@ Close(vlc_object_t *p_obj)
else
vlc_assert_unreachable();
vlc_smb2_disconnect_share(access);
smb2_destroy_context(sys->smb2);
assert(sys->smb2_connected);
vlc_access_cache_AddEntry(&smb2_cache, sys->cache_entry);
vlc_UrlClean(&sys->encoded_url);
}