Skip to content

Commit

Permalink
netutil: extract socket activation helpers from daemon package.
Browse files Browse the repository at this point in the history
  • Loading branch information
jhenstridge committed Jun 25, 2019
1 parent 57f9ad7 commit c1fdc93
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 59 deletions.
63 changes: 4 additions & 59 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,11 @@ import (
"os"
"os/exec"
"os/signal"
"runtime"
"strconv"
"strings"
"sync"
unix "syscall"
"time"

"github.com/coreos/go-systemd/activation"
"github.com/gorilla/mux"
"gopkg.in/tomb.v2"

Expand All @@ -42,6 +39,7 @@ import (
"github.com/snapcore/snapd/httputil"
"github.com/snapcore/snapd/i18n"
"github.com/snapcore/snapd/logger"
"github.com/snapcore/snapd/netutil"
"github.com/snapcore/snapd/osutil"
"github.com/snapcore/snapd/overlord"
"github.com/snapcore/snapd/overlord/auth"
Expand Down Expand Up @@ -312,75 +310,22 @@ func logit(handler http.Handler) http.Handler {
})
}

// getListener tries to get a listener for the given socket path from
// the listener map, and if it fails it tries to set it up directly.
func getListener(socketPath string, listenerMap map[string]net.Listener) (net.Listener, error) {
if listener, ok := listenerMap[socketPath]; ok {
return listener, nil
}

if c, err := net.Dial("unix", socketPath); err == nil {
c.Close()
return nil, fmt.Errorf("socket %q already in use", socketPath)
}

if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) {
return nil, err
}

address, err := net.ResolveUnixAddr("unix", socketPath)
if err != nil {
return nil, err
}

runtime.LockOSThread()
oldmask := unix.Umask(0111)
listener, err := net.ListenUnix("unix", address)
unix.Umask(oldmask)
runtime.UnlockOSThread()
if err != nil {
return nil, err
}

logger.Debugf("socket %q was not activated; listening", socketPath)

return listener, nil
}

// activationListeners builds a map of addresses to listeners that were passed
// during systemd activation
func activationListeners() (lns map[string]net.Listener, err error) {
// pass false to keep LISTEN_* environment variables passed by systemd
files := activation.Files(false)
lns = make(map[string]net.Listener, len(files))

for _, f := range files {
ln, err := net.FileListener(f)
if err != nil {
return nil, err
}
addr := ln.Addr().String()
lns[addr] = ln
}
return lns, nil
}

// Init sets up the Daemon's internal workings.
// Don't call more than once.
func (d *Daemon) Init() error {
listenerMap, err := activationListeners()
listenerMap, err := netutil.ActivationListeners()
if err != nil {
return err
}

// The SnapdSocket is required-- without it, die.
if listener, err := getListener(dirs.SnapdSocket, listenerMap); err == nil {
if listener, err := netutil.GetListener(dirs.SnapdSocket, listenerMap); err == nil {
d.snapdListener = &ucrednetListener{listener}
} else {
return fmt.Errorf("when trying to listen on %s: %v", dirs.SnapdSocket, err)
}

if listener, err := getListener(dirs.SnapSocket, listenerMap); err == nil {
if listener, err := netutil.GetListener(dirs.SnapSocket, listenerMap); err == nil {
// This listener may also be nil if that socket wasn't among
// the listeners, so check it before using it.
d.snapListener = &ucrednetListener{listener}
Expand Down
85 changes: 85 additions & 0 deletions netutil/activation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2015-2019 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package netutil

import (
"fmt"
"net"
"os"
"runtime"
unix "syscall"

"github.com/coreos/go-systemd/activation"

"github.com/snapcore/snapd/logger"
)

// GetListener tries to get a listener for the given socket path from
// the listener map, and if it fails it tries to set it up directly.
func GetListener(socketPath string, listenerMap map[string]net.Listener) (net.Listener, error) {
if listener, ok := listenerMap[socketPath]; ok {
return listener, nil
}

if c, err := net.Dial("unix", socketPath); err == nil {
c.Close()
return nil, fmt.Errorf("socket %q already in use", socketPath)
}

if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) {
return nil, err
}

address, err := net.ResolveUnixAddr("unix", socketPath)
if err != nil {
return nil, err
}

runtime.LockOSThread()
oldmask := unix.Umask(0111)
listener, err := net.ListenUnix("unix", address)
unix.Umask(oldmask)
runtime.UnlockOSThread()
if err != nil {
return nil, err
}

logger.Debugf("socket %q was not activated; listening", socketPath)

return listener, nil
}

// ActivationListeners builds a map of addresses to listeners that were passed
// during systemd activation
func ActivationListeners() (lns map[string]net.Listener, err error) {
// pass false to keep LISTEN_* environment variables passed by systemd
files := activation.Files(false)
lns = make(map[string]net.Listener, len(files))

for _, f := range files {
ln, err := net.FileListener(f)
if err != nil {
return nil, err
}
addr := ln.Addr().String()
lns[addr] = ln
}
return lns, nil
}

0 comments on commit c1fdc93

Please sign in to comment.