You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2017/08/04 21:41:14 UTC

[mynewt-newtmgr] 05/05: newtmgr - revendor

This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newtmgr.git

commit 90663a0c1bef1fbe387fb0482a6c8fb32ceaadde
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Fri Aug 4 14:14:29 2017 -0700

    newtmgr - revendor
---
 newtmgr/Godeps/Godeps.json                         | 56 ++++++-------
 .../newtmgr/nmxact/bledefs/bledefs.go              | 14 ++--
 .../newtmgr/nmxact/nmble/ble_sesn.go               |  6 ++
 .../newtmgr/nmxact/nmble/ble_util.go               | 22 ++---
 .../newtmgr/nmxact/nmserial/serial_oic_sesn.go     |  7 ++
 .../newtmgr/nmxact/nmserial/serial_plain_sesn.go   |  7 ++
 .../newtmgr/nmxact/nmxutil/nmxutil.go              | 10 +++
 .../mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go  |  3 +-
 .../newtmgr/nmxact/sesn/sesn_util.go               | 21 +++++
 .../newtmgr/nmxact/udp/udp_oic_sesn.go             |  7 ++
 .../newtmgr/nmxact/udp/udp_plain_sesn.go           |  7 ++
 .../mynewt.apache.org/newtmgr/nmxact/xact/image.go | 98 ++++++++++++++++------
 .../newtmgr/nmxact/xact/{getres.go => res.go}      | 40 +++++++++
 13 files changed, 225 insertions(+), 73 deletions(-)

diff --git a/newtmgr/Godeps/Godeps.json b/newtmgr/Godeps/Godeps.json
index d960ed4..7991e99 100644
--- a/newtmgr/Godeps/Godeps.json
+++ b/newtmgr/Godeps/Godeps.json
@@ -127,73 +127,73 @@
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/adv",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/bledefs",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/mgmt",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmble",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmp",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmserial",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmxutil",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/oic",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/omp",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/scan",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/sesn",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/udp",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/xact",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/xport",
-			"Comment": "mynewt_1_1_0_rc1_tag-6-g01881bf",
-			"Rev": "01881bff3fb90177cffca6f997a93e92e3c6fac9"
+			"Comment": "mynewt_1_1_0_rc1_tag-12-g58826c5",
+			"Rev": "58826c537189524e886a723ef90e7838c9fa9fcb"
 		}
 	]
 }
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/bledefs/bledefs.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/bledefs/bledefs.go
index 4f0b8c9..d19d7e9 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/bledefs/bledefs.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/bledefs/bledefs.go
@@ -44,9 +44,9 @@ const OmpSecSvcUuid = 0xfe18
 const OmpSecReqChrUuid = 0x1000
 const OmpSecRspChrUuid = 0x1001
 
-const GwSvcUuid = "0c08c213-98ed-4e43-a499-7e1137c39567"
-const GwReqChrUuid = "69b8a928-2ab2-487b-923e-54ce53a18bc1"
-const GwRspChrUuid = "bca10aea-5df1-4248-b72b-f52955ad9c88"
+const UnauthSvcUuid = "0c08c213-98ed-4e43-a499-7e1137c39567"
+const UnauthReqChrUuid = "69b8a928-2ab2-487b-923e-54ce53a18bc1"
+const UnauthRspChrUuid = "bca10aea-5df1-4248-b72b-f52955ad9c88"
 
 type BleAddrType int
 
@@ -814,8 +814,8 @@ type BleMgmtChrs struct {
 	NmpRspChr        *BleChrId
 	ResPublicReqChr  *BleChrId
 	ResPublicRspChr  *BleChrId
-	ResGwReqChr      *BleChrId
-	ResGwRspChr      *BleChrId
-	ResPrivateReqChr *BleChrId
-	ResPrivateRspChr *BleChrId
+	ResUnauthReqChr  *BleChrId
+	ResUnauthRspChr  *BleChrId
+	ResSecureReqChr *BleChrId
+	ResSecureRspChr *BleChrId
 }
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_sesn.go
index 0918e58..63e0d96 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_sesn.go
@@ -340,3 +340,9 @@ func (s *BleSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 
 	return rsp.Code(), rsp.Payload(), nil
 }
+
+func (s *BleSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte, opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("SerialPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_util.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_util.go
index 2630536..b620d78 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_util.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_util.go
@@ -715,9 +715,9 @@ func GenCoapService(x *BleXport, svcUuid BleUuid, reqChrUuid BleUuid,
 }
 
 func GwService(x *BleXport) (BleSvc, error) {
-	svcUuid, _ := ParseUuid(GwSvcUuid)
-	reqChrUuid, _ := ParseUuid(GwReqChrUuid)
-	rspChrUuid, _ := ParseUuid(GwRspChrUuid)
+	svcUuid, _ := ParseUuid(UnauthSvcUuid)
+	reqChrUuid, _ := ParseUuid(UnauthReqChrUuid)
+	rspChrUuid, _ := ParseUuid(UnauthRspChrUuid)
 
 	resources := []oic.Resource{
 		oic.Resource{
@@ -733,9 +733,9 @@ func GwService(x *BleXport) (BleSvc, error) {
 
 func ResChrIdLookup(mgmtChrs BleMgmtChrs, resType sesn.ResourceType) *BleChrId {
 	m := map[sesn.ResourceType]*BleChrId{
-		sesn.RES_TYPE_PUBLIC:  mgmtChrs.ResPublicReqChr,
-		sesn.RES_TYPE_UNAUTH: mgmtChrs.ResGwReqChr,
-		sesn.RES_TYPE_SECURE: mgmtChrs.ResPrivateReqChr,
+		sesn.RES_TYPE_PUBLIC: mgmtChrs.ResPublicReqChr,
+		sesn.RES_TYPE_UNAUTH: mgmtChrs.ResUnauthReqChr,
+		sesn.RES_TYPE_SECURE: mgmtChrs.ResSecureReqChr,
 	}
 
 	return m[resType]
@@ -751,9 +751,9 @@ func BuildMgmtChrs(mgmtProto sesn.MgmtProto) (BleMgmtChrs, error) {
 	ompReqChrUuid, _ := ParseUuid(OmpUnsecReqChrUuid)
 	ompRspChrUuid, _ := ParseUuid(OmpUnsecRspChrUuid)
 
-	gwSvcUuid, _ := ParseUuid(GwSvcUuid)
-	gwReqChrUuid, _ := ParseUuid(GwReqChrUuid)
-	gwRspChrUuid, _ := ParseUuid(GwRspChrUuid)
+	unauthSvcUuid, _ := ParseUuid(UnauthSvcUuid)
+	unauthReqChrUuid, _ := ParseUuid(UnauthReqChrUuid)
+	unauthRspChrUuid, _ := ParseUuid(UnauthRspChrUuid)
 
 	switch mgmtProto {
 	case sesn.MGMT_PROTO_NMP:
@@ -769,8 +769,8 @@ func BuildMgmtChrs(mgmtProto sesn.MgmtProto) (BleMgmtChrs, error) {
 			fmt.Errorf("invalid management protocol: %+v", mgmtProto)
 	}
 
-	mgmtChrs.ResGwReqChr = &BleChrId{gwSvcUuid, gwReqChrUuid}
-	mgmtChrs.ResGwRspChr = &BleChrId{gwSvcUuid, gwRspChrUuid}
+	mgmtChrs.ResUnauthReqChr = &BleChrId{unauthSvcUuid, unauthReqChrUuid}
+	mgmtChrs.ResUnauthRspChr = &BleChrId{unauthSvcUuid, unauthRspChrUuid}
 
 	return mgmtChrs, nil
 }
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_oic_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_oic_sesn.go
index 8279065..f97655e 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_oic_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_oic_sesn.go
@@ -183,3 +183,10 @@ func (sos *SerialOicSesn) GetResourceOnce(resType sesn.ResourceType,
 		}
 	}
 }
+
+func (sos *SerialOicSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("SerialOicSesn.PutResourceOnce() unsupported")
+}
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_plain_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_plain_sesn.go
index 5f219da..c6a88db 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_plain_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmserial/serial_plain_sesn.go
@@ -162,3 +162,10 @@ func (sps *SerialPlainSesn) GetResourceOnce(resType sesn.ResourceType,
 
 	return 0, nil, fmt.Errorf("SerialPlainSesn.GetResourceOnce() unsupported")
 }
+
+func (sps *SerialPlainSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("SerialPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmxutil/nmxutil.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmxutil/nmxutil.go
index d95c368..ff1e5f8 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmxutil/nmxutil.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmxutil/nmxutil.go
@@ -116,6 +116,16 @@ func DecodeCborMap(cbor []byte) (map[string]interface{}, error) {
 	return m, nil
 }
 
+func EncodeCborMap(value map[string]interface{}) ([]byte, error) {
+	b := []byte{}
+	enc := codec.NewEncoderBytes(&b, new(codec.CborHandle))
+	if err := enc.Encode(value); err != nil {
+		return nil, fmt.Errorf("failure encoding cbor; %s", err.Error())
+	}
+
+	return b, nil
+}
+
 var nextId uint32
 
 func GetNextId() uint32 {
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
index 8db9438..0c7507f 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
@@ -97,5 +97,6 @@ type Sesn interface {
 	GetResourceOnce(resType ResourceType, uri string, opt TxOptions) (
 		coap.COAPCode, []byte, error)
 
-	//SetResource(uri string, value []byte, opt TxOptions) error
+	PutResourceOnce(resType ResourceType, uri string,
+		value []byte, opt TxOptions) (coap.COAPCode, error)
 }
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn_util.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn_util.go
index 6399ee9..a66aed6 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn_util.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn_util.go
@@ -55,3 +55,24 @@ func GetResource(s Sesn, resType ResourceType, uri string, o TxOptions) (
 		}
 	}
 }
+
+func PutResource(s Sesn, resType ResourceType, uri string,
+	value map[string]interface{}, o TxOptions) (coap.COAPCode, error) {
+
+	b, err := nmxutil.EncodeCborMap(value)
+	if err != nil {
+		return 0, err
+	}
+
+	retries := o.Tries - 1
+	for i := 0; ; i++ {
+		code, err := s.PutResourceOnce(resType, uri, b, o)
+		if err == nil {
+			return code, nil
+		}
+
+		if !nmxutil.IsRspTimeout(err) || i >= retries {
+			return code, err
+		}
+	}
+}
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_oic_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_oic_sesn.go
index 9690221..9244048 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_oic_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_oic_sesn.go
@@ -176,3 +176,10 @@ func (uos *UdpOicSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 		}
 	}
 }
+
+func (uos *UdpOicSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("UdpOicSesn.PutResourceOnce() unsupported")
+}
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_plain_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_plain_sesn.go
index 4f79310..e6265f1 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_plain_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/udp/udp_plain_sesn.go
@@ -139,3 +139,10 @@ func (ups *UdpPlainSesn) GetResourceOnce(resType sesn.ResourceType,
 
 	return 0, nil, fmt.Errorf("UdpPlainSesn.GetResourceOnce() unsupported")
 }
+
+func (ups *UdpPlainSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("UdpPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
index 3787560..2fd2d9c 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
@@ -34,6 +34,7 @@ type ImageUploadProgressFn func(c *ImageUploadCmd, r *nmp.ImageUploadRsp)
 type ImageUploadCmd struct {
 	CmdBase
 	Data       []byte
+	StartOff   int
 	ProgressCb ImageUploadProgressFn
 }
 
@@ -117,7 +118,7 @@ func nextImageUploadReq(s sesn.Sesn, data []byte, off int) (
 func (c *ImageUploadCmd) Run(s sesn.Sesn) (Result, error) {
 	res := newImageUploadResult()
 
-	for off := 0; off < len(c.Data); {
+	for off := c.StartOff; off < len(c.Data); {
 		r, err := nextImageUploadReq(s, c.Data, off)
 		if err != nil {
 			return nil, err
@@ -150,8 +151,8 @@ func (c *ImageUploadCmd) Run(s sesn.Sesn) (Result, error) {
 
 // Image upgrade combines the image erase and image upload commands into a
 // single command.  Some hardware and / or BLE connection settings cause the
-// connection to drop during the initial erase.  The image upgrade command
-// addresses this issue with the following sequence:
+// connection to drop while flash is being erased or written to.  The image
+// upgrade command addresses this issue with the following sequence:
 // 1. Send image erase command.
 // 2. If the image erase command succeeded, proceed to step 5.
 // 3. Else if the peer is disconnected, attempt to reconnect to the peer.  If
@@ -159,7 +160,8 @@ func (c *ImageUploadCmd) Run(s sesn.Sesn) (Result, error) {
 //    the reconnect attempt succeeded, proceed to step 5.
 // 4. Else (the erase command failed and the peer is still connected), proceed
 //    to step 5.
-// 5. Execute the upload command.
+// 5. Execute the upload command.  If the connection drops before the final
+//    part is uploaded, reconnect and retry the previous part.
 
 type ImageUpgradeCmd struct {
 	CmdBase
@@ -192,36 +194,80 @@ func (r *ImageUpgradeResult) Status() int {
 	}
 }
 
-func (c *ImageUpgradeCmd) Run(s sesn.Sesn) (Result, error) {
-	upgradeRes := newImageUpgradeResult()
+// Attempts to recover from a disconnect.
+func (c *ImageUpgradeCmd) rescue(s sesn.Sesn, err error) error {
+	if err != nil {
+		if !s.IsOpen() {
+			if err := s.Open(); err == nil {
+				return nil
+			}
+		}
+	}
+
+	return err
+}
 
-	eraseCmd := NewImageEraseCmd()
-	res, err := eraseCmd.Run(s)
+func (c *ImageUpgradeCmd) runErase(s sesn.Sesn) (*ImageEraseResult, error) {
+	cmd := NewImageEraseCmd()
+	res, err := cmd.Run(s)
 
-	if res != nil {
-		upgradeRes.EraseRes = res.(*ImageEraseResult)
+	if err := c.rescue(s, err); err != nil {
+		return nil, err
 	}
-	if err != nil || res.Status() != 0 {
-		// If the erase command failed and the peer is no longer connected, the
-		// disconnect could have been caused by a stall in the destination
-		// device's processor.  In this case, the erase command succeeded.  Try
-		// to recover by reconnecting.
-		if !s.IsOpen() {
-			if err := s.Open(); err != nil {
-				return upgradeRes, err
-			}
+
+	if res == nil {
+		// We didn't get a response back but we rescued ourselves from the
+		// disconnect.
+		res = newImageEraseResult()
+	}
+
+	return res.(*ImageEraseResult), nil
+}
+
+func (c *ImageUpgradeCmd) runUpload(s sesn.Sesn) (*ImageUploadResult, error) {
+	startOff := 0
+	progressCb := func(uc *ImageUploadCmd, r *nmp.ImageUploadRsp) {
+		if r.Rc == 0 {
+			startOff = int(r.Off)
 		}
+		c.ProgressCb(uc, r)
 	}
 
-	uploadCmd := NewImageUploadCmd()
-	uploadCmd.Data = c.Data
-	uploadCmd.ProgressCb = c.ProgressCb
-	res, err = uploadCmd.Run(s)
+	for {
+		cmd := NewImageUploadCmd()
+		cmd.Data = c.Data
+		cmd.StartOff = startOff
+		cmd.ProgressCb = progressCb
+
+		res, err := cmd.Run(s)
+		if err == nil {
+			return res.(*ImageUploadResult), nil
+		}
+
+		if err := c.rescue(s, err); err != nil {
+			// Disconnected and couldn't recover.
+			return nil, err
+		}
 
-	if res != nil {
-		upgradeRes.UploadRes = res.(*ImageUploadResult)
+		// Disconnected but recovered; retry last part.
 	}
-	return upgradeRes, err
+}
+
+func (c *ImageUpgradeCmd) Run(s sesn.Sesn) (Result, error) {
+	eres, err := c.runErase(s)
+	if err != nil {
+		return nil, err
+	}
+
+	ures, err := c.runUpload(s)
+	if err != nil {
+		return nil, err
+	}
+
+	upgradeRes := newImageUpgradeResult()
+	upgradeRes.EraseRes = eres
+	upgradeRes.UploadRes = ures
+	return upgradeRes, nil
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/getres.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/res.go
similarity index 70%
rename from newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/getres.go
rename to newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/res.go
index e56067d..6cfa47e 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/getres.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/res.go
@@ -65,3 +65,43 @@ func (c *GetResCmd) Run(s sesn.Sesn) (Result, error) {
 	res.Value = val
 	return res, nil
 }
+
+type PutResCmd struct {
+	CmdBase
+	Uri   string
+	Typ   sesn.ResourceType
+	Value map[string]interface{}
+}
+
+func NewPutResCmd() *PutResCmd {
+	return &PutResCmd{
+		CmdBase: NewCmdBase(),
+	}
+}
+
+type PutResResult struct {
+	Code coap.COAPCode
+}
+
+func newPutResResult() *PutResResult {
+	return &PutResResult{}
+}
+
+func (r *PutResResult) Status() int {
+	if r.Code == coap.Content {
+		return 0
+	} else {
+		return int(r.Code)
+	}
+}
+
+func (c *PutResCmd) Run(s sesn.Sesn) (Result, error) {
+	status, err := sesn.PutResource(s, c.Typ, c.Uri, c.Value, c.TxOptions())
+	if err != nil {
+		return nil, err
+	}
+
+	res := newPutResResult()
+	res.Code = status
+	return res, nil
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@mynewt.apache.org" <co...@mynewt.apache.org>.