diff --git a/mapping.go b/mapping.go
new file mode 100644
index 0000000000000000000000000000000000000000..2f45726308c2246c9b3fd464f8267f43652f5812
--- /dev/null
+++ b/mapping.go
@@ -0,0 +1,141 @@
+package nat
+
+import (
+	"fmt"
+	"sync"
+	"time"
+
+	ma "github.com/jbenet/go-multiaddr"
+	manet "github.com/jbenet/go-multiaddr-net"
+	"github.com/jbenet/goprocess"
+)
+
+// Mapping represents a port mapping in a NAT.
+type Mapping interface {
+	// NAT returns the NAT object this Mapping belongs to.
+	NAT() *NAT
+
+	// Protocol returns the protocol of this port mapping. This is either
+	// "tcp" or "udp" as no other protocols are likely to be NAT-supported.
+	Protocol() string
+
+	// InternalPort returns the internal device port. Mapping will continue to
+	// try to map InternalPort() to an external facing port.
+	InternalPort() int
+
+	// ExternalPort returns the external facing port. If the mapping is not
+	// established, port will be 0
+	ExternalPort() int
+
+	// InternalAddr returns the internal address.
+	InternalAddr() ma.Multiaddr
+
+	// ExternalAddr returns the external facing address. If the mapping is not
+	// established, addr will be nil, and and ErrNoMapping will be returned.
+	ExternalAddr() (addr ma.Multiaddr, err error)
+
+	// Close closes the port mapping
+	Close() error
+}
+
+// keeps republishing
+type mapping struct {
+	sync.Mutex // guards all fields
+
+	nat       *NAT
+	proto     string
+	intport   int
+	extport   int
+	permanent bool
+	intaddr   ma.Multiaddr
+	proc      goprocess.Process
+
+	comment string
+
+	cached    ma.Multiaddr
+	cacheTime time.Time
+	cacheLk   sync.Mutex
+}
+
+func (m *mapping) NAT() *NAT {
+	m.Lock()
+	defer m.Unlock()
+	return m.nat
+}
+
+func (m *mapping) Protocol() string {
+	m.Lock()
+	defer m.Unlock()
+	return m.proto
+}
+
+func (m *mapping) InternalPort() int {
+	m.Lock()
+	defer m.Unlock()
+	return m.intport
+}
+
+func (m *mapping) ExternalPort() int {
+	m.Lock()
+	defer m.Unlock()
+	return m.extport
+}
+
+func (m *mapping) setExternalPort(p int) {
+	m.Lock()
+	defer m.Unlock()
+	m.extport = p
+}
+
+func (m *mapping) InternalAddr() ma.Multiaddr {
+	m.Lock()
+	defer m.Unlock()
+	return m.intaddr
+}
+
+func (m *mapping) ExternalAddr() (ma.Multiaddr, error) {
+	m.cacheLk.Lock()
+	ctime := m.cacheTime
+	cval := m.cached
+	m.cacheLk.Unlock()
+	if time.Since(ctime) < CacheTime {
+		return cval, nil
+	}
+
+	if m.ExternalPort() == 0 { // dont even try right now.
+		return nil, ErrNoMapping
+	}
+
+	ip, err := m.nat.nat.GetExternalAddress()
+	if err != nil {
+		return nil, err
+	}
+
+	ipmaddr, err := manet.FromIP(ip)
+	if err != nil {
+		return nil, fmt.Errorf("error parsing ip")
+	}
+
+	// call m.ExternalPort again, as mapping may have changed under our feet. (tocttou)
+	extport := m.ExternalPort()
+	if extport == 0 {
+		return nil, ErrNoMapping
+	}
+
+	tcp, err := ma.NewMultiaddr(fmt.Sprintf("/%s/%d", m.Protocol(), extport))
+	if err != nil {
+		return nil, err
+	}
+
+	maddr2 := ipmaddr.Encapsulate(tcp)
+
+	m.cacheLk.Lock()
+	m.cached = maddr2
+	m.cacheTime = time.Now()
+	m.cacheLk.Unlock()
+	return maddr2, nil
+}
+
+func (m *mapping) Close() error {
+	return m.proc.Close()
+}
diff --git a/nat.go b/nat.go
index a7fc75b0d33d7a885cf21fc8ef5ccc9ad04caf1f..210512cd1ad3c90c80a2c8a14b161a587ab9325a 100644
--- a/nat.go
+++ b/nat.go
@@ -14,7 +14,6 @@ import (
 	manet "github.com/jbenet/go-multiaddr-net"
 	goprocess "github.com/jbenet/goprocess"
 	periodic "github.com/jbenet/goprocess/periodic"
-	notifier "github.com/whyrusleeping/go-notifier"
 )
 
 var (
@@ -81,178 +80,6 @@ func (nat *NAT) Process() goprocess.Process {
 	return nat.proc
 }
 
-// Notifier is an object that assists NAT in notifying listeners.
-// It is implemented using thirdparty/notifier
-type Notifier struct {
-	n notifier.Notifier
-}
-
-func (n *Notifier) notifyAll(notify func(n Notifiee)) {
-	n.n.NotifyAll(func(n notifier.Notifiee) {
-		notify(n.(Notifiee))
-	})
-}
-
-// Notify signs up notifiee to listen to NAT events.
-func (n *Notifier) Notify(notifiee Notifiee) {
-	n.n.Notify(n)
-}
-
-// StopNotify stops signaling events to notifiee.
-func (n *Notifier) StopNotify(notifiee Notifiee) {
-	n.n.StopNotify(notifiee)
-}
-
-// Notifiee is an interface objects must implement to listen to NAT events.
-type Notifiee interface {
-
-	// Called every time a successful mapping happens
-	// Warning: the port mapping may have changed. If that is the
-	// case, both MappingSuccess and MappingChanged are called.
-	MappingSuccess(nat *NAT, m Mapping)
-
-	// Called when mapping a port succeeds, but the mapping is
-	// with a different port than an earlier success.
-	MappingChanged(nat *NAT, m Mapping, oldport int, newport int)
-
-	// Called when a port mapping fails. NAT will continue attempting after
-	// the next period. To stop trying, use: mapping.Close(). After this failure,
-	// mapping.ExternalPort() will be zero, and nat.ExternalAddrs() will not
-	// return the address for this mapping. With luck, the next attempt will
-	// succeed, without the client needing to do anything.
-	MappingFailed(nat *NAT, m Mapping, oldport int, err error)
-}
-
-// Mapping represents a port mapping in a NAT.
-type Mapping interface {
-	// NAT returns the NAT object this Mapping belongs to.
-	NAT() *NAT
-
-	// Protocol returns the protocol of this port mapping. This is either
-	// "tcp" or "udp" as no other protocols are likely to be NAT-supported.
-	Protocol() string
-
-	// InternalPort returns the internal device port. Mapping will continue to
-	// try to map InternalPort() to an external facing port.
-	InternalPort() int
-
-	// ExternalPort returns the external facing port. If the mapping is not
-	// established, port will be 0
-	ExternalPort() int
-
-	// InternalAddr returns the internal address.
-	InternalAddr() ma.Multiaddr
-
-	// ExternalAddr returns the external facing address. If the mapping is not
-	// established, addr will be nil, and and ErrNoMapping will be returned.
-	ExternalAddr() (addr ma.Multiaddr, err error)
-
-	// Close closes the port mapping
-	Close() error
-}
-
-// keeps republishing
-type mapping struct {
-	sync.Mutex // guards all fields
-
-	nat       *NAT
-	proto     string
-	intport   int
-	extport   int
-	permanent bool
-	intaddr   ma.Multiaddr
-	proc      goprocess.Process
-
-	comment string
-
-	cached    ma.Multiaddr
-	cacheTime time.Time
-	cacheLk   sync.Mutex
-}
-
-func (m *mapping) NAT() *NAT {
-	m.Lock()
-	defer m.Unlock()
-	return m.nat
-}
-
-func (m *mapping) Protocol() string {
-	m.Lock()
-	defer m.Unlock()
-	return m.proto
-}
-
-func (m *mapping) InternalPort() int {
-	m.Lock()
-	defer m.Unlock()
-	return m.intport
-}
-
-func (m *mapping) ExternalPort() int {
-	m.Lock()
-	defer m.Unlock()
-	return m.extport
-}
-
-func (m *mapping) setExternalPort(p int) {
-	m.Lock()
-	defer m.Unlock()
-	m.extport = p
-}
-
-func (m *mapping) InternalAddr() ma.Multiaddr {
-	m.Lock()
-	defer m.Unlock()
-	return m.intaddr
-}
-
-func (m *mapping) ExternalAddr() (ma.Multiaddr, error) {
-	m.cacheLk.Lock()
-	ctime := m.cacheTime
-	cval := m.cached
-	m.cacheLk.Unlock()
-	if time.Since(ctime) < CacheTime {
-		return cval, nil
-	}
-
-	if m.ExternalPort() == 0 { // dont even try right now.
-		return nil, ErrNoMapping
-	}
-
-	ip, err := m.nat.nat.GetExternalAddress()
-	if err != nil {
-		return nil, err
-	}
-
-	ipmaddr, err := manet.FromIP(ip)
-	if err != nil {
-		return nil, fmt.Errorf("error parsing ip")
-	}
-
-	// call m.ExternalPort again, as mapping may have changed under our feet. (tocttou)
-	extport := m.ExternalPort()
-	if extport == 0 {
-		return nil, ErrNoMapping
-	}
-
-	tcp, err := ma.NewMultiaddr(fmt.Sprintf("/%s/%d", m.Protocol(), extport))
-	if err != nil {
-		return nil, err
-	}
-
-	maddr2 := ipmaddr.Encapsulate(tcp)
-
-	m.cacheLk.Lock()
-	m.cached = maddr2
-	m.cacheTime = time.Now()
-	m.cacheLk.Unlock()
-	return maddr2, nil
-}
-
-func (m *mapping) Close() error {
-	return m.proc.Close()
-}
-
 // Mappings returns a slice of all NAT mappings
 func (nat *NAT) Mappings() []Mapping {
 	nat.mappingmu.Lock()
diff --git a/notifier.go b/notifier.go
new file mode 100644
index 0000000000000000000000000000000000000000..462a78b953e9607d470a9b42d46615e41d73ef6a
--- /dev/null
+++ b/notifier.go
@@ -0,0 +1,47 @@
+package nat
+
+import (
+	notifier "github.com/whyrusleeping/go-notifier"
+)
+
+// Notifier is an object that assists NAT in notifying listeners.
+// It is implemented using thirdparty/notifier
+type Notifier struct {
+	n notifier.Notifier
+}
+
+func (n *Notifier) notifyAll(notify func(n Notifiee)) {
+	n.n.NotifyAll(func(n notifier.Notifiee) {
+		notify(n.(Notifiee))
+	})
+}
+
+// Notify signs up notifiee to listen to NAT events.
+func (n *Notifier) Notify(notifiee Notifiee) {
+	n.n.Notify(n)
+}
+
+// StopNotify stops signaling events to notifiee.
+func (n *Notifier) StopNotify(notifiee Notifiee) {
+	n.n.StopNotify(notifiee)
+}
+
+// Notifiee is an interface objects must implement to listen to NAT events.
+type Notifiee interface {
+
+	// Called every time a successful mapping happens
+	// Warning: the port mapping may have changed. If that is the
+	// case, both MappingSuccess and MappingChanged are called.
+	MappingSuccess(nat *NAT, m Mapping)
+
+	// Called when mapping a port succeeds, but the mapping is
+	// with a different port than an earlier success.
+	MappingChanged(nat *NAT, m Mapping, oldport int, newport int)
+
+	// Called when a port mapping fails. NAT will continue attempting after
+	// the next period. To stop trying, use: mapping.Close(). After this failure,
+	// mapping.ExternalPort() will be zero, and nat.ExternalAddrs() will not
+	// return the address for this mapping. With luck, the next attempt will
+	// succeed, without the client needing to do anything.
+	MappingFailed(nat *NAT, m Mapping, oldport int, err error)
+}