copyparty 1.15.9__py3-none-any.whl → 1.16.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
copyparty/httpsrv.py CHANGED
@@ -81,6 +81,7 @@ from .util import (
81
81
  )
82
82
 
83
83
  if TYPE_CHECKING:
84
+ from .authsrv import VFS
84
85
  from .broker_util import BrokerCli
85
86
  from .ssdp import SSDPr
86
87
 
@@ -127,6 +128,12 @@ class HttpSrv(object):
127
128
  self.bans = {}
128
129
  self.aclose = {}
129
130
 
131
+ dli = {} # info
132
+ dls = {} # state
133
+ self.dli = self.tdli = dli
134
+ self.dls = self.tdls = dls
135
+ self.iiam = '<img src="%s.cpr/iiam.gif" />' % (self.args.SRS,)
136
+
130
137
  self.bound = set()
131
138
  self.name = "hsrv" + nsuf
132
139
  self.mutex = threading.Lock()
@@ -201,6 +208,9 @@ class HttpSrv(object):
201
208
  self.start_threads(4)
202
209
 
203
210
  if nid:
211
+ self.tdli = {}
212
+ self.tdls = {}
213
+
204
214
  if self.args.stackmon:
205
215
  start_stackmon(self.args.stackmon, nid)
206
216
 
@@ -573,3 +583,32 @@ class HttpSrv(object):
573
583
  ident += "a"
574
584
 
575
585
  self.u2idx_free[ident] = u2idx
586
+
587
+ def read_dls(
588
+ self,
589
+ ):
590
+
591
+
592
+ """
593
+ mp-broker asking for local dl-info + dl-state;
594
+ reduce overhead by sending just the vfs vpath
595
+ """
596
+ dli = {k: (a, b, c.vpath, d, e) for k, (a, b, c, d, e) in self.dli.items()}
597
+ return (dli, self.dls)
598
+
599
+ def write_dls(
600
+ self,
601
+ sdli ,
602
+ dls ,
603
+ ) :
604
+ """
605
+ mp-broker pushing total dl-info + dl-state;
606
+ swap out the vfs vpath with the vfs node
607
+ """
608
+ dli = {}
609
+ for k, (a, b, c, d, e) in sdli.items():
610
+ vn = self.asrv.vfs.all_vols[c]
611
+ dli[k] = (a, b, vn, d, e)
612
+
613
+ self.tdli = dli
614
+ self.tdls = dls
copyparty/metrics.py CHANGED
@@ -72,6 +72,9 @@ class Metrics(object):
72
72
  v = "{:.3f}".format(self.hsrv.t0)
73
73
  addug("cpp_boot_unixtime", "seconds", v, t)
74
74
 
75
+ t = "number of active downloads"
76
+ addg("cpp_active_dl", str(len(self.hsrv.tdls)), t)
77
+
75
78
  t = "number of open http(s) client connections"
76
79
  addg("cpp_http_conns", str(self.hsrv.ncli), t)
77
80
 
copyparty/svchub.py CHANGED
@@ -106,7 +106,7 @@ class SvcHub(object):
106
106
  self.stopping = False
107
107
  self.stopped = False
108
108
  self.reload_req = False
109
- self.reloading = 0
109
+ self.reload_mutex = threading.Lock()
110
110
  self.stop_cond = threading.Condition()
111
111
  self.nsigs = 3
112
112
  self.retcode = 0
@@ -205,6 +205,15 @@ class SvcHub(object):
205
205
  t = "WARNING: --s-rd-sz (%d) is larger than --iobuf (%d); this may lead to reduced performance"
206
206
  self.log("root", t % (args.s_rd_sz, args.iobuf), 3)
207
207
 
208
+ zs = ""
209
+ if args.th_ram_max < 0.22:
210
+ zs = "generate thumbnails"
211
+ elif args.th_ram_max < 1:
212
+ zs = "generate audio waveforms or spectrograms"
213
+ if zs:
214
+ t = "WARNING: --th-ram-max is very small (%.2f GiB); will not be able to %s"
215
+ self.log("root", t % (args.th_ram_max, zs), 3)
216
+
208
217
  if args.chpw and args.idp_h_usr:
209
218
  t = "ERROR: user-changeable passwords is incompatible with IdP/identity-providers; you must disable either --chpw or --idp-h-usr"
210
219
  self.log("root", t, 1)
@@ -217,13 +226,14 @@ class SvcHub(object):
217
226
  args.chpw_no = noch
218
227
 
219
228
  if args.ipu:
220
- iu, nm = load_ipu(self.log, args.ipu)
229
+ iu, nm = load_ipu(self.log, args.ipu, True)
221
230
  setattr(args, "ipu_iu", iu)
222
231
  setattr(args, "ipu_nm", nm)
223
232
 
224
233
  if not self.args.no_ses:
225
234
  self.setup_session_db()
226
235
 
236
+ args.shr1 = ""
227
237
  if args.shr:
228
238
  self.setup_share_db()
229
239
 
@@ -372,6 +382,14 @@ class SvcHub(object):
372
382
 
373
383
  self.broker = Broker(self)
374
384
 
385
+ # create netmaps early to avoid firewall gaps,
386
+ # but the mutex blocks multiprocessing startup
387
+ for zs in "ipu_iu ftp_ipa_nm tftp_ipa_nm".split():
388
+ try:
389
+ getattr(args, zs).mutex = threading.Lock()
390
+ except:
391
+ pass
392
+
375
393
  def setup_session_db(self) :
376
394
  if not HAVE_SQLITE3:
377
395
  self.args.no_ses = True
@@ -444,6 +462,7 @@ class SvcHub(object):
444
462
  raise Exception(t)
445
463
 
446
464
  al.shr = "/%s/" % (al.shr,)
465
+ al.shr1 = al.shr[1:]
447
466
 
448
467
  create = True
449
468
  modified = False
@@ -751,8 +770,8 @@ class SvcHub(object):
751
770
  al.idp_h_grp = al.idp_h_grp.lower()
752
771
  al.idp_h_key = al.idp_h_key.lower()
753
772
 
754
- al.ftp_ipa_nm = build_netmap(al.ftp_ipa or al.ipa)
755
- al.tftp_ipa_nm = build_netmap(al.tftp_ipa or al.ipa)
773
+ al.ftp_ipa_nm = build_netmap(al.ftp_ipa or al.ipa, True)
774
+ al.tftp_ipa_nm = build_netmap(al.tftp_ipa or al.ipa, True)
756
775
 
757
776
  mte = ODict.fromkeys(DEF_MTE.split(","), True)
758
777
  al.mte = odfusion(mte, al.mte)
@@ -799,6 +818,24 @@ class SvcHub(object):
799
818
  if len(al.tcolor) == 3: # fc5 => ffcc55
800
819
  al.tcolor = "".join([x * 2 for x in al.tcolor])
801
820
 
821
+ zs = al.u2sz
822
+ zsl = zs.split(",")
823
+ if len(zsl) not in (1, 3):
824
+ t = "invalid --u2sz; must be either one number, or a comma-separated list of three numbers (min,default,max)"
825
+ raise Exception(t)
826
+ if len(zsl) < 3:
827
+ zsl = ["1", zs, zs]
828
+ zi2 = 1
829
+ for zs in zsl:
830
+ zi = int(zs)
831
+ # arbitrary constraint (anything above 2 GiB is probably unintended)
832
+ if zi < 1 or zi > 2047:
833
+ raise Exception("invalid --u2sz; minimum is 1, max is 2047")
834
+ if zi < zi2:
835
+ raise Exception("invalid --u2sz; values must be equal or ascending")
836
+ zi2 = zi
837
+ al.u2sz = ",".join(zsl)
838
+
802
839
  return True
803
840
 
804
841
  def _ipa2re(self, txt) :
@@ -966,41 +1003,18 @@ class SvcHub(object):
966
1003
  except:
967
1004
  self.log("root", "ssdp startup failed;\n" + min_ex(), 3)
968
1005
 
969
- def reload(self) :
970
- with self.up2k.mutex:
971
- if self.reloading:
972
- return "cannot reload; already in progress"
973
- self.reloading = 1
974
-
975
- Daemon(self._reload, "reloading")
976
- return "reload initiated"
977
-
978
- def _reload(self, rescan_all_vols = True, up2k = True) :
979
- with self.up2k.mutex:
980
- if self.reloading != 1:
981
- return
982
- self.reloading = 2
1006
+ def reload(self, rescan_all_vols , up2k ) :
1007
+ t = "config has been reloaded"
1008
+ with self.reload_mutex:
983
1009
  self.log("root", "reloading config")
984
1010
  self.asrv.reload(9 if up2k else 4)
985
1011
  if up2k:
986
1012
  self.up2k.reload(rescan_all_vols)
1013
+ t += "; volumes are now reinitializing"
987
1014
  else:
988
1015
  self.log("root", "reload done")
989
1016
  self.broker.reload()
990
- self.reloading = 0
991
-
992
- def _reload_blocking(self, rescan_all_vols = True, up2k = True) :
993
- while True:
994
- with self.up2k.mutex:
995
- if self.reloading < 2:
996
- self.reloading = 1
997
- break
998
- time.sleep(0.05)
999
-
1000
- # try to handle multiple pending IdP reloads at once:
1001
- time.sleep(0.2)
1002
-
1003
- self._reload(rescan_all_vols=rescan_all_vols, up2k=up2k)
1017
+ return t
1004
1018
 
1005
1019
  def _reload_sessions(self) :
1006
1020
  with self.asrv.mutex:
@@ -1014,7 +1028,7 @@ class SvcHub(object):
1014
1028
 
1015
1029
  if self.reload_req:
1016
1030
  self.reload_req = False
1017
- self.reload()
1031
+ self.reload(True, True)
1018
1032
 
1019
1033
  self.shutdown()
1020
1034
 
copyparty/szip.py CHANGED
@@ -94,7 +94,7 @@ def gen_hdr(
94
94
 
95
95
  # spec says to put zeros when !crc if bit3 (streaming)
96
96
  # however infozip does actual sz and it even works on winxp
97
- # (same reasning for z64 extradata later)
97
+ # (same reasoning for z64 extradata later)
98
98
  vsz = 0xFFFFFFFF if z64 else sz
99
99
  ret += spack(b"<LL", vsz, vsz)
100
100
 
copyparty/tcpsrv.py CHANGED
@@ -368,7 +368,7 @@ class TcpSrv(object):
368
368
  if self.args.q:
369
369
  print(msg)
370
370
 
371
- self.hub.broker.say("listen", srv)
371
+ self.hub.broker.say("httpsrv.listen", srv)
372
372
 
373
373
  self.srv = srvs
374
374
  self.bound = bound
@@ -376,7 +376,7 @@ class TcpSrv(object):
376
376
  self._distribute_netdevs()
377
377
 
378
378
  def _distribute_netdevs(self):
379
- self.hub.broker.say("set_netdevs", self.netdevs)
379
+ self.hub.broker.say("httpsrv.set_netdevs", self.netdevs)
380
380
  self.hub.start_zeroconf()
381
381
  gencert(self.log, self.args, self.netdevs)
382
382
  self.hub.restart_ftpd()
copyparty/tftpd.py CHANGED
@@ -266,6 +266,7 @@ class Tftpd(object):
266
266
  "*",
267
267
  not self.args.no_scandir,
268
268
  [[True, False]],
269
+ throw=True,
269
270
  )
270
271
  dnames = set([x[0] for x in vfs_ls if stat.S_ISDIR(x[1].st_mode)])
271
272
  dirs1 = [(v.st_mtime, v.st_size, k + "/") for k, v in vfs_ls if k in dnames]
copyparty/th_srv.py CHANGED
@@ -20,7 +20,6 @@ from .util import (
20
20
  FFMPEG_URL,
21
21
  Cooldown,
22
22
  Daemon,
23
- Pebkac,
24
23
  afsenc,
25
24
  fsenc,
26
25
  min_ex,
@@ -161,6 +160,7 @@ class ThumbSrv(object):
161
160
  self.ram = {}
162
161
  self.memcond = threading.Condition(self.mutex)
163
162
  self.stopping = False
163
+ self.rm_nullthumbs = True # forget failed conversions on startup
164
164
  self.nthr = max(1, self.args.th_mt)
165
165
 
166
166
  self.q = Queue(self.nthr * 4)
@@ -858,7 +858,6 @@ class ThumbSrv(object):
858
858
  def cleaner(self) :
859
859
  interval = self.args.th_clean
860
860
  while True:
861
- time.sleep(interval)
862
861
  ndirs = 0
863
862
  for vol, histpath in self.asrv.vfs.histtab.items():
864
863
  if histpath.startswith(vol):
@@ -872,6 +871,8 @@ class ThumbSrv(object):
872
871
  self.log("\033[Jcln err in %s: %r" % (histpath, ex), 3)
873
872
 
874
873
  self.log("\033[Jcln ok; rm {} dirs".format(ndirs))
874
+ self.rm_nullthumbs = False
875
+ time.sleep(interval)
875
876
 
876
877
  def clean(self, histpath ) :
877
878
  ret = 0
@@ -892,7 +893,9 @@ class ThumbSrv(object):
892
893
  prev_b64 = None
893
894
  prev_fp = ""
894
895
  try:
895
- t1 = statdir(self.log_func, not self.args.no_scandir, False, thumbpath)
896
+ t1 = statdir(
897
+ self.log_func, not self.args.no_scandir, False, thumbpath, False
898
+ )
896
899
  ents = sorted(list(t1))
897
900
  except:
898
901
  return 0
@@ -933,6 +936,10 @@ class ThumbSrv(object):
933
936
 
934
937
  continue
935
938
 
939
+ if self.rm_nullthumbs and not inf.st_size:
940
+ bos.unlink(fp)
941
+ continue
942
+
936
943
  if b64 == prev_b64:
937
944
  self.log("rm replaced [{}]".format(fp))
938
945
  bos.unlink(prev_fp)