diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 6c3543e80..026d0f78f 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -9,6 +9,9 @@ import ( "sort" cmds "github.com/ipfs/go-ipfs/commands" + repo "github.com/ipfs/go-ipfs/repo" + config "github.com/ipfs/go-ipfs/repo/config" + "github.com/ipfs/go-ipfs/repo/fsrepo" iaddr "github.com/ipfs/go-ipfs/thirdparty/ipfsaddr" pstore "gx/ipfs/QmXHUpFsnpCmanRnacqYkFoLoFfEq5yS2nUgGkAjJ1Nj9j/go-libp2p-peerstore" swarm "gx/ipfs/QmdBpVuSYuTGDA8Kn66CbKvEThXqKUh2nTANZEhzSxqrmJ/go-libp2p/p2p/net/swarm" @@ -458,6 +461,23 @@ add your filters to the ipfs config file. return } + if len(req.Arguments()) == 0 { + res.SetError(errors.New("no filters to add"), cmds.ErrClient) + return + } + + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + defer r.Close() + cfg, err := r.Config() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + for _, arg := range req.Arguments() { mask, err := mafilter.NewMask(arg) if err != nil { @@ -467,7 +487,20 @@ add your filters to the ipfs config file. snet.Filters.AddDialFilter(mask) } + + added, err := filtersAdd(r, cfg, req.Arguments()) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + + } + + res.SetOutput(&stringList{added}) }, + Marshalers: cmds.MarshalerMap{ + cmds.Text: stringListMarshaler, + }, + Type: stringList{}, } var swarmFiltersRmCmd = &cmds.Command{ @@ -500,11 +533,32 @@ remove your filters from the ipfs config file. return } + r, err := fsrepo.Open(req.InvocContext().ConfigRoot) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + defer r.Close() + cfg, err := r.Config() + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + if req.Arguments()[0] == "all" || req.Arguments()[0] == "*" { fs := snet.Filters.Filters() for _, f := range fs { snet.Filters.Remove(f) } + + removed, err := filtersRemoveAll(r, cfg) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + + res.SetOutput(&stringList{removed}) + return } @@ -517,5 +571,89 @@ remove your filters from the ipfs config file. snet.Filters.Remove(mask) } + + removed, err := filtersRemove(r, cfg, req.Arguments()) + + res.SetOutput(&stringList{removed}) }, + Marshalers: cmds.MarshalerMap{ + cmds.Text: stringListMarshaler, + }, + Type: stringList{}, +} + +func filtersAdd(r repo.Repo, cfg *config.Config, filters []string) ([]string, error) { + addedMap := map[string]struct{}{} + addedList := make([]string, 0, len(filters)) + + // re-add cfg swarm filters to rm dupes + oldFilters := cfg.Swarm.AddrFilters + cfg.Swarm.AddrFilters = nil + + // add new filters + for _, filter := range filters { + if _, found := addedMap[filter]; found { + continue + } + + cfg.Swarm.AddrFilters = append(cfg.Swarm.AddrFilters, filter) + addedList = append(addedList, filter) + addedMap[filter] = struct{}{} + } + + // add back original filters. in this order so that we output them. + for _, filter := range oldFilters { + if _, found := addedMap[filter]; found { + continue + } + + cfg.Swarm.AddrFilters = append(cfg.Swarm.AddrFilters, filter) + addedMap[filter] = struct{}{} + } + + if err := r.SetConfig(cfg); err != nil { + return nil, err + } + + return addedList, nil +} + +func filtersRemoveAll(r repo.Repo, cfg *config.Config) ([]string, error) { + removed := cfg.Swarm.AddrFilters + cfg.Swarm.AddrFilters = nil + + if err := r.SetConfig(cfg); err != nil { + return nil, err + } + + return removed, nil +} + +func filtersRemove(r repo.Repo, cfg *config.Config, toRemoveFilters []string) ([]string, error) { + removed := make([]string, 0, len(toRemoveFilters)) + keep := make([]string, 0, len(cfg.Swarm.AddrFilters)) + + oldFilters := cfg.Swarm.AddrFilters + + for _, oldFilter := range oldFilters { + found := false + for _, toRemoveFilter := range toRemoveFilters { + if oldFilter == toRemoveFilter { + found = true + removed = append(removed, toRemoveFilter) + break + } + } + + if !found { + keep = append(keep, oldFilter) + } + } + cfg.Swarm.AddrFilters = keep + + if err := r.SetConfig(cfg); err != nil { + return nil, err + } + + return removed, nil } diff --git a/test/sharness/t0141-addfilter.sh b/test/sharness/t0141-addfilter.sh index 4e31f3271..ab75e832d 100755 --- a/test/sharness/t0141-addfilter.sh +++ b/test/sharness/t0141-addfilter.sh @@ -31,38 +31,74 @@ test_swarm_filter_cmd() { ' } +test_config_swarm_addrfilters_cmd() { + printf "" > list_expected + for AF in "$@" + do + echo "$AF" >>list_expected + done + + test_expect_success "'ipfs config Swarm.AddrFilters' succeeds" ' + ipfs config Swarm.AddrFilters > list_actual + ' + + printf "" > list_actual_cleaned + if [ "$( cat list_actual )" != "[]" -a "$( cat list_actual )" != "null" ]; + then + grep -v "^\]" list_actual | + grep -v "^\[" | + tr -d '" ,' > list_actual_cleaned + fi + + test_expect_success "'ipfs config Swarm.AddrFilters' output looks good" ' + test_sort_cmp list_expected list_actual_cleaned + ' +} + test_swarm_filters() { # expect first address from config test_swarm_filter_cmd $AF1 $AF4 + test_config_swarm_addrfilters_cmd $AF1 $AF4 + ipfs swarm filters rm all test_swarm_filter_cmd + test_config_swarm_addrfilters_cmd + test_expect_success "'ipfs swarm filter add' succeeds" ' ipfs swarm filters add $AF1 $AF2 $AF3 ' test_swarm_filter_cmd $AF1 $AF2 $AF3 + test_config_swarm_addrfilters_cmd $AF1 $AF2 $AF3 + test_expect_success "'ipfs swarm filter rm' succeeds" ' ipfs swarm filters rm $AF2 $AF3 ' test_swarm_filter_cmd $AF1 + test_config_swarm_addrfilters_cmd $AF1 + test_expect_success "'ipfs swarm filter add' succeeds" ' ipfs swarm filters add $AF4 $AF2 ' test_swarm_filter_cmd $AF1 $AF2 $AF4 + test_config_swarm_addrfilters_cmd $AF1 $AF2 $AF4 + test_expect_success "'ipfs swarm filter rm' succeeds" ' ipfs swarm filters rm $AF1 $AF2 $AF4 ' test_swarm_filter_cmd + + test_config_swarm_addrfilters_cmd } test_expect_success "init without any filters" '