[Merge] lp:~sergiusens/nuntium/message-api into lp:nuntium
Sergio Schvezov
sergio.schvezov at canonical.com
Wed Jul 2 13:06:11 UTC 2014
Fixed, comments inline
Diff comments:
> === modified file 'mediator.go'
> --- mediator.go 2014-07-01 12:24:38 +0000
> +++ mediator.go 2014-07-01 12:24:38 +0000
> @@ -41,7 +41,7 @@
> NewMSendReq chan *mms.MSendReq
> NewMRetrieveConfFile chan string
> NewMNotifyRespIndFile chan string
> - NewMSendReqFile chan string
> + NewMSendReqFile chan struct{ filePath, uuid string }
> outMessage chan *telepathy.OutgoingMessage
> terminate chan bool
> }
> @@ -62,7 +62,7 @@
> mediator.NewMNotifyRespInd = make(chan *mms.MNotifyRespInd)
> mediator.NewMNotifyRespIndFile = make(chan string)
> mediator.NewMSendReq = make(chan *mms.MSendReq)
> - mediator.NewMSendReqFile = make(chan string)
> + mediator.NewMSendReqFile = make(chan struct{ filePath, uuid string })
> mediator.outMessage = make(chan *telepathy.OutgoingMessage)
> mediator.terminate = make(chan bool)
> return mediator
> @@ -100,8 +100,8 @@
> go mediator.handleOutgoingMessage(msg)
> case mSendReq := <-mediator.NewMSendReq:
> go mediator.handleMSendReq(mSendReq)
> - case mSendReqFilePath := <-mediator.NewMSendReqFile:
> - go mediator.sendMSendReq(mSendReqFilePath)
> + case mSendReqFile := <-mediator.NewMSendReqFile:
> + go mediator.sendMSendReq(mSendReqFile.filePath, mSendReqFile.uuid)
> case id := <-mediator.modem.IdentityAdded:
> var err error
> mediator.telepathyService, err = mmsManager.AddService(id, mediator.outMessage, useDeliveryReports)
> @@ -256,8 +256,10 @@
> cts = append(cts, ct)
> }
> mSendReq := mms.NewMSendReq(msg.Recipients, cts)
> - //TODO
> - mediator.telepathyService.ReplySendMessage(msg.Reply, mSendReq.UUID)
> + if _, err := mediator.telepathyService.ReplySendMessage(msg.Reply, mSendReq.UUID); err != nil {
> + log.Print(err)
> + return
> + }
> mediator.NewMSendReq <- mSendReq
> }
>
> @@ -272,17 +274,28 @@
> enc := mms.NewEncoder(f)
> if err := enc.Encode(mSendReq); err != nil {
> log.Print("Unable to encode m-send.req for ", mSendReq.UUID)
> + if err := mediator.telepathyService.MessageStatusChanged(mSendReq.UUID, telepathy.PERMANENT_ERROR); err != nil {
> + log.Println(err)
> + }
> return
> }
> filePath := f.Name()
> log.Printf("Created %s to handle m-send.req for %s", filePath, mSendReq.UUID)
> - mediator.NewMSendReqFile <- filePath
> + mediator.sendMSendReq(filePath, mSendReq.UUID)
> }
>
> -func (mediator *Mediator) sendMSendReq(mSendReqFile string) {
> +func (mediator *Mediator) sendMSendReq(mSendReqFile, uuid string) {
> defer os.Remove(mSendReqFile)
> + defer mediator.telepathyService.MessageDestroy(uuid)
> if err := mediator.uploadFile(mSendReqFile); err != nil {
> + if err := mediator.telepathyService.MessageStatusChanged(uuid, telepathy.TRANSIENT_ERROR); err != nil {
> + log.Println(err)
> + }
> log.Printf("Cannot upload m-send.req encoded file %s to message center: %s", mSendReqFile, err)
> + return
> + }
> + if err := mediator.telepathyService.MessageStatusChanged(uuid, telepathy.SENT); err != nil {
> + log.Println(err)
> }
> }
>
>
> === modified file 'storage/storage.go'
> --- storage/storage.go 2014-07-01 12:24:38 +0000
> +++ storage/storage.go 2014-07-01 12:24:38 +0000
> @@ -44,6 +44,24 @@
> return writeState(state, storePath)
> }
>
> +func Destroy(uuid string) error {
> + if storePath, err := xdg.Data.Ensure(path.Join(SUBPATH, uuid+".db")); err == nil {
> + if err := os.Remove(storePath); err != nil {
> + return err
> + }
> + } else {
> + return err
> + }
> + if mmsPath, err := GetMMS(uuid); err == nil {
> + if err := os.Remove(mmsPath); err != nil {
> + return err
> + }
> + } else {
> + return err
> + }
> + return nil
> +}
> +
> func CreateResponseFile(uuid string) (*os.File, error) {
> filePath, err := xdg.Cache.Ensure(path.Join(SUBPATH, uuid+".m-notifyresp.ind"))
> if err != nil {
>
> === modified file 'telepathy/const.go'
> --- telepathy/const.go 2014-04-04 19:54:59 +0000
> +++ telepathy/const.go 2014-07-01 12:24:38 +0000
> @@ -24,6 +24,7 @@
> const (
> MMS_DBUS_NAME = "org.ofono.mms"
> MMS_DBUS_PATH = "/org/ofono/mms"
> + MMS_MESSAGE_DBUS_IFACE = "org.ofono.mms.Message"
> MMS_SERVICE_DBUS_IFACE = "org.ofono.mms.Service"
> MMS_MANAGER_DBUS_IFACE = "org.ofono.mms.Manager"
> )
> @@ -32,8 +33,17 @@
> IDENTITY = "Identity"
> USE_DELIVERY_REPORTS = "UseDeliveryReports"
> MESSAGE_ADDED = "MessageAdded"
> + MESSAGE_REMOVED = "MessageRemoved"
> SERVICE_ADDED = "ServiceAdded"
> SERVICE_REMOVED = "ServiceRemoved"
> + PROPERTY_CHANGED = "PropertyChanged"
> + STATUS = "Status"
> +)
> +
> +const (
> + PERMANENT_ERROR = "PermanentError"
> + SENT = "Sent"
> + TRANSIENT_ERROR = "TransientError"
> )
>
> const (
>
> === added file 'telepathy/message.go'
> --- telepathy/message.go 1970-01-01 00:00:00 +0000
> +++ telepathy/message.go 2014-07-01 12:24:38 +0000
> @@ -0,0 +1,104 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * Authors:
> + * Sergio Schvezov: sergio.schvezov at cannical.com
> + *
> + * This file is part of telepathy.
> + *
> + * mms 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.
> + *
> + * mms 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 telepathy
> +
> +import (
> + "fmt"
> + "log"
> +
> + "launchpad.net/go-dbus/v1"
> +)
> +
> +type MessageInterface struct {
> + conn *dbus.Connection
> + objectPath dbus.ObjectPath
> + msgChan chan *dbus.Message
> + deleteChan chan dbus.ObjectPath
> + status string
> +}
> +
> +func NewMessageInterface(conn *dbus.Connection, objectPath dbus.ObjectPath, deleteChan chan dbus.ObjectPath) *MessageInterface {
> + msgInterface := MessageInterface{
> + conn: conn,
> + objectPath: objectPath,
> + deleteChan: deleteChan,
> + msgChan: make(chan *dbus.Message),
> + }
> + go msgInterface.watchDBusMethodCalls()
> + conn.RegisterObjectPath(msgInterface.objectPath, msgInterface.msgChan)
> + return &msgInterface
> +}
> +
> +func (msgInterface *MessageInterface) Close() {
> + close(msgInterface.msgChan)
> + msgInterface.msgChan = nil
> + msgInterface.conn.UnregisterObjectPath(msgInterface.objectPath)
> +}
> +
> +func (msgInterface *MessageInterface) watchDBusMethodCalls() {
> + var reply *dbus.Message
> +
> + for msg := range msgInterface.msgChan {
> + if msg.Interface != MMS_MESSAGE_DBUS_IFACE {
> + log.Println("Received unkown method call on", msg.Interface, msg.Member)
> + reply = dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")
> + continue
> + }
> + switch msg.Member {
> + case "Delete":
> + reply = dbus.NewMethodReturnMessage(msg)
> + //TODO implement store and forward
> + if err := msgInterface.conn.Send(reply); err != nil {
> + log.Println("Could not send reply:", err)
> + }
> + msgInterface.deleteChan <- msgInterface.objectPath
> + default:
> + log.Println("Received unkown method call on", msg.Interface, msg.Member)
> + reply = dbus.NewErrorMessage(msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")
> + if err := msgInterface.conn.Send(reply); err != nil {
> + log.Println("Could not send reply:", err)
> + }
> + }
> + }
> +}
> +
> +func (msgInterface *MessageInterface) StatusChanged(status string) error {
> + var found bool
> + for _, validStatus := range []string{SENT, PERMANENT_ERROR, TRANSIENT_ERROR} {
> + if status == validStatus {
> + found = true
> + break
> + }
> + }
> + if !found {
> + return fmt.Errorf("status %s is not a valid status", status)
> + }
> + msgInterface.status = status
> + signal := dbus.NewSignalMessage(msgInterface.objectPath, MMS_MESSAGE_DBUS_IFACE, PROPERTY_CHANGED)
> + if err := signal.AppendArgs(STATUS, dbus.Variant{status}); err != nil {
> + return err
> + }
> + if err := msgInterface.conn.Send(signal); err != nil {
> + return err
> + }
> + return nil
> +}
I'm using a variation of your proposal (given that sort alone is just the package and not a method ;-))
I opted to use a sort.StringSlice, seemed fancier and less error prone.
>
> === modified file 'telepathy/service.go'
> --- telepathy/service.go 2014-07-01 12:24:38 +0000
> +++ telepathy/service.go 2014-07-01 12:24:38 +0000
> @@ -24,6 +24,7 @@
> import (
> "fmt"
> "log"
> + "path/filepath"
> "strings"
> "time"
>
> @@ -40,12 +41,14 @@
> }
>
> type MMSService struct {
> - Payload ServicePayload
> - Properties map[string]dbus.Variant
> - conn *dbus.Connection
> - msgChan chan *dbus.Message
> - identity string
> - outMessage chan *OutgoingMessage
> + Payload ServicePayload
> + Properties map[string]dbus.Variant
> + conn *dbus.Connection
> + msgChan chan *dbus.Message
> + messageHandlers map[dbus.ObjectPath]*MessageInterface
> + msgDeleteChan chan dbus.ObjectPath
> + identity string
> + outMessage chan *OutgoingMessage
> }
>
> type Attachment struct {
> @@ -78,18 +81,29 @@
> Properties: properties,
> }
> service := MMSService{
> - Payload: payload,
> - Properties: serviceProperties,
> - conn: conn,
> - msgChan: make(chan *dbus.Message),
> - outMessage: outgoingChannel,
> - identity: identity,
> + Payload: payload,
> + Properties: serviceProperties,
> + conn: conn,
> + msgChan: make(chan *dbus.Message),
> + msgDeleteChan: make(chan dbus.ObjectPath),
> + messageHandlers: make(map[dbus.ObjectPath]*MessageInterface),
> + outMessage: outgoingChannel,
> + identity: identity,
> }
> go service.watchDBusMethodCalls()
> + go service.watchMessageDeleteCalls()
> conn.RegisterObjectPath(payload.Path, service.msgChan)
> return &service
> }
>
> +func (service *MMSService) watchMessageDeleteCalls() {
> + for msgObjectPath := range service.msgDeleteChan {
> + if err := service.MessageRemoved(msgObjectPath); err != nil {
> + log.Print("Failed to delete ", msgObjectPath, ": ", err)
> + }
> + }
> +}
> +
> func (service *MMSService) watchDBusMethodCalls() {
> for msg := range service.msgChan {
> var reply *dbus.Message
> @@ -147,6 +161,44 @@
> }
> }
>
> +func getUUIDFromObjectPath(objectPath dbus.ObjectPath) (string, error) {
> + str := string(objectPath)
> + defaultError := fmt.Errorf("%s is not a proper object path for a Message", str)
> + if str == "" {
> + return "", defaultError
> + }
> + uuid := filepath.Base(str)
> + if uuid == "" || uuid == ".." || uuid == "." {
> + return "", defaultError
> + }
> + return uuid, nil
> +}
> +
> +//MessageRemoved emits the MessageRemoved signal with the path of the removed
> +//message.
> +//It also actually removes the message from storage.
> +func (service *MMSService) MessageRemoved(objectPath dbus.ObjectPath) error {
> + service.messageHandlers[objectPath].Close()
> + delete(service.messageHandlers, objectPath)
> +
> + uuid, err := getUUIDFromObjectPath(objectPath)
> + if err != nil {
> + return err
> + }
> + if err := storage.Destroy(uuid); err != nil {
> + return err
> + }
> +
> + signal := dbus.NewSignalMessage(service.Payload.Path, MMS_SERVICE_DBUS_IFACE, MESSAGE_REMOVED)
> + if err := signal.AppendArgs(objectPath); err != nil {
> + return err
> + }
> + if err := service.conn.Send(signal); err != nil {
> + return err
> + }
> + return nil
> +}
> +
> //MessageAdded emits a MessageAdded with the path to the added message which
> //is taken as a parameter
> func (service *MMSService) MessageAdded(mRetConf *mms.MRetrieveConf) error {
> @@ -154,6 +206,7 @@
> if err != nil {
> return err
> }
> + service.messageHandlers[payload.Path] = NewMessageInterface(service.conn, payload.Path, service.msgDeleteChan)
> signal := dbus.NewSignalMessage(service.Payload.Path, MMS_SERVICE_DBUS_IFACE, MESSAGE_ADDED)
> if err := signal.AppendArgs(payload.Path, payload.Properties); err != nil {
> return err
> @@ -175,6 +228,7 @@
> func (service *MMSService) Close() {
> service.conn.UnregisterObjectPath(service.Payload.Path)
> close(service.msgChan)
> + close(service.msgDeleteChan)
> }
>
> func (service *MMSService) parseMessage(mRetConf *mms.MRetrieveConf) (ServicePayload, error) {
> @@ -236,9 +290,31 @@
> return recipients
> }
>
> -func (service *MMSService) ReplySendMessage(reply *dbus.Message, uuid string) error {
> - reply.AppendArgs(service.genMessagePath(uuid))
> - return service.conn.Send(reply)
> +func (service *MMSService) MessageDestroy(uuid string) error {
> + msgObjectPath := service.genMessagePath(uuid)
> + if msgInterface, ok := service.messageHandlers[msgObjectPath]; ok {
> + msgInterface.Close()
> + delete(service.messageHandlers, msgObjectPath)
> + }
> + return fmt.Errorf("no message interface handler for object path %s", msgObjectPath)
> +}
> +
> +func (service *MMSService) MessageStatusChanged(uuid, status string) error {
> + msgObjectPath := service.genMessagePath(uuid)
> + if msgInterface, ok := service.messageHandlers[msgObjectPath]; ok {
> + return msgInterface.StatusChanged(status)
> + }
> + return fmt.Errorf("no message interface handler for object path %s", msgObjectPath)
> +}
> +
> +func (service *MMSService) ReplySendMessage(reply *dbus.Message, uuid string) (dbus.ObjectPath, error) {
> + msgObjectPath := service.genMessagePath(uuid)
> + reply.AppendArgs(msgObjectPath)
> + if err := service.conn.Send(reply); err != nil {
> + return "", err
> + }
> + service.messageHandlers[msgObjectPath] = NewMessageInterface(service.conn, msgObjectPath, service.msgDeleteChan)
> + return msgObjectPath, nil
> }
>
> //TODO randomly creating a uuid until the download manager does this for us
>
--
https://code.launchpad.net/~sergiusens/nuntium/message-api/+merge/225147
Your team Ubuntu Phablet Team is subscribed to branch lp:nuntium.
More information about the Ubuntu-reviews
mailing list