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;
}
|