=== modified file 'main.go'
--- main.go	2014-04-28 10:54:41 +0000
+++ main.go	2014-05-12 13:50:54 +0000
@@ -40,29 +40,37 @@
 	if connSession, err = dbus.Connect(dbus.SessionBus); err != nil {
 		log.Fatal("Connection error: ", err)
 	}
+	log.Print("Using session bus on ", connSession.UniqueName)
+
 	mmsManager, err := telepathy.NewMMSManager(connSession)
 	if err != nil {
 		log.Fatal(err)
 	}
-	log.Print("Using session bus on ", connSession.UniqueName)
 
 	if conn, err = dbus.Connect(dbus.SystemBus); err != nil {
 		log.Fatal("Connection error: ", err)
 	}
 	log.Print("Using system bus on ", conn.UniqueName)
-	modems, err := ofono.NewModems(conn)
-	if err != nil {
-		log.Fatal("Could not add modems")
-	}
-	log.Print("Amount of modems found: ", len(modems))
 
-	//TODO refactor with new ofono work
-	for i, _ := range modems {
-		mediator := NewMediator(modems[i])
-		go mediator.init(mmsManager)
-		if err := mediator.kickstart(); err != nil {
-			log.Fatal(err)
+	modemManager := ofono.NewModemManager(conn)
+	mediators := make(map[dbus.ObjectPath]*Mediator)
+	go func() {
+		for {
+			select {
+			case modem := <-modemManager.ModemAdded:
+				mediators[modem.Modem] = NewMediator(modem)
+				go mediators[modem.Modem].init(mmsManager)
+				if err := modem.Init(); err != nil {
+					log.Printf("Cannot initialize modem %s", modem.Modem)
+				}
+			case modem := <-modemManager.ModemRemoved:
+				mediators[modem.Modem].Delete()
+			}
 		}
+	}()
+
+	if err := modemManager.Init(); err != nil {
+		log.Fatal(err)
 	}
 
 	m := Mainloop{

=== modified file 'mediator.go'
--- mediator.go	2014-05-12 13:50:54 +0000
+++ mediator.go	2014-05-12 13:50:54 +0000
@@ -40,6 +40,7 @@
 	NewMRetrieveConf      chan *mms.MRetrieveConf
 	NewMRetrieveConfFile  chan string
 	NewMNotifyRespIndFile chan string
+	terminate             chan bool
 }
 
 //TODO these vars need a configuration location managed by system settings or
@@ -57,19 +58,19 @@
 	mediator.NewMRetrieveConfFile = make(chan string)
 	mediator.NewMNotifyRespInd = make(chan *mms.MNotifyRespInd)
 	mediator.NewMNotifyRespIndFile = make(chan string)
+	mediator.terminate = make(chan bool)
 	return mediator
 }
 
 func (mediator *Mediator) Delete() {
-	close(mediator.NewMNotificationInd)
-	close(mediator.NewMRetrieveConf)
-	close(mediator.NewMRetrieveConfFile)
+	mediator.terminate <- mediator.telepathyService == nil
 }
 
 func (mediator *Mediator) init(mmsManager *telepathy.MMSManager) {
+mediatorLoop:
 	for {
 		select {
-		case push, ok := <-mediator.modem.PushChannel:
+		case push, ok := <-mediator.modem.PushAgent.Push:
 			if !ok {
 				log.Print("PushChannel is closed")
 				continue
@@ -101,28 +102,31 @@
 				log.Fatal(err)
 			}
 			mediator.telepathyService = nil
-		case <-mediator.modem.ReadySignal:
-			if err := mediator.modem.RegisterAgent(); err != nil {
-				log.Fatal("Error while registering agent: ", err)
+		case ok := <-mediator.modem.PushInterfaceAvailable:
+			if ok {
+				if err := mediator.modem.PushAgent.Register(); err != nil {
+					log.Fatal(err)
+				}
+			} else {
+				if err := mediator.modem.PushAgent.Unregister(); err != nil {
+					log.Fatal(err)
+				}
+			}
+		case terminate := <-mediator.terminate:
+			/*
+				close(mediator.terminate)
+				close(mediator.NewMNotificationInd)
+				close(mediator.NewMRetrieveConf)
+				close(mediator.NewMRetrieveConfFile)
+				close(mediator.NewMNotifyRespInd)
+				close(mediator.NewMNotifyRespIndFile)
+			*/
+			if terminate {
+				break mediatorLoop
 			}
 		}
 	}
-}
-
-func (mediator *Mediator) handleModemReady() {
-	if err := mediator.modem.RegisterAgent(); err != nil {
-		log.Fatal("Error while registering agent: ", err)
-	}
-}
-
-func (mediator *Mediator) kickstart() error {
-	if err := mediator.modem.WatchPushInterface(); err != nil {
-		return err
-	}
-	if err := mediator.modem.GetIdentity(); err != nil {
-		return err
-	}
-	return nil
+	log.Print("Ending mediator instance loop for modem")
 }
 
 func (mediator *Mediator) handleMNotificationInd(pushMsg *ofono.PushPDU) {

=== added file 'ofono/common.go'
--- ofono/common.go	1970-01-01 00:00:00 +0000
+++ ofono/common.go	2014-05-12 13:50:54 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * Authors:
+ * Sergio Schvezov: sergio.schvezov@cannical.com
+ *
+ * This file is part of nuntium.
+ *
+ * nuntium is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * nuntium 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 ofono
+
+import "launchpad.net/go-dbus/v1"
+
+const (
+	AGENT_TAG                         = dbus.ObjectPath("/nuntium")
+	PUSH_NOTIFICATION_INTERFACE       = "org.ofono.PushNotification"
+	PUSH_NOTIFICATION_AGENT_INTERFACE = "org.ofono.PushNotificationAgent"
+	CONNECTION_MANAGER_INTERFACE      = "org.ofono.ConnectionManager"
+	CONNECTION_CONTEXT_INTERFACE      = "org.ofono.ConnectionContext"
+	SIM_MANAGER_INTERFACE             = "org.ofono.SimManager"
+	OFONO_MANAGER_INTERFACE           = "org.ofono.Manager"
+	OFONO_SENDER                      = "org.ofono"
+	MODEM_INTERFACE                   = "org.ofono.Modem"
+)
+
+type PropertiesType map[string]dbus.Variant
+
+func getModems(conn *dbus.Connection) (modemPaths []dbus.ObjectPath, err error) {
+	obj := conn.Object("org.ofono", "/")
+	modemsReply, err := getOfonoProps(obj, "org.ofono.Manager", "GetModems")
+	if err != nil {
+		return nil, err
+	}
+	for _, modemReply := range modemsReply {
+		modemPaths = append(modemPaths, modemReply.ObjectPath)
+	}
+	return modemPaths, nil
+}
+
+func connectToPropertySignal(conn *dbus.Connection, path dbus.ObjectPath, inter string) (*dbus.SignalWatch, error) {
+	w, err := conn.WatchSignal(&dbus.MatchRule{
+		Type:      dbus.TypeSignal,
+		Sender:    OFONO_SENDER,
+		Interface: inter,
+		Member:    "PropertyChanged",
+		Path:      path})
+	return w, err
+}
+
+func connectToSignal(conn *dbus.Connection, path dbus.ObjectPath, inter, member string) (*dbus.SignalWatch, error) {
+	w, err := conn.WatchSignal(&dbus.MatchRule{
+		Type:      dbus.TypeSignal,
+		Sender:    OFONO_SENDER,
+		Interface: inter,
+		Member:    member,
+		Path:      path})
+	return w, err
+}

=== added file 'ofono/manager.go'
--- ofono/manager.go	1970-01-01 00:00:00 +0000
+++ ofono/manager.go	2014-05-12 13:50:54 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * Authors:
+ * Sergio Schvezov: sergio.schvezov@cannical.com
+ *
+ * This file is part of nuntium.
+ *
+ * nuntium is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * nuntium 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 ofono
+
+import (
+	"log"
+
+	"launchpad.net/go-dbus/v1"
+)
+
+type Modems map[dbus.ObjectPath]*Modem
+
+type ModemManager struct {
+	ModemAdded   chan (*Modem)
+	ModemRemoved chan (*Modem)
+	modems       Modems
+	conn         *dbus.Connection
+}
+
+func NewModemManager(conn *dbus.Connection) *ModemManager {
+	return &ModemManager{
+		conn:         conn,
+		ModemAdded:   make(chan *Modem),
+		ModemRemoved: make(chan *Modem),
+		modems:       make(Modems),
+	}
+}
+
+func (mm *ModemManager) Init() error {
+	modemAddedSignal, err := connectToSignal(mm.conn, "/", OFONO_MANAGER_INTERFACE, "ModemAdded")
+	if err != nil {
+		return err
+	}
+	modemRemovedSignal, err := connectToSignal(mm.conn, "/", OFONO_MANAGER_INTERFACE, "ModemRemoved")
+	if err != nil {
+		return err
+	}
+	go mm.watchModems(modemAddedSignal, modemRemovedSignal)
+
+	//Check for existing modems
+	modemPaths, err := getModems(mm.conn)
+	if err != nil {
+		log.Print("Cannot preemptively add modems: ", err)
+	} else {
+		for _, objectPath := range modemPaths {
+			mm.addModem(objectPath)
+		}
+	}
+	return nil
+}
+
+func (mm *ModemManager) watchModems(modemAdded, modemRemoved *dbus.SignalWatch) {
+	for {
+		var objectPath dbus.ObjectPath
+		select {
+		case m := <-modemAdded.C:
+			var signalProps PropertiesType
+			if err := m.Args(&objectPath, &signalProps); err != nil {
+				log.Print(err)
+				continue
+			}
+			mm.addModem(objectPath)
+		case m := <-modemRemoved.C:
+			if err := m.Args(&objectPath); err != nil {
+				log.Print(err)
+				continue
+			}
+			mm.removeModem(objectPath)
+		}
+	}
+}
+
+func (mm *ModemManager) addModem(objectPath dbus.ObjectPath) {
+	if modem, ok := mm.modems[objectPath]; ok {
+		log.Print("Need to delete stale modem instance %s", modem.Modem)
+		modem.Delete()
+		delete(mm.modems, objectPath)
+	}
+	mm.modems[objectPath] = NewModem(mm.conn, objectPath)
+	mm.ModemAdded <- mm.modems[objectPath]
+}
+
+func (mm *ModemManager) removeModem(objectPath dbus.ObjectPath) {
+	if modem, ok := mm.modems[objectPath]; ok {
+		mm.ModemRemoved <- mm.modems[objectPath]
+		log.Printf("Deleting modem instance %s", modem.Modem)
+		modem.Delete()
+		delete(mm.modems, objectPath)
+	} else {
+		log.Printf("Cannot satisfy request to remove modem %s as it does not exist", objectPath)
+	}
+}

=== renamed file 'ofono/ofono.go' => 'ofono/modem.go'
--- ofono/ofono.go	2014-04-28 10:54:41 +0000
+++ ofono/modem.go	2014-05-12 13:50:54 +0000
@@ -22,7 +22,6 @@
 package ofono
 
 import (
-	"encoding/hex"
 	"errors"
 	"fmt"
 	"log"
@@ -34,43 +33,23 @@
 	"launchpad.net/go-dbus/v1"
 )
 
-const (
-	AGENT_TAG                         = dbus.ObjectPath("/nuntium")
-	PUSH_NOTIFICATION_INTERFACE       = "org.ofono.PushNotification"
-	PUSH_NOTIFICATION_AGENT_INTERFACE = "org.ofono.PushNotificationAgent"
-	CONNECTION_MANAGER_INTERFACE      = "org.ofono.ConnectionManager"
-	CONNECTION_CONTEXT_INTERFACE      = "org.ofono.ConnectionContext"
-	SIM_MANAGER_INTERFACE             = "org.ofono.SimManager"
-	OFONO_SENDER                      = "org.ofono"
-	MODEM_INTERFACE                   = "org.ofono.Modem"
-)
-
-type PropertiesType map[string]dbus.Variant
-
 type OfonoContext struct {
 	ObjectPath dbus.ObjectPath
 	Properties PropertiesType
 }
 
-/*
- in = "aya{sv}", out = ""
-*/
-type OfonoPushNotification struct {
-	Data []byte
-	Info map[string]*dbus.Variant
-}
-
 type Modem struct {
-	conn            *dbus.Connection
-	modem           dbus.ObjectPath
-	agentRegistered bool
-	messageChannel  chan *dbus.Message
-	PushChannel     chan *PushPDU
-	identity        string
-	IdentityAdded   chan string
-	IdentityRemoved chan string
-	ReadySignal     chan bool
-	ready           bool
+	conn                   *dbus.Connection
+	Modem                  dbus.ObjectPath
+	PushAgent              *PushAgent
+	identity               string
+	IdentityAdded          chan string
+	IdentityRemoved        chan string
+	endWatch               chan bool
+	PushInterfaceAvailable chan bool
+	pushInterfaceAvailable bool
+	online                 bool
+	modemSignal, simSignal *dbus.SignalWatch
 }
 
 type ProxyInfo struct {
@@ -87,90 +66,132 @@
 	return s
 }
 
-func NewModems(conn *dbus.Connection) ([]*Modem, error) {
-	var modems []*Modem
-	obj := conn.Object("org.ofono", "/")
-	modemsReply, err := getOfonoProps(obj, "org.ofono.Manager", "GetModems")
-	if err != nil {
-		return modems, err
-	}
-	for _, modemReply := range modemsReply {
-		modem := new(Modem)
-		modem.conn = conn
-		modem.modem = modemReply.ObjectPath
-		modem.ReadySignal = make(chan bool)
-		modem.IdentityAdded = make(chan string)
-		modem.IdentityRemoved = make(chan string)
-		modems = append(modems, modem)
-	}
-	return modems, nil
+func NewModem(conn *dbus.Connection, objectPath dbus.ObjectPath) *Modem {
+	return &Modem{
+		conn:                   conn,
+		Modem:                  objectPath,
+		IdentityAdded:          make(chan string),
+		IdentityRemoved:        make(chan string),
+		PushInterfaceAvailable: make(chan bool),
+		endWatch:               make(chan bool),
+		PushAgent:              NewPushAgent(objectPath),
+	}
 }
 
-func (modem *Modem) WatchPushInterface() error {
+func (modem *Modem) Init() (err error) {
+	log.Printf("Initializing modem %s", modem.Modem)
+	modem.modemSignal, err = connectToPropertySignal(modem.conn, modem.Modem, MODEM_INTERFACE)
+	if err != nil {
+		return err
+	}
+
+	modem.simSignal, err = connectToPropertySignal(modem.conn, modem.Modem, SIM_MANAGER_INTERFACE)
+	if err != nil {
+		return err
+	}
+
+	go modem.watchModem()
+
 	if v, err := modem.getProperty(MODEM_INTERFACE, "Interfaces"); err == nil {
-		availableInterfaces := reflect.ValueOf(v.Value)
-		for i := 0; i < availableInterfaces.Len(); i++ {
-			interfaceName := reflect.ValueOf(availableInterfaces.Index(i).Interface().(string)).String()
-			if interfaceName == PUSH_NOTIFICATION_INTERFACE {
-				modem.ready = true
-				modem.ReadySignal <- modem.ready
-				break
+		modem.updatePushInterfaceState(*v)
+	} else {
+		log.Print("Initial value couldn't be retrieved: ", err)
+	}
+	if v, err := modem.getProperty(MODEM_INTERFACE, "Online"); err == nil {
+		modem.handleOnlineState(*v)
+	} else {
+		log.Print("Initial value couldn't be retrieved: ", err)
+	}
+	if v, err := modem.getProperty(SIM_MANAGER_INTERFACE, "SubscriberIdentity"); err == nil {
+		modem.handleIdentity(*v)
+	}
+	return nil
+}
+
+func (modem *Modem) watchModem() {
+	var propName string
+	var propValue dbus.Variant
+watchloop:
+	for {
+		select {
+		case <-modem.endWatch:
+			log.Printf("Ending modem watch for %s", modem.Modem)
+			break watchloop
+		case msg, ok := <-modem.modemSignal.C:
+			if !ok {
+				modem.modemSignal.C = nil
+				continue watchloop
 			}
-		}
-	} else {
-		log.Print("Initial value couldn't be retrieved: ", err)
-	}
-	propModemSignal, err := connectToPropertySignal(modem.conn, modem.modem, MODEM_INTERFACE)
-	if err != nil {
-		return err
-	}
-	go func() {
-		log.Print("Watching push interface to see if we can Register an Agent")
-		var propName string
-		var propValue dbus.Variant
-		var pushInterfaceAvailable, online bool
-		//TODO once we start tracking modems, these watches need to become members
-		for msg := range propModemSignal.C {
 			if err := msg.Args(&propName, &propValue); err != nil {
-				log.Print(err)
-				continue
-			}
-			if modem.ready {
-				continue
+				log.Printf("Cannot interpret Modem Property change: %s", err)
+				continue watchloop
 			}
 			switch propName {
 			case "Interfaces":
-				availableInterfaces := reflect.ValueOf(propValue.Value)
-				pushInterfaceAvailable = false
-				for i := 0; i < availableInterfaces.Len(); i++ {
-					interfaceName := reflect.ValueOf(availableInterfaces.Index(i).Interface().(string)).String()
-					if interfaceName == PUSH_NOTIFICATION_INTERFACE {
-						pushInterfaceAvailable = true
-						break
-					}
-				}
+				modem.updatePushInterfaceState(propValue)
 			case "Online":
-				online = reflect.ValueOf(propValue.Value).Bool()
+				modem.handleOnlineState(propValue)
 			default:
-				continue
-			}
-			if pushInterfaceAvailable && online {
-				modem.ready = true
-				modem.ReadySignal <- modem.ready
-			}
-		}
-	}()
-	return nil
-}
-
-func connectToPropertySignal(conn *dbus.Connection, path dbus.ObjectPath, inter string) (*dbus.SignalWatch, error) {
-	w, err := conn.WatchSignal(&dbus.MatchRule{
-		Type:      dbus.TypeSignal,
-		Sender:    OFONO_SENDER,
-		Interface: inter,
-		Member:    "PropertyChanged",
-		Path:      path})
-	return w, err
+				continue watchloop
+			}
+		case msg, ok := <-modem.simSignal.C:
+			if !ok {
+				modem.simSignal.C = nil
+				continue watchloop
+			}
+			if err := msg.Args(&propName, &propValue); err != nil {
+				log.Printf("Cannot interpret Sim Property change: %s", err)
+				continue watchloop
+			}
+			if propName != "SubscriberIdentity" {
+				continue watchloop
+			}
+			modem.handleIdentity(propValue)
+		}
+	}
+}
+
+func (modem *Modem) handleOnlineState(propValue dbus.Variant) {
+	origState := modem.online
+	modem.online = reflect.ValueOf(propValue.Value).Bool()
+	if modem.online != origState {
+		log.Printf("Modem online: %t", modem.online)
+	}
+}
+
+func (modem *Modem) handleIdentity(propValue dbus.Variant) {
+	identity := reflect.ValueOf(propValue.Value).String()
+	if identity == "" && modem.identity != "" {
+		log.Printf("Identity before remove %s", modem.identity)
+
+		modem.IdentityRemoved <- identity
+		modem.identity = identity
+	}
+	log.Printf("Identity added %s", identity)
+	if identity != "" && modem.identity == "" {
+		modem.identity = identity
+		modem.IdentityAdded <- identity
+	}
+}
+
+func (modem *Modem) updatePushInterfaceState(interfaces dbus.Variant) {
+	origState := modem.pushInterfaceAvailable
+	availableInterfaces := reflect.ValueOf(interfaces.Value)
+	for i := 0; i < availableInterfaces.Len(); i++ {
+		interfaceName := reflect.ValueOf(availableInterfaces.Index(i).Interface().(string)).String()
+		if interfaceName == PUSH_NOTIFICATION_INTERFACE {
+			modem.pushInterfaceAvailable = true
+			break
+		}
+	}
+	if modem.pushInterfaceAvailable != origState {
+		log.Printf("Push interface state: %t", modem.pushInterfaceAvailable)
+		if modem.pushInterfaceAvailable {
+			modem.PushInterfaceAvailable <- true
+		} else if modem.PushAgent.Registered {
+			modem.PushInterfaceAvailable <- false
+		}
+	}
 }
 
 func getOfonoProps(obj *dbus.ObjectProxy, iface, method string) (oProps []OfonoContext, err error) {
@@ -243,7 +264,7 @@
 //Returns either the type=internet context or the type=mms, if none is found
 //an error is returned.
 func (modem *Modem) GetMMSContext() (OfonoContext, error) {
-	rilObj := modem.conn.Object("org.ofono", modem.modem)
+	rilObj := modem.conn.Object("org.ofono", modem.Modem)
 	contexts, err := getOfonoProps(rilObj, CONNECTION_MANAGER_INTERFACE, "GetContexts")
 	if err != nil {
 		return OfonoContext{}, err
@@ -282,150 +303,26 @@
 
 func (modem *Modem) getProperty(interfaceName, propertyName string) (*dbus.Variant, error) {
 	errorString := "Cannot retrieve %s from %s for %s: %s"
-	rilObj := modem.conn.Object(OFONO_SENDER, modem.modem)
+	rilObj := modem.conn.Object(OFONO_SENDER, modem.Modem)
 	if reply, err := rilObj.Call(interfaceName, "GetProperties"); err == nil {
 		var property PropertiesType
 		if err := reply.Args(&property); err != nil {
-			return nil, fmt.Errorf(errorString, propertyName, interfaceName, modem.modem, err)
+			return nil, fmt.Errorf(errorString, propertyName, interfaceName, modem.Modem, err)
 		}
 		if v, ok := property[propertyName]; ok {
 			return &v, nil
 		}
-		return nil, fmt.Errorf(errorString, propertyName, interfaceName, modem.modem, "property not found")
+		return nil, fmt.Errorf(errorString, propertyName, interfaceName, modem.Modem, "property not found")
 	} else {
-		return nil, fmt.Errorf(errorString, propertyName, interfaceName, modem.modem, err)
-	}
-}
-
-func (modem *Modem) GetIdentity() error {
-	if v, err := modem.getProperty(SIM_MANAGER_INTERFACE, "SubscriberIdentity"); err == nil {
-		modem.identity = reflect.ValueOf(v.Value).String()
-		if modem.identity != "" {
-			log.Print("Updating id ", modem.identity)
-			modem.IdentityAdded <- modem.identity
-		}
-	}
-	propSimSignal, err := connectToPropertySignal(modem.conn, modem.modem, SIM_MANAGER_INTERFACE)
-	if err != nil {
-		return err
-	}
-	go func() {
-		var propName string
-		var propValue dbus.Variant
-		for msg := range propSimSignal.C {
-			if err := msg.Args(&propName, &propValue); err != nil {
-				log.Print(err)
-				continue
-			}
-			if propName != "SubscriberIdentity" {
-				continue
-			}
-			identity := reflect.ValueOf(propValue.Value).String()
-			if identity == "" && modem.identity != "" {
-				fmt.Println("Identity before remove", modem.identity)
-
-				modem.IdentityRemoved <- identity
-				modem.identity = identity
-			}
-			fmt.Println("Identity before add", modem.identity)
-			if identity != "" && modem.identity == "" {
-				//wait for the push interface to be available
-				modem.identity = identity
-				modem.IdentityAdded <- identity
-			}
-		}
-	}()
-	return nil
-}
-
-func (modem *Modem) RegisterAgent() error {
-	if modem.agentRegistered {
-		log.Print("Agent already registered")
-		return nil
-	}
-	//it seems that ofono is still doing stuff after advertising the interface as available
-	//we will need to sleep a bit
-	log.Print("Registering Agent for", modem.modem, " on path ", AGENT_TAG)
-	obj := modem.conn.Object("org.ofono", modem.modem)
-	_, err := obj.Call(PUSH_NOTIFICATION_INTERFACE, "RegisterAgent", AGENT_TAG)
-	if err != nil {
-		return fmt.Errorf("Cannot register agent for %s: %s", modem.modem, err)
-	}
-	modem.agentRegistered = true
-	modem.PushChannel = make(chan *PushPDU)
-	modem.messageChannel = make(chan *dbus.Message)
-	go modem.watchDBusMethodCalls()
-	modem.conn.RegisterObjectPath(AGENT_TAG, modem.messageChannel)
-	log.Print("Agent Registered for ", modem.modem, " on path ", AGENT_TAG)
-	return nil
-}
-
-func (modem *Modem) UnregisterAgent() error {
-	log.Print("Unregistering agent on ", modem.modem)
-	obj := modem.conn.Object("org.ofono", modem.modem)
-	_, err := obj.Call(PUSH_NOTIFICATION_INTERFACE, "UnregisterAgent", AGENT_TAG)
-	if err != nil {
-		log.Print("Unregister failed ", err)
-		return err
-	}
-	modem.Reset()
-	return nil
-}
-
-func (modem *Modem) Reset() {
-	log.Print("Resetting modem")
-	modem.conn.UnregisterObjectPath(AGENT_TAG)
-	modem.agentRegistered = false
-	close(modem.PushChannel)
-	modem.PushChannel = nil
-	close(modem.messageChannel)
-	modem.messageChannel = nil
+		return nil, fmt.Errorf(errorString, propertyName, interfaceName, modem.Modem, err)
+	}
+}
+
+func (modem *Modem) Delete() {
 	modem.IdentityRemoved <- modem.identity
-	modem.identity = ""
-	modem.ready = false
-}
-
-func (modem *Modem) watchDBusMethodCalls() {
-	var reply *dbus.Message
-	for msg := range modem.messageChannel {
-		switch {
-		case msg.Interface == PUSH_NOTIFICATION_AGENT_INTERFACE && msg.Member == "ReceiveNotification":
-			reply = modem.notificationReceived(msg)
-		case msg.Interface == PUSH_NOTIFICATION_AGENT_INTERFACE && msg.Member == "Release":
-			log.Print("Received Release")
-			reply = dbus.NewMethodReturnMessage(msg)
-			fmt.Println("Identity before reset", modem.identity)
-			modem.Reset()
-		default:
-			log.Print("Received unkown method call on", msg.Interface, msg.Member)
-			reply = dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")
-		}
-		if err := modem.conn.Send(reply); err != nil {
-			log.Print("Could not send reply: ", err)
-		}
-	}
-}
-
-func (modem *Modem) notificationReceived(msg *dbus.Message) (reply *dbus.Message) {
-	var push OfonoPushNotification
-	if err := msg.Args(&(push.Data), &(push.Info)); err != nil {
-		log.Print("Error in received ReceiveNotification() method call ", msg)
-		return dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error", "FormatError")
-	} else {
-		log.Print("Received ReceiveNotification() method call from ", push.Info["Sender"].Value)
-		log.Print("Push data\n", hex.Dump(push.Data))
-		dec := NewDecoder(push.Data)
-		pdu := new(PushPDU)
-		if err := dec.Decode(pdu); err != nil {
-			log.Print("Error ", err)
-			return dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error", "DecodeError")
-		}
-		// TODO later switch on ApplicationId and ContentType to different channels
-		if pdu.ApplicationId == 0x04 && pdu.ContentType == "application/vnd.wap.mms-message" {
-			modem.PushChannel <- pdu
-		} else {
-			log.Print("Unhandled push pdu", pdu)
-		}
-		return dbus.NewMethodReturnMessage(msg)
-	}
+	modem.modemSignal.Cancel()
+	modem.modemSignal.C = nil
+	modem.simSignal.Cancel()
+	modem.simSignal.C = nil
+	modem.endWatch <- true
 }

=== added file 'ofono/pushagent.go'
--- ofono/pushagent.go	1970-01-01 00:00:00 +0000
+++ ofono/pushagent.go	2014-05-12 13:50:54 +0000
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2014 Canonical Ltd.
+ *
+ * Authors:
+ * Sergio Schvezov: sergio.schvezov@cannical.com
+ *
+ * This file is part of nuntium.
+ *
+ * nuntium is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * nuntium 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 ofono
+
+import (
+	"encoding/hex"
+	"fmt"
+	"log"
+	"sync"
+
+	"launchpad.net/go-dbus/v1"
+)
+
+/*
+ in = "aya{sv}", out = ""
+*/
+type OfonoPushNotification struct {
+	Data []byte
+	Info map[string]*dbus.Variant
+}
+
+type PushAgent struct {
+	conn           *dbus.Connection
+	modem          dbus.ObjectPath
+	Push           chan *PushPDU
+	messageChannel chan *dbus.Message
+	Registered     bool
+	m              sync.Mutex
+}
+
+func NewPushAgent(modem dbus.ObjectPath) *PushAgent {
+	return &PushAgent{modem: modem}
+}
+
+func (agent *PushAgent) Register() (err error) {
+	agent.m.Lock()
+	defer agent.m.Unlock()
+	if agent.conn == nil {
+		if agent.conn, err = dbus.Connect(dbus.SystemBus); err != nil {
+			return err
+		}
+	}
+	if agent.Registered {
+		log.Printf("Agent already registered for %s", agent.modem)
+		return nil
+	}
+	agent.Registered = true
+	log.Print("Registering agent for ", agent.modem, " on path ", AGENT_TAG, " and name ", agent.conn.UniqueName)
+	obj := agent.conn.Object("org.ofono", agent.modem)
+	_, err = obj.Call(PUSH_NOTIFICATION_INTERFACE, "RegisterAgent", AGENT_TAG)
+	if err != nil {
+		return fmt.Errorf("Cannot register agent for %s: %s", agent.modem, err)
+	}
+	agent.Push = make(chan *PushPDU)
+	agent.messageChannel = make(chan *dbus.Message)
+	go agent.watchDBusMethodCalls()
+	agent.conn.RegisterObjectPath(AGENT_TAG, agent.messageChannel)
+	log.Print("Agent Registered for ", agent.modem, " on path ", AGENT_TAG)
+	return nil
+}
+
+func (agent *PushAgent) Unregister() error {
+	agent.m.Lock()
+	defer agent.m.Unlock()
+	if !agent.Registered {
+		log.Print("Agent no registered for %s", agent.modem)
+		return nil
+	}
+	log.Print("Unregistering agent on ", agent.modem)
+	obj := agent.conn.Object("org.ofono", agent.modem)
+	_, err := obj.Call(PUSH_NOTIFICATION_INTERFACE, "UnregisterAgent", AGENT_TAG)
+	if err != nil {
+		log.Print("Unregister failed ", err)
+		return err
+	}
+	agent.release()
+	agent.modem = dbus.ObjectPath("")
+	return nil
+}
+
+func (agent *PushAgent) release() {
+	agent.Registered = false
+	//BUG this seems to not return, but I can't close the channel or panic
+	agent.conn.UnregisterObjectPath(AGENT_TAG)
+	close(agent.Push)
+	agent.Push = nil
+	close(agent.messageChannel)
+	agent.messageChannel = nil
+}
+
+func (agent *PushAgent) watchDBusMethodCalls() {
+	var reply *dbus.Message
+	for msg := range agent.messageChannel {
+		switch {
+		case msg.Interface == PUSH_NOTIFICATION_AGENT_INTERFACE && msg.Member == "ReceiveNotification":
+			reply = agent.notificationReceived(msg)
+		case msg.Interface == PUSH_NOTIFICATION_AGENT_INTERFACE && msg.Member == "Release":
+			log.Printf("Push Agent on %s received Release", agent.modem)
+			reply = dbus.NewMethodReturnMessage(msg)
+			agent.release()
+		default:
+			log.Print("Received unkown method call on", msg.Interface, msg.Member)
+			reply = dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")
+		}
+		if err := agent.conn.Send(reply); err != nil {
+			log.Print("Could not send reply: ", err)
+		}
+	}
+}
+
+func (agent *PushAgent) notificationReceived(msg *dbus.Message) (reply *dbus.Message) {
+	var push OfonoPushNotification
+	if err := msg.Args(&(push.Data), &(push.Info)); err != nil {
+		log.Print("Error in received ReceiveNotification() method call ", msg)
+		return dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error", "FormatError")
+	} else {
+		log.Print("Received ReceiveNotification() method call from ", push.Info["Sender"].Value)
+		log.Print("Push data\n", hex.Dump(push.Data))
+		dec := NewDecoder(push.Data)
+		pdu := new(PushPDU)
+		if err := dec.Decode(pdu); err != nil {
+			log.Print("Error ", err)
+			return dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error", "DecodeError")
+		}
+		// TODO later switch on ApplicationId and ContentType to different channels
+		if pdu.ApplicationId == 0x04 && pdu.ContentType == "application/vnd.wap.mms-message" {
+			agent.Push <- pdu
+		} else {
+			log.Print("Unhandled push pdu", pdu)
+		}
+		return dbus.NewMethodReturnMessage(msg)
+	}
+}

