Merge lp:~sergiusens/nuntium/uploads into lp:nuntium
- uploads
- Merge into trunk
Proposed by
Sergio Schvezov
Status: | Merged |
---|---|
Approved by: | Manuel de la Peña |
Approved revision: | 49 |
Merged at revision: | 46 |
Proposed branch: | lp:~sergiusens/nuntium/uploads |
Merge into: | lp:nuntium |
Prerequisite: | lp:~sergiusens/nuntium/telepathy_switch |
Diff against target: |
730 lines (+64/-574) 5 files modified
debian/control (+2/-1) mediator.go (+17/-16) mms/download.go (+37/-4) ofono/modem.go (+8/-1) udm/udm.go (+0/-552) |
To merge this branch: | bzr merge lp:~sergiusens/nuntium/uploads |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Manuel de la Peña (community) | Approve | ||
Review via email:
|
Commit message
Upload support while moving udm to it's new package namespace
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Manuel de la Peña (mandel) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/control' | |||
2 | --- debian/control 2014-05-13 17:06:46 +0000 | |||
3 | +++ debian/control 2014-07-01 12:18:20 +0000 | |||
4 | @@ -10,6 +10,7 @@ | |||
5 | 10 | golang-go-dbus-dev, | 10 | golang-go-dbus-dev, |
6 | 11 | golang-go-xdg-dev, | 11 | golang-go-xdg-dev, |
7 | 12 | golang-gocheck-dev, | 12 | golang-gocheck-dev, |
8 | 13 | golang-udm-dev, | ||
9 | 13 | Standards-Version: 3.9.5 | 14 | Standards-Version: 3.9.5 |
10 | 14 | Homepage: https://launchpad.net/nuntium | 15 | Homepage: https://launchpad.net/nuntium |
11 | 15 | Vcs-Browser: http://bazaar.launchpad.net/~phablet-team/nuntium/trunk/files | 16 | Vcs-Browser: http://bazaar.launchpad.net/~phablet-team/nuntium/trunk/files |
12 | @@ -17,7 +18,7 @@ | |||
13 | 17 | 18 | ||
14 | 18 | Package: nuntium | 19 | Package: nuntium |
15 | 19 | Architecture: any | 20 | Architecture: any |
17 | 20 | Depends: ofono, ubuntu-download-manager, ${misc:Depends}, ${shlibs:Depends} | 21 | Depends: ofono, ubuntu-download-manager, ubuntu-upload-manager, ${misc:Depends}, ${shlibs:Depends} |
18 | 21 | Built-Using: ${misc:Built-Using} | 22 | Built-Using: ${misc:Built-Using} |
19 | 22 | Recommends: telepathy-ofono | 23 | Recommends: telepathy-ofono |
20 | 23 | Conflicts: mmsd | 24 | Conflicts: mmsd |
21 | 24 | 25 | ||
22 | === modified file 'mediator.go' | |||
23 | --- mediator.go 2014-05-12 13:47:34 +0000 | |||
24 | +++ mediator.go 2014-07-01 12:18:20 +0000 | |||
25 | @@ -190,7 +190,9 @@ | |||
26 | 190 | } | 190 | } |
27 | 191 | mediator.NewMRetrieveConf <- mRetrieveConf | 191 | mediator.NewMRetrieveConf <- mRetrieveConf |
28 | 192 | if mediator.telepathyService != nil { | 192 | if mediator.telepathyService != nil { |
30 | 193 | mediator.telepathyService.MessageAdded(mRetrieveConf) | 193 | if err := mediator.telepathyService.MessageAdded(mRetrieveConf); err != nil { |
31 | 194 | log.Println("Cannot notify telepathy-ofono about new message", err) | ||
32 | 195 | } | ||
33 | 194 | } else { | 196 | } else { |
34 | 195 | log.Print("Not sending recently retrieved message") | 197 | log.Print("Not sending recently retrieved message") |
35 | 196 | } | 198 | } |
36 | @@ -226,23 +228,22 @@ | |||
37 | 226 | func (mediator *Mediator) sendMNotifyRespInd(mNotifyRespIndFile string) { | 228 | func (mediator *Mediator) sendMNotifyRespInd(mNotifyRespIndFile string) { |
38 | 227 | defer os.Remove(mNotifyRespIndFile) | 229 | defer os.Remove(mNotifyRespIndFile) |
39 | 228 | if err := mediator.uploadFile(mNotifyRespIndFile); err != nil { | 230 | if err := mediator.uploadFile(mNotifyRespIndFile); err != nil { |
41 | 229 | log.Printf("Cannot upload m-notifyresp.ind encoded file %s to message center", mNotifyRespIndFile) | 231 | log.Printf("Cannot upload m-notifyresp.ind encoded file %s to message center: %s", mNotifyRespIndFile, err) |
42 | 230 | } | 232 | } |
43 | 231 | } | 233 | } |
44 | 232 | 234 | ||
45 | 233 | func (mediator *Mediator) uploadFile(filePath string) error { | 235 | func (mediator *Mediator) uploadFile(filePath string) error { |
60 | 234 | // TODO Upload file part | 236 | mmsContext, err := mediator.modem.ActivateMMSContext() |
61 | 235 | /* | 237 | if err != nil { |
62 | 236 | mmsContext, err := mediator.modem.ActivateMMSContext() | 238 | return err |
63 | 237 | if err != nil { | 239 | } |
64 | 238 | log.Print("Cannot activate ofono context: ", err) | 240 | proxy, err := mmsContext.GetProxy() |
65 | 239 | return | 241 | if err != nil { |
66 | 240 | } | 242 | return err |
67 | 241 | proxy, err := mmsContext.GetProxy() | 243 | } |
68 | 242 | if err != nil { | 244 | msc, err := mmsContext.GetMessageCenter() |
69 | 243 | log.Print("Error retrieving proxy: ", err) | 245 | if err != nil { |
70 | 244 | return | 246 | return err |
71 | 245 | } | 247 | } |
72 | 246 | */ | 248 | return mms.Upload(filePath, msc, proxy.Host, int32(proxy.Port)) |
59 | 247 | return nil | ||
73 | 248 | } | 249 | } |
74 | 249 | 250 | ||
75 | === modified file 'mms/download.go' | |||
76 | --- mms/download.go 2014-04-30 14:24:26 +0000 | |||
77 | +++ mms/download.go 2014-07-01 12:18:20 +0000 | |||
78 | @@ -22,26 +22,27 @@ | |||
79 | 22 | package mms | 22 | package mms |
80 | 23 | 23 | ||
81 | 24 | import ( | 24 | import ( |
82 | 25 | "errors" | ||
83 | 25 | "fmt" | 26 | "fmt" |
84 | 26 | "log" | 27 | "log" |
85 | 27 | "time" | 28 | "time" |
86 | 28 | 29 | ||
88 | 29 | "launchpad.net/nuntium/udm" | 30 | "launchpad.net/udm" |
89 | 30 | ) | 31 | ) |
90 | 31 | 32 | ||
92 | 32 | func (pdu *MNotificationInd) DownloadContent(proxyHostname string, proxyPort int32) (string, error) { | 33 | func (pdu *MNotificationInd) DownloadContent(proxyHost string, proxyPort int32) (string, error) { |
93 | 33 | downloadManager, err := udm.NewDownloadManager() | 34 | downloadManager, err := udm.NewDownloadManager() |
94 | 34 | if err != nil { | 35 | if err != nil { |
95 | 35 | return "", err | 36 | return "", err |
96 | 36 | } | 37 | } |
98 | 37 | download, err := downloadManager.CreateMmsDownload(pdu.ContentLocation, proxyHostname, proxyPort) | 38 | download, err := downloadManager.CreateMmsDownload(pdu.ContentLocation, proxyHost, proxyPort) |
99 | 38 | if err != nil { | 39 | if err != nil { |
100 | 39 | return "", err | 40 | return "", err |
101 | 40 | } | 41 | } |
102 | 41 | f := download.Finished() | 42 | f := download.Finished() |
103 | 42 | p := download.DownloadProgress() | 43 | p := download.DownloadProgress() |
104 | 43 | e := download.Error() | 44 | e := download.Error() |
106 | 44 | log.Print("Starting download") | 45 | log.Print("Starting download of ", pdu.ContentLocation, " with proxy ", proxyHost, ":", proxyPort) |
107 | 45 | download.Start() | 46 | download.Start() |
108 | 46 | for { | 47 | for { |
109 | 47 | select { | 48 | select { |
110 | @@ -57,3 +58,35 @@ | |||
111 | 57 | } | 58 | } |
112 | 58 | } | 59 | } |
113 | 59 | } | 60 | } |
114 | 61 | |||
115 | 62 | func Upload(file, msc, proxyHost string, proxyPort int32) error { | ||
116 | 63 | udm, err := udm.NewUploadManager() | ||
117 | 64 | if err != nil { | ||
118 | 65 | return err | ||
119 | 66 | } | ||
120 | 67 | upload, err := udm.CreateMmsUpload(msc, file, proxyHost, proxyPort) | ||
121 | 68 | if err != nil { | ||
122 | 69 | return err | ||
123 | 70 | } | ||
124 | 71 | f := upload.Finished() | ||
125 | 72 | p := upload.UploadProgress() | ||
126 | 73 | e := upload.Error() | ||
127 | 74 | log.Print("Starting upload of ", file, " to ", msc, " with proxy ", proxyHost, ":", proxyPort) | ||
128 | 75 | if err := upload.Start(); err != nil { | ||
129 | 76 | return err | ||
130 | 77 | } | ||
131 | 78 | |||
132 | 79 | for { | ||
133 | 80 | select { | ||
134 | 81 | case progress := <-p: | ||
135 | 82 | log.Print("Progress:", progress.Total, progress.Received) | ||
136 | 83 | case f := <-f: | ||
137 | 84 | log.Print("File ", f, " uploaded") | ||
138 | 85 | return nil | ||
139 | 86 | case <-time.After(10 * time.Minute): | ||
140 | 87 | return errors.New("upload timeout") | ||
141 | 88 | case err := <-e: | ||
142 | 89 | return err | ||
143 | 90 | } | ||
144 | 91 | } | ||
145 | 92 | } | ||
146 | 60 | 93 | ||
147 | === modified file 'ofono/modem.go' | |||
148 | --- ofono/modem.go 2014-05-13 11:29:13 +0000 | |||
149 | +++ ofono/modem.go 2014-07-01 12:18:20 +0000 | |||
150 | @@ -244,6 +244,14 @@ | |||
151 | 244 | return reflect.ValueOf(oContext.Properties["Active"].Value).Bool() | 244 | return reflect.ValueOf(oContext.Properties["Active"].Value).Bool() |
152 | 245 | } | 245 | } |
153 | 246 | 246 | ||
154 | 247 | func (oContext OfonoContext) GetMessageCenter() (string, error) { | ||
155 | 248 | if msc := reflect.ValueOf(oContext.Properties["MessageCenter"].Value).String(); msc != "" { | ||
156 | 249 | return msc, nil | ||
157 | 250 | } else { | ||
158 | 251 | return "", errors.New("context setting for the Message Center value is empty") | ||
159 | 252 | } | ||
160 | 253 | } | ||
161 | 254 | |||
162 | 247 | func (oContext OfonoContext) GetProxy() (proxyInfo ProxyInfo, err error) { | 255 | func (oContext OfonoContext) GetProxy() (proxyInfo ProxyInfo, err error) { |
163 | 248 | proxy := reflect.ValueOf(oContext.Properties["MessageProxy"].Value).String() | 256 | proxy := reflect.ValueOf(oContext.Properties["MessageProxy"].Value).String() |
164 | 249 | if strings.HasPrefix(proxy, "http://") { | 257 | if strings.HasPrefix(proxy, "http://") { |
165 | @@ -254,7 +262,6 @@ | |||
166 | 254 | if err != nil { | 262 | if err != nil { |
167 | 255 | proxyInfo.Host = proxy | 263 | proxyInfo.Host = proxy |
168 | 256 | proxyInfo.Port = 80 | 264 | proxyInfo.Port = 80 |
169 | 257 | fmt.Println("Setting proxy to:", proxyInfo) | ||
170 | 258 | return proxyInfo, nil | 265 | return proxyInfo, nil |
171 | 259 | } | 266 | } |
172 | 260 | proxyInfo.Port, err = strconv.ParseUint(portString, 0, 64) | 267 | proxyInfo.Port, err = strconv.ParseUint(portString, 0, 64) |
173 | 261 | 268 | ||
174 | === removed directory 'udm' | |||
175 | === removed file 'udm/udm.go' | |||
176 | --- udm/udm.go 2014-04-24 21:33:38 +0000 | |||
177 | +++ udm/udm.go 1970-01-01 00:00:00 +0000 | |||
178 | @@ -1,552 +0,0 @@ | |||
179 | 1 | /* | ||
180 | 2 | * Copyright 2014 Canonical Ltd. | ||
181 | 3 | * | ||
182 | 4 | * Authors: | ||
183 | 5 | * Manuel de la Pena: manuel.delapena@canonical.com | ||
184 | 6 | * | ||
185 | 7 | * This file is part of ubuntu-download-manager. | ||
186 | 8 | * | ||
187 | 9 | * ubuntu-download-manager is free software; you can redistribute it and/or modify | ||
188 | 10 | * it under the terms of the GNU General Public License as published by | ||
189 | 11 | * the Free Software Foundation; version 3. | ||
190 | 12 | * | ||
191 | 13 | * ubuntu-download-manager is distributed in the hope that it will be useful, | ||
192 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
193 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
194 | 16 | * GNU General Public License for more details. | ||
195 | 17 | * | ||
196 | 18 | * You should have received a copy of the GNU General Public License | ||
197 | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
198 | 20 | */ | ||
199 | 21 | |||
200 | 22 | // Package udm provides a go interface to work with the ubuntu download manager | ||
201 | 23 | package udm | ||
202 | 24 | |||
203 | 25 | import ( | ||
204 | 26 | "errors" | ||
205 | 27 | "runtime" | ||
206 | 28 | |||
207 | 29 | "launchpad.net/go-dbus/v1" | ||
208 | 30 | ) | ||
209 | 31 | |||
210 | 32 | const ( | ||
211 | 33 | DOWNLOAD_SERVICE = "com.canonical.applications.Downloader" | ||
212 | 34 | DOWNLOAD_INTERFACE = "com.canonical.applications.Download" | ||
213 | 35 | DOWNLOAD_MANAGER_INTERFACE = "com.canonical.applications.DownloadManager" | ||
214 | 36 | ) | ||
215 | 37 | |||
216 | 38 | type hashType string | ||
217 | 39 | |||
218 | 40 | const ( | ||
219 | 41 | MD5 hashType = "md5" | ||
220 | 42 | SHA1 hashType = "sha1" | ||
221 | 43 | SHA224 hashType = "sha224" | ||
222 | 44 | SHA256 hashType = "sha256" | ||
223 | 45 | SHA384 hashType = "sha384" | ||
224 | 46 | SHA512 hashType = "sha512" | ||
225 | 47 | ) | ||
226 | 48 | |||
227 | 49 | const ( | ||
228 | 50 | LOCAL_PATH = "local-path" | ||
229 | 51 | OBJECT_PATH = "objectpath" | ||
230 | 52 | POST_DOWNLOAD_COMMAND = "post-download-command" | ||
231 | 53 | ) | ||
232 | 54 | |||
233 | 55 | // Progress provides how much progress has been performed in a download that was | ||
234 | 56 | // already started. | ||
235 | 57 | type Progress struct { | ||
236 | 58 | Received uint64 | ||
237 | 59 | Total uint64 | ||
238 | 60 | } | ||
239 | 61 | |||
240 | 62 | // Download is the common interface of a download. It provides all the required | ||
241 | 63 | // methods to interact with a download created by udm. | ||
242 | 64 | type Download interface { | ||
243 | 65 | TotalSize() (uint64, error) | ||
244 | 66 | Progress() (uint64, error) | ||
245 | 67 | Metadata() (map[string]string, error) | ||
246 | 68 | SetThrottle(uint64) error | ||
247 | 69 | Throttle() (uint64, error) | ||
248 | 70 | AllowMobileDownload(bool) error | ||
249 | 71 | IsMobileDownload() (bool, error) | ||
250 | 72 | Start() error | ||
251 | 73 | Pause() error | ||
252 | 74 | Resume() error | ||
253 | 75 | Cancel() error | ||
254 | 76 | Started() chan bool | ||
255 | 77 | Paused() chan bool | ||
256 | 78 | DownloadProgress() chan Progress | ||
257 | 79 | Resumed() chan bool | ||
258 | 80 | Canceled() chan bool | ||
259 | 81 | Finished() chan string | ||
260 | 82 | Error() chan error | ||
261 | 83 | } | ||
262 | 84 | |||
263 | 85 | // Manager is the single point of entry of the API. Allows to interact with the | ||
264 | 86 | // general setting of udm as well as to create downloads at will. | ||
265 | 87 | type Manager interface { | ||
266 | 88 | CreateDownload(string, string, string, map[string]interface{}, map[string]string) (Download, error) | ||
267 | 89 | CreateMmsDownload(string, string, int, string, string) (Download, error) | ||
268 | 90 | } | ||
269 | 91 | |||
270 | 92 | // FileDownload represents a single file being downloaded by udm. | ||
271 | 93 | type FileDownload struct { | ||
272 | 94 | conn *dbus.Connection | ||
273 | 95 | proxy *dbus.ObjectProxy | ||
274 | 96 | path dbus.ObjectPath | ||
275 | 97 | started chan bool | ||
276 | 98 | started_w *dbus.SignalWatch | ||
277 | 99 | paused chan bool | ||
278 | 100 | paused_w *dbus.SignalWatch | ||
279 | 101 | resumed chan bool | ||
280 | 102 | resumed_w *dbus.SignalWatch | ||
281 | 103 | canceled chan bool | ||
282 | 104 | canceled_w *dbus.SignalWatch | ||
283 | 105 | finished chan string | ||
284 | 106 | finished_w *dbus.SignalWatch | ||
285 | 107 | errors chan error | ||
286 | 108 | error_w *dbus.SignalWatch | ||
287 | 109 | progress chan Progress | ||
288 | 110 | progress_w *dbus.SignalWatch | ||
289 | 111 | } | ||
290 | 112 | |||
291 | 113 | func connectToSignal(conn *dbus.Connection, path dbus.ObjectPath, signal string) (*dbus.SignalWatch, error) { | ||
292 | 114 | w, err := conn.WatchSignal(&dbus.MatchRule{ | ||
293 | 115 | Type: dbus.TypeSignal, | ||
294 | 116 | Sender: DOWNLOAD_SERVICE, | ||
295 | 117 | Interface: DOWNLOAD_INTERFACE, | ||
296 | 118 | Member: signal, | ||
297 | 119 | Path: path}) | ||
298 | 120 | return w, err | ||
299 | 121 | } | ||
300 | 122 | |||
301 | 123 | func (down *FileDownload) free() { | ||
302 | 124 | // cancel all watches so that goroutines are done and close the | ||
303 | 125 | // channels | ||
304 | 126 | down.started_w.Cancel() | ||
305 | 127 | down.paused_w.Cancel() | ||
306 | 128 | down.resumed_w.Cancel() | ||
307 | 129 | down.canceled_w.Cancel() | ||
308 | 130 | down.finished_w.Cancel() | ||
309 | 131 | down.error_w.Cancel() | ||
310 | 132 | down.progress_w.Cancel() | ||
311 | 133 | } | ||
312 | 134 | |||
313 | 135 | func cleanDownloadData(down *FileDownload) { | ||
314 | 136 | down.free() | ||
315 | 137 | } | ||
316 | 138 | |||
317 | 139 | func newFileDownload(conn *dbus.Connection, path dbus.ObjectPath) (*FileDownload, error) { | ||
318 | 140 | proxy := conn.Object(DOWNLOAD_SERVICE, path) | ||
319 | 141 | started_ch := make(chan bool) | ||
320 | 142 | started_w, err := connectToSignal(conn, path, "started") | ||
321 | 143 | if err != nil { | ||
322 | 144 | return nil, err | ||
323 | 145 | } | ||
324 | 146 | |||
325 | 147 | paused_ch := make(chan bool) | ||
326 | 148 | paused_w, err := connectToSignal(conn, path, "paused") | ||
327 | 149 | if err != nil { | ||
328 | 150 | return nil, err | ||
329 | 151 | } | ||
330 | 152 | |||
331 | 153 | resumed_ch := make(chan bool) | ||
332 | 154 | resumed_w, err := connectToSignal(conn, path, "resumed") | ||
333 | 155 | if err != nil { | ||
334 | 156 | return nil, err | ||
335 | 157 | } | ||
336 | 158 | |||
337 | 159 | canceled_ch := make(chan bool) | ||
338 | 160 | canceled_w, err := connectToSignal(conn, path, "canceled") | ||
339 | 161 | if err != nil { | ||
340 | 162 | return nil, err | ||
341 | 163 | } | ||
342 | 164 | |||
343 | 165 | finished_ch := make(chan string) | ||
344 | 166 | finished_w, err := connectToSignal(conn, path, "finished") | ||
345 | 167 | if err != nil { | ||
346 | 168 | return nil, err | ||
347 | 169 | } | ||
348 | 170 | |||
349 | 171 | errors_ch := make(chan error) | ||
350 | 172 | errors_w, err := connectToSignal(conn, path, "error") | ||
351 | 173 | if err != nil { | ||
352 | 174 | return nil, err | ||
353 | 175 | } | ||
354 | 176 | |||
355 | 177 | progress_ch := make(chan Progress) | ||
356 | 178 | progress_w, err := connectToSignal(conn, path, "progress") | ||
357 | 179 | if err != nil { | ||
358 | 180 | return nil, err | ||
359 | 181 | } | ||
360 | 182 | |||
361 | 183 | d := FileDownload{conn, proxy, path, started_ch, started_w, paused_ch, paused_w, resumed_ch, resumed_w, canceled_ch, canceled_w, finished_ch, finished_w, errors_ch, errors_w, progress_ch, progress_w} | ||
362 | 184 | |||
363 | 185 | // connect to the diff signals so that we have nice channels that do | ||
364 | 186 | // not expose dbus watchers | ||
365 | 187 | d.connectToStarted() | ||
366 | 188 | d.connectToPaused() | ||
367 | 189 | d.connectToResumed() | ||
368 | 190 | d.connectToCanceled() | ||
369 | 191 | d.connectToFinished() | ||
370 | 192 | d.connectToError() | ||
371 | 193 | d.connectToProgress() | ||
372 | 194 | runtime.SetFinalizer(&d, cleanDownloadData) | ||
373 | 195 | return &d, nil | ||
374 | 196 | } | ||
375 | 197 | |||
376 | 198 | // TotalSize returns the total size of the file being downloaded. | ||
377 | 199 | func (down *FileDownload) TotalSize() (size uint64, err error) { | ||
378 | 200 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "totalSize") | ||
379 | 201 | if err != nil || reply.Type == dbus.TypeError { | ||
380 | 202 | return 0, err | ||
381 | 203 | } | ||
382 | 204 | if err = reply.Args(&size); err != nil { | ||
383 | 205 | return 0, err | ||
384 | 206 | } | ||
385 | 207 | return size, nil | ||
386 | 208 | } | ||
387 | 209 | |||
388 | 210 | // Process returns the process so far in downloading the file. | ||
389 | 211 | func (down *FileDownload) Progress() (progress uint64, err error) { | ||
390 | 212 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "progress") | ||
391 | 213 | if err != nil || reply.Type == dbus.TypeError { | ||
392 | 214 | return 0, err | ||
393 | 215 | } | ||
394 | 216 | if err = reply.Args(&progress); err != nil { | ||
395 | 217 | return 0, err | ||
396 | 218 | } | ||
397 | 219 | return progress, nil | ||
398 | 220 | } | ||
399 | 221 | |||
400 | 222 | // Metadata returns the metadata that was provided at creating time to the download. | ||
401 | 223 | func (down *FileDownload) Metadata() (metadata map[string]string, err error) { | ||
402 | 224 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "metadata") | ||
403 | 225 | if err != nil || reply.Type == dbus.TypeError { | ||
404 | 226 | return nil, err | ||
405 | 227 | } | ||
406 | 228 | if err = reply.Args(&metadata); err != nil { | ||
407 | 229 | return nil, err | ||
408 | 230 | } | ||
409 | 231 | return metadata, nil | ||
410 | 232 | } | ||
411 | 233 | |||
412 | 234 | // SetThrottle sets the network throttle to be used in the download. | ||
413 | 235 | func (down *FileDownload) SetThrottle(throttle uint64) (err error) { | ||
414 | 236 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "setThrottle", throttle) | ||
415 | 237 | if err != nil || reply.Type == dbus.TypeError { | ||
416 | 238 | return err | ||
417 | 239 | } | ||
418 | 240 | return nil | ||
419 | 241 | } | ||
420 | 242 | |||
421 | 243 | // Throttle returns the network throttle that is currently used in the download. | ||
422 | 244 | func (down *FileDownload) Throttle() (throttle uint64, err error) { | ||
423 | 245 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "throttle") | ||
424 | 246 | if err != nil || reply.Type == dbus.TypeError { | ||
425 | 247 | return 0, err | ||
426 | 248 | } | ||
427 | 249 | if err = reply.Args(&throttle); err != nil { | ||
428 | 250 | return 0, err | ||
429 | 251 | } | ||
430 | 252 | return throttle, nil | ||
431 | 253 | } | ||
432 | 254 | |||
433 | 255 | // AllowMobileDownload returns if the download is allow to use the mobile connect | ||
434 | 256 | // connection. | ||
435 | 257 | func (down *FileDownload) AllowMobileDownload(allowed bool) (err error) { | ||
436 | 258 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "allowGSMDownload", allowed) | ||
437 | 259 | if err != nil || reply.Type == dbus.TypeError { | ||
438 | 260 | return err | ||
439 | 261 | } | ||
440 | 262 | return nil | ||
441 | 263 | } | ||
442 | 264 | |||
443 | 265 | // IsMobileDownload returns if the download will be performed over the mobile data. | ||
444 | 266 | func (down *FileDownload) IsMobileDownload() (allowed bool, err error) { | ||
445 | 267 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "isGSMDownloadAllowed", allowed) | ||
446 | 268 | if err != nil || reply.Type == dbus.TypeError { | ||
447 | 269 | return false, err | ||
448 | 270 | } | ||
449 | 271 | if err = reply.Args(&allowed); err != nil { | ||
450 | 272 | return false, err | ||
451 | 273 | } | ||
452 | 274 | return allowed, nil | ||
453 | 275 | } | ||
454 | 276 | |||
455 | 277 | // Start tells udm that the download is ready to be peformed and that the client is | ||
456 | 278 | // ready to recieve signals. The following is a commong pattern to be used when | ||
457 | 279 | // creating downloads in udm. | ||
458 | 280 | // | ||
459 | 281 | // man, err := udm.NewDownloadManager() | ||
460 | 282 | // if err != nil { | ||
461 | 283 | // } | ||
462 | 284 | // | ||
463 | 285 | // // variables used to create the download | ||
464 | 286 | // | ||
465 | 287 | // url := "http://www.python.org/ftp/python/3.3.3/Python-3.3.3.tar.xz" | ||
466 | 288 | // hash := "8af44d33ea3a1528fc56b3a362924500" | ||
467 | 289 | // hashAlgo := MD5 | ||
468 | 290 | // var metadata map[string]interface{} | ||
469 | 291 | // var headers map[string]string | ||
470 | 292 | // | ||
471 | 293 | // // create the download BUT do not start downloading just yet | ||
472 | 294 | // down, err := man.CreateDownload(url, hash, hashAlgo, metadata, headers) | ||
473 | 295 | // | ||
474 | 296 | // // connect routines to the download channels so that we can get the | ||
475 | 297 | // // information of the download the channel will not get any data until the | ||
476 | 298 | // // Start is called. | ||
477 | 299 | // | ||
478 | 300 | // started_signal := down.Started() | ||
479 | 301 | // go func() { | ||
480 | 302 | // <-started_signal | ||
481 | 303 | // fmt.Println("Download started") | ||
482 | 304 | // }() | ||
483 | 305 | // progress_signal := down.DownloadProgress() | ||
484 | 306 | // go func() { | ||
485 | 307 | // for progress := range p { | ||
486 | 308 | // fmt.Printf("Recieved %d out of %d\n", progress.Received, progress.Total) | ||
487 | 309 | // } | ||
488 | 310 | // }() | ||
489 | 311 | // | ||
490 | 312 | // finished_signal := down.Finished() | ||
491 | 313 | // | ||
492 | 314 | // // start download | ||
493 | 315 | // down.Start() | ||
494 | 316 | // | ||
495 | 317 | // // block until we are finished downloading | ||
496 | 318 | // <- finished_signal | ||
497 | 319 | func (down *FileDownload) Start() (err error) { | ||
498 | 320 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "start") | ||
499 | 321 | if err != nil || reply.Type == dbus.TypeError { | ||
500 | 322 | return err | ||
501 | 323 | } | ||
502 | 324 | return nil | ||
503 | 325 | } | ||
504 | 326 | |||
505 | 327 | // Pause pauses a download that was started and if not nothing is done. | ||
506 | 328 | func (down *FileDownload) Pause() (err error) { | ||
507 | 329 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "pause") | ||
508 | 330 | if err != nil || reply.Type == dbus.TypeError { | ||
509 | 331 | return err | ||
510 | 332 | } | ||
511 | 333 | return nil | ||
512 | 334 | } | ||
513 | 335 | |||
514 | 336 | // Resumes a download that was paused or does nothing otherwise. | ||
515 | 337 | func (down *FileDownload) Resume() (err error) { | ||
516 | 338 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "resume") | ||
517 | 339 | if err != nil || reply.Type == dbus.TypeError { | ||
518 | 340 | return err | ||
519 | 341 | } | ||
520 | 342 | return nil | ||
521 | 343 | } | ||
522 | 344 | |||
523 | 345 | // Cancel cancels a download that was in process and deletes any local files | ||
524 | 346 | // that were created. | ||
525 | 347 | func (down *FileDownload) Cancel() (err error) { | ||
526 | 348 | reply, err := down.proxy.Call(DOWNLOAD_INTERFACE, "cancel") | ||
527 | 349 | if err != nil || reply.Type == dbus.TypeError { | ||
528 | 350 | return err | ||
529 | 351 | } | ||
530 | 352 | return nil | ||
531 | 353 | } | ||
532 | 354 | |||
533 | 355 | func (down *FileDownload) connectToStarted() { | ||
534 | 356 | go func() { | ||
535 | 357 | for msg := range down.started_w.C { | ||
536 | 358 | var started bool | ||
537 | 359 | msg.Args(&started) | ||
538 | 360 | down.started <- started | ||
539 | 361 | } | ||
540 | 362 | close(down.started) | ||
541 | 363 | }() | ||
542 | 364 | } | ||
543 | 365 | |||
544 | 366 | // Started returns a channel that will be used to communicate the started signals. | ||
545 | 367 | func (down *FileDownload) Started() chan bool { | ||
546 | 368 | return down.started | ||
547 | 369 | } | ||
548 | 370 | |||
549 | 371 | func (down *FileDownload) connectToPaused() { | ||
550 | 372 | go func() { | ||
551 | 373 | for msg := range down.paused_w.C { | ||
552 | 374 | var paused bool | ||
553 | 375 | msg.Args(&paused) | ||
554 | 376 | down.paused <- paused | ||
555 | 377 | } | ||
556 | 378 | close(down.paused) | ||
557 | 379 | }() | ||
558 | 380 | } | ||
559 | 381 | |||
560 | 382 | // Paused returns a channel that will be used to communicate the paused signals. | ||
561 | 383 | func (down *FileDownload) Paused() chan bool { | ||
562 | 384 | return down.paused | ||
563 | 385 | } | ||
564 | 386 | |||
565 | 387 | func (down *FileDownload) connectToProgress() { | ||
566 | 388 | go func() { | ||
567 | 389 | for msg := range down.progress_w.C { | ||
568 | 390 | var received uint64 | ||
569 | 391 | var total uint64 | ||
570 | 392 | msg.Args(&received, &total) | ||
571 | 393 | down.progress <- Progress{received, total} | ||
572 | 394 | } | ||
573 | 395 | close(down.progress) | ||
574 | 396 | }() | ||
575 | 397 | } | ||
576 | 398 | |||
577 | 399 | // DownloadProgress returns a channel that will be used to communicate the progress | ||
578 | 400 | // signals. | ||
579 | 401 | func (down *FileDownload) DownloadProgress() chan Progress { | ||
580 | 402 | return down.progress | ||
581 | 403 | } | ||
582 | 404 | |||
583 | 405 | func (down *FileDownload) connectToResumed() { | ||
584 | 406 | go func() { | ||
585 | 407 | for msg := range down.resumed_w.C { | ||
586 | 408 | var resumed bool | ||
587 | 409 | msg.Args(&resumed) | ||
588 | 410 | down.resumed <- resumed | ||
589 | 411 | } | ||
590 | 412 | close(down.resumed) | ||
591 | 413 | }() | ||
592 | 414 | } | ||
593 | 415 | |||
594 | 416 | // Resumed returns a channel that will be used to communicate the paused signals. | ||
595 | 417 | func (down *FileDownload) Resumed() chan bool { | ||
596 | 418 | return down.resumed | ||
597 | 419 | } | ||
598 | 420 | |||
599 | 421 | func (down *FileDownload) connectToCanceled() { | ||
600 | 422 | go func() { | ||
601 | 423 | for msg := range down.canceled_w.C { | ||
602 | 424 | var canceled bool | ||
603 | 425 | msg.Args(&canceled) | ||
604 | 426 | down.canceled <- canceled | ||
605 | 427 | } | ||
606 | 428 | close(down.canceled) | ||
607 | 429 | }() | ||
608 | 430 | } | ||
609 | 431 | |||
610 | 432 | // Canceled returns a channel that will be used to communicate the canceled signals. | ||
611 | 433 | func (down *FileDownload) Canceled() chan bool { | ||
612 | 434 | return down.canceled | ||
613 | 435 | } | ||
614 | 436 | |||
615 | 437 | func (down *FileDownload) connectToFinished() { | ||
616 | 438 | go func() { | ||
617 | 439 | for msg := range down.finished_w.C { | ||
618 | 440 | var path string | ||
619 | 441 | msg.Args(&path) | ||
620 | 442 | down.finished <- path | ||
621 | 443 | } | ||
622 | 444 | close(down.finished) | ||
623 | 445 | }() | ||
624 | 446 | } | ||
625 | 447 | |||
626 | 448 | // Finished returns a channel that will ne used to communicate the finished signals. | ||
627 | 449 | func (down *FileDownload) Finished() chan string { | ||
628 | 450 | return down.finished | ||
629 | 451 | } | ||
630 | 452 | |||
631 | 453 | func (down *FileDownload) connectToError() { | ||
632 | 454 | go func() { | ||
633 | 455 | for msg := range down.error_w.C { | ||
634 | 456 | var reason string | ||
635 | 457 | msg.Args(&reason) | ||
636 | 458 | down.errors <- errors.New(reason) | ||
637 | 459 | } | ||
638 | 460 | close(down.errors) | ||
639 | 461 | }() | ||
640 | 462 | } | ||
641 | 463 | |||
642 | 464 | // Error returns the channel that will be used to communicate the error signals. | ||
643 | 465 | func (down *FileDownload) Error() chan error { | ||
644 | 466 | return down.errors | ||
645 | 467 | } | ||
646 | 468 | |||
647 | 469 | type DownloadManager struct { | ||
648 | 470 | conn *dbus.Connection | ||
649 | 471 | proxy *dbus.ObjectProxy | ||
650 | 472 | } | ||
651 | 473 | |||
652 | 474 | // NewDownloadManager creates a new manager that can be used to create download in the | ||
653 | 475 | // udm daemon. | ||
654 | 476 | func NewDownloadManager() (*DownloadManager, error) { | ||
655 | 477 | conn, err := dbus.Connect(dbus.SessionBus) | ||
656 | 478 | if err != nil { | ||
657 | 479 | return nil, err | ||
658 | 480 | } | ||
659 | 481 | |||
660 | 482 | if err != nil { | ||
661 | 483 | return nil, err | ||
662 | 484 | } | ||
663 | 485 | |||
664 | 486 | proxy := conn.Object(DOWNLOAD_SERVICE, "/") | ||
665 | 487 | d := DownloadManager{conn, proxy} | ||
666 | 488 | return &d, nil | ||
667 | 489 | } | ||
668 | 490 | |||
669 | 491 | // CreateDownload creates a new download in the udm daemon that can be used to get | ||
670 | 492 | // a remote resource. Udm allows to pass a hash signature and method that will be | ||
671 | 493 | // check once the download has been complited. | ||
672 | 494 | // | ||
673 | 495 | // The download hash can be one of the the following constants: | ||
674 | 496 | // | ||
675 | 497 | // MD5 | ||
676 | 498 | // SHA1 | ||
677 | 499 | // SHA224 | ||
678 | 500 | // SHA256 | ||
679 | 501 | // SHA384 | ||
680 | 502 | // SHA512 | ||
681 | 503 | // | ||
682 | 504 | // The metadata attribute can be used to pass extra information to the udm daemon | ||
683 | 505 | // that will just be considered if the caller is not a apparmor confined application. | ||
684 | 506 | // | ||
685 | 507 | // LOCAL_PATH => allows to provide the local path for the download. | ||
686 | 508 | // OBJECT_PATH => allows to provide the object path to be used in the dbus daemon. | ||
687 | 509 | // POST_DOWNLOAD_COMMAND => allows to provide a command that will be executed on the | ||
688 | 510 | // download | ||
689 | 511 | // | ||
690 | 512 | // The headers attribute allows to provide extra headers to be used in the request used | ||
691 | 513 | // to perform the download. | ||
692 | 514 | func (man *DownloadManager) CreateDownload(url string, hash string, algo hashType, metadata map[string]interface{}, headers map[string]string) (down Download, err error) { | ||
693 | 515 | var t map[string]*dbus.Variant | ||
694 | 516 | for key, value := range metadata { | ||
695 | 517 | t[key] = &dbus.Variant{Value: value} | ||
696 | 518 | } | ||
697 | 519 | s := struct { | ||
698 | 520 | U string | ||
699 | 521 | H string | ||
700 | 522 | A string | ||
701 | 523 | M map[string]*dbus.Variant | ||
702 | 524 | HD map[string]string | ||
703 | 525 | }{url, hash, string(algo), t, headers} | ||
704 | 526 | var path dbus.ObjectPath | ||
705 | 527 | reply, err := man.proxy.Call(DOWNLOAD_MANAGER_INTERFACE, "createDownload", s) | ||
706 | 528 | if err != nil || reply.Type == dbus.TypeError { | ||
707 | 529 | return nil, err | ||
708 | 530 | } | ||
709 | 531 | if err = reply.Args(&path); err != nil { | ||
710 | 532 | return nil, err | ||
711 | 533 | } | ||
712 | 534 | down, err = newFileDownload(man.conn, path) | ||
713 | 535 | return down, err | ||
714 | 536 | } | ||
715 | 537 | |||
716 | 538 | // CreateMmsDownload creates an mms download that will be performed right away. An | ||
717 | 539 | // mms download only uses mobile that and an apn proxy to download a multime media | ||
718 | 540 | // message. | ||
719 | 541 | func (man *DownloadManager) CreateMmsDownload(url string, hostname string, port int32) (down Download, err error) { | ||
720 | 542 | var path dbus.ObjectPath | ||
721 | 543 | reply, err := man.proxy.Call(DOWNLOAD_MANAGER_INTERFACE, "createMmsDownload", url, hostname, port) | ||
722 | 544 | if err != nil || reply.Type == dbus.TypeError { | ||
723 | 545 | return nil, err | ||
724 | 546 | } | ||
725 | 547 | if err = reply.Args(&path); err != nil { | ||
726 | 548 | return nil, err | ||
727 | 549 | } | ||
728 | 550 | down, err = newFileDownload(man.conn, path) | ||
729 | 551 | return down, err | ||
730 | 552 | } |