parsav  Diff

Differences From Artifact [dafa2dc374]:

To Artifact [1938b717c7]:


1
2
3
4
5
6
7

8
9
10
11
12
13
14
..
30
31
32
33
34
35
36
37
38


39
40
41
42
43
44
45
46
47
48
49
50
51
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
...
654
655
656
657
658
659
660

661
662
663
664
665
666
667
...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
...
715
716
717
718
719
720
721
722
723






724
725
726
727
728
729
730
731
732
733
734

735

736
737
738
739
740
741
742
743
744
745
746

747

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802

803

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
-- vim: ft=terra
local util = lib.util
local secmode = lib.enum { 'public', 'private', 'lockdown', 'isolate' }
local pstring = lib.mem.ptr(int8)

local struct srv
local struct cfgcache {

	secret: pstring
	pol_sec: secmode.t
	pol_reg: bool
	pol_autoherald: bool
	credmgd: bool
	maxupsz: intptr
	poolinitsz: intptr
................................................................................
	webmgr: lib.net.mg_mgr
	webcon: &lib.net.mg_connection
	cfg: cfgcache
	id: rawstring
	pool: lib.mem.pool
}

terra cfgcache:free() -- :/ TODO replace with pool
	self.secret:free()


	self.instance:free()
	self.domain:free()
	self.ui_cue_staff:free()
	self.ui_cue_founder:free()
	self.usrdef_pol_follow:free()
	self.usrdef_pol_follow_req:free()
end

terra srv:post_enum_author_uid(uid: uint64, r: lib.store.range): lib.mem.vec(lib.mem.ptr(lib.store.post))
	var all: lib.mem.vec(lib.mem.ptr(lib.store.post)) all:init(64)
	for i=0,self.sources.ct do var src = self.sources.ptr + i
		if src.handle ~= nil and src.backend.timeline_instance_fetch ~= nil then
			var lst = src:post_enum_author_uid(uid,r)
................................................................................
								co:complain(400,'bad request','unrecognized content-type')
								goto fail
							end
							var boundary = pstring {ptr=p+9,ct=ctt.ct - ((p - ctt.ptr) + 9)}
							co.method = lib.http.method.post_file
							co.uploads:init(8)

							var bsr = (lib.str.acc{}):compose('\r\n--',boundary,'\r\n'):finalize()

							var upmap = lib.str.splitmap(co.body,bsr,8)
							-- first entry may not be preceded by header-break
							if lib.str.find(upmap(0), pstring {
								ptr = bsr.ptr + 2, ct = bsr.ct - 2
							}):ref() then
								upmap(0).ptr = upmap(0).ptr + (bsr.ct - 2)
................................................................................
												nextup.field = fld
												nextup.filename = file
											end
										end
									end
								end
							end
							bsr:free()
							upmap:free()
						end
					end
				end

				var mtt = lib.http.mime._str(co.reqtype)
				lib.dbg('routing with negotiated type of ', {mtt.ptr,mtt.ct})
				route.dispatch_http(&co, uri)

				::fail::
				if co.uploads.run > 0 then
					for i=0,co.uploads.sz do
						co.uploads(i).filename:free()
						co.uploads(i).field:free()
................................................................................
--
--	return 0
--end

terra cfgcache.methods.load :: {&cfgcache} -> {}
terra cfgcache:init(o: &srv)
	self.overlord = o

	self:load()
end

terra srv:setup(befile: rawstring)
	cfg(self, befile)
	var success = false
	if self.sources.ct == 0 then lib.bail('no data sources specified') end
................................................................................
	end
end

terra srv:start(iname: rawstring)
	self:conprep(lib.store.prepmode.full)
	self.cfg:init(self)
	self.pool:init(self.cfg.poolinitsz)
	var dbbind = self:conf_get('bind')
	if iname == nil then iname = lib.proc.getenv('parsav_instance') end
	if iname == nil then
		self.id = self.cfg.instance.ptr;
		-- let this leak -- it'll be needed for the lifetime of the process anyway
	else self.id = iname end 

	if iname ~= nil then
................................................................................
		bind = dbbind.ptr
	else bind = '[::1]:10917' end

	lib.report('binding to ', bind)
	lib.net.mg_mgr_init(&self.webmgr)
	self.webcon = lib.net.mg_http_listen(&self.webmgr, bind, handle.http, self)

	if dbbind.ptr ~= nil then dbbind:free() end
end

terra srv:poll()
	lib.net.mg_mgr_poll(&self.webmgr,300)
end

terra srv:shutdown()
................................................................................
		lib.report('closing data source ', src.id.ptr, '(', src.backend.id, ')')
		src:close()
	end
	self.sources:free()
	self.pool:free()
end

terra cfgcache:cfint(name: rawstring, default: intptr)
	var str = self.overlord:conf_get(name)






	if str.ptr ~= nil then
		var i,ok = lib.math.decparse(str)
		if ok then default = i else
			lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected integer; using default value instead')
		end
		str:free()
	end
	return default
end

terra cfgcache:cffsz(name: rawstring, default: intptr)

	var str = self.overlord:conf_get(name)

	if str:ref() then
		var sz, ok = lib.math.fsz_parse(str)
		if ok then default = sz else
			lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected byte length; using default value instead')
		end
		str:free()
	end
	return default
end

terra cfgcache:cfbool(name: rawstring, default: bool)

	var str = self.overlord:conf_get(name)

	if str.ptr ~= nil then
		if str:cmp('true') or str:cmp('on') or
		   str:cmp('yes')  or str:cmp('1') then
			default = true
		elseif str:cmp('false') or str:cmp('off') or
		       str:cmp('no')    or str:cmp('0') then
			default = false
		else
			lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected boolean; using default value instead')
		end
		str:free()
	end
	return default
end

terra cfgcache:load()

	self.instance = self.overlord:conf_get('instance-name')
	self.domain = self.overlord:conf_get('domain')
	self.secret = self.overlord:conf_get('server-secret')

	self.pol_reg = self:cfbool('policy-self-register', false)
	self.pol_autoherald = self:cfbool('policy-self-herald', true)

	do self.credmgd = false

	var sreg = self.overlord:conf_get('credential-store')
	if sreg:ref() then
		if lib.str.cmp(sreg.ptr, 'managed') == 0
			then self.credmgd = true
			else self.credmgd = false
		end
		sreg:free()
	end end

	self.maxupsz = self:cffsz('maximum-artifact-size', [1024 * 100]) -- 100 kilobyte default
	self.poolinitsz = self:cffsz('server-pool-size-initial', [1024 * 10]) -- 10 kilobyte default
	
	self.pol_sec = secmode.lockdown

	var smode = self.overlord:conf_get('policy-security')
	if smode.ptr ~= nil then
		if lib.str.cmp(smode.ptr, 'public') == 0 then
			self.pol_sec = secmode.public
		elseif lib.str.cmp(smode.ptr, 'private') == 0 then
			self.pol_sec = secmode.private
		elseif lib.str.cmp(smode.ptr, 'lockdown') == 0 then
			self.pol_sec = secmode.lockdown
		elseif lib.str.cmp(smode.ptr, 'isolate') == 0 then
			self.pol_sec = secmode.isolate
		end
		smode:free()
	end

	self.ui_hue = self:cfint('ui-accent',config.default_ui_accent)
	self.nranks = self:cfint('user-ranks',10)
	self.maxinvites = self:cfint('max-invites',64)
	

	var webmaster = self.overlord:conf_get('master')

	if webmaster:ref() then defer webmaster:free()
		var wma = self.overlord:actor_fetch_xid(webmaster)
		if not wma then
			lib.warn('the webmaster specified in the configuration store does not seem to exist or is not known to this instance; preceding as if no master defined. if the master is a remote user, you can rectify this with the `actor "',{webmaster.ptr,webmaster.ct},'" instantiate` and `conf refresh` commands')
		else
			self.master = wma(0).id
			wma:free()
		end
	end

	self.ui_cue_staff = self.overlord:conf_get('ui-profile-cue-staff')
	self.ui_cue_founder = self.overlord:conf_get('ui-profile-cue-master')

	self.usrdef_pol_follow = self.overlord:conf_get('user-default-acl-follow')
	self.usrdef_pol_follow_req = self.overlord:conf_get('user-default-acl-follow-req')
end

return {
	overlord = srv;
	convo = convo;
	route = route;
	secmode = secmode;
}







>







 







|
|
>
>
|
|
<
<
<
<







 







|







 







<





<
<







 







>







 







|







 







|







 







|
|
>
>
>
>
>
>



|

<




|
>
|
>



|

<




|
>
|
>








|

<





>
|
|
|





>
|





|






>
|










|
|





>
|
>
|







|

|
|

|
|








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
..
31
32
33
34
35
36
37
38
39
40
41
42
43




44
45
46
47
48
49
50
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
...
450
451
452
453
454
455
456

457
458
459
460
461


462
463
464
465
466
467
468
...
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
...
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
-- vim: ft=terra
local util = lib.util
local secmode = lib.enum { 'public', 'private', 'lockdown', 'isolate' }
local pstring = lib.mem.ptr(int8)

local struct srv
local struct cfgcache {
	_pool: lib.mem.pool
	secret: pstring
	pol_sec: secmode.t
	pol_reg: bool
	pol_autoherald: bool
	credmgd: bool
	maxupsz: intptr
	poolinitsz: intptr
................................................................................
	webmgr: lib.net.mg_mgr
	webcon: &lib.net.mg_connection
	cfg: cfgcache
	id: rawstring
	pool: lib.mem.pool
}

terra cfgcache:purge()
	self._pool:clear()
end

terra cfgcache:free()
	self._pool:free()




end

terra srv:post_enum_author_uid(uid: uint64, r: lib.store.range): lib.mem.vec(lib.mem.ptr(lib.store.post))
	var all: lib.mem.vec(lib.mem.ptr(lib.store.post)) all:init(64)
	for i=0,self.sources.ct do var src = self.sources.ptr + i
		if src.handle ~= nil and src.backend.timeline_instance_fetch ~= nil then
			var lst = src:post_enum_author_uid(uid,r)
................................................................................
								co:complain(400,'bad request','unrecognized content-type')
								goto fail
							end
							var boundary = pstring {ptr=p+9,ct=ctt.ct - ((p - ctt.ptr) + 9)}
							co.method = lib.http.method.post_file
							co.uploads:init(8)

							var bsr = co:qstr('\r\n--',boundary,'\r\n')

							var upmap = lib.str.splitmap(co.body,bsr,8)
							-- first entry may not be preceded by header-break
							if lib.str.find(upmap(0), pstring {
								ptr = bsr.ptr + 2, ct = bsr.ct - 2
							}):ref() then
								upmap(0).ptr = upmap(0).ptr + (bsr.ct - 2)
................................................................................
												nextup.field = fld
												nextup.filename = file
											end
										end
									end
								end
							end

							upmap:free()
						end
					end
				end



				route.dispatch_http(&co, uri)

				::fail::
				if co.uploads.run > 0 then
					for i=0,co.uploads.sz do
						co.uploads(i).filename:free()
						co.uploads(i).field:free()
................................................................................
--
--	return 0
--end

terra cfgcache.methods.load :: {&cfgcache} -> {}
terra cfgcache:init(o: &srv)
	self.overlord = o
	self._pool:init(256)
	self:load()
end

terra srv:setup(befile: rawstring)
	cfg(self, befile)
	var success = false
	if self.sources.ct == 0 then lib.bail('no data sources specified') end
................................................................................
	end
end

terra srv:start(iname: rawstring)
	self:conprep(lib.store.prepmode.full)
	self.cfg:init(self)
	self.pool:init(self.cfg.poolinitsz)
	var dbbind = self:conf_get(&self.pool, 'bind')
	if iname == nil then iname = lib.proc.getenv('parsav_instance') end
	if iname == nil then
		self.id = self.cfg.instance.ptr;
		-- let this leak -- it'll be needed for the lifetime of the process anyway
	else self.id = iname end 

	if iname ~= nil then
................................................................................
		bind = dbbind.ptr
	else bind = '[::1]:10917' end

	lib.report('binding to ', bind)
	lib.net.mg_mgr_init(&self.webmgr)
	self.webcon = lib.net.mg_http_listen(&self.webmgr, bind, handle.http, self)

	--if dbbind.ptr ~= nil then dbbind:free() end
end

terra srv:poll()
	lib.net.mg_mgr_poll(&self.webmgr,300)
end

terra srv:shutdown()
................................................................................
		lib.report('closing data source ', src.id.ptr, '(', src.backend.id, ')')
		src:close()
	end
	self.sources:free()
	self.pool:free()
end

terra cfgcache:cfstr(name: pstring)
	return self.overlord:conf_get(&self._pool, name)
end

terra cfgcache:cfint(name: pstring, default: intptr)
	var f = self._pool:frame()
	var str = self:cfstr(name)
	defer self._pool:reset(f)
	if str.ptr ~= nil then
		var i,ok = lib.math.decparse(str)
		if ok then default = i else
			lib.warn('invalid configuration setting ',{name.ptr,name.ct},'="',{str.ptr,str.ct},'", expected integer; using default value instead')
		end

	end
	return default
end

terra cfgcache:cffsz(name: pstring, default: intptr)
	var f = self._pool:frame()
	var str = self:cfstr(name)
	defer self._pool:reset(f)
	if str:ref() then
		var sz, ok = lib.math.fsz_parse(str)
		if ok then default = sz else
			lib.warn('invalid configuration setting ',{name.ptr,name.ct},'="',{str.ptr,str.ct},'", expected byte length; using default value instead')
		end

	end
	return default
end

terra cfgcache:cfbool(name: pstring, default: bool)
	var f = self._pool:frame()
	var str = self:cfstr(name)
	defer self._pool:reset(f)
	if str.ptr ~= nil then
		if str:cmp('true') or str:cmp('on') or
		   str:cmp('yes')  or str:cmp('1') then
			default = true
		elseif str:cmp('false') or str:cmp('off') or
		       str:cmp('no')    or str:cmp('0') then
			default = false
		else
			lib.warn('invalid configuration setting ',{name.ptr,name.ct},'="',{str.ptr,str.ct},'", expected boolean; using default value instead')
		end

	end
	return default
end

terra cfgcache:load()
	
	self.instance = self:cfstr('instance-name')
	self.domain = self:cfstr('domain')
	self.secret = self:cfstr('server-secret')

	self.pol_reg = self:cfbool('policy-self-register', false)
	self.pol_autoherald = self:cfbool('policy-self-herald', true)

	do self.credmgd = false
	var fr = self._pool:frame()
	var sreg = self:cfstr('credential-store')
	if sreg:ref() then
		if lib.str.cmp(sreg.ptr, 'managed') == 0
			then self.credmgd = true
			else self.credmgd = false
		end
		self._pool:reset(fr)
	end end

	self.maxupsz = self:cffsz('maximum-artifact-size', [1024 * 100]) -- 100 kilobyte default
	self.poolinitsz = self:cffsz('server-pool-size-initial', [1024 * 10]) -- 10 kilobyte default
	
	self.pol_sec = secmode.lockdown
	do var fr = self._pool:frame()
	var smode = self:cfstr('policy-security')
	if smode.ptr ~= nil then
		if lib.str.cmp(smode.ptr, 'public') == 0 then
			self.pol_sec = secmode.public
		elseif lib.str.cmp(smode.ptr, 'private') == 0 then
			self.pol_sec = secmode.private
		elseif lib.str.cmp(smode.ptr, 'lockdown') == 0 then
			self.pol_sec = secmode.lockdown
		elseif lib.str.cmp(smode.ptr, 'isolate') == 0 then
			self.pol_sec = secmode.isolate
		end
		self._pool:reset(fr)
	end end

	self.ui_hue = self:cfint('ui-accent',config.default_ui_accent)
	self.nranks = self:cfint('user-ranks',10)
	self.maxinvites = self:cfint('max-invites',64)
	
	do var fr = self._pool:frame()
	var webmaster = self:cfstr('master')
	defer self._pool:reset(fr)
	if webmaster:ref() then 
		var wma = self.overlord:actor_fetch_xid(webmaster)
		if not wma then
			lib.warn('the webmaster specified in the configuration store does not seem to exist or is not known to this instance; preceding as if no master defined. if the master is a remote user, you can rectify this with the `actor "',{webmaster.ptr,webmaster.ct},'" instantiate` and `conf refresh` commands')
		else
			self.master = wma(0).id
			wma:free()
		end
	end end

	self.ui_cue_staff = self:cfstr('ui-profile-cue-staff')
	self.ui_cue_founder = self:cfstr('ui-profile-cue-master')

	self.usrdef_pol_follow = self:cfstr('user-default-acl-follow')
	self.usrdef_pol_follow_req = self:cfstr('user-default-acl-follow-req')
end

return {
	overlord = srv;
	convo = convo;
	route = route;
	secmode = secmode;
}