From 2facc60f8eb246d48ddc4276e364678b3b7a8812 Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Tue, 8 Sep 2015 23:03:44 +0900 Subject: [PATCH] tizen 2.3.1 release --- CMakeLists.txt | 153 +- LICENSE | 206 -- LICENSE.Apache-2.0 | 35 + NOTICE | 13 + agent/CMakeLists.txt | 116 ++ agent/download-agent-client-mgr.c | 145 ++ agent/download-agent-dl-info.c | 462 +++++ agent/download-agent-dl-mgr.c | 186 ++ {src/agent => agent}/download-agent-encoding.c | 86 +- agent/download-agent-file.c | 910 +++++++++ agent/download-agent-http-mgr.c | 1519 ++++++++++++++ .../download-agent-http-msg-handler.c | 607 ++---- agent/download-agent-interface.c | 152 ++ {src/agent => agent}/download-agent-mime-util.c | 156 +- agent/download-agent-plugin-conf.c | 109 + agent/download-agent-plugin-drm.c | 124 ++ agent/download-agent-plugin-libcurl.c | 702 +++++++ agent/include/download-agent-client-mgr.h | 27 + agent/include/download-agent-debug.h | 68 + agent/include/download-agent-defs.h | 85 + agent/include/download-agent-dl-info.h | 197 ++ agent/include/download-agent-dl-mgr.h | 27 + .../include/download-agent-encoding.h | 18 +- agent/include/download-agent-file.h | 45 + agent/include/download-agent-http-mgr.h | 34 + agent/include/download-agent-http-msg-handler.h | 77 + agent/include/download-agent-interface.h | 97 + agent/include/download-agent-mime-util.h | 48 + agent/include/download-agent-plugin-conf.h | 30 + agent/include/download-agent-plugin-drm.h | 25 + agent/include/download-agent-plugin-libcurl.h | 35 + agent/include/download-agent-pthread.h | 144 ++ agent/include/download-agent-type.h | 73 + debian/changelog | 8 - download-provider-service | 9 - download-provider-w.manifest | 36 + download-provider.manifest | 33 +- download-provider.pc.in | 11 +- dump-download-provider.sh | 14 + include/download-provider-config.h | 48 - include/download-provider-db.h | 55 - include/download-provider-ipc.h | 13 - include/download-provider-log.h | 22 - include/download-provider-notification.h | 11 - include/download-provider-pthread.h | 90 - include/download-provider-utils.h | 17 - include/download-provider.h | 113 -- packaging/download-provider.spec | 274 +-- po/redwood/CMakeLists.txt | 27 + po/redwood/az.po | 6 + po/redwood/bg.po | 6 + po/redwood/ca.po | 6 + po/redwood/cs.po | 6 + po/redwood/da.po | 6 + po/redwood/de.po | 6 + po/redwood/el_GR.po | 6 + po/redwood/en.po | 6 + po/redwood/en_US.po | 6 + po/redwood/es_ES.po | 6 + po/redwood/es_US.po | 6 + po/redwood/et.po | 6 + po/redwood/eu.po | 6 + po/redwood/fi.po | 6 + po/redwood/fr.po | 6 + po/redwood/fr_CA.po | 6 + po/redwood/gl.po | 6 + po/redwood/hr.po | 6 + po/redwood/hu.po | 6 + po/redwood/hy.po | 6 + po/redwood/is.po | 6 + po/redwood/it_IT.po | 6 + po/redwood/ka.po | 6 + po/redwood/kk.po | 6 + po/redwood/ko_KR.po | 6 + po/redwood/lt.po | 6 + po/redwood/lv.po | 6 + po/redwood/mn_MN.po | 6 + po/redwood/nb.po | 6 + po/redwood/nl.po | 6 + po/redwood/pl.po | 6 + po/redwood/pt_BR.po | 6 + po/redwood/pt_PT.po | 6 + po/redwood/ro.po | 6 + po/redwood/ru_RU.po | 6 + po/redwood/sk.po | 6 + po/redwood/sl.po | 6 + po/redwood/sr.po | 6 + po/redwood/sv.po | 6 + po/redwood/tr_TR.po | 6 + po/redwood/uk.po | 6 + po/redwood/uz.po | 6 + po/tizen2.3/CMakeLists.txt | 30 + po/tizen2.3/ar.po | 6 + po/tizen2.3/az.po | 6 + po/tizen2.3/bg.po | 6 + po/tizen2.3/ca.po | 6 + po/tizen2.3/cs.po | 6 + po/tizen2.3/da.po | 6 + po/tizen2.3/de.po | 6 + po/tizen2.3/el_GR.po | 6 + po/tizen2.3/en.po | 6 + po/tizen2.3/en_PH.po | 6 + po/tizen2.3/en_US.po | 6 + po/tizen2.3/es_ES.po | 6 + po/tizen2.3/es_US.po | 6 + po/tizen2.3/et.po | 6 + po/tizen2.3/eu.po | 6 + po/tizen2.3/fi.po | 6 + po/tizen2.3/fr.po | 6 + po/tizen2.3/fr_CA.po | 6 + po/tizen2.3/ga.po | 6 + po/tizen2.3/gl.po | 6 + po/tizen2.3/hi.po | 6 + po/tizen2.3/hr.po | 6 + po/tizen2.3/hu.po | 6 + po/tizen2.3/hy.po | 6 + po/tizen2.3/is.po | 6 + po/tizen2.3/it_IT.po | 6 + po/tizen2.3/ja_JP.po | 6 + po/tizen2.3/ka.po | 6 + po/tizen2.3/kk.po | 6 + po/tizen2.3/ko_KR.po | 6 + po/tizen2.3/lt.po | 6 + po/tizen2.3/lv.po | 6 + po/tizen2.3/mk.po | 6 + po/tizen2.3/nb.po | 6 + po/tizen2.3/nl.po | 6 + po/tizen2.3/pl.po | 6 + po/tizen2.3/pt_BR.po | 6 + po/tizen2.3/pt_PT.po | 6 + po/tizen2.3/ro.po | 6 + po/tizen2.3/ru_RU.po | 6 + po/tizen2.3/sk.po | 6 + po/tizen2.3/sl.po | 6 + po/tizen2.3/sr.po | 6 + po/tizen2.3/sv.po | 6 + po/tizen2.3/tr_TR.po | 6 + po/tizen2.3/uk.po | 6 + po/tizen2.3/uz.po | 6 + po/tizen2.3/zh_CN.po | 6 + po/tizen2.3/zh_HK.po | 6 + po/tizen2.3/zh_TW.po | 6 + provider-interface/CMakeLists.txt | 49 + provider-interface/download-provider-interface.c | 1560 +++++++++++++++ .../download-provider-interface.pc.in | 8 + .../include/download-provider-interface.h | 143 ++ provider/CMakeLists.txt | 122 ++ provider/download-provider-client-manager.c | 741 +++++++ provider/download-provider-client.c | 2110 ++++++++++++++++++++ provider/download-provider-db.c | 1322 ++++++++++++ provider/download-provider-ipc.c | 132 ++ provider/download-provider-main.c | 66 + provider/download-provider-network.c | 267 +++ provider/download-provider-notification-manager.c | 573 ++++++ provider/download-provider-notification.c | 627 ++++++ provider/download-provider-notify.c | 103 + provider/download-provider-plugin-download-agent.c | 994 +++++++++ provider/download-provider-pthread.c | 110 + provider/download-provider-queue-manager.c | 315 +++ provider/download-provider-queue.c | 194 ++ provider/download-provider-smack.c | 174 ++ provider/download-provider-utils.c | 103 + .../include/download-provider-client-manager.h | 35 + provider/include/download-provider-client.h | 60 + provider/include/download-provider-config.h | 39 + provider/include/download-provider-db-defs.h | 157 ++ provider/include/download-provider-db.h | 55 + provider/include/download-provider-ipc.h | 36 + provider/include/download-provider-log.h | 64 + provider/include/download-provider-network.h | 34 + .../download-provider-notification-manager.h | 33 + provider/include/download-provider-notification.h | 33 + provider/include/download-provider-notify.h | 24 + .../download-provider-plugin-download-agent.h | 31 + provider/include/download-provider-pthread.h | 44 + provider/include/download-provider-queue-manager.h | 25 + provider/include/download-provider-queue.h | 31 + provider/include/download-provider-smack.h | 33 + provider/include/download-provider-utils.h | 25 + provider/include/download-provider.h | 191 ++ .../B03_processing_download_complete.png} | Bin 4493 -> 3117 bytes .../redwood/B03_processing_download_fail.png | Bin 0 -> 1600 bytes res/images/redwood/U01_icon_broken.png | Bin 0 -> 4017 bytes res/images/redwood/U01_icon_drm.png | Bin 0 -> 4077 bytes res/images/redwood/U01_icon_excel.png | Bin 0 -> 4512 bytes res/images/redwood/U01_icon_html.png | Bin 0 -> 5063 bytes res/images/redwood/U01_icon_pdf.png | Bin 0 -> 4686 bytes res/images/redwood/U01_icon_ppt.png | Bin 0 -> 3946 bytes res/images/redwood/U01_icon_swf.png | Bin 0 -> 4233 bytes res/images/redwood/U01_icon_text.png | Bin 0 -> 3832 bytes res/images/redwood/U01_icon_tpk.png | Bin 0 -> 5319 bytes res/images/redwood/U01_icon_unkown.png | Bin 0 -> 3888 bytes res/images/redwood/U01_icon_vcs.png | Bin 0 -> 3835 bytes res/images/redwood/U01_icon_word.png | Bin 0 -> 4669 bytes res/images/redwood/U01_list_icon_image.png | Bin 0 -> 4162 bytes res/images/redwood/U01_list_icon_mp3.png | Bin 0 -> 4154 bytes res/images/redwood/U01_list_icon_mp4.png | Bin 0 -> 3851 bytes res/images/redwood/noti_download_complete.png | Bin 0 -> 6935 bytes res/images/redwood/noti_download_failed.png | Bin 0 -> 8035 bytes .../tizen2.3/B03_Processing_download_complete.png | Bin 0 -> 1268 bytes .../tizen2.3/B03_Processing_download_failed.png | Bin 0 -> 1421 bytes res/images/tizen2.3/download_manager_icon_date.png | Bin 0 -> 1606 bytes res/images/tizen2.3/download_manager_icon_drm.png | Bin 0 -> 1701 bytes res/images/tizen2.3/download_manager_icon_html.png | Bin 0 -> 2359 bytes res/images/tizen2.3/download_manager_icon_img.png | Bin 0 -> 1765 bytes .../tizen2.3/download_manager_icon_movie.png | Bin 0 -> 1640 bytes .../tizen2.3/download_manager_icon_music.png | Bin 0 -> 1786 bytes res/images/tizen2.3/download_manager_icon_pdf.png | Bin 0 -> 2005 bytes res/images/tizen2.3/download_manager_icon_ppt.png | Bin 0 -> 1499 bytes res/images/tizen2.3/download_manager_icon_swf.png | Bin 0 -> 1878 bytes res/images/tizen2.3/download_manager_icon_text.png | Bin 0 -> 1600 bytes res/images/tizen2.3/download_manager_icon_tpk.png | Bin 0 -> 2546 bytes .../tizen2.3/download_manager_icon_unknown.png | Bin 0 -> 1631 bytes res/images/tizen2.3/download_manager_icon_word.png | Bin 0 -> 1930 bytes res/images/tizen2.3/download_manager_icon_xls.png | Bin 0 -> 1854 bytes src/agent/CMakeLists.txt | 89 - src/agent/download-agent-basic.c | 382 ---- src/agent/download-agent-client-mgr.c | 620 ------ src/agent/download-agent-debug.c | 214 -- src/agent/download-agent-dl-info-util.c | 688 ------- src/agent/download-agent-dl-mgr.c | 520 ----- src/agent/download-agent-file.c | 1134 ----------- src/agent/download-agent-http-mgr.c | 1691 ---------------- src/agent/download-agent-http-misc.c | 71 - src/agent/download-agent-http-queue.c | 392 ---- src/agent/download-agent-installation.c | 136 -- src/agent/download-agent-interface.c | 322 --- src/agent/download-agent-plugin-conf.c | 176 -- src/agent/download-agent-plugin-install.c | 44 - src/agent/download-agent-plugin-libsoup.c | 968 --------- src/agent/download-agent-utils-dl-req-id-history.c | 79 - src/agent/download-agent-utils.c | 350 ---- src/agent/include/download-agent-basic.h | 45 - src/agent/include/download-agent-client-mgr.h | 102 - src/agent/include/download-agent-debug.h | 102 - src/agent/include/download-agent-defs.h | 317 --- src/agent/include/download-agent-dl-info-util.h | 294 --- src/agent/include/download-agent-dl-mgr.h | 45 - src/agent/include/download-agent-file.h | 65 - src/agent/include/download-agent-http-mgr.h | 56 - src/agent/include/download-agent-http-misc.h | 56 - .../include/download-agent-http-msg-handler.h | 128 -- src/agent/include/download-agent-http-queue.h | 133 -- src/agent/include/download-agent-installation.h | 36 - src/agent/include/download-agent-interface.h | 611 ------ src/agent/include/download-agent-mime-util.h | 43 - src/agent/include/download-agent-plugin-conf.h | 36 - .../include/download-agent-plugin-http-interface.h | 60 - src/agent/include/download-agent-plugin-install.h | 33 - src/agent/include/download-agent-plugin-libsoup.h | 84 - src/agent/include/download-agent-pthread.h | 156 -- src/agent/include/download-agent-type.h | 44 - .../download-agent-utils-dl-req-id-history.h | 44 - src/agent/include/download-agent-utils.h | 83 - src/download-provider-db.c | 1096 ---------- src/download-provider-ipc.c | 324 --- src/download-provider-main.c | 99 - src/download-provider-notification.c | 396 ---- src/download-provider-pid.c | 14 - src/download-provider-receiver.c | 1239 ------------ src/download-provider-utils.c | 231 --- systemd/download-provider.service | 13 + systemd/download-provider.socket | 10 + 263 files changed, 17436 insertions(+), 15172 deletions(-) mode change 100644 => 100755 CMakeLists.txt delete mode 100755 LICENSE create mode 100755 LICENSE.Apache-2.0 create mode 100644 NOTICE create mode 100755 agent/CMakeLists.txt create mode 100755 agent/download-agent-client-mgr.c create mode 100644 agent/download-agent-dl-info.c create mode 100755 agent/download-agent-dl-mgr.c rename {src/agent => agent}/download-agent-encoding.c (71%) mode change 100644 => 100755 create mode 100755 agent/download-agent-file.c create mode 100755 agent/download-agent-http-mgr.c rename {src/agent => agent}/download-agent-http-msg-handler.c (61%) mode change 100644 => 100755 create mode 100755 agent/download-agent-interface.c rename {src/agent => agent}/download-agent-mime-util.c (69%) mode change 100644 => 100755 create mode 100755 agent/download-agent-plugin-conf.c create mode 100644 agent/download-agent-plugin-drm.c create mode 100644 agent/download-agent-plugin-libcurl.c create mode 100755 agent/include/download-agent-client-mgr.h create mode 100755 agent/include/download-agent-debug.h create mode 100755 agent/include/download-agent-defs.h create mode 100644 agent/include/download-agent-dl-info.h create mode 100755 agent/include/download-agent-dl-mgr.h rename {src/agent => agent}/include/download-agent-encoding.h (52%) mode change 100644 => 100755 create mode 100755 agent/include/download-agent-file.h create mode 100755 agent/include/download-agent-http-mgr.h create mode 100755 agent/include/download-agent-http-msg-handler.h create mode 100755 agent/include/download-agent-interface.h create mode 100755 agent/include/download-agent-mime-util.h create mode 100755 agent/include/download-agent-plugin-conf.h create mode 100644 agent/include/download-agent-plugin-drm.h create mode 100644 agent/include/download-agent-plugin-libcurl.h create mode 100755 agent/include/download-agent-pthread.h create mode 100755 agent/include/download-agent-type.h delete mode 100755 debian/changelog delete mode 100644 download-provider-service create mode 100644 download-provider-w.manifest create mode 100644 dump-download-provider.sh delete mode 100644 include/download-provider-config.h delete mode 100644 include/download-provider-db.h delete mode 100644 include/download-provider-ipc.h delete mode 100644 include/download-provider-log.h delete mode 100644 include/download-provider-notification.h delete mode 100644 include/download-provider-pthread.h delete mode 100644 include/download-provider-utils.h delete mode 100644 include/download-provider.h create mode 100644 po/redwood/CMakeLists.txt create mode 100644 po/redwood/az.po create mode 100644 po/redwood/bg.po create mode 100644 po/redwood/ca.po create mode 100644 po/redwood/cs.po create mode 100644 po/redwood/da.po create mode 100644 po/redwood/de.po create mode 100644 po/redwood/el_GR.po create mode 100644 po/redwood/en.po create mode 100644 po/redwood/en_US.po create mode 100644 po/redwood/es_ES.po create mode 100644 po/redwood/es_US.po create mode 100644 po/redwood/et.po create mode 100644 po/redwood/eu.po create mode 100644 po/redwood/fi.po create mode 100644 po/redwood/fr.po create mode 100644 po/redwood/fr_CA.po create mode 100644 po/redwood/gl.po create mode 100644 po/redwood/hr.po create mode 100644 po/redwood/hu.po create mode 100644 po/redwood/hy.po create mode 100644 po/redwood/is.po create mode 100644 po/redwood/it_IT.po create mode 100644 po/redwood/ka.po create mode 100644 po/redwood/kk.po create mode 100644 po/redwood/ko_KR.po create mode 100644 po/redwood/lt.po create mode 100644 po/redwood/lv.po create mode 100644 po/redwood/mn_MN.po create mode 100644 po/redwood/nb.po create mode 100644 po/redwood/nl.po create mode 100644 po/redwood/pl.po create mode 100644 po/redwood/pt_BR.po create mode 100644 po/redwood/pt_PT.po create mode 100644 po/redwood/ro.po create mode 100644 po/redwood/ru_RU.po create mode 100644 po/redwood/sk.po create mode 100644 po/redwood/sl.po create mode 100644 po/redwood/sr.po create mode 100644 po/redwood/sv.po create mode 100644 po/redwood/tr_TR.po create mode 100644 po/redwood/uk.po create mode 100644 po/redwood/uz.po create mode 100644 po/tizen2.3/CMakeLists.txt create mode 100644 po/tizen2.3/ar.po create mode 100644 po/tizen2.3/az.po create mode 100644 po/tizen2.3/bg.po create mode 100644 po/tizen2.3/ca.po create mode 100644 po/tizen2.3/cs.po create mode 100644 po/tizen2.3/da.po create mode 100644 po/tizen2.3/de.po create mode 100644 po/tizen2.3/el_GR.po create mode 100644 po/tizen2.3/en.po create mode 100644 po/tizen2.3/en_PH.po create mode 100644 po/tizen2.3/en_US.po create mode 100644 po/tizen2.3/es_ES.po create mode 100644 po/tizen2.3/es_US.po create mode 100644 po/tizen2.3/et.po create mode 100644 po/tizen2.3/eu.po create mode 100644 po/tizen2.3/fi.po create mode 100644 po/tizen2.3/fr.po create mode 100644 po/tizen2.3/fr_CA.po create mode 100644 po/tizen2.3/ga.po create mode 100644 po/tizen2.3/gl.po create mode 100644 po/tizen2.3/hi.po create mode 100644 po/tizen2.3/hr.po create mode 100644 po/tizen2.3/hu.po create mode 100644 po/tizen2.3/hy.po create mode 100644 po/tizen2.3/is.po create mode 100644 po/tizen2.3/it_IT.po create mode 100644 po/tizen2.3/ja_JP.po create mode 100644 po/tizen2.3/ka.po create mode 100644 po/tizen2.3/kk.po create mode 100644 po/tizen2.3/ko_KR.po create mode 100644 po/tizen2.3/lt.po create mode 100644 po/tizen2.3/lv.po create mode 100644 po/tizen2.3/mk.po create mode 100644 po/tizen2.3/nb.po create mode 100644 po/tizen2.3/nl.po create mode 100644 po/tizen2.3/pl.po create mode 100644 po/tizen2.3/pt_BR.po create mode 100644 po/tizen2.3/pt_PT.po create mode 100644 po/tizen2.3/ro.po create mode 100644 po/tizen2.3/ru_RU.po create mode 100644 po/tizen2.3/sk.po create mode 100644 po/tizen2.3/sl.po create mode 100644 po/tizen2.3/sr.po create mode 100644 po/tizen2.3/sv.po create mode 100644 po/tizen2.3/tr_TR.po create mode 100644 po/tizen2.3/uk.po create mode 100644 po/tizen2.3/uz.po create mode 100644 po/tizen2.3/zh_CN.po create mode 100644 po/tizen2.3/zh_HK.po create mode 100644 po/tizen2.3/zh_TW.po create mode 100755 provider-interface/CMakeLists.txt create mode 100755 provider-interface/download-provider-interface.c create mode 100644 provider-interface/download-provider-interface.pc.in create mode 100755 provider-interface/include/download-provider-interface.h create mode 100755 provider/CMakeLists.txt create mode 100644 provider/download-provider-client-manager.c create mode 100644 provider/download-provider-client.c create mode 100755 provider/download-provider-db.c create mode 100644 provider/download-provider-ipc.c create mode 100755 provider/download-provider-main.c create mode 100755 provider/download-provider-network.c create mode 100644 provider/download-provider-notification-manager.c create mode 100755 provider/download-provider-notification.c create mode 100644 provider/download-provider-notify.c create mode 100644 provider/download-provider-plugin-download-agent.c create mode 100644 provider/download-provider-pthread.c create mode 100644 provider/download-provider-queue-manager.c create mode 100644 provider/download-provider-queue.c create mode 100644 provider/download-provider-smack.c create mode 100644 provider/download-provider-utils.c create mode 100644 provider/include/download-provider-client-manager.h create mode 100644 provider/include/download-provider-client.h create mode 100755 provider/include/download-provider-config.h create mode 100644 provider/include/download-provider-db-defs.h create mode 100755 provider/include/download-provider-db.h create mode 100644 provider/include/download-provider-ipc.h create mode 100755 provider/include/download-provider-log.h create mode 100755 provider/include/download-provider-network.h create mode 100644 provider/include/download-provider-notification-manager.h create mode 100755 provider/include/download-provider-notification.h create mode 100644 provider/include/download-provider-notify.h create mode 100644 provider/include/download-provider-plugin-download-agent.h create mode 100755 provider/include/download-provider-pthread.h create mode 100644 provider/include/download-provider-queue-manager.h create mode 100755 provider/include/download-provider-queue.h create mode 100644 provider/include/download-provider-smack.h create mode 100644 provider/include/download-provider-utils.h create mode 100755 provider/include/download-provider.h rename res/images/{Q02_Notification_Download_failed.png => redwood/B03_processing_download_complete.png} (59%) create mode 100644 res/images/redwood/B03_processing_download_fail.png create mode 100644 res/images/redwood/U01_icon_broken.png create mode 100644 res/images/redwood/U01_icon_drm.png create mode 100644 res/images/redwood/U01_icon_excel.png create mode 100644 res/images/redwood/U01_icon_html.png create mode 100644 res/images/redwood/U01_icon_pdf.png create mode 100644 res/images/redwood/U01_icon_ppt.png create mode 100644 res/images/redwood/U01_icon_swf.png create mode 100644 res/images/redwood/U01_icon_text.png create mode 100644 res/images/redwood/U01_icon_tpk.png create mode 100644 res/images/redwood/U01_icon_unkown.png create mode 100644 res/images/redwood/U01_icon_vcs.png create mode 100644 res/images/redwood/U01_icon_word.png create mode 100644 res/images/redwood/U01_list_icon_image.png create mode 100644 res/images/redwood/U01_list_icon_mp3.png create mode 100644 res/images/redwood/U01_list_icon_mp4.png create mode 100644 res/images/redwood/noti_download_complete.png create mode 100644 res/images/redwood/noti_download_failed.png create mode 100644 res/images/tizen2.3/B03_Processing_download_complete.png create mode 100644 res/images/tizen2.3/B03_Processing_download_failed.png create mode 100644 res/images/tizen2.3/download_manager_icon_date.png create mode 100644 res/images/tizen2.3/download_manager_icon_drm.png create mode 100644 res/images/tizen2.3/download_manager_icon_html.png create mode 100644 res/images/tizen2.3/download_manager_icon_img.png create mode 100644 res/images/tizen2.3/download_manager_icon_movie.png create mode 100644 res/images/tizen2.3/download_manager_icon_music.png create mode 100644 res/images/tizen2.3/download_manager_icon_pdf.png create mode 100644 res/images/tizen2.3/download_manager_icon_ppt.png create mode 100644 res/images/tizen2.3/download_manager_icon_swf.png create mode 100644 res/images/tizen2.3/download_manager_icon_text.png create mode 100644 res/images/tizen2.3/download_manager_icon_tpk.png create mode 100644 res/images/tizen2.3/download_manager_icon_unknown.png create mode 100644 res/images/tizen2.3/download_manager_icon_word.png create mode 100644 res/images/tizen2.3/download_manager_icon_xls.png delete mode 100644 src/agent/CMakeLists.txt delete mode 100644 src/agent/download-agent-basic.c delete mode 100644 src/agent/download-agent-client-mgr.c delete mode 100644 src/agent/download-agent-debug.c delete mode 100644 src/agent/download-agent-dl-info-util.c delete mode 100644 src/agent/download-agent-dl-mgr.c delete mode 100644 src/agent/download-agent-file.c delete mode 100644 src/agent/download-agent-http-mgr.c delete mode 100644 src/agent/download-agent-http-misc.c delete mode 100644 src/agent/download-agent-http-queue.c delete mode 100644 src/agent/download-agent-installation.c delete mode 100644 src/agent/download-agent-interface.c delete mode 100644 src/agent/download-agent-plugin-conf.c delete mode 100644 src/agent/download-agent-plugin-install.c delete mode 100644 src/agent/download-agent-plugin-libsoup.c delete mode 100644 src/agent/download-agent-utils-dl-req-id-history.c delete mode 100644 src/agent/download-agent-utils.c delete mode 100644 src/agent/include/download-agent-basic.h delete mode 100644 src/agent/include/download-agent-client-mgr.h delete mode 100644 src/agent/include/download-agent-debug.h delete mode 100644 src/agent/include/download-agent-defs.h delete mode 100644 src/agent/include/download-agent-dl-info-util.h delete mode 100644 src/agent/include/download-agent-dl-mgr.h delete mode 100644 src/agent/include/download-agent-file.h delete mode 100644 src/agent/include/download-agent-http-mgr.h delete mode 100644 src/agent/include/download-agent-http-misc.h delete mode 100644 src/agent/include/download-agent-http-msg-handler.h delete mode 100644 src/agent/include/download-agent-http-queue.h delete mode 100644 src/agent/include/download-agent-installation.h delete mode 100644 src/agent/include/download-agent-interface.h delete mode 100644 src/agent/include/download-agent-mime-util.h delete mode 100644 src/agent/include/download-agent-plugin-conf.h delete mode 100644 src/agent/include/download-agent-plugin-http-interface.h delete mode 100644 src/agent/include/download-agent-plugin-install.h delete mode 100644 src/agent/include/download-agent-plugin-libsoup.h delete mode 100644 src/agent/include/download-agent-pthread.h delete mode 100644 src/agent/include/download-agent-type.h delete mode 100644 src/agent/include/download-agent-utils-dl-req-id-history.h delete mode 100644 src/agent/include/download-agent-utils.h delete mode 100644 src/download-provider-db.c delete mode 100644 src/download-provider-ipc.c delete mode 100644 src/download-provider-main.c delete mode 100644 src/download-provider-notification.c delete mode 100644 src/download-provider-pid.c delete mode 100644 src/download-provider-receiver.c delete mode 100644 src/download-provider-utils.c create mode 100644 systemd/download-provider.service create mode 100644 systemd/download-provider.socket diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 9470ff3..903e89d --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,76 +1,91 @@ -ADD_SUBDIRECTORY(src/agent) - CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -## PROJECT NAME -PROJECT(download-provider C) -SET(VERSION "0.0.1") - -IF("${CMAKE_BUILD_TYPE}" STREQUAL "") - SET(CMAKE_BUILD_TYPE "Debug") -ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") -MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") - -SET(DATABASE_DIR "/opt/dbspace") -SET(DATABASE_NAME ".download-provider.db") -SET(RES_DIR "/opt/data/download-provider") -SET(IMAGE_DIR "${RES_DIR}") - -INCLUDE(FindPkgConfig) - -pkg_check_modules(pkgs REQUIRED glib-2.0 - gobject-2.0 - db-util - sqlite3 - capi-appfw-application - capi-network-connection - bundle - dlog) - -FOREACH(flag ${pkgs_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -## INCLUDES -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/agent/include) - -set(LINK_LIBRARIES ${GLIB-2_LIBRARIES} - ${GOBJECT-2_LIBRARIES} - pthread - capi-appfw-application - downloadagent - ) - -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC") -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g -fpie -Wall") - -SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -Wl -fpie,--hash-style=both") - -ADD_DEFINITIONS( - -DDATABASE_DIR=\"${DATABASE_DIR}\" - -DDATABASE_NAME=\"${DATABASE_NAME}\" - -DIMAGE_DIR=\"${IMAGE_DIR}\" - ) - -ADD_EXECUTABLE(${PROJECT_NAME} - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-pid.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-ipc.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-notification.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-db.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-utils.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-receiver.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/download-provider-main.c ) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${LINK_LIBRARIES}) -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) +MESSAGE("PROJECT : ${PKG_NAME}") + +# DEFINES + +SET(VERSION ${PKG_VERSION}-${PKG_RELEASE}) +MESSAGE("VERSION : ${VERSION}") + +IF(DEFINED SUPPORT_WIFI_DIRECT) + MESSAGE("SUPPORT_WIFI_DIRECT: ${SUPPORT_WIFI_DIRECT}") + IF(SUPPORT_WIFI_DIRECT) + ADD_DEFINITIONS(-DSUPPORT_WIFI_DIRECT) + ENDIF(SUPPORT_WIFI_DIRECT) +ENDIF(DEFINED SUPPORT_WIFI_DIRECT) + +IF(DEFINED SUPPORT_LOG_MESSAGE) + MESSAGE("SUPPORT_LOG_MESSAGE: ${SUPPORT_LOG_MESSAGE}") + IF(SUPPORT_LOG_MESSAGE) + ADD_DEFINITIONS(-DSUPPORT_LOG_MESSAGE) + ENDIF(SUPPORT_LOG_MESSAGE) +ENDIF(DEFINED SUPPORT_LOG_MESSAGE) + +IF(DEFINED IPC_SOCKET) + ADD_DEFINITIONS(-DIPC_SOCKET=\"${IPC_SOCKET}\") +ENDIF(DEFINED IPC_SOCKET) + +IF(DEFINED NOTIFY_DIR) + ADD_DEFINITIONS(-DNOTIFY_DIR=\"${NOTIFY_DIR}\") +ENDIF(DEFINED NOTIFY_DIR) + +IF(DEFINED LOCALE_DIR) + ADD_DEFINITIONS(-DLOCALE_DIR=\"${LOCALE_DIR}\") +ENDIF(DEFINED LOCALE_DIR) + +IF(DEFINED SUPPORT_SECURITY_PRIVILEGE) + MESSAGE("SUPPORT_SECURITY_PRIVILEGE: ${SUPPORT_SECURITY_PRIVILEGE}") + IF(SUPPORT_SECURITY_PRIVILEGE) + ADD_DEFINITIONS(-DSUPPORT_SECURITY_PRIVILEGE) + ENDIF(SUPPORT_SECURITY_PRIVILEGE) +ENDIF(DEFINED SUPPORT_SECURITY_PRIVILEGE) + +IF(DEFINED SUPPORT_COMPANION_MODE) + MESSAGE("SUPPORT_COMPANION_MODE: ${SUPPORT_COMPANION_MODE}") + IF(SUPPORT_COMPANION_MODE) + ADD_DEFINITIONS(-DSUPPORT_COMPANION_MODE) + ENDIF(SUPPORT_COMPANION_MODE) +ENDIF(DEFINED SUPPORT_COMPANION_MODE) + +IF (TIZEN_2_3_UX) + MESSAGE("TIZEN_2_3_UX:On") + ADD_DEFINITIONS("-D_TIZEN_2_3_UX") +ENDIF(TIZEN_2_3_UX) + +# BUILD + +ADD_SUBDIRECTORY(agent) +ADD_SUBDIRECTORY(provider-interface) +ADD_SUBDIRECTORY(provider) +# i18n +IF(TIZEN_2_3_UX) +ADD_SUBDIRECTORY(po/tizen2.3) +ELSE(TIZEN_2_3_UX) +ADD_SUBDIRECTORY(po/redwood) +ENDIF(TIZEN_2_3_UX) + +# INSTALL + +PROJECT(${PKG_NAME} C) +SET(PACKAGE_DESCRIPTION "Defines for ${PROJECT_NAME}") CONFIGURE_FILE(download-provider.pc.in download-provider.pc @ONLY) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider.pc DESTINATION lib/pkgconfig) -INSTALL(FILES include/download-provider.h DESTINATION include/${PROJECT_NAME}) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -INSTALL(PROGRAMS download-provider-service DESTINATION /etc/rc.d/init.d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/download-provider.service DESTINATION /usr/lib/systemd/system) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/systemd/download-provider.socket DESTINATION /usr/lib/systemd/system) # install images -INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/ DESTINATION /opt/data/download-provider/ - FILES_MATCHING - PATTERN "*.png" - ) +IF(TIZEN_2_3_UX) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/tizen2.3/ DESTINATION ${IMAGE_DIR}) +ELSE(TIZEN_2_3_UX) +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/redwood/ DESTINATION ${IMAGE_DIR}) +ENDIF(TIZEN_2_3_UX) + +IF(DEFINED LICENSE_DIR) + CONFIGURE_FILE(LICENSE.Apache-2.0 share/license/${PROJECT_NAME}) + INSTALL(FILES share/license/${PROJECT_NAME} DESTINATION ${LICENSE_DIR}) +ENDIF(DEFINED LICENSE_DIR) + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/dump-download-provider.sh DESTINATION ${CMAKE_LOG_DUMP_SCRIPT_DIR}) + diff --git a/LICENSE b/LICENSE deleted file mode 100755 index bbe9d02..0000000 --- a/LICENSE +++ /dev/null @@ -1,206 +0,0 @@ -Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - diff --git a/LICENSE.Apache-2.0 b/LICENSE.Apache-2.0 new file mode 100755 index 0000000..798d252 --- /dev/null +++ b/LICENSE.Apache-2.0 @@ -0,0 +1,35 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +1. Definitions. +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. +END OF TERMS AND CONDITIONS +APPENDIX: How to apply the Apache License to your work. +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. +Copyright [yyyy] [name of copyright owner] +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.If work from Apache: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. If licensing your own work: Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..dc6f246 --- /dev/null +++ b/NOTICE @@ -0,0 +1,13 @@ +Copyright 2014 Samsung Electronics Co., Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/agent/CMakeLists.txt b/agent/CMakeLists.txt new file mode 100755 index 0000000..c92fc48 --- /dev/null +++ b/agent/CMakeLists.txt @@ -0,0 +1,116 @@ +PROJECT(downloadagent2 C) + +SET(VERSION "0.1.0") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-D_TARGET") + SET(CMAKE_C_FLAGS_RELEASE "-mabi=aapcs-linux -msoft-float -O2") +ENDIF("${ARCH}" MATCHES "^arm.*") + +#DA Engine Include Directory +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include) + +SET(SRCS_PATH ".") +SET(SRCS_DA + ${SRCS_PATH}/download-agent-interface.c + ${SRCS_PATH}/download-agent-client-mgr.c + ${SRCS_PATH}/download-agent-dl-mgr.c + ${SRCS_PATH}/download-agent-dl-info.c + ${SRCS_PATH}/download-agent-http-mgr.c + ${SRCS_PATH}/download-agent-http-msg-handler.c + ${SRCS_PATH}/download-agent-encoding.c + ${SRCS_PATH}/download-agent-file.c + ${SRCS_PATH}/download-agent-plugin-conf.c + ${SRCS_PATH}/download-agent-mime-util.c +) + +SET(HEADERS + include/download-agent-defs.h + include/download-agent-interface.h +) + +INCLUDE(FindPkgConfig) + +MESSAGE("SUPPORT_SYS_RESOURCE: ${SUPPORT_SYS_RESOURCE}") +IF (SUPPORT_SYS_RESOURCE) +pkg_check_modules(subpkgs REQUIRED + xdgmime + vconf + capi-network-connection + dlog + system-resource + storage +) +ELSE (SUPPORT_SYS_RESOURCE) +pkg_check_modules(subpkgs REQUIRED + xdgmime + vconf + capi-network-connection + dlog + storage +) +ENDIF (SUPPORT_SYS_RESOURCE) + +IF ("${HTTP_LIB}" MATCHES "libcurl") + MESSAGE("HTTP_LIB: ${HTTP_LIB}") + pkg_check_modules(httppkgs REQUIRED + libcurl + ) + LIST(APPEND SRCS_DA + ${SRCS_PATH}/download-agent-plugin-libcurl.c + ) +ENDIF ("${HTTP_LIB}" MATCHES "libcurl") + +IF (SUPPORT_OMA_DRM) + MESSAGE("SUPPORT_OMA_DRM: ${SUPPORT_OMA_DRM}") + ADD_DEFINITIONS("-D_ENABLE_OMA_DRM") + LIST(APPEND SRCS_DA + ${SRCS_PATH}/download-agent-plugin-drm.c + ) + pkg_check_modules(drmpkgs REQUIRED + drm-client + drm-trusted + ) +ENDIF (SUPPORT_OMA_DRM) + +IF (SUPPORT_SYS_RESOURCE) + ADD_DEFINITIONS("-D_ENABLE_SYS_RESOURCE") +ENDIF (SUPPORT_SYS_RESOURCE) + +IF (SUPPORT_DOWNLOAD_BOOSTER) + MESSAGE("SUPPORT_DOWNLOAD_BOOSTER:${SUPPORT_DOWNLOAD_BOOSTER}") + ADD_DEFINITIONS("-D_RAF_SUPPORT") + ADD_DEFINITIONS("-D_DOWNLOAD_BOOSTER_SUPPORT") +ENDIF (SUPPORT_DOWNLOAD_BOOSTER) + +FOREACH(flag ${subpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${httppkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF (SUPPORT_OMA_DRM) + FOREACH(flag ${drmpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") + ENDFOREACH(flag) + #This is request of DRM Team. + ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64") +ENDIF (SUPPORT_OMA_DRM) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -Wall") + +ADD_DEFINITIONS("-D_ENABLE_DLOG") +#This should be removed when release a target +ADD_DEFINITIONS("-D_SAMSUNG_MIME_POLICY") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DA}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS} ${httppkgs_LDFLAGS} ${drmpkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/agent/download-agent-client-mgr.c b/agent/download-agent-client-mgr.c new file mode 100755 index 0000000..82dd516 --- /dev/null +++ b/agent/download-agent-client-mgr.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "download-agent-client-mgr.h" + +da_ret_t send_client_paused_info(da_info_t *da_info) +{ + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + if (da_info->is_cb_update && da_info->cb_info.paused_cb) { + da_info->cb_info.paused_cb(da_info->da_id, + req_info->user_req_data, req_info->user_client_data); + DA_LOGV("id[%d]", da_info->da_id); + } else { + DA_LOGV("No CB:id[%d]", da_info->da_id); + } + + return DA_RESULT_OK; +} + +da_ret_t send_client_update_dl_info(da_info_t *da_info) +{ + download_info_t *info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (da_info->is_cb_update && da_info->cb_info.download_info_cb) { + info = (download_info_t *)calloc(1, sizeof(download_info_t)); + if (!info) + return DA_ERR_FAIL_TO_MEMALLOC; + info->download_id = da_info->da_id; + info->file_size = http_info->content_len_from_header; + if (http_info->content_type_from_header) + info->file_type = strdup(http_info->content_type_from_header); + if (file_info->file_path) + info->tmp_saved_path = strdup(file_info->file_path); + if (file_info->pure_file_name) + info->content_name = strdup(file_info->pure_file_name); + if (http_info->etag_from_header) { + info->etag = strdup(http_info->etag_from_header); + //DA_SECURE_LOGI("etag[%s]", info->etag); + } + da_info->cb_info.download_info_cb(info, + req_info->user_req_data, req_info->user_client_data); + DA_LOGD("id[%d]", info->download_id); + //DA_LOGI("id[%d]total_size[%lu]", info->download_id, info->file_size); + //if (http_info->content_type_from_header) + //DA_SECURE_LOGI("mime_type[%s]", http_info->content_type_from_header); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); + } + return DA_RESULT_OK; +} + +da_ret_t send_client_update_progress_info(da_info_t *da_info) +{ + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + if (!file_info->is_updated) + return DA_RESULT_OK; + + if (da_info->is_cb_update && da_info->cb_info.progress_cb) { + da_info->cb_info.progress_cb(da_info->da_id, + file_info->bytes_written_to_file, + req_info->user_req_data, req_info->user_client_data); + DA_LOGV("id[%d],size[%llu]", da_info->da_id, + file_info->bytes_written_to_file); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); + } + file_info->is_updated = DA_FALSE; + return DA_RESULT_OK; +} + +da_ret_t send_client_finished_info(da_info_t *da_info, int err) +{ + finished_info_t *info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (da_info->is_cb_update && da_info->cb_info.finished_cb) { + info = (finished_info_t *)calloc(1, sizeof(finished_info_t)); + if (!info) + return DA_ERR_FAIL_TO_MEMALLOC; + info->download_id = da_info->da_id; + if (http_info->http_msg_response) + info->http_status = http_info->http_msg_response->status_code; + else + DA_LOGE("http_msg_response is NULL"); + if (file_info->file_path) + info->saved_path = strdup(file_info->file_path); + if (http_info->etag_from_header) + info->etag = strdup(http_info->etag_from_header); + info->err = err; + da_info->cb_info.finished_cb(info, + req_info->user_req_data, req_info->user_client_data); + DA_LOGD("id[%d]", info->download_id); + //DA_LOGI("id[%d],err[%d], http_status[%d]", info->download_id, + //info->err, info->http_status); + } else { + DA_LOGI("No CB:id[%d]", da_info->da_id); + } + return DA_RESULT_OK; +} + diff --git a/agent/download-agent-dl-info.c b/agent/download-agent-dl-info.c new file mode 100644 index 0000000..6e49145 --- /dev/null +++ b/agent/download-agent-dl-info.c @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "download-agent-dl-info.h" +#include "download-agent-http-mgr.h" +#include "download-agent-http-msg-handler.h" + +static pthread_mutex_t mutex_da_info_list = PTHREAD_MUTEX_INITIALIZER; + +static void __init_da_info(int id) +{ + da_info_t *da_info = DA_NULL; + file_info_t *file_info = DA_NULL; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + da_info = (da_info_t *)calloc(1, sizeof(da_info_t)); + if (!da_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + da_info_list[id] = DA_NULL; + return; + } + file_info = (file_info_t *)calloc(1, sizeof(file_info_t)); + if (!file_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + da_info_list[id] = DA_NULL; + return; + } + http_info = (http_info_t *)calloc(1, sizeof(http_info_t)); + if (!http_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + free(file_info); + da_info_list[id] = DA_NULL; + return; + } + req_info = (req_info_t *)calloc(1, sizeof(req_info_t)); + if (!req_info) { + DA_LOGE("Fail to calloc. id[%d]",id); + free(da_info); + free(file_info); + free(http_info); + da_info_list[id] = DA_NULL; + return; + } + + da_info->da_id = DA_INVALID_ID; + da_info->tid = DA_INVALID_ID; + memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t)); + da_info->is_cb_update = DA_FALSE; + da_info->http_info = http_info; + da_info->file_info = file_info; + da_info->req_info = req_info; + da_info->update_time = 0; + da_info_list[id] = da_info; +} + +da_ret_t init_http_msg_t(http_msg_t **http_msg) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *temp = DA_NULL; + temp = (http_msg_t *)calloc(1, sizeof(http_msg_t)); + if (!temp) { + DA_LOGE("Fail to calloc. id"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + *http_msg = temp; + return ret; +} + +void destroy_http_msg_t(http_msg_t *http_msg) +{ + if (http_msg) + free(http_msg); + http_msg = DA_NULL; + return; +} + +da_ret_t get_available_da_id(int *available_id) +{ + da_ret_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD; + int i = 0; + + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if (da_info_list[i] == DA_NULL) { + *available_id = i; + DA_LOGV("available download id[%d]", *available_id); + __init_da_info(i); + ret = DA_RESULT_OK; + break; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + + return ret; +} + +da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info) +{ + da_ret_t ret = DA_ERR_INVALID_ARGUMENT; + int i = 0; + + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if (DA_NULL != da_info_list[i] && da_info_list[i]->da_id == id) { + *out_info = da_info_list[i]; + ret = DA_RESULT_OK; + break; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + + return ret; +} + +da_ret_t __is_supporting_protocol(const char *url) +{ + da_ret_t ret = DA_RESULT_OK; + int wanted_str_len = 0; + char *protocol = NULL; + char *wanted_str_start = NULL; + char *wanted_str_end = NULL; + + if (DA_NULL == url || strlen(url) < 1) + return DA_ERR_INVALID_URL; + + wanted_str_start = (char*)url; + wanted_str_end = strstr(url, "://"); + if (!wanted_str_end) { + DA_LOGE("No protocol on this url"); + return DA_ERR_INVALID_URL; + } + + wanted_str_len = wanted_str_end - wanted_str_start; + protocol = (char*)calloc(1, wanted_str_len + 1); + if (!protocol) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + strncpy(protocol, wanted_str_start, wanted_str_len); + + if (strlen(protocol) < 1) + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + else if (strcasecmp(protocol, "http") != 0 && + strcasecmp(protocol, "https") != 0) + ret = DA_ERR_UNSUPPORTED_PROTOCAL; + + free(protocol); + return ret; +} + +da_ret_t copy_user_input_data(da_info_t *da_info, const char *url, + req_data_t *ext_data, da_cb_t *da_cb_data) +{ + da_ret_t ret = DA_RESULT_OK; + + if (!url || !da_info) { + DA_LOGE("Invalid Param"); + return DA_ERR_INVALID_ARGUMENT; + } + + ret = __is_supporting_protocol(url); + if (ret != DA_RESULT_OK) { + DA_SECURE_LOGE("url[%s]", url); + return ret; + } + + if (ext_data) { + req_info_t *req_info = da_info->req_info; + + if (ext_data->request_header_count > 0) { + int i = 0; + int count = ext_data->request_header_count; + req_info->req_header = (char **)calloc(count, sizeof(char *)); + if(DA_NULL == req_info->req_header) { + DA_LOGE("Fail to calloc"); + free(req_info); + da_info->req_info = DA_NULL; + return DA_ERR_FAIL_TO_MEMALLOC; + } + for (i = 0; i < count; i++) { + if (ext_data->request_header[i]) + req_info->req_header[i] = + strdup(ext_data->request_header[i]); + } + req_info->req_header_count = count; + } + + if (url) + req_info->url = strdup(url); + if (ext_data->install_path) + req_info->install_path = strdup(ext_data->install_path); + if (ext_data->file_name) + req_info->file_name = strdup(ext_data->file_name); + if (ext_data->etag) + req_info->etag = strdup(ext_data->etag); + if (ext_data->temp_file_path) + req_info->temp_file_path = strdup(ext_data->temp_file_path); + if (ext_data->pkg_name) + req_info->pkg_name = strdup(ext_data->pkg_name); + req_info->network_bonding = ext_data->network_bonding; + if (ext_data->user_req_data) + req_info->user_req_data = ext_data->user_req_data; + if (ext_data->user_client_data) + req_info->user_client_data = ext_data->user_client_data; + da_info->req_info = req_info; + } + if (da_cb_data) { + da_info->is_cb_update = DA_TRUE; + memcpy(&(da_info->cb_info), da_cb_data, sizeof(da_cb_t)); + } + return ret; +} + +static void __destroy_http_msg(http_msg_t *msg) +{ + msg->curl = DA_NULL; + free(msg); +} + +static void __destroy_http_msg_request(http_msg_request_t *msg) +{ + if (msg) { + http_msg_request_destroy(&msg); + free(msg); + } +} + +static void __destroy_http_msg_response(http_msg_response_t *msg) +{ + if (msg) { + http_msg_response_destroy(&msg); + free(msg); + } +} + +static void __destroy_req_info(req_info_t *req_info) +{ + if (req_info) { + free(req_info->url); + if (req_info->req_header && req_info->req_header_count > 0) { + int i = 0; + int count = req_info->req_header_count; + for (i = 0; i < count; i++) { + free(req_info->req_header[i]); + req_info->req_header[i] = DA_NULL; + } + free(req_info->req_header); + req_info->req_header = DA_NULL; + req_info->req_header_count = 0; + } + free(req_info->install_path); + free(req_info->file_name); + free(req_info->etag); + free(req_info->temp_file_path); + free(req_info->pkg_name); + req_info->user_req_data = DA_NULL; + req_info->user_client_data = DA_NULL; + free(req_info); + } +} + +void destroy_http_info(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + free(http_info->proxy_addr); + free(http_info->content_type_from_header); + free(http_info->etag_from_header); + free(http_info->file_name_from_header); + if (http_info->http_msg_request) { + __destroy_http_msg_request(http_info->http_msg_request); + http_info->http_msg_request = DA_NULL; + } + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + DA_MUTEX_DESTROY(&(http_info->mutex_state)); + DA_MUTEX_DESTROY(&(http_info->mutex_http)); + DA_COND_DESTROY(&(http_info->cond_http)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + http_info->error_code = 0; + free(http_info); + } +} + +void destroy_file_info(file_info_t *file_info) +{ + if (file_info) { + file_info->file_handle = DA_NULL; + free(file_info->pure_file_name); + free(file_info->extension); + free(file_info->file_path); + free(file_info->mime_type); + free(file_info->buffer); + file_info->buffer_len = 0; + file_info->file_size = 0; +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = 0; +#endif + file_info->bytes_written_to_file = 0; + file_info->is_updated = DA_FALSE; + free(file_info); + } +} + +// For pause and resume case +void reset_http_info_for_resume(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + http_info->location_url = DA_NULL; + free(http_info->proxy_addr); + http_info->proxy_addr = DA_NULL; + free(http_info->content_type_from_header); + http_info->content_type_from_header = DA_NULL; + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + } +} + +void reset_http_info(http_info_t *http_info) +{ + if (http_info) { + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + free(http_info->location_url); + http_info->location_url = DA_NULL; + free(http_info->proxy_addr); + http_info->proxy_addr = DA_NULL; + free(http_info->content_type_from_header); + http_info->content_type_from_header = DA_NULL; + if (http_info->http_msg_request) { + __destroy_http_msg_request(http_info->http_msg_request); + http_info->http_msg_request = DA_NULL; + } + if (http_info->http_msg_response) { + __destroy_http_msg_response(http_info->http_msg_response); + http_info->http_msg_response = DA_NULL; + } + if (http_info->http_msg) { + __destroy_http_msg(http_info->http_msg); + http_info->http_msg = DA_NULL; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->content_len_from_header = 0; + http_info->total_size = 0; + } +} + +da_bool_t is_valid_download_id(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + DA_MUTEX_LOCK(&mutex_da_info_list); + if (DA_NULL == da_info_list[download_id]) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_FALSE; + } + if (is_stopped_state(da_info_list[download_id])) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_TRUE; + } + if (da_info_list[download_id]->da_id != DA_INVALID_ID) { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_TRUE; + } else { + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return DA_FALSE; + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); + return ret; +} + +void destroy_da_info_list() +{ + int i = 0; + DA_MUTEX_LOCK(&mutex_da_info_list); + for (i = 0; i < DA_MAX_ID; i++) { + if(DA_NULL != da_info_list[i]) { + if (da_info_list[i]->req_info) { + __destroy_req_info(da_info_list[i]->req_info); + da_info_list[i]->req_info = DA_NULL; + } + if (da_info_list[i]->http_info) { + destroy_http_info(da_info_list[i]->http_info); + da_info_list[i]->http_info = DA_NULL; + } + if (da_info_list[i]->file_info) { + destroy_file_info(da_info_list[i]->file_info); + da_info_list[i]->file_info = DA_NULL; + } + free(da_info_list[i]); + da_info_list[i] = DA_NULL; + } + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); +} + +void destroy_da_info(int id) +{ + da_info_t *da_info = DA_NULL; + DA_MUTEX_LOCK(&mutex_da_info_list); + da_info = da_info_list[id]; + if (da_info) { + if (da_info->req_info) { + __destroy_req_info(da_info->req_info); + da_info->req_info = DA_NULL; + } + if (da_info->http_info) { + destroy_http_info(da_info->http_info); + da_info->http_info = DA_NULL; + } + if (da_info->file_info) { + destroy_file_info(da_info->file_info); + da_info->file_info = DA_NULL; + } + da_info->da_id = DA_INVALID_ID; + da_info->tid = DA_INVALID_ID; + memset(&(da_info->cb_info), 0x00, sizeof(da_cb_t)); + free(da_info); + da_info_list[id] = DA_NULL; + } + DA_MUTEX_UNLOCK(&mutex_da_info_list); +} diff --git a/agent/download-agent-dl-mgr.c b/agent/download-agent-dl-mgr.c new file mode 100755 index 0000000..e57f3f3 --- /dev/null +++ b/agent/download-agent-dl-mgr.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifdef _ENABLE_SYS_RESOURCE +#include "resourced.h" +#endif + +#include "download-agent-dl-mgr.h" +#include "download-agent-dl-info.h" +#include "download-agent-http-mgr.h" + +void __thread_clean_up_handler_for_start_download(void *arg) +{ + DA_LOGI("cleanup for thread id[%lu]", pthread_self()); +} + +da_ret_t __download_content(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + ret = DA_ERR_INVALID_ARGUMENT; + return ret; + } + + ret = request_http_download(da_info); + return ret; +} + + +static void *__thread_start_download(void *data) +{ + da_info_t *da_info = DA_NULL; + req_info_t *req_info = DA_NULL; + int da_id = DA_INVALID_ID; + +// DA_LOGV(""); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); + + da_info = (da_info_t *)data; + NULL_CHECK_RET_OPT(da_info, DA_NULL); + req_info = da_info->req_info; + NULL_CHECK_RET_OPT(req_info, DA_NULL); + + da_id = da_info->da_id; + pthread_cleanup_push(__thread_clean_up_handler_for_start_download, DA_NULL); +#ifdef _ENABLE_SYS_RESOURCE + if (req_info->pkg_name) { + pid_t tid = (pid_t) syscall(SYS_gettid); + da_info->tid = (pid_t) syscall(SYS_gettid); + DA_SECURE_LOGI("pkg_name[%s] threadid[%lu]", + req_info->pkg_name,pthread_self()); + if (join_app_performance(req_info->pkg_name, tid) != + RESOURCED_ERROR_OK) { + DA_LOGE("Can not put app to network performance id[%d]", da_id); + } + } +#endif + __download_content(da_info); + destroy_da_info(da_id); + pthread_cleanup_pop(0); + DA_LOGI("=====EXIT thread : da_id[%d]=====", da_id); + pthread_exit((void *)DA_NULL); + return DA_NULL; +} + +da_ret_t start_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + pthread_attr_t thread_attr; + pthread_t tid; + if (pthread_attr_init(&thread_attr) != 0) { + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } + + if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0) { + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } + + if (pthread_create(&(tid), &thread_attr, + __thread_start_download, da_info) < 0) { + DA_LOGE("Fail to make thread:id[%d]", da_info->da_id); + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + } else { + if (tid < 1) { + DA_LOGE("The thread start is failed before calling this"); +// When http resource is leaked, the thread ID is initialized at error handling section of thread_start_download() +// Because the thread ID is initialized, the ptrhead_detach should not be called. This is something like timing issue between threads. +// thread info and basic_dl_input is freed at thread_start_download(). And it should not returns error code in this case. + ret = DA_ERR_FAIL_TO_CREATE_THREAD; + goto ERR; + } + } + da_info->thread_id = tid; + DA_LOGI("Thread create:thread id[%lu]", da_info->thread_id); +ERR: + if (DA_RESULT_OK != ret) { + destroy_da_info(da_info->da_id); + } + return ret; +} + +da_ret_t cancel_download(int dl_id, da_bool_t is_enable_cb) +{ + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; + + DA_LOGV(""); + + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = is_enable_cb; + ret = request_to_cancel_http_download(da_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOGI("Download cancel Successful for download id[%d]", da_info->da_id); + +ERR: + return ret; +} + +da_ret_t suspend_download(int dl_id, da_bool_t is_enable_cb) +{ + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; + + DA_LOGV(""); + + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = is_enable_cb; + ret = request_to_suspend_http_download(da_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOGV("Download Suspend Successful for download id[%d]", da_info->da_id); +ERR: + return ret; + +} + +da_ret_t resume_download(int dl_id) +{ + da_ret_t ret = DA_RESULT_OK; + da_info_t *da_info = DA_NULL; + + DA_LOGV(""); + + ret = get_da_info_with_da_id(dl_id, &da_info); + if (ret != DA_RESULT_OK || !da_info) { + return DA_ERR_INVALID_ARGUMENT; + } + da_info->is_cb_update = DA_TRUE; + ret = request_to_resume_http_download(da_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_LOGV("Download Resume Successful for download id[%d]", da_info->da_id); +ERR: + return ret; +} + diff --git a/src/agent/download-agent-encoding.c b/agent/download-agent-encoding.c old mode 100644 new mode 100755 similarity index 71% rename from src/agent/download-agent-encoding.c rename to agent/download-agent-encoding.c index 18c9643..3f14fca --- a/src/agent/download-agent-encoding.c +++ b/agent/download-agent-encoding.c @@ -1,36 +1,27 @@ /* - * Download Agent + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * @file download-agent-encoding.c - * @brief Utilities to manipulate encoding and charset - * @author Keunsoon Lee (keunsoon.lee@samsung.com) */ -#include #include #include -#include +#include "glib.h" -#include "download-agent-encoding.h" #include "download-agent-debug.h" +#include "download-agent-encoding.h" -da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, +da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str, char **out_charset_type, char *out_encoding_type, char **out_raw_encoded_str); @@ -43,7 +34,7 @@ da_bool_t is_base64_encoded_word(const char *in_str) char *found_str = DA_NULL; if (!in_str) { - DA_LOG_ERR(Default, "input string is NULL"); + DA_LOGE("input string is NULL"); return DA_FALSE; } @@ -56,14 +47,10 @@ da_bool_t is_base64_encoded_word(const char *in_str) snprintf(second_needle, sizeof(second_needle), "%s", "?="); // ?= } -// DA_LOG(Default, "needle = [%s], haystack = [%s]", first_needle, haystack); - found_str = strstr(haystack, first_needle); if (found_str) { if (found_str == haystack) { -// DA_LOG(Default, "Input string is starting with %s", needle); haystack = haystack + strlen(haystack) - strlen(second_needle); -// DA_LOG(Default, "second haystack is [%s]", haystack); if(!strcmp(haystack, second_needle)) return DA_TRUE; } @@ -71,11 +58,10 @@ da_bool_t is_base64_encoded_word(const char *in_str) return DA_FALSE; } -da_result_t decode_base64_encoded_str(const char *in_encoded_str, +da_ret_t decode_base64_encoded_str(const char *in_encoded_str, char **out_decoded_ascii_str) { - da_result_t ret = DA_RESULT_OK; - + da_ret_t ret = DA_RESULT_OK; const char *org_str = DA_NULL; char *charset_type = NULL; char encoding_type = '\0'; @@ -85,11 +71,11 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, guchar *g_decoded_text = NULL; gsize g_decoded_text_len = 0; - DA_LOG(Default, "input str = [%s]", in_encoded_str); + DA_SECURE_LOGD("input str = [%s]", in_encoded_str); org_str = in_encoded_str; if(!org_str) { - DA_LOG_ERR(Default, "Input string is NULL"); + DA_LOGE("Input string is NULL"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } @@ -100,10 +86,8 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, goto ERR; } -// DA_LOG(Default, "charset = [%s], encoding = [%c], raw = [%s]", charset_type, encoding_type, raw_encoded_str); - if(encoding_type != 'B') { - DA_LOG_ERR(Default, "Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type); + DA_LOGE("Encoded Word is not encoded with Base64, but %c. We can only handle Base64.", encoding_type); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } @@ -118,54 +102,46 @@ da_result_t decode_base64_encoded_str(const char *in_encoded_str, g_decoded_text = g_base64_decode(g_encoded_text, &g_decoded_text_len); if(g_decoded_text) { - DA_LOG(Default, "g_decoded_text = [%s]", g_decoded_text); + DA_SECURE_LOGD("g_decoded_text = [%s]", g_decoded_text); decoded_str = (char*)calloc(1, g_decoded_text_len+1); if(!decoded_str) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } else { memcpy(decoded_str, g_decoded_text, g_decoded_text_len); } } - DA_LOG(Default, "decoded_str = [%s]", decoded_str); + DA_SECURE_LOGD("decoded_str = [%s]", decoded_str); ERR: *out_decoded_ascii_str = decoded_str; - if(charset_type) { free(charset_type); charset_type = NULL; } - if(raw_encoded_str) { free(raw_encoded_str); raw_encoded_str = NULL; } - if(g_decoded_text) { g_free(g_decoded_text); } - return ret; } - -da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, +da_ret_t _parsing_base64_encoded_str(const char *in_encoded_str, char **out_charset_type, char *out_encoding_type, char **out_raw_encoded_str) { - da_result_t ret = DA_RESULT_OK; - + da_ret_t ret = DA_RESULT_OK; const char *org_str = DA_NULL; // e.g. =?UTF-8?B?7Jew7JWE7JmA7IKs7J6QLmpwZw==?= char *charset_type = NULL; // e.g. UTF-8 char encoding_type = '\0'; // e.g. B (means Base64) char *raw_encoded_str = NULL; // e.g. 7Jew7JWE7JmA7IKs7J6QLmpwZw== - char *haystack = DA_NULL; char needle[8] = {0,}; - char *wanted_str = DA_NULL; int wanted_str_len = 0; char *wanted_str_start = DA_NULL; @@ -173,7 +149,7 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, org_str = in_encoded_str; if (!org_str) { - DA_LOG_ERR(Default, "Input string is NULL"); + DA_LOGE("Input string is NULL"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } @@ -183,12 +159,11 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, snprintf(needle, sizeof(needle), "=?"); wanted_str_end = strstr(haystack, needle); if (!wanted_str_end) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } else { wanted_str = wanted_str_end + strlen(needle); - DA_LOG(Default, "strip [%s]", wanted_str); } // for charset @@ -196,14 +171,14 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, needle[0] = '?'; wanted_str_end = strchr(haystack, needle[0]); if (!wanted_str_end) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } else { wanted_str_len = wanted_str_end - wanted_str_start + 1; wanted_str = (char*)calloc(1, wanted_str_len+1); if (!wanted_str) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } else { @@ -212,27 +187,26 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, wanted_str = DA_NULL; } - DA_LOG(Default, "charset [%s]", charset_type); + DA_LOGV("charset [%s]", charset_type); } - // for encoding encoding_type = *(++wanted_str_end); - DA_LOG(Default, "encoding [%c]", encoding_type); + DA_LOGV("encoding [%c]", encoding_type); // for raw encoded str haystack = wanted_str_start = wanted_str_end + 1; snprintf(needle, sizeof(needle), "?="); wanted_str_end = strstr(haystack, needle); if (!wanted_str_end) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); ret = DA_ERR_INVALID_ARGUMENT; goto ERR; } else { wanted_str_len = wanted_str_end - wanted_str_start + 1; wanted_str = (char*)calloc(1, wanted_str_len+1); if (!wanted_str) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } else { @@ -241,9 +215,8 @@ da_result_t _parsing_base64_encoded_str(const char *in_encoded_str, wanted_str = NULL; } - DA_LOG(Default, "raw encoded str [%s]", raw_encoded_str); + DA_SECURE_LOGD("raw encoded str [%s]", raw_encoded_str); } - ERR: if (ret != DA_RESULT_OK) { if (charset_type) { @@ -251,17 +224,15 @@ ERR: charset_type = NULL; } } - *out_charset_type = charset_type; *out_encoding_type = encoding_type; *out_raw_encoded_str = raw_encoded_str; - return ret; } void decode_url_encoded_str(const char *in_encoded_str, char **out_str) { - char *in = NULL; + char *in = NULL; char *out = NULL; *out_str = calloc(1, strlen(in_encoded_str) + 1); if (*out_str == NULL) @@ -288,4 +259,3 @@ void decode_url_encoded_str(const char *in_encoded_str, char **out_str) out++; } } - diff --git a/agent/download-agent-file.c b/agent/download-agent-file.c new file mode 100755 index 0000000..466a0dd --- /dev/null +++ b/agent/download-agent-file.c @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "download-agent-debug.h" +#include "download-agent-file.h" +#include "download-agent-mime-util.h" +/* FIXME Later */ +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-drm.h" +#include "download-agent-plugin-conf.h" +#include + + +#define NO_NAME_TEMP_STR "No name" +#define MAX_SUFFIX_COUNT 1000000000 + +da_ret_t __saved_file_open(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *actual_file_path = DA_NULL; + void *fd = DA_NULL; + + DA_LOGV(""); + + actual_file_path = file_info->file_path; + if (!actual_file_path) + return DA_ERR_INVALID_ARGUMENT; + + fd = fopen(actual_file_path, "a+"); // for resume + if (fd == DA_NULL) { + DA_LOGE("File open failed"); + if (errno == ENOSPC) + ret = DA_ERR_DISK_FULL; + else + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + file_info->file_handle = fd; + //DA_SECURE_LOGD("file path for saving[%s]", file_info->file_path); + +ERR: + if (DA_RESULT_OK != ret) { + file_info->file_handle = DA_NULL; + } + return ret; +} + +da_ret_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char **out_pure_file_name, char **out_extension) +{ + char *file_name = DA_NULL; + char *tmp_ptr = DA_NULL; + char temp_file[DA_MAX_FILE_PATH_LEN] = {0,}; + char tmp_ext[DA_MAX_STR_LEN] = {0,}; + int len = 0; + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + + if (!in_file_name) + return DA_ERR_INVALID_ARGUMENT; + + file_name = (char *)in_file_name; + tmp_ptr = strrchr(file_name, '.'); + if (tmp_ptr) + tmp_ptr++; + if (tmp_ptr && out_extension) { + strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1); + *out_extension = strdup((const char*) tmp_ext); + DA_SECURE_LOGD("extension [%s]", *out_extension); + } + + if (!out_pure_file_name) + return ret; + + if (tmp_ptr) + len = tmp_ptr - file_name - 1; + else + len = strlen(file_name); + + if (len >= DA_MAX_FILE_PATH_LEN) { + strncpy((char*) temp_file, file_name, + DA_MAX_FILE_PATH_LEN - 1); + } else { + strncpy((char*) temp_file, file_name, len); + } + + delete_prohibited_char((char*) temp_file, + strlen((char*) temp_file)); + if (strlen(temp_file) < 1) { + *out_pure_file_name = strdup(NO_NAME_TEMP_STR); + } else { + *out_pure_file_name = strdup( + (const char*) temp_file); + } + + DA_LOGV( "pure file name [%s]", *out_pure_file_name); + return ret; +} + +da_ret_t __file_write_buf_make_buf(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + + DA_LOGV(""); + + buffer = (char*) calloc(1, DA_FILE_BUF_SIZE); + if (DA_NULL == buffer) { + DA_LOGE("Calloc failure "); + ret = DA_ERR_FAIL_TO_MEMALLOC; + } else { + file_info->buffer_len = 0; + file_info->buffer = buffer; + } + + return ret; +} + +da_ret_t __file_write_buf_destroy_buf(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + NULL_CHECK_RET(file_info); + + free(file_info->buffer); + file_info->buffer = DA_NULL; + file_info->buffer_len = 0; + + return ret; +} + +da_ret_t __file_write_buf_flush_buf(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + int buffer_size = 0; + int write_success_len = 0; + void *fd = DA_NULL; + + // DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (buffer_size == 0) { + DA_LOGE("no data on buffer.."); + return ret; + } + + fd = file_info->file_handle; + if (DA_NULL == fd) { + DA_LOGE("There is no file handle."); + + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + write_success_len = fwrite(buffer, sizeof(char), buffer_size, + (FILE *) fd); + /* FIXME : This can be necessary later due to progressive download. + * The solution for reducing fflush is needed */ + //fflush((FILE *) fd); + if (write_success_len != buffer_size) { + DA_LOGE("write fails "); + if (errno == ENOSPC) + ret = DA_ERR_DISK_FULL; + else + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + file_info->bytes_written_to_file += write_success_len; + file_info->is_updated = DA_TRUE; + file_info->buffer_len = 0; +ERR: + return ret; +} + +da_ret_t __file_write_buf_copy_to_buf(file_info_t *file_info, char *body, + int body_len) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + int buffer_size = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info->buffer); + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + memcpy(buffer + buffer_size, body, body_len); + file_info->buffer_len += body_len; + + return ret; +} + +da_ret_t __file_write_buf_directly_write(file_info_t *file_info, + char *body, int body_len) +{ + da_ret_t ret = DA_RESULT_OK; + size_t write_success_len = 0; + void *fd = DA_NULL; + + // DA_LOGV(""); + + fd = file_info->file_handle; + if (DA_NULL == fd) { + DA_LOGE("There is no file handle."); + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + + write_success_len = fwrite(body, sizeof(char), (size_t)body_len, + (FILE *) fd); + /* FIXME : This can be necessary later due to progressive download. + * The solution for reducing fflush is needed */ + //fflush((FILE *) fd); + if (write_success_len != (size_t)body_len) { + DA_LOGE("write fails "); + if (errno == ENOSPC) + ret = DA_ERR_DISK_FULL; + else + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + file_info->bytes_written_to_file += write_success_len; + DA_LOGV( "write %llu bytes", write_success_len); + file_info->is_updated = DA_TRUE; + +ERR: + return ret; +} + +/* Priority to derive extension + * 1. extension name which client set + * 2. according to MIME-Type + * 3. if MIME-Type is ambiguous or blank, + * 3-1. derived from field's "filename" attribute + * 3-2. derived from url + * 4. if url does not have extension, leave blank for extension + */ +char *__get_extension_name(char *mime_type, + char *file_name_from_header, char *url) +{ + char *extension = DA_NULL; + + /* Priority 1 */ + if (mime_type && !is_ambiguous_MIME_Type(mime_type)) { + char *extension = DA_NULL; + da_ret_t ret = get_extension_from_mime_type(mime_type, &extension); + if (ret == DA_RESULT_OK && extension) + return extension; + } + /* Priority 2-1 */ + if (file_name_from_header) { + char *extension = DA_NULL; + DA_SECURE_LOGI("Content-Disposition :[%s]", file_name_from_header); + __divide_file_name_into_pure_name_N_extesion(file_name_from_header, + DA_NULL, &extension); + if (extension) + return extension; + } + /* Priority 2-2 */ + if (url) { + DA_LOGV("Get extension from url"); + da_bool_t b_ret = da_get_extension_name_from_url(url, &extension); + if (b_ret && extension) + return extension; + } + return DA_NULL; +} + +/** Priority for deciding file name + * 1. file name which client set + * 2. 'filename' option on HTTP response header's Content-Disposition field + * 3. requesting URL + * 4. Otherwise, define it as "No name" + */ +da_ret_t __get_candidate_file_name(char *user_file_name, char *url, + char *file_name_from_header, + char **out_pure_file_name, char **out_extension) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + + /* Priority 1 */ + if (user_file_name) { + __divide_file_name_into_pure_name_N_extesion( + user_file_name, out_pure_file_name, out_extension); + } + if (*out_pure_file_name) + return ret; + /* Priority 2 */ + if (file_name_from_header) { + DA_SECURE_LOGI("Content-Disposition:[%s]", file_name_from_header); + __divide_file_name_into_pure_name_N_extesion(file_name_from_header, + out_pure_file_name, DA_NULL); + } + if (*out_pure_file_name) + return ret ; + /* Priority 3 */ + if (url) { + DA_LOGV("Get file name from url"); + da_get_file_name_from_url(url, out_pure_file_name); + } + if (*out_pure_file_name) + return ret ; + /* Priority 4 */ + *out_pure_file_name = strdup(NO_NAME_TEMP_STR); + if (*out_pure_file_name == DA_NULL) + ret = DA_ERR_FAIL_TO_MEMALLOC; + return ret; +} + +da_ret_t __decide_file_path(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *extension = DA_NULL; + char *file_name = DA_NULL; + char *tmp_file_path = DA_NULL; + char *install_dir = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + char *user_file_name = DA_NULL; + char *file_name_from_header = DA_NULL; + char *url = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + http_info_t *http_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + if (req_info->install_path) + install_dir = req_info->install_path; + user_file_name = req_info->file_name; + /* If there is location url from response header in case of redirection, + * it try to parse the file name from the location url */ + if (http_info->location_url) { + url = http_info->location_url; + DA_LOGI("[TEST] location_url[%s][%p]",http_info->location_url, http_info->location_url); + } else + url = req_info->url; + + file_name_from_header = http_info->file_name_from_header; + + /* extension is extracted only if User set specific name */ + ret = __get_candidate_file_name(user_file_name, url, file_name_from_header, + &file_name, &extension); + if (ret != DA_RESULT_OK) + goto ERR; + + if (file_name && strpbrk(file_name, DA_INVALID_PATH_STRING) != NULL) { + DA_LOGI("Invalid string at file name"); + free(file_name); + file_name = strdup(NO_NAME_TEMP_STR); + if (!file_name) { + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + + } + + DA_SECURE_LOGI("candidate file name [%s]", file_name); + + if (!extension) { + extension = __get_extension_name(file_info->mime_type, + file_name_from_header, url); + } + if (file_name && !file_info->pure_file_name) { + file_info->pure_file_name = file_name; + file_name = DA_NULL; + } + if (extension && !file_info->extension) { + DA_LOGV("candidate extension [%s]", extension); + file_info->extension = extension; + extension = DA_NULL; + } + + // for resume + tmp_file_path = get_full_path_avoided_duplication(install_dir, + file_info->pure_file_name, file_info->extension); + if (tmp_file_path) { + file_info->file_path = tmp_file_path; + tmp_file_path = DA_NULL; + } else { + ret = DA_ERR_FAIL_TO_ACCESS_FILE; + goto ERR; + } + +ERR: + DA_SECURE_LOGI("decided file path [%s]", file_info->file_path); + free(file_name); + free(extension); + return ret; +} + +// for resume with new download request +da_ret_t __decide_file_path_for_resume(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *extension = DA_NULL; + char *file_name = DA_NULL; + char *file_path = DA_NULL; + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info); + + file_path = file_info->file_path; + ptr = strrchr(file_path, '/'); + if (ptr) { + ptr++; + ptr2 = strrchr(ptr, '.'); + if (ptr2) { + int len = 0; + len = ptr2 - ptr; + ptr2++; + extension = strdup(ptr2); + file_name = calloc(1, len + 1); + if (file_name) + snprintf(file_name, len + 1, "%s", ptr); + } else { + file_name = strdup(ptr); + } + } + + if (file_name && !file_info->pure_file_name) { + file_info->pure_file_name = file_name; + file_name = DA_NULL; + } else { + free(file_name); + } + if (extension && !file_info->extension) { + DA_LOGV( "candidate extension [%s]", extension); + file_info->extension = extension; + extension = DA_NULL; + } else { + free(extension); + } + return ret; +} + +da_ret_t start_file_writing(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + /* resume case */ + if (req_info->etag || req_info->temp_file_path) { + char *file_path = DA_NULL; + char *origin_path = DA_NULL; + file_path = req_info->temp_file_path; + if (!file_path) + return DA_ERR_INVALID_ARGUMENT; + origin_path = file_info->file_path; + file_info->file_path = strdup(file_path); + if(file_info->file_path == NULL) + return DA_ERR_INVALID_ARGUMENT; + free(origin_path); + ret = __decide_file_path_for_resume(file_info); + } else { + ret = __decide_file_path(da_info); + } + + if (ret != DA_RESULT_OK) + goto ERR; + + if (req_info->etag || req_info->temp_file_path) { + da_size_t file_size = 0; + get_file_size(req_info->temp_file_path, &file_size); + if (file_size < 1) + goto ERR; +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = file_size; +#endif + file_info->bytes_written_to_file = file_size; + } else { + file_info->bytes_written_to_file = 0; + } + ret = __saved_file_open(file_info); +ERR: + return ret; +} + +da_ret_t start_file_append(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + + NULL_CHECK_RET(file_info); + + ret = __saved_file_open(file_info); + return ret; +} + +da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len) +{ + da_ret_t ret = DA_RESULT_OK; + int buffer_size = 0; + char *buffer = DA_NULL; + + DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (DA_NULL == buffer) { + if (body_len < DA_FILE_BUF_SIZE) { + ret = __file_write_buf_make_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + __file_write_buf_copy_to_buf(file_info, body, body_len); + } else { + ret = __file_write_buf_directly_write(file_info, + body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + } else { + if (DA_FILE_BUF_SIZE <= body_len) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + ret = __file_write_buf_directly_write(file_info, + body, body_len); + if (ret != DA_RESULT_OK) + goto ERR; + } else if ((DA_FILE_BUF_SIZE - buffer_size) <= body_len) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + __file_write_buf_copy_to_buf(file_info, body, body_len); + } else { + __file_write_buf_copy_to_buf(file_info, body, body_len); + } + } +ERR: + if (ret != DA_RESULT_OK) { + file_info->buffer_len = 0; + free(file_info->buffer); + file_info->buffer = DA_NULL; + } + return ret; +} + +#ifdef _RAF_SUPPORT +da_ret_t file_write_complete_for_raf(file_info_t *file_info) { + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + da_size_t wrriten_size = 0; + da_size_t file_size = 0; + void *fd = DA_NULL; + + DA_LOGV(""); + fd = file_info->file_handle; + + wrriten_size = file_info->bytes_written_to_file; + // test code + get_file_size(file_info->file_path, &file_size); + DA_LOGI("wrriten_size:%llu file_size:%llu file[%s]", + wrriten_size, file_size, file_info->file_path); + if (fd) { + fclose(fd); + fd = DA_NULL; + } + file_info->file_handle = DA_NULL; + if (wrriten_size < file_size) { + DA_LOGD("Try truncate"); + if (truncate(file_info->file_path, wrriten_size) < 0) { + DA_LOGE("Fail to ftruncate: errno[%d,%s]", errno, strerror(errno)); + } + DA_LOGD("Try truncate done"); + } + + ERR: + return ret; +} +#endif + +da_ret_t file_write_complete(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *buffer = DA_NULL; + unsigned int buffer_size = 0; + void *fd = DA_NULL; + + DA_LOGV(""); + + buffer = file_info->buffer; + buffer_size = file_info->buffer_len; + + if (DA_NULL == buffer) { + DA_LOGE("file buffer is NULL"); + } else { + if (buffer_size != 0) { + ret = __file_write_buf_flush_buf(file_info); + if (ret != DA_RESULT_OK) + goto ERR; + } + __file_write_buf_destroy_buf(file_info); + } + fd = file_info->file_handle; + + if (fd) { + fclose(fd); + fd = DA_NULL; + } + file_info->file_handle = DA_NULL; +ERR: + return ret; +} + +da_ret_t discard_download(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + FILE *f_handle = DA_NULL; + + DA_LOGV(""); + + f_handle = file_info->file_handle; + if (f_handle) { + fclose(f_handle); + file_info->file_handle = DA_NULL; + } + return ret; +} + +void clean_paused_file(file_info_t *file_info) +{ + char *paused_file_path = DA_NULL; + FILE *fd = DA_NULL; + + DA_LOGV(""); + + fd = file_info->file_handle; + if (fd) { + fclose(fd); + file_info->file_handle = DA_NULL; + } + + paused_file_path = file_info->file_path; + file_info->bytes_written_to_file = 0; // Ignore resume flow after failed or cancled. + remove_file((const char*) paused_file_path); + + return; +} + +da_bool_t is_file_exist(const char *file_path) +{ + struct stat dir_state; + int stat_ret; + + if (file_path == DA_NULL) { + DA_LOGE("file path is DA_NULL"); + return DA_FALSE; + } + stat_ret = stat(file_path, &dir_state); + if (stat_ret == 0) { + if (dir_state.st_mode & S_IFREG) { + //DA_SECURE_LOGD("Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size); + return DA_TRUE; + } + + return DA_FALSE; + } + return DA_FALSE; + +} + +void get_file_size(char *file_path, da_size_t *out_file_size) +{ + struct stat dir_state; + int stat_ret; + + *out_file_size = -1; + + if (file_path == DA_NULL) { + DA_LOGE("file path is DA_NULL"); + return; + } + /* Please do not use ftell() to obtain file size, use stat instead. + * This is a guide from www.securecoding.cert.org + * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file + */ + stat_ret = stat(file_path, &dir_state); + if (stat_ret == 0) { + if (dir_state.st_mode & S_IFREG) { + DA_LOGV( "size = %lu", dir_state.st_size); + *out_file_size = dir_state.st_size; + } + } + return; +} + +char *get_full_path_avoided_duplication(char *in_dir, + char *in_candidate_file_name, char *in_extension) +{ + char *dir = in_dir; + char *file_name = in_candidate_file_name; + char *extension = in_extension; + char *final_path = DA_NULL; + + int dir_path_len = 0; + int final_path_len = 0; + int extension_len = 0; + + int suffix_count = 0; /* means suffix on file name. up to "_99" */ + int suffix_len = (int)log10(MAX_SUFFIX_COUNT + 1) + 1; /* 1 means "_" */ + + if (!in_dir || !in_candidate_file_name) + return DA_NULL; + + //DA_SECURE_LOGI("in_candidate_file_name=[%s],in_extension=[%s]", + //in_candidate_file_name, in_extension); + + if (extension) + extension_len = strlen(extension); + + // to remove trailing slash from dir path + dir_path_len = strlen(dir); + if (dir[dir_path_len - 1] == '/') { + dir[dir_path_len - 1] = '\0'; + --dir_path_len; + } + + /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */ + final_path_len = dir_path_len + 1 + strlen(file_name) + 1 + + suffix_len + extension_len + 1; + + final_path = (char*)calloc(1, final_path_len); + if (!final_path) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + return DA_NULL; + } + + do { + /* e.g) /tmp/abc.jpg + * if there is no extension name, just make a file name without extension */ + if (0 == extension_len) { + if (suffix_count == 0) { + snprintf(final_path, final_path_len, + "%s/%s", dir, file_name); + } else { + snprintf(final_path, final_path_len, + "%s/%s_%d", dir, file_name, suffix_count); + } + } else { + if (suffix_count == 0) { + snprintf(final_path, final_path_len, + "%s/%s.%s", dir, file_name, extension); + } else { + snprintf(final_path, final_path_len, + "%s/%s_%d.%s", + dir, file_name, suffix_count, extension); + } + } + if (is_file_exist(final_path)) { + suffix_count++; + if (suffix_count > MAX_SUFFIX_COUNT) { + free(final_path); + final_path = DA_NULL; + break; + } else { + memset(final_path, 0x00, final_path_len); + continue; + } + } + break; + } while (1); + + //DA_SECURE_LOGD("decided path = [%s]", final_path); + return final_path; +} + + +da_ret_t check_drm_convert(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + da_bool_t ret_b = DA_TRUE; + + DA_LOGD(""); + + NULL_CHECK_RET(file_info); + +#ifdef _ENABLE_OMA_DRM + + /* In case of OMA DRM 1.0 SD, it is not necessary to call DRM convert API. + * Because it is already converted itself. + * And, the case will return fail because The SD is not supported now. + */ + if (is_content_drm_dcf(file_info->mime_type)) { + DA_LOGI("DRM SD case"); + unlink(file_info->file_path); + free(file_info->file_path); + file_info->file_path = DA_NULL; + return DA_ERR_DRM_FAIL; + } + if (is_content_drm_dm(file_info->mime_type)) { + char *actual_file_path = DA_NULL; + char *out_file_path = DA_NULL; + + actual_file_path = file_info->file_path; + DA_SECURE_LOGD("actual_file_path = %s", actual_file_path); + if (!actual_file_path) + return DA_ERR_INVALID_ARGUMENT; + ret_b = EDRM_convert(actual_file_path, &out_file_path); + unlink(actual_file_path); + free(actual_file_path); + if (!ret_b) + ret = DA_ERR_DRM_FAIL; + file_info->file_path = out_file_path; + } else { + return ret; + } +#endif + + return ret; +} + +void remove_file(const char *file_path) +{ + DA_LOGV(""); + + if (file_path && is_file_exist(file_path)) { + DA_SECURE_LOGD("remove file [%s]", file_path); + if (unlink(file_path) < 0) { + DA_LOGE("file removing failed."); + } + } +} + +da_ret_t get_available_memory(char *dir_path, da_size_t len) +{ + da_ret_t ret = DA_RESULT_OK; + int fs_ret = 0; + //struct statfs filesys_info = {0, }; + struct statvfs filesys_info; + + DA_LOGV(""); + + if (!dir_path) + return DA_ERR_INVALID_INSTALL_PATH; + + //fs_ret = statfs(dir_path, &filesys_info); + // Using this as it considers FOTA memory while returning available memory + fs_ret = storage_get_internal_memory_size(&filesys_info); + + if (fs_ret != 0) { + // DA_LOGE("statfs error[%s]", strerror(errno)); + return DA_ERR_INVALID_ARGUMENT; + // return DA_ERR_INVALID_INSTALL_PATH; + } + + double available_size = (double)filesys_info.f_bsize * filesys_info.f_bavail; + double total_size = (double)filesys_info.f_frsize * filesys_info.f_blocks; + DA_SECURE_LOGI(" total = %lf ", total_size); + DA_SECURE_LOGI(" available = %lf ",available_size); + + DA_LOGV("Available Memory(f_bavail) : %lu", filesys_info.f_bavail); + DA_LOGV("Available Memory(f_bsize) : %d", filesys_info.f_bsize); + DA_LOGD("Available Memory(kbytes) : %d", (filesys_info.f_bavail/1024)*filesys_info.f_bsize); + DA_LOGV("Content: %llu", len); + if (available_size < (len + + SAVE_FILE_BUFFERING_SIZE_50KB)) /* 50KB buffering */ + ret = DA_ERR_DISK_FULL; + + return ret; +} diff --git a/agent/download-agent-http-mgr.c b/agent/download-agent-http-mgr.c new file mode 100755 index 0000000..3a2feb9 --- /dev/null +++ b/agent/download-agent-http-mgr.c @@ -0,0 +1,1519 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "download-agent-dl-info.h" +#include "download-agent-file.h" +#include "download-agent-mime-util.h" +#include "download-agent-client-mgr.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-conf.h" +#include "download-agent-plugin-drm.h" +#include "download-agent-plugin-libcurl.h" + +void __http_update_cb(http_raw_data_t *data, void *user_param); + +#define CONVERT_STR(NAME) (#NAME) + +static const char *__get_state_str(http_state_t state) +{ + char *str = NULL; + switch(state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + str = CONVERT_STR(HTTP_STATE_READY_TO_DOWNLOAD); + break; + case HTTP_STATE_REDIRECTED: + str = CONVERT_STR(HTTP_STATE_REDIRECTED); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_REQUESTED); + break; + case HTTP_STATE_DOWNLOAD_STARTED: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_STARTED); + break; + case HTTP_STATE_DOWNLOADING: + str = CONVERT_STR(HTTP_STATE_DOWNLOADING); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + str = CONVERT_STR(HTTP_STATE_DOWNLOAD_FINISH); + break; + case HTTP_STATE_REQUEST_CANCEL: + str = CONVERT_STR(HTTP_STATE_REQUEST_CANCEL); + break; + case HTTP_STATE_REQUEST_PAUSE: + str = CONVERT_STR(HTTP_STATE_REQUEST_PAUSE); + break; + case HTTP_STATE_REQUEST_RESUME: + str = CONVERT_STR(HTTP_STATE_REQUEST_RESUME); + break; + case HTTP_STATE_CANCELED: + str = CONVERT_STR(HTTP_STATE_CANCELED); + break; + case HTTP_STATE_FAILED: + str = CONVERT_STR(HTTP_STATE_FAILED); + break; + case HTTP_STATE_PAUSED: + str = CONVERT_STR(HTTP_STATE_PAUSED); + break; + case HTTP_STATE_RESUMED: + str = CONVERT_STR(HTTP_STATE_RESUMED); + break; + case HTTP_STATE_ABORTED: + str = CONVERT_STR(HTTP_STATE_ABORTED); + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + str = CONVERT_STR(HTTP_STATE_WAIT_FOR_NET_ERR); + break; + default: + str = "Unknown State"; + break; + } + return str; +} + +void __init_http_info(http_info_t *http_info) +{ + DA_LOGV(""); + + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + http_info->update_cb = __http_update_cb; + DA_MUTEX_INIT(&(http_info->mutex_state), DA_NULL); + DA_MUTEX_INIT(&(http_info->mutex_http), DA_NULL); + DA_COND_INIT(&(http_info->cond_http), DA_NULL); +} + +void __parsing_user_request_header(char *user_request_header, + char **out_field, char **out_value) +{ + int len = 0; + char *pos = NULL; + char *temp_pos = NULL; + char *field = NULL; + char *value = NULL; + + DA_LOGV(""); + + if (!user_request_header) { + DA_LOGE("NULL CHECK!: user_request_header"); + goto ERR; + } + + pos = strchr(user_request_header, ':'); + if (!pos) { + DA_LOGE("Fail to parse"); + goto ERR; + } + temp_pos = (char *)user_request_header; + while (*temp_pos) + { + if (temp_pos == pos || *temp_pos == ' ') { + len = temp_pos - user_request_header; + break; + } + temp_pos++; + } + if (len < 1) { + DA_LOGE("Wrong field name"); + goto ERR; + } + field = (char *)calloc(1, len + 1); + if (!field) { + DA_LOGE("Fail to calloc"); + goto ERR; + } + strncpy(field, user_request_header, len); + pos++; + while (*pos) + { + if (*pos != ' ') + break; + pos++; + } + len = strlen(pos) + 1; + value = (char *)calloc(1, len + 1); + if (!value) { + DA_LOGE("Fail to calloc"); + goto ERR; + } + strncpy(value, pos, len); + *out_field = field; + *out_value = value; + DA_SECURE_LOGD("field[%s], value[%s]", field, value); + + return; +ERR: + if (field) { + free(field); + field = NULL; + } + return; +} + + +da_ret_t __set_http_request_hdr(req_info_t *req_info, http_info_t *http_info, file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_request_t *http_msg_request = NULL; + char *user_agent = NULL; + int count = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(req_info); + NULL_CHECK_RET(http_info); + NULL_CHECK_RET(file_info); + NULL_CHECK_RET_OPT(req_info->url, DA_ERR_INVALID_URL); + count = req_info->req_header_count; + + ret = http_msg_request_create(&http_msg_request); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = http_msg_request_set_url(http_msg_request, req_info->url); + if (ret != DA_RESULT_OK) + goto ERR; + + ret = get_user_agent_string(&user_agent); + if (user_agent && ret == DA_RESULT_OK) + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_UAGENT, user_agent); + + + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_ACCEPT_LANGUAGE, "en"); + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_ACCEPT_CHARSET, "utf-8"); + + if (req_info->req_header && count > 0) { + int i = 0; + for (i = 0; i < count; i++) { + char *field = NULL; + char *value = NULL; + __parsing_user_request_header(req_info->req_header[i], + &field, &value); + if (field && value) { + http_msg_request_add_field(http_msg_request, field, value); + if (field) { + free(field); + field = NULL; + } + if (value) { + free(value); + value= NULL; + } + } else { + if (field) { + free(field); + field = NULL; + } + if (value) { + free(value); + value= NULL; + } + DA_LOGE("Fail to parse user request header"); + } + } + } + if (req_info->etag) { + char buff[64] = {0,}; + da_size_t size = 0; + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_IF_RANGE, req_info->etag); + get_file_size(req_info->temp_file_path, &size); +#ifdef _RAF_SUPPORT + file_info->file_size_of_temp_file = size; +#endif + snprintf(buff, sizeof(buff)-1, "bytes=%llu-", size); + http_msg_request_add_field(http_msg_request, + HTTP_FIELD_RANGE, buff); + } + + http_info->http_msg_request = http_msg_request; + free(user_agent); + return ret; +ERR: + if (http_msg_request) + http_msg_request_destroy(&http_msg_request); + + return ret; + +} + +da_ret_t __create_http_resume_hdr(req_info_t *req_info, http_info_t *http_info, + file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + char *value = NULL; + char temp_size_str[32] = { 0, }; + char *etag_from_response = NULL; + char *date_from_response = NULL; + http_msg_response_t *first_response = NULL; + http_msg_request_t *resume_request = NULL; + http_msg_request_t *old_request = NULL; + + DA_LOGV(""); + + first_response = http_info->http_msg_response; + if (first_response) { + b_ret = http_msg_response_get_ETag(first_response, &value); + if (b_ret) { + etag_from_response = value; + value = NULL; + DA_SECURE_LOGD("[ETag][%s]", etag_from_response); + } + b_ret = http_msg_response_get_date(first_response, &value); + if (b_ret) { + date_from_response = value; + value = NULL; + DA_LOGV("[Date][%s]", date_from_response); + } + DA_SECURE_LOGD("downloaded_size[%u]", file_info->bytes_written_to_file); + snprintf(temp_size_str, sizeof(temp_size_str), "bytes=%llu-", + file_info->bytes_written_to_file); + DA_SECURE_LOGD("size str[%s]", temp_size_str); + free(first_response); + http_info->http_msg_response = DA_NULL; + } + old_request = http_info->http_msg_request; + free(old_request); + http_info->http_msg_request = DA_NULL; + + ret = __set_http_request_hdr(req_info, http_info, file_info); + if (ret != DA_RESULT_OK) + goto ERR; + + resume_request = http_info->http_msg_request; + if (etag_from_response) { + http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE, + etag_from_response); + } else { + if (date_from_response) { + http_msg_request_add_field(resume_request, + HTTP_FIELD_IF_RANGE, date_from_response); + } + } + + if (strlen(temp_size_str) > 0) + http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE, + temp_size_str); + +ERR: + if (etag_from_response) { + free(etag_from_response); + etag_from_response = NULL; + } + if (date_from_response) { + free(date_from_response); + date_from_response = NULL; + } + return ret; +} + + +da_ret_t __start_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info; + DA_LOGV(""); + + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + return DA_ERR_INVALID_ARGUMENT; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL CHECK!: http_info"); + return DA_ERR_INVALID_ARGUMENT; + } + http_info->http_method = HTTP_METHOD_GET; + http_info->proxy_addr = get_proxy_address(); + + ret = PI_http_start(da_info); + + return ret; +} + +da_ret_t __start_resume_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + + ret = __create_http_resume_hdr(req_info, http_info, + file_info); + if (ret != DA_RESULT_OK) + return ret; + + reset_http_info_for_resume(http_info); + if (file_info->file_path) { + req_info->temp_file_path = strdup(file_info->file_path); + } else { + DA_LOGE("file_path cannot be NULL in resume case"); + return DA_ERR_INVALID_ARGUMENT; + } + ret = __start_transaction(da_info); + return ret; +} + + +da_ret_t __start_new_transaction(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + + if (!da_info) { + DA_LOGE("NULL CHECK!: da_info"); + return DA_ERR_INVALID_ARGUMENT; + } + + ret = __set_http_request_hdr(da_info->req_info, da_info->http_info, da_info->file_info); + if (ret != DA_RESULT_OK) + return ret; + + ret = __start_transaction(da_info); + return ret; +} + +int __check_wait_for_auto_retry(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + struct timespec ts; + struct timeval tp; + NULL_CHECK_RET_OPT(http_info, 0); + gettimeofday(&tp, NULL); + ts.tv_sec = tp.tv_sec + DA_MAX_TIME_OUT; + ts.tv_nsec = tp.tv_usec * 1000; + DA_LOGI("Network Fail case, wait for a while"); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_WAIT_FOR_NET_ERR; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + ret = pthread_cond_timedwait(&(http_info->cond_http), + &(http_info->mutex_http), &ts); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + if (ret == ETIMEDOUT) { + DA_LOGI("Waiting is done by timeout"); + } else if (ret != 0) { + DA_LOGE("fail to pthread_cond_waittime[%d][%s]",ret, strerror(ret)); + } else { + DA_LOGI("Waiting is done by control"); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + DA_LOGI("http_state[%s]", __get_state_str(http_info->state)); + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + return 1; + } + + return 0; +} + +// In download thread +da_ret_t request_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + req_info_t *req_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + da_bool_t need_wait = DA_TRUE; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + __init_http_info(http_info); + + do { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s][%d]",__get_state_str(http_info->state), da_info->da_id); + switch (http_state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __start_new_transaction(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_LOGD("http_state[%s][%d]",__get_state_str(http_info->state), da_info->da_id); + http_info->error_code = ret; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) { + DA_LOGE("Network failed"); + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_REDIRECTED: + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGE("Cannot enter here:[%s][id]", + __get_state_str(http_info->state), da_info->da_id); + break; + case HTTP_STATE_REQUEST_CANCEL: + break; + case HTTP_STATE_REQUEST_RESUME: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + need_wait = DA_TRUE; + break; + case HTTP_STATE_CANCELED: + need_wait = DA_FALSE; + ret = DA_RESULT_USER_CANCELED; + break; + case HTTP_STATE_PAUSED: + DA_LOGD("error_code[%d]", http_info->error_code); + send_client_paused_info(da_info); + DA_LOGD("Waiting thread for paused state"); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + pthread_cond_wait(&(http_info->cond_http),&(http_info->mutex_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + DA_LOGD("Wake up thread due to resume"); + break; + case HTTP_STATE_RESUMED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_REQUESTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __start_resume_transaction(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (ret == DA_ERR_NETWORK_FAIL && http_state != HTTP_STATE_PAUSED) { + DA_LOGE("Network failed"); + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_DOWNLOAD_FINISH: + need_wait = DA_FALSE; + if (ret == DA_RESULT_OK) + ret = check_drm_convert(da_info->file_info); + break; + case HTTP_STATE_FAILED: + if (ret == DA_ERR_NETWORK_FAIL) { + if (__check_wait_for_auto_retry(http_info) == 1) + need_wait = DA_TRUE; + else + need_wait = DA_FALSE; + } else { + need_wait = DA_FALSE; + } + break; + case HTTP_STATE_ABORTED: + need_wait = DA_FALSE; + break; + default: + break; + } + } while (need_wait == DA_TRUE); + DA_LOGD("Final http_state[%s][%d] err[%d]",__get_state_str(http_info->state), da_info->da_id, ret); + if (http_info->state != HTTP_STATE_PAUSED) + send_client_finished_info(da_info ,ret); + DA_LOGI("=== Exiting http_download ret[%d] ===", ret); + return ret; +} + +da_ret_t __disconnect_transaction(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGD(""); + ret = PI_http_disconnect(http_info); + return ret; +} + +da_ret_t __handle_event_abort(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t state = 0; + + DA_LOGD(""); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("http_state[%s]", __get_state_str(state)); + + switch (state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + case HTTP_STATE_REDIRECTED: + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_CANCEL: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_CANCELED: + case HTTP_STATE_PAUSED: + case HTTP_STATE_RESUMED: + case HTTP_STATE_ABORTED: + case HTTP_STATE_WAIT_FOR_NET_ERR: + /* IF the network session is terminated due to some error, + * the state can be aborted.(data aborted case) */ + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_ABORTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + __disconnect_transaction(http_info); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + break; + default: + DA_LOGE("Cannot enter here"); + break; + } + return ret; +} + +da_ret_t __check_enough_memory(http_info_t *http_info, char *user_install_path) +{ + da_ret_t ret = DA_RESULT_OK; + da_size_t cont_len = 0; + char *dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + + DA_LOGV(""); + NULL_CHECK_RET(http_info); + cont_len = http_info->content_len_from_header; + if (cont_len > 0) { + if (user_install_path) + dir_path = user_install_path; + ret = get_available_memory(dir_path, cont_len); + } + return ret; +} + +da_ret_t request_to_abort_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + ret = __handle_event_abort(da_info->http_info); + return ret; +} + +da_ret_t request_to_cancel_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + switch (http_state) { + case HTTP_STATE_READY_TO_DOWNLOAD: + ret = PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (da_info->thread_id > 0) { + if (pthread_cancel(da_info->thread_id) != 0) { + DA_LOGE("Fail to cancel thread id[%d] err[%s]", + da_info->thread_id, strerror(errno)); + } else { + DA_LOGI("====Exit thread with cancel:da_id[%d]===", + da_info->da_id); + } + } + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + break; + case HTTP_STATE_PAUSED: + reset_http_info(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_DOWNLOAD_STARTED: + case HTTP_STATE_DOWNLOADING: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_RESUMED: + ret = PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REQUEST_CANCEL; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_FINISH: + ret = DA_ERR_INVALID_STATE; + break; + case HTTP_STATE_REQUEST_CANCEL: + DA_LOGV("cancel is already in progress... "); + ret = DA_ERR_INVALID_STATE; + break; + default: + ret = DA_ERR_INVALID_STATE; + DA_LOGE("Cannot enter here"); + break; + } + return ret; +} + +da_ret_t request_to_suspend_http_download(da_info_t *da_info) +{ + + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + + switch (http_state) { + case HTTP_STATE_PAUSED: + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGI("Already paused. http_state[%s]", __get_state_str(http_state)); + ret = DA_ERR_ALREADY_SUSPENDED; + break; + case HTTP_STATE_READY_TO_DOWNLOAD: + DA_LOGE("Download has not been started yet"); + ret = DA_ERR_INVALID_STATE; + break; + case HTTP_STATE_WAIT_FOR_NET_ERR: + DA_LOGD("error_code[%d]", http_info->error_code); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + break; + default: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REQUEST_PAUSE; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("error_code[%d]", http_info->error_code); + if (http_info->error_code != DA_ERR_NETWORK_FAIL) + ret = PI_http_pause(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + break; + } + return ret; +} + +da_ret_t request_to_resume_http_download(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + http_state_t http_state = 0; + int retry_count = 0; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + + switch (http_state) { + case HTTP_STATE_PAUSED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_RESUMED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("Wake up thread for paused state"); + DA_MUTEX_LOCK(&(http_info->mutex_http)); + DA_COND_SIGNAL(&(http_info->cond_http)); + DA_MUTEX_UNLOCK(&(http_info->mutex_http)); + DA_LOGD("error_code[%d]", http_info->error_code); + if (http_info->error_code != DA_ERR_NETWORK_FAIL) { + ret = PI_http_unpause(http_info); + if (ret != DA_RESULT_OK) + PI_http_cancel(http_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + } + break; + case HTTP_STATE_REQUEST_PAUSE: + DA_LOGD("Waiting to handle pause request"); + do { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + if (http_state == HTTP_STATE_PAUSED) { + DA_LOGD("Change to paused state"); + ret = PI_http_unpause(http_info); + break; + } + retry_count++; + } while(retry_count < 10000); + if (ret != DA_RESULT_OK || retry_count >= 10000) + PI_http_cancel(http_info); + break; + case HTTP_STATE_RESUMED: + ret = DA_ERR_ALREADY_RESUMED; + break; + default: + DA_LOGE("Fail to resume. Invalid state check. http_state[%s]", + __get_state_str(http_state)); + ret = DA_ERR_INVALID_STATE; + // If resume is failed due to invalid state, the previous pause should be canceled. + PI_http_cancel(http_info); + break; + } + return ret; +} + +da_ret_t __check_resume_download_is_available( + req_info_t *req_info, http_info_t *http_info, file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + da_bool_t b_ret = DA_FALSE; + char *origin_ETag = NULL; + char *new_ETag = NULL; + da_size_t remained_content_len = 0; + char *value = NULL; + da_size_t size = 0; + char *temp_file_path = DA_NULL; + char *dir_path = DA_DEFAULT_INSTALL_PATH_FOR_PHONE; + + DA_LOGV(""); + + origin_ETag = req_info->etag; + + b_ret = http_msg_response_get_content_length(http_info->http_msg_response, + &size); + if (b_ret) { + remained_content_len = size; + size = 0; + DA_SECURE_LOGD("remained_content_len[%llu]", remained_content_len); + } + + b_ret = http_msg_response_get_ETag(http_info->http_msg_response, &value); + if (b_ret) { + new_ETag = value; + value = NULL; + DA_SECURE_LOGD("new ETag[%s]", new_ETag); + } else { + goto ERR; + } + + if (origin_ETag && new_ETag && + 0 != strncmp(origin_ETag, new_ETag, strlen(new_ETag))) { + DA_LOGE("ETag is not identical! revoke!"); + /* FIXME Later : Need to detail error exception handling */ + ret = DA_ERR_NETWORK_FAIL; + /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */ + goto ERR; + } + + if (remained_content_len > 0) { + if (req_info->install_path) + dir_path = req_info->install_path; + ret = get_available_memory(dir_path, remained_content_len); + if (ret != DA_RESULT_OK) + goto ERR; + } + + if (!http_info->content_type_from_header) { + b_ret = http_msg_response_get_content_type(http_info->http_msg_response, + &value); + if (b_ret) { + http_info->content_type_from_header = value; + value = NULL; + DA_SECURE_LOGD("Content-Type[%s]", + http_info->content_type_from_header); + } + } + temp_file_path = req_info->temp_file_path; + if (!temp_file_path) { + DA_LOGE("Temporary file path cannot be NULL"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + get_file_size(temp_file_path, &size); + http_info->content_len_from_header = remained_content_len + size; + DA_SECURE_LOGD("Content-Length[%llu]", http_info->content_len_from_header); +ERR: + if (new_ETag) { + free(new_ETag); + new_ETag = DA_NULL; + } + return ret; +} + + +da_ret_t __check_content_type_is_matched(http_info_t *http_info) +{ + da_ret_t ret = DA_RESULT_OK; + char *content_type_from_server = DA_NULL; + + DA_LOGV(""); + + content_type_from_server = http_info->content_type_from_header; + if (content_type_from_server == DA_NULL) { + DA_LOGV("http header has no Content-Type field, no need to compare"); + return DA_RESULT_OK; + } + return ret; +} + +da_ret_t __handle_http_status_code(http_info_t *http_info, + file_info_t *file_info, req_info_t *req_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_msg_response_t *http_msg_response = DA_NULL; + char *location = DA_NULL; + char *if_range_str = DA_NULL; + char *range_str = DA_NULL; + int http_status = 0; + + NULL_CHECK_RET(http_info); + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(req_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + http_msg_response = http_info->http_msg_response; + NULL_CHECK_RET(http_msg_response); + http_status = http_msg_response->status_code; + switch (http_status) { + case 200: + case 201: + case 202: + case 203: +// Although expecting 206, 200 response is received. Remove temporary file and reset file info + if (http_info->http_msg_request && + http_msg_request_get_if_range(http_info->http_msg_request, &if_range_str) == DA_TRUE && + http_msg_request_get_range(http_info->http_msg_request, &range_str) == DA_TRUE) { + DA_LOGI("Server do not support if-range option"); + clean_paused_file(file_info); + } + free(if_range_str); + free(range_str); + if (http_state == HTTP_STATE_REQUEST_RESUME) + clean_paused_file(file_info); + ret = __check_content_type_is_matched(http_info); + if (ret != DA_RESULT_OK) + goto ERR; + ret = __check_enough_memory(http_info, req_info->install_path); + if (ret != DA_RESULT_OK) + goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + + case 206: + DA_LOGV("HTTP Status is %d - Partial download for resume!", http_status); + /* The resume can be started with start API. + * So the state should be not HTTP_STATE_RESUME_REQUESTED but HTTP_STATE_DOWNLOAD_REQUESTED*/ + if (http_state == HTTP_STATE_DOWNLOAD_REQUESTED) { + ret = __check_resume_download_is_available(req_info, http_info, file_info); + if (ret != DA_RESULT_OK) + goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + } else if (http_state == HTTP_STATE_REQUEST_RESUME) { + ///FIXME later : how get previous response header + ///ret = __check_this_partial_download_is_available(http_info, + /// previous_ http_msg_response); + //if (ret != DA_RESULT_OK) + //goto ERR; + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_RESUMED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } else { + DA_LOGE("This download is not resumed, revoke"); + ret = DA_ERR_INVALID_STATE; + goto ERR; + } + break; + + case 300: + case 301: + case 302: + case 303: + case 305: + case 306: + case 307: + DA_LOGV("HTTP Status is %d - redirection!",http_status); + if (http_msg_response_get_location(http_msg_response, &location)) { + DA_SECURE_LOGD("location = %s\n", location); + http_info->location_url = location; + DA_LOGI("[TEST] location_url[%p]",http_info->location_url); + } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_REDIRECTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + http_msg_response_destroy(&http_msg_response); + http_info->http_msg_response = DA_NULL; + break; + + case 100: + case 101: + case 102: + case 204: + case 304: + DA_LOGV("HTTP Status is %d - 204 server got the request, \ + but no content to reply back, \ + 304 means not modified!", http_status); + ret = DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT; + break; + + case 416: // Requested range not satisfiable + case 503: + case 504: + default: +/// GET_REQUEST_HTTP_RESULT(request_info) +/// = DA_ERR_UNREACHABLE_SERVER; + DA_LOGI("set internal error code : DA_ERR_UNREACHABLE_SERVER"); + break; + } + +ERR: + return ret; +} + +da_ret_t __check_before_downloading(da_info_t *da_info, http_state_t state) +{ + da_ret_t ret = DA_RESULT_OK; + http_info_t *http_info = DA_NULL; + req_info_t *req_info = DA_NULL; + file_info_t *file_info = DA_NULL; + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + DA_LOGD("state:%s",__get_state_str(state)); + // resume case + if (req_info->temp_file_path && file_info->bytes_written_to_file > 0) { + ret = start_file_append(file_info); + } else if (state == HTTP_STATE_DOWNLOAD_STARTED) { + ret = start_file_writing(da_info); + } else { + DA_LOGE("Cannot enter here!"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + if (DA_RESULT_OK != ret) + goto ERR; + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + ret = send_client_update_dl_info(da_info); +ERR: + return ret; +} + +da_ret_t __handle_event_http_header(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + req_info_t *req_info = DA_NULL; + http_msg_response_t *http_msg_response = DA_NULL; + da_size_t size = 0; + char *mime_type = DA_NULL; + char *etag = DA_NULL; + char *file_name = DA_NULL; + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + req_info = da_info->req_info; + NULL_CHECK_RET(req_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + http_msg_response = http_info->http_msg_response; + switch (http_state) { + case HTTP_STATE_DOWNLOAD_REQUESTED: + case HTTP_STATE_REQUEST_PAUSE: + case HTTP_STATE_REQUEST_RESUME: + case HTTP_STATE_REDIRECTED: + http_msg_response_get_content_length(http_msg_response, &size); + http_info->content_len_from_header = size; + http_msg_response_get_content_type(http_msg_response, &mime_type); + http_info->content_type_from_header = mime_type; + if (mime_type) + file_info->mime_type = strdup(mime_type); + http_msg_response_get_ETag(http_msg_response, &etag); + http_info->etag_from_header = etag; + http_msg_response_get_content_disposition( + http_msg_response, DA_NULL, &file_name); + http_info->file_name_from_header = file_name; + ret = __handle_http_status_code(http_info, file_info, req_info); + if (ret != DA_RESULT_OK) { + DA_LOGE("Fail to handle http status code"); + goto ERR; + } +#ifdef _RAF_SUPPORT + char *val = NULL; + http_msg_response_get_RAF_mode(http_msg_response, &val); + if (!val) { + DA_LOGE("Fail to raf mode value from response header"); + } else { + DA_LOGI("[RAF] val[%s:%s]", HTTP_FIELD_RAF_MODE, val); + if (strncmp(val, "yes", strlen("yes")) == 0) { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_STARTED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = __check_before_downloading(da_info, http_info->state); + if (ret != DA_RESULT_OK) { + free(val); + goto ERR; + } + http_info->is_raf_mode_confirmed = DA_TRUE; + ret = PI_http_set_file_name_to_curl(http_info->http_msg, file_info->file_path); + if (ret != DA_RESULT_OK) { + DA_LOGE("Fail to set file name to curl"); + free(val); + goto ERR; + } + } + free(val); + } +#endif + break; + case HTTP_STATE_REQUEST_CANCEL: + DA_LOGV("Cancel is in progress.. http_state[%s]", + __get_state_str(http_state)); + break; + + default: + DA_LOGE("http_state[%s]", __get_state_str(http_state)); + goto ERR; + } + +ERR: + if (ret != DA_RESULT_OK) { + DA_LOGE("Request to cancel due to error[%d]", ret); + PI_http_cancel(http_info); + http_info->error_code = ret; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + free(raw_data); + return ret; +} + +da_ret_t __handle_event_http_packet(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + time_t t; + struct tm *lc_time; + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + + switch (http_state) { + case HTTP_STATE_DOWNLOAD_STARTED: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + ret = __check_before_downloading(da_info, http_state); + if (ret != DA_RESULT_OK) + goto ERR; + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + ret = send_client_update_progress_info(da_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = HTTP_STATE_DOWNLOADING; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_RESUMED: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + __check_before_downloading(da_info, http_state); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + ret = send_client_update_progress_info(da_info); + break; + case HTTP_STATE_REDIRECTED: + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + break; + case HTTP_STATE_DOWNLOADING: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + /* Should this function before updating download info + * Because it extract mime type at once only if first download updating at client */ + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + // send event every 1 second. + if ((t = time(DA_NULL)) > 0) { + if ((lc_time = localtime(&t)) != DA_NULL) { + if (da_info->update_time != lc_time->tm_sec) { + da_info->update_time = lc_time->tm_sec; + ret = send_client_update_progress_info(da_info); + } + } else { + DA_LOGE("Fail to call localtime[%s]",strerror(errno)); + ret = send_client_update_progress_info(da_info); + } + } else { + DA_LOGE("Fail to call time[%s]",strerror(errno)); + ret = send_client_update_progress_info(da_info); + } + break; + case HTTP_STATE_REQUEST_PAUSE: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_FALSE) { +#endif + DA_LOGV("http_state[%s]", __get_state_str(http_state)); + ret = file_write_ongoing(file_info, + raw_data->body, raw_data->body_len); + if (ret != DA_RESULT_OK) + goto ERR; +#ifdef _RAF_SUPPORT + } else { + file_info->bytes_written_to_file = + raw_data->received_len + file_info->file_size_of_temp_file; + file_info->is_updated = DA_TRUE; + } +#endif + + break; + default: + DA_LOGE("Do nothing! http_state is in case[%s]", + __get_state_str(http_state)); + goto ERR; + } +ERR: + if (ret != DA_RESULT_OK) { + DA_LOGE("Request to cancel due to error[%d]", ret); + PI_http_cancel(http_info); + http_info->error_code = ret; + discard_download(da_info->file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + if (raw_data->body) + free(raw_data->body); + free(raw_data); + return ret; +} + +da_ret_t __check_file_size_with_header_content_size(file_info_t *file_info) +{ + da_ret_t ret = DA_RESULT_OK; + unsigned long long tmp_file_size = 0; + + DA_LOGV(""); + + if (file_info->file_size > 0) { + +#ifdef _ENABLE_OMA_DRM + if (is_content_drm_dm(file_info->mime_type)) { + /* FIXME Later : How can get the file size of DRM file. */ + return ret; + } +#endif + + get_file_size(file_info->file_path, &tmp_file_size); + + if (tmp_file_size != file_info->file_size) { + DA_SECURE_LOGE("Real file size[%llu], MISMATCH CONTENT SIZE", + tmp_file_size); + ret = DA_ERR_MISMATCH_CONTENT_SIZE; + } + } + return ret; +} + +da_ret_t __handle_event_http_final(http_raw_data_t *raw_data, da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_state_t http_state = 0; + http_info_t *http_info = DA_NULL; + file_info_t *file_info = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(da_info); + http_info = da_info->http_info; + NULL_CHECK_RET(http_info); + file_info = da_info->file_info; + NULL_CHECK_RET(file_info); + NULL_CHECK_RET(raw_data); + + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGD("http_state[%s]", __get_state_str(http_state)); + + switch (http_state) { + case HTTP_STATE_REDIRECTED: + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_READY_TO_DOWNLOAD; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOAD_REQUESTED: + DA_LOGV("case HTTP_STATE_DOWNLOAD_REQUESTED"); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_DOWNLOADING: + DA_LOGD("case HTTP_STATE_DOWNLOADING"); +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) { + discard_download(file_info); + goto ERR; + } + ret = __check_file_size_with_header_content_size(file_info); + if(ret != DA_RESULT_OK) { + discard_download(file_info) ; + goto ERR; + } + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + ret = send_client_update_progress_info(da_info); + break; + case HTTP_STATE_REQUEST_PAUSE: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + if (file_info->file_handle) + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + if (file_info->file_handle) { + ret = file_write_complete(file_info); +// send_client_update_progress_info(da_info); + } +#endif + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_PAUSED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + DA_LOGV("Server Notification code is set to NULL"); + break; + case HTTP_STATE_ABORTED: + case HTTP_STATE_CANCELED: + discard_download(file_info); + break; + case HTTP_STATE_REQUEST_CANCEL: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_CANCELED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + case HTTP_STATE_PAUSED: + DA_LOGD("Remain paused stated"); + break; + default: +#ifdef _RAF_SUPPORT + if (http_info->is_raf_mode_confirmed == DA_TRUE) { + ret = file_write_complete_for_raf(file_info); + } else { + ret = file_write_complete(file_info); + } +#else + ret = file_write_complete(file_info); +#endif + if (ret != DA_RESULT_OK) + goto ERR; + discard_download(file_info); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_FAILED; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + break; + } + +ERR: + /* When file complete is failed */ + if (DA_RESULT_OK != ret) { + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_info->state = HTTP_STATE_DOWNLOAD_FINISH; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + } + if (raw_data->body) + free(raw_data->body); + free(raw_data); + return ret; +} + +void __http_update_cb(http_raw_data_t *data, void *user_param) +{ + http_raw_data_t *raw_data = DA_NULL; + da_info_t *da_info = DA_NULL; + if (!data || !user_param) { + DA_LOGE("NULL CHECK!: data, user_param"); + return; + } + DA_LOGV(""); + raw_data = data; + da_info = (da_info_t *)user_param; + + switch(data->type) { + case HTTP_EVENT_GOT_HEADER: + __handle_event_http_header(raw_data, da_info); + break; + case HTTP_EVENT_GOT_PACKET: + __handle_event_http_packet(raw_data, da_info); + break; + case HTTP_EVENT_FINAL: + __handle_event_http_final(raw_data, da_info); + break; +/* + case HTTP_EVENT_ABORT: + ret = __handle_event_http_abort(raw_data, da_info); + break; +*/ + } +} + +da_bool_t is_stopped_state(da_info_t *da_info) +{ + http_info_t *http_info = DA_NULL; + http_state_t http_state; + NULL_CHECK_RET_OPT(da_info, DA_FALSE); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, DA_FALSE); + DA_MUTEX_LOCK(&(http_info->mutex_state)); + http_state = http_info->state; + DA_MUTEX_UNLOCK(&(http_info->mutex_state)); + switch (http_state) { + case HTTP_STATE_REQUEST_CANCEL: + case HTTP_STATE_CANCELED: + case HTTP_STATE_FAILED: + case HTTP_STATE_ABORTED: + //case HTTP_STATE_REQUEST_PAUSE: + //case HTTP_STATE_REQUEST_RESUME: + //case HTTP_STATE_WAIT_FOR_NET_ERR: + return DA_TRUE; + default: + return DA_FALSE; + } + return DA_FALSE; +} diff --git a/src/agent/download-agent-http-msg-handler.c b/agent/download-agent-http-msg-handler.c old mode 100644 new mode 100755 similarity index 61% rename from src/agent/download-agent-http-msg-handler.c rename to agent/download-agent-http-msg-handler.c index d5e3333..231a61d --- a/src/agent/download-agent-http-msg-handler.c +++ b/agent/download-agent-http-msg-handler.c @@ -1,25 +1,17 @@ /* - * Download Agent + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * @file download-agent-http-msg-handler.c - * @brief Utilities to manipulate HTTP messages - * @author Keunsoon Lee (keunsoon.lee@samsung.com) */ #include @@ -28,20 +20,19 @@ #include "download-agent-http-msg-handler.h" #include "download-agent-debug.h" -#include "download-agent-http-misc.h" #include "download-agent-encoding.h" // '.' and ';' are request from Vodafone -#define IS_TERMINATING_CHAR(c) ( ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) -#define IS_TERMINATING_CHAR_EX(c) ( ((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) -#define IS_URI_TERMINATING_CHAR(c) ( ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_TERMINATING_CHAR(c) ( ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_TERMINATING_CHAR_EX(c) ( ((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) +#define IS_URI_TERMINATING_CHAR(c) ( ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20) ) enum parsing_type { WITH_PARSING_OPTION, WITHOUT_PARSING_OPTION }; -static da_result_t __http_header_add_field(http_header_t **head, +static da_ret_t __http_header_add_field(http_header_t **head, const char *field, const char *value, enum parsing_type type); static void __http_header_destroy_all_field(http_header_t **head); static da_bool_t __get_http_header_for_field( @@ -49,29 +40,27 @@ static da_bool_t __get_http_header_for_field( http_header_t **out_header); static void __exchange_header_value(http_header_t *header, const char *in_raw_value); - static http_header_options_t *__create_http_header_option(const char *field, const char *value); static void __http_header_destroy_all_option(http_header_options_t **head); static da_bool_t __get_http_header_option_for_field( http_header_options_t *header_option, const char *in_field, char **out_value); - static http_header_options_t *__parsing_N_create_option_str(char *org_str); static http_header_options_t *__parsing_options(char *org_str); static void __parsing_raw_value(http_header_t *http_header); -da_result_t http_msg_request_create(http_msg_request_t **http_msg_request) +da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request) { http_msg_request_t *temp_http_msg_request = NULL; - DA_LOG_FUNC_START(HTTPManager); +// DA_LOGV(""); temp_http_msg_request = (http_msg_request_t *)calloc(1, sizeof(http_msg_request_t)); if (!temp_http_msg_request) { *http_msg_request = NULL; - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_ERR_FAIL_TO_MEMALLOC; } @@ -81,7 +70,7 @@ da_result_t http_msg_request_create(http_msg_request_t **http_msg_request) temp_http_msg_request->http_body = NULL; *http_msg_request = temp_http_msg_request; - DA_LOG(HTTPManager, "http_msg_request: %x", (unsigned int)(*http_msg_request)); + DA_LOGV( "http_msg_request: %x", (unsigned int)(*http_msg_request)); return DA_RESULT_OK; } @@ -90,99 +79,54 @@ void http_msg_request_destroy(http_msg_request_t **http_msg_request) { http_msg_request_t *temp_http_msg_request = *http_msg_request; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (temp_http_msg_request) { if (temp_http_msg_request->http_method) { free(temp_http_msg_request->http_method); temp_http_msg_request->http_method = NULL; } - if (temp_http_msg_request->url) { free(temp_http_msg_request->url); temp_http_msg_request->url = NULL; } - if (temp_http_msg_request->http_body) { free(temp_http_msg_request->http_body); temp_http_msg_request->http_body = NULL; } - __http_header_destroy_all_field(&(temp_http_msg_request->head)); - free(temp_http_msg_request); *http_msg_request = NULL; } - -} - -da_result_t http_msg_request_set_method(http_msg_request_t *http_msg_request, - const char *method) -{ - DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_request || !method) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - // ToDo: check method is valid - - http_msg_request->http_method = strdup(method); - - DA_LOG(HTTPManager, "http method : %s", http_msg_request->http_method); - - return DA_RESULT_OK; -} - -da_result_t http_msg_request_get_method(http_msg_request_t *http_msg_request, - const char **method) -{ - // DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (http_msg_request->http_method) { - *method = http_msg_request->http_method; - return DA_RESULT_OK; - } else { - *method = DA_NULL; - return DA_ERR_INVALID_ARGUMENT; - } } -da_result_t http_msg_request_set_url(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request, const char *url) { - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } if (!url) { - DA_LOG_ERR(HTTPManager, "url is NULL; DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("url is NULL; DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_URL; } http_msg_request->url = strdup(url); - - DA_LOG(HTTPManager, "http url : %s", http_msg_request->url); - + DA_SECURE_LOGI("http url[%s]", http_msg_request->url); return DA_RESULT_OK; } -da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request, const char **url) { - // DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } @@ -195,76 +139,34 @@ da_result_t http_msg_request_get_url(http_msg_request_t *http_msg_request, } } -da_result_t http_msg_request_set_body(http_msg_request_t *http_msg_request, - const char *body) -{ - // DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (!body) - return DA_RESULT_OK; - - http_msg_request->http_body = strdup(body); - - DA_LOG(HTTPManager, "http body : %s", http_msg_request->http_body); - - return DA_RESULT_OK; -} - -da_result_t http_msg_request_get_body(http_msg_request_t *http_msg_request, - const char **body) -{ - // DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (http_msg_request->http_body) { - *body = http_msg_request->http_body; - return DA_RESULT_OK; - } else { - *body = DA_NULL; - return DA_ERR_INVALID_ARGUMENT; - } -} - -/* FIXME later : check to free filed and value after this API is called */ -da_result_t http_msg_request_add_field(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request, const char *field, const char *value) { - // DA_LOG_FUNC_START(HTTPManager); + // DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("Check NULL! : http_msg_request"); return DA_ERR_INVALID_ARGUMENT; } return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION); } -da_result_t http_msg_response_create(http_msg_response_t **http_msg_response) +da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response) { http_msg_response_t *temp_http_msg_response = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); temp_http_msg_response = (http_msg_response_t *)calloc(1, sizeof(http_msg_response_t)); if (!temp_http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_ERR_FAIL_TO_MEMALLOC; } else { temp_http_msg_response->status_code = 0; temp_http_msg_response->head = NULL; - *http_msg_response = temp_http_msg_response; - return DA_RESULT_OK; } } @@ -273,66 +175,33 @@ void http_msg_response_destroy(http_msg_response_t **http_msg_response) { http_msg_response_t *temp_http_msg_response = *http_msg_response; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (temp_http_msg_response) { __http_header_destroy_all_field(&(temp_http_msg_response->head)); - free(temp_http_msg_response); *http_msg_response = DA_NULL; } } -da_result_t http_msg_response_set_status_code( - http_msg_response_t *http_msg_response, int status_code) -{ - // DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - http_msg_response->status_code = status_code; - - return DA_RESULT_OK; -} - -da_result_t http_msg_response_get_status_code( - http_msg_response_t *http_msg_response, int *status_code) -{ - DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - *status_code = http_msg_response->status_code; - - return DA_RESULT_OK; -} - -da_result_t http_msg_response_add_field(http_msg_response_t *http_msg_response, +da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response, const char *field, const char *value) { - // DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } - return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION); } -da_result_t __http_header_add_field(http_header_t **head, +da_ret_t __http_header_add_field(http_header_t **head, const char *field, const char *value, enum parsing_type type) { http_header_t *pre = NULL; http_header_t *cur = NULL; - // DA_LOG_FUNC_START(HTTPManager); - DA_LOG(HTTPManager, "[%s][%s]", field, value); + //DA_SECURE_LOGD("[%s][%s]", field, value); pre = cur = *head; while (cur) { @@ -341,8 +210,8 @@ da_result_t __http_header_add_field(http_header_t **head, * Remove the value which is stored before and add a new value. */ if (cur->field && cur->raw_value && - strncmp(cur->field, field, strlen(field)) == 0) { - DA_LOG(HTTPManager, "Remove value for replacement [%s][%s]", cur->field, cur->raw_value); + strncasecmp(cur->field, field, strlen(field)) == 0) { + DA_SECURE_LOGD("Remove value for replacement [%s][%s]", cur->field, cur->raw_value); if (cur->field) { free(cur->field); cur->field = NULL; @@ -374,7 +243,7 @@ da_result_t __http_header_add_field(http_header_t **head, else *head = cur; } else { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_ERR_FAIL_TO_MEMALLOC; } @@ -386,35 +255,28 @@ void __http_header_destroy_all_field(http_header_t **head) http_header_t *pre = NULL; http_header_t *cur = NULL; - // DA_LOG_FUNC_START(HTTPManager); - cur = *head; while (cur) { if (cur->field) { - DA_LOG(HTTPManager, "field= %s", cur->field); free(cur->field); cur->field = DA_NULL; } - if (cur->value) { free(cur->value); cur->value = DA_NULL; } - if (cur->raw_value) { free(cur->raw_value); cur->raw_value = DA_NULL; } - __http_header_destroy_all_option(&(cur->options)); - + free(cur->options); + cur->options = DA_NULL; pre = cur; cur = cur->next; - free(pre); } - *head = DA_NULL; } @@ -428,13 +290,10 @@ http_header_options_t *__create_http_header_option(const char *field, if (option) { if (field) option->field = strdup(field); - if (value) option->value = strdup(value); - option->next = NULL; } - return option; } @@ -443,38 +302,34 @@ void __http_header_destroy_all_option(http_header_options_t **head) http_header_options_t *pre = NULL; http_header_options_t *cur = NULL; - // DA_LOG_FUNC_START(HTTPManager); + // DA_LOGV(""); cur = *head; while (cur) { if (cur->field) { - DA_LOG(HTTPManager, "field= %s", cur->field); + DA_SECURE_LOGD("field= %s", cur->field); free(cur->field); cur->field = DA_NULL; } - if (cur->value) { free(cur->value); cur->value = DA_NULL; } - pre = cur; cur = cur->next; - free(pre); } - *head = DA_NULL; } -da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, +da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, http_msg_iter_t *http_msg_iter) { - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!http_msg_request) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } @@ -483,19 +338,15 @@ da_result_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, return DA_RESULT_OK; } -da_result_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, +da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, http_msg_iter_t *http_msg_iter) { - // DA_LOG_FUNC_START(HTTPManager); - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); + DA_LOGE("DA_ERR_INVALID_ARGUMENT"); return DA_ERR_INVALID_ARGUMENT; } *http_msg_iter = http_msg_response->head; - // DA_LOG(HTTPManager, "retrieve iter = 0x%x", (unsigned int)http_msg_iter); - return DA_RESULT_OK; } @@ -504,18 +355,12 @@ da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter, { http_header_t *cur = *http_msg_iter; - // DA_LOG_FUNC_START(HTTPManager); - - // DA_LOG(HTTPManager, "getting iter = 0x%x", (unsigned int)cur); - if (cur) { *out_field = cur->field; *out_value = cur->value; *http_msg_iter = cur->next; - return DA_TRUE; } else { - // DA_LOG(HTTPManager, "end of iter"); return DA_FALSE; } } @@ -525,18 +370,12 @@ da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter, { http_header_t *cur = *http_msg_iter; - // DA_LOG_FUNC_START(HTTPManager); - - // DA_LOG(HTTPManager, "getting iter = 0x%x", (unsigned int)cur); - if (cur) { *out_field = cur->field; *out_header = cur; *http_msg_iter = cur->next; - return DA_TRUE; } else { - // DA_LOG(HTTPManager, "end of iter"); return DA_FALSE; } } @@ -547,21 +386,18 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) char *option_value = NULL; int option_field_len = 0; int option_value_len = 0; - char *org_pos = NULL; int org_str_len = 0; - char *working_str = NULL; char *working_pos = NULL; char *working_pos_field_start = NULL; char *working_pos_value_start = NULL; - da_bool_t is_inside_quotation = DA_FALSE; da_bool_t is_working_for_field = DA_TRUE; int i = 0; http_header_options_t *option = NULL; - // DA_LOG_FUNC_START(HTTPManager); + // DA_LOGV(""); if (!org_str) return NULL; @@ -580,7 +416,6 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) for (i = 0; i < org_str_len; i++) { if (*org_pos == '"') is_inside_quotation = !is_inside_quotation; - if (is_inside_quotation) { // Leave anything including blank if it is inside of double quotation mark. *working_pos = *org_pos; @@ -596,7 +431,6 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) is_working_for_field = DA_FALSE; working_pos_value_start = working_pos; } - org_pos++; } else { *working_pos = *org_pos; @@ -614,20 +448,18 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) strncpy(option_field, working_pos_field_start, option_field_len); } - if (option_value_len > 0 && working_pos_value_start) { option_value = (char *)calloc(1, option_value_len + 1); if (option_value) strncpy(option_value, working_pos_value_start, option_value_len); } - if (working_str) { free(working_str); working_pos = working_str = NULL; } - DA_LOG(HTTPManager, "option_field = [%s], option_value = [%s]", + DA_SECURE_LOGD("option_field = [%s], option_value = [%s]", option_field, option_value); if (option_field || option_value) { @@ -637,7 +469,6 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) free(option_field); option_field = NULL; } - if (option_value) { free(option_value); option_value = NULL; @@ -648,7 +479,7 @@ http_header_options_t *__parsing_N_create_option_str(char *org_str) http_header_options_t *__parsing_options(char *org_str) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; http_header_options_t *head = NULL; http_header_options_t *pre = NULL; http_header_options_t *cur = NULL; @@ -659,13 +490,13 @@ http_header_options_t *__parsing_options(char *org_str) char *wanted_str_end = NULL; char *cur_pos = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!org_str) return NULL; /* Do Not use strtok(). It's not thread safe. */ - // DA_LOG_CRITICAL(HTTPManager, "org_str = %s", org_str); + // DA_SECURE_LOGD("org_str = %s", org_str); cur_pos = org_str; @@ -678,17 +509,16 @@ http_header_options_t *__parsing_options(char *org_str) wanted_str_end = org_str + strlen(org_str); cur_pos = NULL; } - wanted_str_len = wanted_str_end - wanted_str_start; wanted_str = (char *)calloc(1, wanted_str_len + 1); if (!wanted_str) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); ret = DA_ERR_FAIL_TO_MEMALLOC; goto ERR; } strncpy(wanted_str, wanted_str_start, wanted_str_len); - // DA_LOG_CRITICAL(HTTPManager, "wanted_str = [%s]", wanted_str); + // DA_SECURE_LOGD("wanted_str = [%s]", wanted_str); cur = __parsing_N_create_option_str(wanted_str); if (pre) { pre->next = cur; @@ -704,7 +534,6 @@ http_header_options_t *__parsing_options(char *org_str) ERR: if (ret != DA_RESULT_OK) __http_header_destroy_all_option(&head); - return head; } @@ -712,23 +541,18 @@ void __parsing_raw_value(http_header_t *http_header_field) { char *raw_value = NULL; char *option_str_start = NULL; - char *trimed_value = NULL; int trimed_value_len = 0; - char *trimed_value_start = NULL; char *trimed_value_end = NULL; - // DA_LOG_FUNC_START(HTTPManager); - raw_value = http_header_field->raw_value; - // DA_LOG_CRITICAL(HTTPManager, "raw_value = [%s]", raw_value); + // DA_SECURE_LOGD("raw_value = [%s]", raw_value); if (!raw_value) return; trimed_value_start = raw_value; - trimed_value_end = strchr(raw_value, ';'); if (!trimed_value_end) { // No options @@ -740,10 +564,9 @@ void __parsing_raw_value(http_header_t *http_header_field) // for trimed value trimed_value_len = trimed_value_end - trimed_value_start; - trimed_value = (char *)calloc(1, trimed_value_len + 1); if (!trimed_value) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return; } strncpy(trimed_value, trimed_value_start, trimed_value_len); @@ -751,18 +574,15 @@ void __parsing_raw_value(http_header_t *http_header_field) // for option parsing option_str_start = trimed_value_end + 1; - http_header_field->options = __parsing_options(option_str_start); /////////////// show http_header_options_t *cur = NULL; - cur = http_header_field->options; while (cur) { - DA_LOG(HTTPManager, "field = [%s], value = [%s]", cur->field, cur->value); +// DA_SECURE_LOGD("field = [%s], value = [%s]", cur->field, cur->value); cur = cur->next; } - } da_bool_t __get_http_header_option_for_field( @@ -771,18 +591,19 @@ da_bool_t __get_http_header_option_for_field( { http_header_options_t *cur = NULL; - // DA_LOG_FUNC_START(HTTPManager); + // DA_LOGV(""); if (!header_option) { - DA_LOG_ERR(HTTPManager, "input header_option is NULL."); + DA_LOGE("input header_option is NULL."); return DA_FALSE; } cur = header_option; while (cur) { if (cur->field) { - if (!strncmp(cur->field, in_field, strlen(cur->field))) { - DA_LOG(HTTPManager, "[%s][%s]", cur->field, cur->value); + if (!strncasecmp(cur->field, in_field, strlen(cur->field)) && + cur->value) { + DA_SECURE_LOGD("[%s][%s]", cur->field, cur->value); *out_value = cur->value; return DA_TRUE; } @@ -790,7 +611,6 @@ da_bool_t __get_http_header_option_for_field( } cur = cur->next; } - return DA_FALSE; } @@ -801,12 +621,33 @@ da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response, http_header_t *header = NULL; char *field = NULL; - DA_LOG_FUNC_START(HTTPManager); + //DA_LOGV(""); http_msg_response_get_iter(http_msg_response, &http_msg_iter); while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { - if (field && header && !strncmp(field, in_field, strlen(field))) { - DA_LOG(HTTPManager, "[%s][%s]", field, header->value); + if (field && header && !strncasecmp(field, in_field, strlen(field))) { + //DA_SECURE_LOGD("[%s][%s]", field, header->value); + *out_header = header; + return DA_TRUE; + } + } + + return DA_FALSE; +} + +da_bool_t __get_http_req_header_for_field(http_msg_request_t *http_msg_request, + const char *in_field, http_header_t **out_header) +{ + http_msg_iter_t http_msg_iter; + http_header_t *header = NULL; + char *field = NULL; + + //DA_LOGV(""); + + http_msg_request_get_iter(http_msg_request, &http_msg_iter); + while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { + if (field && header && !strncasecmp(field, in_field, strlen(field))) { + //DA_SECURE_LOGD("[%s][%s]", field, header->value); *out_header = header; return DA_TRUE; } @@ -817,7 +658,7 @@ da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response, void __exchange_header_value(http_header_t *header, const char *in_raw_value) { - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!header || !in_raw_value) return; @@ -828,7 +669,6 @@ void __exchange_header_value(http_header_t *header, const char *in_raw_value) free(header->value); header->value = DA_NULL; } - if (header->raw_value) free(header->raw_value); header->raw_value = strdup(in_raw_value); @@ -842,15 +682,14 @@ da_bool_t http_msg_response_get_content_type( da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "Content-Type", - &header); + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_TYPE, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Content-Type"); + DA_LOGV("no Content-Type"); return DA_FALSE; } - if (out_type) *out_type = strdup(header->value); @@ -863,43 +702,43 @@ void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); if (!http_msg_response || !in_type) return; - b_ret = __get_http_header_for_field(http_msg_response, "Content-Type", - &header); + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_CONTENT_TYPE, &header); if (b_ret) { if (header->raw_value && (!strncmp(header->raw_value, in_type, strlen(header->raw_value)))) return; - DA_LOG(HTTPManager, "exchange Content-Type to [%s] from [%s]", in_type, header->value); + DA_SECURE_LOGD("exchange Content-Type to [%s] from [%s]", in_type, header->value); __exchange_header_value(header, in_type); } else { __http_header_add_field(&(http_msg_response->head), - "Content-Type", in_type, WITH_PARSING_OPTION); + HTTP_FIELD_CONTENT_TYPE, in_type, WITH_PARSING_OPTION); } } da_bool_t http_msg_response_get_content_length( - http_msg_response_t *http_msg_response, int *out_length) + http_msg_response_t *http_msg_response, da_size_t *out_length) { da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); b_ret = __get_http_header_for_field(http_msg_response, - "Content-Length", &header); + HTTP_FIELD_CONTENT_LENGTH, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Content-Length"); + DA_LOGV( "no Content-Length"); return DA_FALSE; } if (out_length) - *out_length = atoi(header->value); + *out_length = atoll(header->value); return DA_TRUE; } @@ -911,32 +750,29 @@ da_bool_t http_msg_response_get_content_disposition( da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; char *file_name = NULL; - char *wanted_str = NULL; char *wanted_str_start = NULL; char *wanted_str_end = NULL; char *decoded_str = NULL; int wanted_str_len = 0; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); b_ret = __get_http_header_for_field(http_msg_response, - "Content-Disposition", &header); + HTTP_FIELD_CONTENT_DISPOSITION, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Content-Disposition"); + DA_LOGV( "no Content-Disposition"); return DA_FALSE; } - if (out_disposition) *out_disposition = strdup(header->value); - if (!out_file_name) return DA_FALSE; b_ret = __get_http_header_option_for_field(header->options, "filename", &file_name); if (!b_ret) { - DA_LOG(HTTPManager, "no option"); + DA_LOGV( "no option"); return DA_FALSE; } @@ -946,49 +782,46 @@ da_bool_t http_msg_response_get_content_disposition( *out_file_name = strdup(file_name); return DA_TRUE; } else { - // DA_LOG(HTTPManager, "wanted_str_start = [%s]", wanted_str_start); + // DA_SECURE_LOGD("wanted_str_start = [%s]", wanted_str_start); wanted_str_start++; wanted_str_end = strchr(wanted_str_start, '"'); if (wanted_str_end) { wanted_str_len = wanted_str_end - wanted_str_start; wanted_str = (char*)calloc(1, wanted_str_len + 1); if (!wanted_str) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); return DA_FALSE; } strncpy(wanted_str, wanted_str_start, wanted_str_len); b_ret = is_base64_encoded_word(wanted_str); if (b_ret) { - DA_LOG(HTTPManager, "It's base64 encoded-word string"); + DA_LOGV("It's base64 encoded-word string"); if (DA_RESULT_OK == decode_base64_encoded_str( wanted_str, &decoded_str)) { - DA_LOG(HTTPManager, "base64 decoded str = [%s]", decoded_str); + DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str); free(wanted_str); wanted_str = decoded_str; decoded_str = NULL; } else { - DA_LOG(HTTPManager, "Fail to base64 decode. Just use un-decoded string."); + DA_LOGV("Fail to base64 decode. Just use un-decoded string."); } } else { - DA_LOG(HTTPManager, "It's NOT base64 encoded-word string"); + DA_LOGV("It's NOT base64 encoded-word string"); } decode_url_encoded_str(wanted_str, &decoded_str); /* If it is url encoded string */ if (decoded_str) { - DA_LOG(HTTPManager, "Url decoded str = [%s]", decoded_str); + DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str); free(wanted_str); wanted_str = decoded_str; decoded_str = NULL; } - *out_file_name = wanted_str; - - DA_LOG(HTTPManager, "out_file_name = [%s]", *out_file_name); - + DA_SECURE_LOGI("out_file_name = [%s]", *out_file_name); return DA_TRUE; } else { - DA_LOG_ERR(HTTPManager, "Not matched \" !"); + DA_LOGE("Not matched \" !"); return DA_FALSE; } } @@ -1000,51 +833,54 @@ da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response, da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "ETag", &header); + b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG, + &header); if (!b_ret) { - DA_LOG(HTTPManager, "no ETag"); + DA_LOGV( "no ETag"); return DA_FALSE; } - if (out_value) *out_value = strdup(header->value); return DA_TRUE; } -da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, +#ifdef _RAF_SUPPORT +da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response, char **out_value) { da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "Date", &header); + b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE, + &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Date"); + DA_LOGV( "no RAF mode"); return DA_FALSE; } - if (out_value) *out_value = strdup(header->value); return DA_TRUE; } +#endif -da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, +da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, char **out_value) { da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); - b_ret = __get_http_header_for_field(http_msg_response, "Location", &header); + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_DATA, &header); if (!b_ret) { - DA_LOG(HTTPManager, "no Location"); + DA_LOGV( "no Date"); return DA_FALSE; } if (out_value) @@ -1053,120 +889,27 @@ da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, return DA_TRUE; } -da_result_t http_msg_response_get_boundary( - http_msg_response_t *http_msg_response, char **out_val) -{ - da_result_t ret = DA_RESULT_OK; - - http_msg_iter_t http_msg_iter; - char *field = NULL; - char *value = NULL; - char *boundary = NULL; - - DA_LOG_FUNC_START(HTTPManager); - - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - http_msg_response_get_iter(http_msg_response, &http_msg_iter); - while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) { - if ((field != DA_NULL) && (value != DA_NULL)) { - if (!strncmp(field, "Content-Type", - strlen("Content-Type"))) { - char *org_str = NULL; - char *boundary_str_start = NULL; - char *boundary_value_start = NULL; - char *boundary_value_end = NULL; - int boundary_value_len = 0; - - org_str = value; - - boundary_str_start - = strstr(org_str, "boundary"); - if (boundary_str_start) { - DA_LOG(HTTPManager, "boundary_str_start = %s", boundary_str_start); - // this "Content-Type" value has "boundary" in it, so get the value - boundary_value_start = strchr( - boundary_str_start, '"'); - boundary_value_start += 1; // start without " - - boundary_value_end = strchr( - boundary_value_start, '"'); - boundary_value_len = boundary_value_end - - boundary_value_start; - - DA_LOG(HTTPManager, "boundary_value_start = %s", boundary_value_start); - DA_LOG(HTTPManager, "boundary_value_end = %s", boundary_value_end); - DA_LOG(HTTPManager, "boundary_value_len = %d", boundary_value_len); - - } else { - // no "boundary" field on this "Content-Type" value - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - // end of clear - - boundary = (char *)calloc(1, - boundary_value_len + 1); - if (!boundary) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - - goto ERR; - } - strncpy(boundary, boundary_value_start, - boundary_value_len); - DA_LOG(HTTPManager, "[boundary][%s]", boundary); - break; - } - } - } - - *out_val = boundary; - -ERR: - return ret; -} - -char *get_http_response_header_raw(http_msg_response_t *http_msg_response) +da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, + char **out_value) { - http_msg_iter_t http_msg_iter; + da_bool_t b_ret = DA_FALSE; http_header_t *header = NULL; - char *field = NULL; - char tmp_buf[1024*4] = {0,}; - char line_buf[1024] = {0,}; - int len = 0; - char *buff = NULL; - DA_LOG_FUNC_START(HTTPManager); + DA_LOGV(""); - http_msg_response_get_iter(http_msg_response, &http_msg_iter); - while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) { - if (field && header) { - // FIXME later :: buffer length is more than total length. think about getting header's conent length from libsoup - len = strlen(field) + strlen(header->value) + 2; - snprintf(line_buf, len,"%s:%s", field, header->value); - strncat(tmp_buf, line_buf, len); - strcat(tmp_buf, "\n"); - } - } - if (strlen(tmp_buf) > 0) { - buff = (char *)calloc(1, strlen(tmp_buf) + 1); - if (buff == DA_NULL) { - DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC"); - return DA_NULL; - } - memcpy(buff, tmp_buf, strlen(tmp_buf)); - DA_LOG(HTTPManager, "\n---raw response header---\n%s\n------\n",buff); - return buff; - } else { - return DA_NULL; + b_ret = __get_http_header_for_field(http_msg_response, + HTTP_FIELD_LOCATION, &header); + if (!b_ret) { + DA_LOGV( "no Location"); + return DA_FALSE; } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; } -char *_stristr(const char *long_str, const char *find_str) +char *__stristr(const char *long_str, const char *find_str) { int i = 0; int length_long = 0; @@ -1176,7 +919,7 @@ char *_stristr(const char *long_str, const char *find_str) char *look_ptr = NULL; if (long_str == NULL || find_str == NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); return NULL; } @@ -1186,14 +929,14 @@ char *_stristr(const char *long_str, const char *find_str) org_ptr = (char*)calloc(1, length_long + 1); if (org_ptr == NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); return NULL; } look_ptr = (char*)calloc(1, length_find + 1); if (look_ptr == NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); free(org_ptr); return NULL; } @@ -1208,7 +951,6 @@ char *_stristr(const char *long_str, const char *find_str) } else { org_ptr[i] = long_str[i]; } - i++; } @@ -1224,7 +966,6 @@ char *_stristr(const char *long_str, const char *find_str) } else { look_ptr[i] = find_str[i]; } - i++; } @@ -1250,7 +991,6 @@ da_bool_t extract_attribute_from_header( const char *szFindStr, char **ppRtnValue) { - char *pValuePos = NULL; int index = 0; int startPos = 0; @@ -1258,21 +998,19 @@ da_bool_t extract_attribute_from_header( int need_to_end_quataion_mark = 0; if (szHeadStr == DA_NULL || szFindStr == DA_NULL) { - DA_LOG_ERR(Default,"INVALID ARGUMENT"); + DA_LOGE("INVALID ARGUMENT"); return DA_FALSE; } - if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) { - DA_LOG_ERR(Default,"INVALID ARGUMENT");; + DA_LOGE("INVALID ARGUMENT");; return DA_FALSE; } - if (ppRtnValue == NULL) { return DA_FALSE; } - pValuePos = _stristr(szHeadStr, (char*)szFindStr); + pValuePos = __stristr(szHeadStr, (char*)szFindStr); if (pValuePos == NULL) { *ppRtnValue = NULL; goto ERR; @@ -1304,7 +1042,8 @@ da_bool_t extract_attribute_from_header( startPos = index; /* Find the end of data. */ - if (0 == strcmp(szFindStr, "Location"))//terminate character list does not contain ';' in case of URI + if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION, + strlen(HTTP_FIELD_LOCATION)))//terminate character list does not contain ';' in case of URI { while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) { index++; @@ -1322,14 +1061,14 @@ da_bool_t extract_attribute_from_header( strLen = index - startPos; if (strLen < 1) { - DA_LOG_ERR(Default," strLen is < 1"); + DA_LOGE(" strLen is < 1"); goto ERR; } *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1)); if (*ppRtnValue == NULL) { - DA_LOG_ERR(Default," *ppRtnValue is NULL"); + DA_LOGE(" *ppRtnValue is NULL"); goto ERR; } @@ -1337,14 +1076,50 @@ da_bool_t extract_attribute_from_header( *(*ppRtnValue + strLen) = '\0'; return DA_TRUE; - ERR: - if (*ppRtnValue) { free(*ppRtnValue); *ppRtnValue = NULL; } - return DA_FALSE; } +da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE, + &header); + if (!b_ret) { + DA_LOGV( "no If Range"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} + +da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request, + char **out_value) +{ + da_bool_t b_ret = DA_FALSE; + http_header_t *header = NULL; + + DA_LOGV(""); + + b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE, + &header); + if (!b_ret) { + DA_LOGV( "no Range"); + return DA_FALSE; + } + if (out_value) + *out_value = strdup(header->value); + + return DA_TRUE; +} diff --git a/agent/download-agent-interface.c b/agent/download-agent-interface.c new file mode 100755 index 0000000..0b19813 --- /dev/null +++ b/agent/download-agent-interface.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "download-agent-interface.h" +#include "download-agent-dl-mgr.h" + +int da_init() +{ + DA_LOGV(""); + da_ret_t ret = DA_RESULT_OK; + DA_LOGI("Return ret = %d", ret); + return ret; +} + +int da_deinit() +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV(""); + destroy_da_info_list(); + DA_LOGI("====== da_deint EXIT ====="); + return ret; +} + +int da_start_download(const char *url, req_data_t *ext_data, + da_cb_t *da_cb_data, int *download_id) +{ + da_ret_t ret = DA_RESULT_OK; + int req_header_count = 0; + int i = 0; + int da_id = DA_INVALID_ID; + da_info_t *da_info = DA_NULL; + + *download_id = DA_INVALID_ID; + + if (ext_data->request_header_count > 0) { + DA_LOGI("request_header_count[%d]", ext_data->request_header_count); + for (i = 0; i < ext_data->request_header_count; i++) { + if (ext_data->request_header[i]) { + req_header_count++; + DA_SECURE_LOGI("request_header[%s]", ext_data->request_header[i]); + } + } + DA_LOGI("actual request_header_count[%d]", req_header_count); + if (ext_data->request_header_count != req_header_count) { + DA_LOGE("Request header count is not matched with number of request header array"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } + } + + if (ext_data->install_path) + DA_SECURE_LOGI("install path[%s]", ext_data->install_path); + if (ext_data->file_name) + DA_SECURE_LOGI("file_name[%s]", ext_data->file_name); + if (ext_data->temp_file_path) + DA_SECURE_LOGI("temp_file_path[%s]", ext_data->temp_file_path); + if (ext_data->etag) + DA_SECURE_LOGI("etag[%s]", ext_data->etag); + if (ext_data->pkg_name) + DA_SECURE_LOGI("pkg_name[%s]", ext_data->pkg_name); + if (ext_data->network_bonding) + DA_LOGD("network bonding option[%d]", ext_data->network_bonding); + if (ext_data->user_req_data) + DA_LOGI("user_req_data[%p]", ext_data->user_req_data); + if (ext_data->user_client_data) + DA_LOGI("user_client_data[%p]", ext_data->user_client_data); + + ret = get_available_da_id(&da_id); + if (ret != DA_RESULT_OK) + goto ERR; + + da_info = da_info_list[da_id]; + da_info->da_id = da_id; + + ret = copy_user_input_data(da_info, url, ext_data, da_cb_data); + if (ret != DA_RESULT_OK) + goto ERR; + *download_id = da_id; + ret = start_download(da_info); +ERR: + DA_LOGI("Return:id[%d],ret[%d]", *download_id, ret); + return ret; +} + +int da_cancel_download(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + + DA_LOGV("download_id[%d]", download_id); + ret = cancel_download(download_id, DA_TRUE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_cancel_download_without_update(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = cancel_download(download_id, DA_FALSE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_suspend_download(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = suspend_download(download_id, DA_TRUE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_suspend_download_without_update(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = suspend_download(download_id, DA_FALSE); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + + +int da_resume_download(int download_id) +{ + da_ret_t ret = DA_RESULT_OK; + DA_LOGV("download_id[%d]", download_id); + ret = resume_download(download_id); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} + +int da_is_valid_download_id(int download_id) +{ + da_bool_t ret = DA_FALSE; + ret = is_valid_download_id(download_id); + DA_LOGI("Return:id[%d],ret[%d]", download_id, ret); + return ret; +} diff --git a/src/agent/download-agent-mime-util.c b/agent/download-agent-mime-util.c old mode 100644 new mode 100755 similarity index 69% rename from src/agent/download-agent-mime-util.c rename to agent/download-agent-mime-util.c index 8b63a21..71e08eb --- a/src/agent/download-agent-mime-util.c +++ b/agent/download-agent-mime-util.c @@ -1,26 +1,18 @@ /* - * Download Agent + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * @file download-agent-mime-util.c - * @brief mime utility functions - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ + */ #include #include @@ -29,14 +21,11 @@ #include "download-agent-debug.h" #include "download-agent-mime-util.h" +#include "download-agent-pthread.h" -#define IS_PROHIBITED_CHAR(c) ((c) == ';' || (c) == '\\' || (c) == '/' || (c) == ':' || (c) == '*' || (c) == '?' || (c) == '"' || (c) == '>' || (c) == '<' || (c) == '|' || (c) == '(' || (c) == ')') -#define IS_SPACE_CHARACTER(c) ((c) == ' ' || (c) == '\t') +#define IS_PROHIBITED_CHAR(c) ((c) == ';' || (c) == '\\' || (c) == '/' || (c) == ':' || (c) == '*' || (c) == '?' || (c) == '"' || (c) == '>' || (c) == '<' || (c) == '|' || (c) == '(' || (c) == ')') +#define IS_SPACE_CHARACTER(c) ((c) == '\t') -#define DD_MIME_STR "application/vnd.oma.dd+xml" -#define DD_EXT_STR "*.dd" -#define DRM_MIME_STR "application/vnd.oma.drm.message" -#define DRM_EXT_STR "*.dcf" #define MAX_EXT_TABLE_INDEX 16 Ext_translation_table ext_trans_table [MAX_EXT_TABLE_INDEX] = { {"*.xla", "*.xls"}, @@ -75,10 +64,11 @@ const char *ambiguous_MIME_Type_list[] = { "application/octet-stream" }; +/* Because xdgmime is not thread safety, this mutex is necessary */ +pthread_mutex_t mutex_for_xdgmime = PTHREAD_MUTEX_INITIALIZER; + da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) { -// DA_LOG_FUNC_START(Default); - if (!in_mime_type) return DA_FALSE; @@ -87,7 +77,7 @@ da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) for (index = 0 ; index < list_size ; index++) { if (0 == strncmp(in_mime_type, ambiguous_MIME_Type_list[index], strlen(ambiguous_MIME_Type_list[index]))) { - DA_LOG(Default,"It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]); + //DA_SECURE_LOGD("It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]); return DA_TRUE; } } @@ -95,38 +85,41 @@ da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type) return DA_FALSE; } -da_result_t da_mime_get_ext_name(char *mime, char **ext) +da_ret_t da_mime_get_ext_name(char *mime, char **ext) { - da_result_t ret = DA_RESULT_OK; + da_ret_t ret = DA_RESULT_OK; const char **extlist = DA_NULL; const char *unaliased_mimetype = DA_NULL; char ext_temp[DA_MAX_STR_LEN] = {0,}; char *temp = NULL; - DA_LOG_FUNC_START(Default); + DA_LOGV(""); if (DA_NULL == mime || DA_NULL == ext) { ret = DA_ERR_INVALID_ARGUMENT; - DA_LOG_ERR(Default,"Invalid mime type"); + DA_LOGE("Invalid mime type"); goto ERR; } - DA_LOG_VERBOSE(Default,"mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime)); +// DA_SECURE_LOGD("mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime)); /* unaliased_mimetype means representative mime among similar types */ + DA_MUTEX_LOCK(&mutex_for_xdgmime); unaliased_mimetype = xdg_mime_unalias_mime_type(mime); if (unaliased_mimetype == DA_NULL) { ret = DA_ERR_INVALID_MIME_TYPE; - DA_LOG_ERR(Default,"Invalid mime type : No unsaliased mime type"); + DA_LOGI("Invalid mime type : No unsaliased mime type"); + DA_MUTEX_UNLOCK(&mutex_for_xdgmime); goto ERR; } - DA_LOG(Default,"unaliased_mimetype[%s]\n",unaliased_mimetype); + DA_SECURE_LOGD("unaliased_mimetype[%s]\n",unaliased_mimetype); /* Get extension name from shared-mime-info */ extlist = xdg_mime_get_file_names_from_mime_type(unaliased_mimetype); + DA_MUTEX_UNLOCK(&mutex_for_xdgmime); if (extlist == DA_NULL || *extlist == DA_NULL) { int i = 0; ret = DA_ERR_INVALID_MIME_TYPE; - DA_LOG(Default,"No extension list"); + DA_LOGV("No extension list"); #ifdef _SAMSUNG_MIME_POLICY for (i = 0; i < MAX_SEC_MIME_TABLE_INDEX; i++) { @@ -138,8 +131,8 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) } #endif } else { /* For drm case, this else statement is needed */ - DA_LOG(Default,"extlist[%s]\n",*extlist); - strncpy(ext_temp, *extlist, DA_MAX_STR_LEN); +// DA_LOGD("extlist[%s]\n",*extlist); + strncpy(ext_temp, *extlist, DA_MAX_STR_LEN - 1); /* If only one extension name is existed, don't enter here */ while (*extlist != NULL) { int i = 0; @@ -155,31 +148,32 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) break; } } - DA_LOG(Default,"index[%d]\n",i); + DA_LOGV("index[%d]\n",i); /* If there is a mime at extension transform table */ if (i < MAX_EXT_TABLE_INDEX) { break; } - DA_LOG(Default,"extlist[%s]\n",*extlist); +// DA_LOGD("extlist[%s]\n",*extlist); extlist++; } - DA_LOG(Default,"extension from shared mime info[%s]",ext_temp); +// DA_SECURE_LOGD("extension from shared mime info[%s]",ext_temp); } if (strlen(ext_temp) < 1) { - /* If there is no mime string for OMD descriptor mime type */ - if (strncmp(DD_MIME_STR,mime,strlen(DD_MIME_STR)) == 0) { - strncpy(ext_temp, DD_EXT_STR, DA_MAX_STR_LEN-1); + /* If there is no mime string for OMA descriptor mime type */ + if (strncmp(DD_MIME_STR, mime, strlen(DD_MIME_STR)) == 0) { + strncpy(ext_temp, DD_EXT_STR, DA_MAX_STR_LEN - 1); ret = DA_RESULT_OK; /* If there is no extension name for "applicaion/vnd.oma.drm.messeages" * at shared-mime-info*/ - } else if (strncmp(DRM_MIME_STR,mime,strlen(DD_MIME_STR)) == 0) { - strncpy(ext_temp, DRM_EXT_STR, DA_MAX_STR_LEN-1); + } else if (strncmp(DRM_MIME_MSG_STR, mime, strlen(DRM_MIME_MSG_STR)) == + 0) { + strncpy(ext_temp, DRM_EXT_STR, DA_MAX_STR_LEN - 1); /* If there is extension name at extlist, the return value can have an error.*/ ret = DA_RESULT_OK; } else { ret = DA_ERR_INVALID_MIME_TYPE; - DA_LOG_ERR(Default,"Invalid mime type : no extension name at list"); + DA_LOGI("Invalid mime type : no extension name at list"); } } if (ret != DA_RESULT_OK) @@ -191,7 +185,7 @@ da_result_t da_mime_get_ext_name(char *mime, char **ext) else temp++; - DA_LOG(Default,"final extension name:[%s]",temp); + DA_SECURE_LOGD("final extension name:[%s]",temp); *ext = (char*)calloc(1, strlen(temp) + 1); if (*ext != DA_NULL) { strncpy(*ext, temp,strlen(temp)); @@ -210,11 +204,11 @@ da_bool_t da_get_extension_name_from_url(char *url, char **ext) char *temp_str = DA_NULL; int buf_len = 0; - DA_LOG_FUNC_START(Default); + DA_LOGV(""); if (DA_NULL == url || DA_NULL == ext) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); return ret; } @@ -233,11 +227,11 @@ da_bool_t da_get_extension_name_from_url(char *url, char **ext) if (DA_NULL == *ext) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Memory Fail"); + DA_LOGE("Memory Fail"); goto ERR; } strncpy(*ext,buff,buf_len); - DA_LOG(Default,"extention name[%s]",*ext); + DA_SECURE_LOGD("extention name[%s]",*ext); return ret; } } @@ -250,7 +244,7 @@ ERR: } /* FIXME move this function to another file */ -da_bool_t da_get_file_name_from_url(char* url, char** name) +da_bool_t da_get_file_name_from_url(char *url, char **name) { da_bool_t ret = DA_TRUE; char *buff = DA_NULL; @@ -262,24 +256,24 @@ da_bool_t da_get_file_name_from_url(char* url, char** name) int len_name = 0; char name_buff[DA_MAX_FILE_PATH_LEN] = {0,}; - DA_LOG_FUNC_START(Default); + DA_LOGV(""); if (DA_NULL == url || DA_NULL == name) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); goto ERR; } - *name = DA_NULL; + if (!strstr(url, "http") && !strstr(url, "https")) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Invalid Argument"); + DA_LOGE("Invalid Argument"); goto ERR; } buff = (char*) calloc(1, strlen(url) +1); if(DA_NULL == buff) { ret = DA_FALSE; - DA_LOG_ERR(Default,"Memory Fail"); + DA_LOGE("Memory Fail"); goto ERR; } @@ -341,16 +335,15 @@ da_bool_t da_get_file_name_from_url(char* url, char** name) if (End != NULL) { *End = '\0'; } - DA_LOG(Default,"file name BEFORE removing prohibited character = %s", name_buff); +// DA_SECURE_LOGD("file name BEFORE removing prohibited character = %s", name_buff); delete_prohibited_char(name_buff, strlen(name_buff)); - DA_LOG(Default,"file name AFTER removing prohibited character = %s", name_buff); len_name = strlen(name_buff); *name = (char*) calloc(1, len_name + 1); if (*name) { strncpy(*name, name_buff,len_name); } } - DA_LOG(Default,"Extracted file name : %s", *name); +// DA_SECURE_LOGD("Extracted file name : %s", *name); ERR: if (buff) { free (buff); @@ -367,7 +360,7 @@ void delete_prohibited_char(char *szTarget, int str_len) int tar_len = 0; if(szTarget == NULL || str_len <= 0 || strlen(szTarget) != str_len) { - DA_LOG_ERR(Default,"Invaild Parameter\n"); + DA_LOGE("Invaild Parameter\n"); return; } @@ -403,3 +396,54 @@ void delete_prohibited_char(char *szTarget, int str_len) return; } +#ifdef _ENABLE_OMA_DRM +da_bool_t is_content_drm_dcf(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, DRM_MIME_CONTENT_STR)) { + DA_LOGV("DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} + +da_bool_t is_content_drm_dm(char *content_type) +{ + if (content_type == DA_NULL) + return DA_FALSE; + + if (0 == strcmp(content_type, DRM_MIME_MSG_STR)) { + DA_LOGV("DRM_DM content"); + return DA_TRUE; + } else { + return DA_FALSE; + } +} +#endif + +da_ret_t get_extension_from_mime_type(char *mime_type, char **extension) +{ + da_ret_t ret = DA_RESULT_OK; + char *ext = DA_NULL; + + DA_LOGV(""); + if (DA_NULL == mime_type || DA_NULL == extension) { + DA_LOGE("received mime_type is null"); + ret = DA_ERR_INVALID_ARGUMENT; + goto ERR; + } +// DA_SECURE_LOGD("input mime type = %s", mime_type); + if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) { + DA_LOGE("can't find proper extension!"); + goto ERR; + } + *extension = ext; +// DA_SECURE_LOGD("found extension = %s", *extension); + +ERR: + return ret; +} + diff --git a/agent/download-agent-plugin-conf.c b/agent/download-agent-plugin-conf.c new file mode 100755 index 0000000..6cb76cb --- /dev/null +++ b/agent/download-agent-plugin-conf.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "vconf.h" +#include "vconf-keys.h" +#include "net_connection.h" + +#include "download-agent-plugin-conf.h" +#include "download-agent-debug.h" +#include "download-agent-file.h" + +#define DEFAULT_UA_STR "Mozilla/5.0 (Linux; U; Tizen 1.0; en-us) AppleWebKit/534.46 (KHTML, like Gecko) Mobile Tizen Browser/1.0" + +da_ret_t __get_conf_string(const char *key, char **out_string) +{ + if (!key || !out_string) { + DA_LOGE("Invalid Argument"); + return DA_ERR_INVALID_ARGUMENT; + } + + *out_string = vconf_get_str(key); + return DA_RESULT_OK; +} + +da_ret_t get_user_agent_string(char **uagent_str) +{ + da_ret_t ret = DA_RESULT_OK; + char *key = DA_NULL; + + DA_LOGV(""); + + if (!uagent_str) { + DA_LOGE("Invalid Argument"); + return DA_ERR_INVALID_ARGUMENT; + } + + key = VCONFKEY_BROWSER_USER_AGENT; + ret = __get_conf_string(key, uagent_str); + if(ret == DA_RESULT_OK) { + if(*uagent_str) { +// DA_SECURE_LOGD("getting uagent_str = \n%s", *uagent_str); + return ret; + } + } + DA_LOGI("No UA information from vconf !!"); + *uagent_str = strdup(DEFAULT_UA_STR); + DA_LOGV("Set default UA"); + return ret; +} + +char *get_proxy_address(void) +{ + char *proxy = NULL; + char *proxyRet = NULL; + connection_h handle = NULL; + connection_address_family_e family = CONNECTION_ADDRESS_FAMILY_IPV4; + + DA_LOGV(""); + if (connection_create(&handle) < 0) { + DA_LOGE("Fail to create connection handle"); + return NULL; + } + + if (connection_get_proxy(handle, family, &proxyRet) < 0) { + DA_LOGE("Fail to get proxy address"); + connection_destroy(handle); + return NULL; + } + + if (proxyRet) { + DA_SECURE_LOGD("===== Proxy address[%s] =====", proxyRet); + proxy = strdup(proxyRet); + free(proxyRet); + proxyRet = NULL; + connection_destroy(handle); + return proxy; + } + + if (connection_destroy(handle) < 0) { + DA_LOGE("Fail to desctory connection handle"); + return NULL; + } + return NULL; +} +#ifdef _RAF_SUPPORT +// test code +void get_smart_bonding_vconf() +{ + int ret = 0; + vconf_get_int("file/private/wifi/network_bonding", &ret); + DA_LOGI("Smart Bonding Vconf:%d", ret); +} +#endif diff --git a/agent/download-agent-plugin-drm.c b/agent/download-agent-plugin-drm.c new file mode 100644 index 0000000..22e6f34 --- /dev/null +++ b/agent/download-agent-plugin-drm.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "drm_client.h" +#include "drm_client_types.h" +#include "drm_trusted_client.h" +#include "drm_trusted_client_types.h" + +#include "download-agent-debug.h" +#include "download-agent-plugin-drm.h" + + +void __EDRM_clean_up() +{ + int ret = 0; + ret = drm_trusted_handle_request(DRM_TRUSTED_REQ_TYPE_CLIENT_CLEAN_UP, NULL, NULL); + if (DRM_RETURN_SUCCESS == ret) { + DA_LOGD( "Clean up successfull"); + } else { + DA_LOGE("ret[%0x%x]",ret); + } +} + +da_bool_t EDRM_convert(const char *in_file_path, char **out_file_path) +{ + drm_trusted_conv_info_s input; + drm_trusted_conv_resp_info_s output; + size_t len = 0; + int ret = 0; + + memset(&input, 0x0, sizeof(drm_trusted_conv_info_s)); + memset(&output, 0x0, sizeof(drm_trusted_conv_resp_info_s)); + + len = strlen(in_file_path); + if (len >= sizeof(input.filePath)) + len = sizeof(input.filePath) - 1; + memcpy(input.filePath, in_file_path, len); + + ret = drm_trusted_convert_dm(&input, &output); + + if (DRM_TRUSTED_RETURN_SUCCESS != ret) { + DA_LOGE("ret[%0x%x]",ret); + __EDRM_clean_up(); + return DA_FALSE; + } else { + DA_SECURE_LOGD("Returned filePath[%s]", output.filePath); + *out_file_path = strdup(output.filePath); + } + __EDRM_clean_up(); + return DA_TRUE; +} + +da_ret_t EDRM_wm_get_license(char *rights_url, char **out_content_url) +{ + int ret = 0; + int len = 0; + drm_initiator_info_s init_info; + drm_web_server_resp_data_s resp_data; + + if (rights_url == NULL) + return DA_ERR_DRM_FAIL; + + memset(&init_info, 0, sizeof(init_info)); + memset(&resp_data, 0, sizeof(resp_data)); + strncpy(init_info.initiator_url, rights_url, + DRM_MAX_LEN_INITIATOR_URL - 1); + len = strlen(rights_url); + if (len > DRM_MAX_LEN_INITIATOR_URL - 1) + init_info.initiator_url_len = (unsigned int)len; + else + init_info.initiator_url_len = DRM_MAX_LEN_INITIATOR_URL; + ret = drm_process_request(DRM_REQUEST_TYPE_SUBMIT_INITIATOR_URL, + &init_info, &resp_data); + if (DRM_RETURN_SUCCESS == ret) { + DA_SECURE_LOGD("resp_data.content_url = %s", resp_data.content_url); + /* Rights or Domain Certificate are installed successfully */ + /* Check for contentURL */ + if (strlen(resp_data.content_url) > 0) { + char *content_url = NULL; + size_t content_url_len = 0; + content_url_len = strlen(resp_data.content_url); + content_url = (char *)calloc(1, content_url_len + 1); + if (content_url) { + strncpy(content_url, resp_data.content_url, + content_url_len); + *out_content_url = content_url; + DA_SECURE_LOGD("drm sumitted initiator url " + "succeeded with [%s]", *out_content_url); + __EDRM_clean_up(); + return DA_RESULT_OK; + } else { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + __EDRM_clean_up(); + return DA_ERR_FAIL_TO_MEMALLOC; + } + } else { + DA_LOGV("content_url is NULL.\ + Join/Leave Domain, Metering case."); + *out_content_url = DA_NULL; + __EDRM_clean_up(); + return DA_RESULT_OK; + } + } else { + DA_LOGE("drm_process_request() failed"); + __EDRM_clean_up(); + return DA_ERR_DRM_FAIL; + } +} + diff --git a/agent/download-agent-plugin-libcurl.c b/agent/download-agent-plugin-libcurl.c new file mode 100644 index 0000000..1fee899 --- /dev/null +++ b/agent/download-agent-plugin-libcurl.c @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "glib.h" + +#include "download-agent-dl-info.h" +#include "download-agent-http-msg-handler.h" +#include "download-agent-plugin-libcurl.h" + +da_bool_t using_content_sniffing = DA_FALSE; + +int __translate_error_code(int curl_error) +{ + switch (curl_error) { + case CURLE_OPERATION_TIMEDOUT: + return DA_ERR_HTTP_TIMEOUT; + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_ENGINE_NOTFOUND: + case CURLE_SSL_ENGINE_SETFAILED: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CIPHER: + case CURLE_SSL_CACERT: + case CURLE_SSL_ENGINE_INITFAILED: + case CURLE_SSL_CACERT_BADFILE: + case CURLE_SSH: + case CURLE_SSL_SHUTDOWN_FAILED: + case CURLE_SSL_CRL_BADFILE: + case CURLE_SSL_ISSUER_ERROR: + return DA_ERR_SSL_FAIL; + case CURLE_TOO_MANY_REDIRECTS: + return DA_ERR_TOO_MANY_REDIRECTS; + case CURLE_OUT_OF_MEMORY: + return DA_ERR_FAIL_TO_MEMALLOC; + case CURLE_UNSUPPORTED_PROTOCOL: + case CURLE_URL_MALFORMAT: + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_HTTP_POST_ERROR: + case CURLE_BAD_DOWNLOAD_RESUME: + return DA_ERR_CONNECTION_FAIL; + case CURLE_ABORTED_BY_CALLBACK: + return DA_RESULT_USER_CANCELED; + default: + return DA_ERR_NETWORK_FAIL; + } +} + +int my_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *user) +{ + switch(type) { + case CURLINFO_TEXT: + if (data) + DA_SECURE_LOGI("[curl] Info:%s", data); + break; + case CURLINFO_HEADER_OUT: + DA_LOGD("[curl] Send header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_DATA_OUT: + DA_LOGD("[curl] Send data"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; + case CURLINFO_SSL_DATA_OUT: + DA_LOGD("[curl] Send SSL data"); + break; + case CURLINFO_HEADER_IN: + DA_LOGD("[curl] Recv header"); + if (data) + DA_SECURE_LOGI("[curl] %s", data); + break; +#if 0 + case CURLINFO_DATA_IN: + DA_LOGD("[curl] Recv data"); + if (data) + DA_SECURE_LOGI("[curl] %d", strlen(data)); + break; +#endif + case CURLINFO_SSL_DATA_IN: + DA_SECURE_LOGI("[curl] Recv SSL data"); + break; + default: + return 0; + } + return 0; +} + +void __parse_raw_header(const char *raw_data, http_info_t *http_info) +{ + char *ptr = DA_NULL; + char *ptr2 = DA_NULL; + int len = 0; + char *field = DA_NULL; + char *value = DA_NULL; + http_msg_response_t *http_msg_response = NULL; + + if (!raw_data || !http_info) { + DA_LOGE("NULL Check!: raw_data or http_info"); + return; + } + + if (!http_info->http_msg_response) { + http_info->http_msg_response = (http_msg_response_t *)calloc(1, + sizeof(http_msg_response_t)); + if (!http_info->http_msg_response) { + DA_LOGE("Fail to calloc"); + return; + } + http_info->http_msg_response->head = DA_NULL; + } + http_msg_response = http_info->http_msg_response; + + ptr = strchr(raw_data, ':'); + if (!ptr) + return; + len = ptr - (char *)raw_data; + field = (char *)calloc(len + 1, sizeof(char)); + if (!field) { + DA_LOGE("Fail to calloc"); + return; + } + memcpy(field, raw_data, len); + field[len] = '\0'; + ptr++; + while(ptr) { + if (*ptr == ' ') + ptr++; + else + break; + } + ptr2 = strchr(raw_data, '\n'); + if (ptr2) { + len = ptr2 - ptr -1; + } else { + len = strlen(ptr); + } + value = (char *)calloc(len + 1, sizeof(char)); + if (!value) { + DA_LOGE("Fail to calloc"); + free(field); + return; + } + memcpy(value, ptr, len); + value[len] = '\0'; + http_msg_response_add_field(http_msg_response, field, value); + free(field); + free(value); +} + +void __store_header(void *msg, da_info_t *da_info, size_t header_size, + const char *sniffed_type) +{ + http_info_t *http_info = DA_NULL; + + if (!da_info || !msg) { + DA_LOGE("NULL Check!: da_info or msg"); + return; + } + http_info = da_info->http_info; + if (!http_info) { + DA_LOGE("NULL Check!: http_info"); + return; + } + + // FIXME later : check status code and redirection case check. + + if (strncmp(msg, HTTP_FIELD_END_OF_FIELD, + strlen(HTTP_FIELD_END_OF_FIELD)) == 0) { + long status = 0; + CURLcode res; + CURL *curl; + http_raw_data_t *raw_data = DA_NULL; + curl = http_info->http_msg->curl; + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); + if (res != CURLE_OK) { + DA_LOGE("Fail to get response status code"); + return; + } + DA_LOGV("status code[%d]", (int)status); + if (http_info->http_msg_response) { + http_info->http_msg_response->status_code = (int)status; + } + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return; + } + + raw_data->status_code = (int)status; + raw_data->type = HTTP_EVENT_GOT_HEADER; + + if (http_info->update_cb) { + http_info->update_cb(raw_data, da_info); + } else { + free(raw_data); + } + return; + } + DA_LOGI("%s",(char *)msg); + __parse_raw_header((const char *)msg, http_info); +} + +size_t __http_gotheaders_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + da_info_t *da_info = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, userdata"); + return 0; + } + da_info = (da_info_t *)userdata; + if (da_info->http_info && da_info->http_info->http_msg + && da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + if (!using_content_sniffing) + __store_header(ptr, da_info, (size * nmemb), DA_NULL); + else + DA_LOGV("ignore because content sniffing is turned on"); +/* +#ifdef _RAF_SUPPORT + DA_LOGI("[RAF] __http_gotheaders_cb done"); +#endif +*/ + return (size * nmemb); +} + +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path) +{ + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(file_path); + DA_LOGI("[RAF]set file_path[%s]", file_path); + curl_easy_setopt(http_msg->curl, CURLOPT_BOOSTER_RAF_FILE, file_path); + return DA_RESULT_OK; +} +#endif + +size_t __http_gotchunk_cb(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + http_info_t *http_info = DA_NULL; + da_info_t *da_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; + if (!ptr || !userdata) { + DA_LOGE("Check NULL!: ptr, stream"); + return 0; + } + da_info = (da_info_t *)userdata; + NULL_CHECK_RET_OPT(da_info, 0); + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, 0); + NULL_CHECK_RET_OPT(http_info->http_msg, 0); + if (da_info->http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + //DA_LOGV("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); +#ifdef _RAF_SUPPORT + //DA_LOGI("size=%ld, nmemb=%ld, datalen=%ld", size, nmemb, strlen((const char *)ptr)); + if (http_info->is_raf_mode_confirmed) { + DA_LOGI("[RAF] return chunked callback"); + return (size * nmemb); + } +#endif + + if (ptr && size * nmemb > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->body = (char *)calloc(size, nmemb); + if (!(raw_data->body)) { + DA_LOGE("Fail to calloc"); + free(raw_data); + return 0; + } + memcpy(raw_data->body, ptr, size * nmemb); + raw_data->body_len = size*nmemb; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return (size * nmemb); +} + +long __http_finished_cb(void *ptr) +{ + if (!ptr) { + DA_LOGE("Check NULL!: ptr"); + return CURL_CHUNK_END_FUNC_FAIL; + } + DA_LOGI(""); + return CURL_CHUNK_END_FUNC_OK; +} + + +da_ret_t __set_proxy_on_soup_session(char *proxy_addr, CURL *curl) +{ + da_ret_t ret = DA_RESULT_OK; + + if (proxy_addr && strlen(proxy_addr) > 0) { + DA_SECURE_LOGI("received proxy[%s]", proxy_addr); + if (!strstr(proxy_addr, "0.0.0.0")) { + if (strstr((const char *)proxy_addr, "http") == DA_NULL) { + char *tmp_str = DA_NULL; + int needed_len = 0; + + needed_len = strlen(proxy_addr) + strlen( + SCHEME_HTTP) + 1; + tmp_str = (char *) calloc(1, needed_len); + if (!tmp_str) { + DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + snprintf(tmp_str, needed_len, "%s%s", + SCHEME_HTTP, proxy_addr); + + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + + free(tmp_str); + } else { + DA_LOGV("There is \"http\" on uri, so, push this address to soup directly."); + curl_easy_setopt(curl, CURLOPT_PROXY, proxy_addr); + } + } + } +ERR: + return ret; +} + +struct curl_slist *__fill_soup_msg_header(CURL *curl, http_info_t *info) +{ + http_msg_request_t *input_http_msg_request; + struct curl_slist *headers = DA_NULL; + + if (!curl) { + DA_LOGE("NULL Check!: curl"); + return DA_NULL; + } + input_http_msg_request = info->http_msg_request; + + if (input_http_msg_request) { + char *field = DA_NULL; + char *value = DA_NULL; + char *buff = DA_NULL; + int len = 0; + http_header_t *cur = DA_NULL; + cur = input_http_msg_request->head; + while (cur) { + field = cur->field; + value = cur->value; + if (field && value) { + len = strlen(field) + strlen(value) + 1; + buff = (char *)calloc(len + 1, sizeof(char)); + if (!buff) { + DA_LOGE("Fail to memalloc"); + break; + } +// DA_SECURE_LOGI("[%s] %s", field, value); + snprintf(buff, len + 1, "%s:%s", field, value); + headers = curl_slist_append(headers, (const char *)buff); + free(buff); + buff = DA_NULL; + } + cur = cur->next; + } + } else { + DA_LOGE("NULL Check!: input_http_msg_request"); + return DA_NULL; + } + if (input_http_msg_request->http_body) { + char buff[256] = {0,}; + int body_len = strlen(input_http_msg_request->http_body); + snprintf(buff, sizeof(buff), "%s:%d", HTTP_FIELD_CONTENT_LENGTH, + body_len); + headers = curl_slist_append(headers, buff); + memset(buff, 0x00, 256); + snprintf(buff, sizeof(buff), "%s:text/plain", HTTP_FIELD_CONTENT_TYPE); + headers = curl_slist_append(headers, buff); + headers = curl_slist_append(headers, input_http_msg_request->http_body); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + return headers; +} + +#ifdef _RAF_SUPPORT +int __http_progress_cb(void *clientp, double dltotal, double dlnow, + double ultotal, double ulnow) +{ + da_info_t *da_info = DA_NULL; + http_info_t *http_info = DA_NULL; + http_raw_data_t *raw_data = DA_NULL; +/* + if (dlnow > 0 || ulnow > 0) + DA_LOGI("[RAF]dlnow/ulnow[%llu/%llu][%llu,%llu]", (da_size_t)dlnow, (da_size_t)ulnow, (da_size_t)dltotal, (da_size_t)ultotal); +*/ + +/* + if (dlnow == 0) { + DA_LOGI("[RAF]dlnow is zero. Why is this callback called although there is zero size?"); + } +*/ + NULL_CHECK_RET_OPT(clientp, -1); + da_info = (da_info_t *)clientp; + http_info = da_info->http_info; + NULL_CHECK_RET_OPT(http_info, -1); + NULL_CHECK_RET_OPT(http_info->http_msg, -1); + + if (http_info->http_msg->is_cancel_reqeusted) { + DA_LOGI("Cancel requested"); + return -1; + } + + if (dlnow > 0) { + if (http_info->update_cb) { + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + return 0; + } + raw_data->received_len = (da_size_t)dlnow; + raw_data->type = HTTP_EVENT_GOT_PACKET; + http_info->update_cb(raw_data, da_info); + } + } + return CURLE_OK; +} +#endif + +da_ret_t PI_http_start(da_info_t *da_info) +{ + da_ret_t ret = DA_RESULT_OK; + http_method_t http_method; + CURL *curl = DA_NULL; + CURLcode res; + http_msg_t *http_msg = DA_NULL; + char *url = DA_NULL; + http_info_t *http_info = DA_NULL; + long http_status = 0; + struct curl_httppost* post = NULL; + struct curl_slist *headers = DA_NULL; + char err_buffer[CURL_ERROR_SIZE] = {0,}; + + DA_LOGV(""); +#ifdef _RAF_SUPPORT + // test code + get_smart_bonding_vconf(); +#endif + NULL_CHECK_GOTO(da_info); + NULL_CHECK_GOTO(da_info->req_info); + url = da_info->req_info->url; + NULL_CHECK_GOTO(url); + http_info = da_info->http_info; + NULL_CHECK_GOTO(http_info); + + http_method = http_info->http_method; + ret = init_http_msg_t(&http_msg); + if (ret != DA_RESULT_OK) + goto ERR; + http_info->http_msg = http_msg; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if (!curl) { + DA_LOGE("Fail to create curl"); + return DA_ERR_FAIL_TO_MEMALLOC; + } + DA_LOGI("curl[%p]", curl); + + curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, MAX_SESSION_COUNT); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, MAX_TIMEOUT); + + __set_proxy_on_soup_session(http_info->proxy_addr, curl); + + curl_easy_setopt(curl, CURLOPT_URL, url); + switch (http_method) { + case HTTP_METHOD_GET: + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + break; + case HTTP_METHOD_POST: + // FIXME later : If the post method is supprot, the post data should be set with curl_fromadd + curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); + DA_LOGI("Need more information for post filed"); + break; + case HTTP_METHOD_HEAD: + DA_LOGI("Donnot implement yet"); + break; + default: + DA_LOGE("Cannot enter here"); + break; + } + + if (using_content_sniffing) { + /* FIXME later*/ + } else { + /* FIXME later*/ + } + headers = __fill_soup_msg_header(curl, http_info); + + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, __http_gotheaders_cb); // can replace to started_cb + curl_easy_setopt(curl, CURLOPT_HEADERDATA, da_info); // param .. same with CURLOPT_WRITEHEADER + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); // does not include header to body + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, __http_gotchunk_cb); // can replace to progress_ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, da_info); // param .. same with CURLOPT_WRITEHEADERcb + curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, __http_finished_cb); + curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, da_info); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); +// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_buffer); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, __http_progress_cb); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, da_info); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); +#endif + + if (da_info->req_info->network_bonding) { +#ifdef _DOWNLOAD_BOOSTER_SUPPORT + DA_LOGI("network bonding enable"); + curl_easy_setopt(curl, CURLOPT_MULTIRAT_NEEDED, 1L); +#endif +#ifdef _RAF_SUPPORT + curl_easy_setopt(curl, CURLOPT_BOOSTER_RAF_MODE, 1L); +#endif + } + http_msg->curl = curl; + res = curl_easy_perform(curl); + DA_LOGD("perform done! res[%d]",res); + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to perform :%d[%s]", res, curl_multi_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } + if (res != CURLE_OK) { + //DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to send data :%d[%s]", res, curl_easy_strerror(res)); + if (strlen(err_buffer) > 1) + DA_LOGE("Fail to error buffer[%s]", err_buffer); + } else { + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status); + if (res != CURLE_OK) { + //DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + DA_LOGE("Fail to get response code:%d[%s]", res, curl_easy_strerror(res)); + ret = DA_ERR_FAIL_TO_MEMALLOC;; + goto ERR; + } else { + DA_LOGD("Response Http Status code[%d]", (int)http_status); + } + } + if (http_info->update_cb) { + http_raw_data_t *raw_data = DA_NULL; + raw_data = (http_raw_data_t *)calloc(1, sizeof(http_raw_data_t)); + if (!raw_data) { + DA_LOGE("Fail to calloc"); + ret = DA_ERR_FAIL_TO_MEMALLOC; + goto ERR; + } + if (http_msg->is_cancel_reqeusted || + res == CURLE_ABORTED_BY_CALLBACK) { + DA_LOGI("canceled exit. Err[%d]", http_info->error_code); + if (http_info->error_code < 0) + ret = http_info->error_code; + else + ret = DA_RESULT_USER_CANCELED; + } else if ((http_status > 0 && http_status < 100)) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else if (res != CURLE_OK) { + raw_data->error = __translate_error_code(res); + ret = DA_ERR_NETWORK_FAIL; + } else { + raw_data->status_code = (int)http_status; + } + raw_data->type = HTTP_EVENT_FINAL; + http_info->update_cb(raw_data, da_info); + } + if (DA_NULL != headers) + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + http_msg->curl = DA_NULL; + DA_MUTEX_INIT(&(http_msg->mutex), DA_NULL); +ERR: + DA_LOGD("Done"); + return ret; + +} + +da_ret_t PI_http_disconnect(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGD(""); + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGV("session [%p]", http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + if (http_msg->is_paused) + PI_http_unpause(info); + if (http_msg->curl) + curl_easy_cleanup(http_msg->curl); + + http_msg->curl = DA_NULL; + http_msg->is_paused = DA_FALSE; + http_msg->is_cancel_reqeusted = DA_FALSE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_MUTEX_DESTROY(&(http_msg->mutex)); + destroy_http_msg_t(http_msg); + info->http_msg = DA_NULL; + return ret; +} + +da_ret_t PI_http_cancel(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGI("curl[%p]", http_msg->curl); + http_msg->is_cancel_reqeusted = DA_TRUE; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + DA_LOGD("Done - soup cancel"); + return ret; +} + +da_ret_t PI_http_pause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + NULL_CHECK_RET(http_msg); + DA_LOGD("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + DA_LOGE("curl_easy_pause call"); + res = curl_easy_pause(http_msg->curl, CURLPAUSE_ALL); + DA_LOGE("curl_easy_pause:%d", res); + if (res == CURLE_OK) { + http_msg->is_paused = DA_TRUE; + } else { + ret = DA_ERR_CANNOT_SUSPEND; + } + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} + +da_ret_t PI_http_unpause(http_info_t *info) +{ + da_ret_t ret = DA_RESULT_OK; + http_msg_t *http_msg = DA_NULL; + CURLcode res = CURLE_OK; + DA_LOGV(""); + + NULL_CHECK_RET(info); + http_msg = info->http_msg; + DA_LOGV("curl [%p]", http_msg->curl); + NULL_CHECK_RET(http_msg->curl); + DA_MUTEX_LOCK(&(http_msg->mutex)); + res = curl_easy_pause(http_msg->curl, CURLPAUSE_CONT); + if (res == CURLE_OK) + http_msg->is_paused = DA_FALSE; + else + ret = DA_ERR_CANNOT_RESUME; + DA_MUTEX_UNLOCK(&(http_msg->mutex)); + return ret; +} diff --git a/agent/include/download-agent-client-mgr.h b/agent/include/download-agent-client-mgr.h new file mode 100755 index 0000000..b2ce1c8 --- /dev/null +++ b/agent/include/download-agent-client-mgr.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_AGENT_CLIENT_MGR_H +#define DOWNLOAD_AGENT_CLIENT_MGR_H + +#include "download-agent-dl-info.h" + +da_ret_t send_client_paused_info(da_info_t *da_info); +da_ret_t send_client_update_dl_info(da_info_t *da_info); +da_ret_t send_client_update_progress_info(da_info_t *da_info); +da_ret_t send_client_finished_info(da_info_t *da_info, int err); + +#endif diff --git a/agent/include/download-agent-debug.h b/agent/include/download-agent-debug.h new file mode 100755 index 0000000..23c2a66 --- /dev/null +++ b/agent/include/download-agent-debug.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_DEBUG_H +#define _DOWNLOAD_AGENT_DEBUG_H + +#include "download-agent-type.h" + +#include +#include +#include + +// ansi color +#define COLOR_RED "\033[0;31m" +#define COLOR_GREEN "\033[0;32m" +#define COLOR_BROWN "\033[0;33m" +#define COLOR_LIGHTBLUE "\033[0;37m" +#define COLOR_END "\033[0;m" + +#ifdef _ENABLE_DLOG +#include +#include +#include + + #ifdef LOG_TAG + #undef LOG_TAG + #endif /* LOG_TAG */ + + #define LOG_TAG "DP_DA" + #define DA_LOGV(format, ...) ((void)0)//LOGD("[%d]:"format, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGD(format, ...) LOGD(COLOR_LIGHTBLUE "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGI(format, ...) LOGI(COLOR_BROWN "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_LOGE(format, ...) LOGE(COLOR_RED "[%d]:"format COLOR_END, syscall(__NR_gettid), ##__VA_ARGS__) + #define DA_SECURE_LOGD(format, ...) SECURE_LOGD(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) + #define DA_SECURE_LOGI(format, ...) SECURE_LOGI(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) + #define DA_SECURE_LOGE(format, ...) SECURE_LOGE(COLOR_GREEN format COLOR_END, ##__VA_ARGS__) +#else + +#include +#include + + #define DA_LOGD(format, ...) do {\ + fprintf(stderr, "[DA][%d][%s():%d] "format"\n",syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__);\ + }while(0) + #define DA_LOGE(format, ...) do {\ + fprintf(stderr, "[DA][%d][ERR][%s():%d]\n",syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__);\ + }while(0) + #define DA_LOGV DA_LOGD + #define DA_LOGI DA_LOGD + #define DA_SECURE_LOGD(format, ...) ((void)0) + #define DA_SECURE_LOGI(format, ...) ((void)0) + #define DA_SECURE_LOGE(format, ...) ((void)0) +#endif /* _ENABLE_DLOG */ + +#endif /* DOWNLOAD_AGENT_DEBUG_H */ diff --git a/agent/include/download-agent-defs.h b/agent/include/download-agent-defs.h new file mode 100755 index 0000000..d5b6a5e --- /dev/null +++ b/agent/include/download-agent-defs.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_DEFS_H +#define _DOWNLOAD_AGENT_DEFS_H + +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +/** + * Max count to download files simultaneously. \n + * Main reason for this restriction is because of Network bandwidth. + */ +#define DA_MAX_DOWNLOAD_REQ_AT_ONCE 50 +#define DA_MAX_TIME_OUT 65 + +#define DA_RESULT_OK 0 + +#define DA_TRUE 1 +#define DA_FALSE 0 +#define DA_NULL (void *)0 +#define DA_INVALID_ID -1 + +#define DA_RESULT_USER_CANCELED -10 + +// InputError Input error (-100 ~ -199) +// Client passed wrong parameter +#define DA_ERR_INVALID_ARGUMENT -100 +#define DA_ERR_INVALID_DL_REQ_ID -101 +#define DA_ERR_INVALID_URL -103 +#define DA_ERR_INVALID_INSTALL_PATH -104 +#define DA_ERR_INVALID_MIME_TYPE -105 + +// Client passed correct parameter, but Download Agent rejects the request because of internal policy. +#define DA_ERR_ALREADY_CANCELED -160 +#define DA_ERR_ALREADY_SUSPENDED -161 +#define DA_ERR_ALREADY_RESUMED -162 +#define DA_ERR_CANNOT_SUSPEND -170 +#define DA_ERR_CANNOT_RESUME -171 +#define DA_ERR_INVALID_STATE -190 +#define DA_ERR_ALREADY_MAX_DOWNLOAD -191 +#define DA_ERR_UNSUPPORTED_PROTOCAL -192 + +// System error (-200 ~ -299) +#define DA_ERR_FAIL_TO_MEMALLOC -200 +#define DA_ERR_FAIL_TO_CREATE_THREAD -210 +#define DA_ERR_FAIL_TO_ACCESS_FILE -230 +#define DA_ERR_DISK_FULL -240 + +// Network error (-400 ~ -499) +#define DA_ERR_NETWORK_FAIL -400 +#define DA_ERR_UNREACHABLE_SERVER -410 +#define DA_ERR_CONNECTION_FAIL -420 +#define DA_ERR_HTTP_TIMEOUT -430 +#define DA_ERR_SSL_FAIL -440 +#define DA_ERR_TOO_MANY_REDIRECTS -450 +#define DA_ERR_NETWORK_UNAUTHORIZED -460 + +// HTTP error - not conforming with HTTP spec (-500 ~ -599) +#define DA_ERR_MISMATCH_CONTENT_TYPE -500 +#define DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT -501 +#define DA_ERR_MISMATCH_CONTENT_SIZE -502 + +// DRM error - not conforming with DRM spec (-600 ~ -699) +#define DA_ERR_DRM_FAIL -600 + +// string to check invalid characters in path before using open() and fopen() API's +#define DA_INVALID_PATH_STRING ";\\\":*?<>|()" + +#endif + diff --git a/agent/include/download-agent-dl-info.h b/agent/include/download-agent-dl-info.h new file mode 100644 index 0000000..820135e --- /dev/null +++ b/agent/include/download-agent-dl-info.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_INFO_H +#define _DOWNLOAD_AGENT_INFO_H + +#include "download-agent-type.h" +#include "download-agent-interface.h" +#include "download-agent-pthread.h" + +#include "curl/curl.h" + +typedef struct { + CURL *curl; + pthread_mutex_t mutex; + da_bool_t is_paused; + da_bool_t is_cancel_reqeusted; +} http_msg_t; + +typedef enum { + HTTP_STATE_READY_TO_DOWNLOAD = 0, + HTTP_STATE_REDIRECTED = 1, + HTTP_STATE_DOWNLOAD_REQUESTED = 2, + HTTP_STATE_DOWNLOAD_STARTED = 3, + HTTP_STATE_DOWNLOADING = 4, + HTTP_STATE_DOWNLOAD_FINISH = 5, + HTTP_STATE_REQUEST_CANCEL = 6, + HTTP_STATE_REQUEST_PAUSE = 7, + HTTP_STATE_REQUEST_RESUME = 8, + HTTP_STATE_CANCELED = 9, + HTTP_STATE_FAILED = 10, + HTTP_STATE_PAUSED = 11, + HTTP_STATE_RESUMED = 12, + HTTP_STATE_ABORTED = 13, + HTTP_STATE_WAIT_FOR_NET_ERR = 14, +} http_state_t; + +typedef enum { + HTTP_METHOD_GET = 1, + HTTP_METHOD_HEAD, + HTTP_METHOD_POST +} http_method_t; + +typedef struct { + char *url; + char **req_header; + int req_header_count; + char *install_path; + char *file_name; + char *etag; + char *temp_file_path; + char *pkg_name; + int network_bonding; + void *user_req_data; + void *user_client_data; +} req_info_t; + +typedef enum { + HTTP_EVENT_GOT_HEADER = 0, + HTTP_EVENT_GOT_PACKET, + HTTP_EVENT_FINAL, +// HTTP_EVENT_ABORT +} http_event_type_t; + +typedef struct _http_header_options_t http_header_options_t; +struct _http_header_options_t{ + char *field; + char *value; + http_header_options_t *next; +}; + +typedef struct _http_header_t http_header_t; +typedef http_header_t *http_msg_iter_t; +struct _http_header_t{ + char *field; + char *value; + http_header_options_t *options; + char *raw_value; // raw string including options + http_header_t *next; +}; + +typedef struct{ + char *http_method; + char *url; + http_header_t *head; + char *http_body; +} http_msg_request_t; + + +typedef struct{ + int status_code; + http_header_t *head; +} http_msg_response_t; + +typedef struct { + http_event_type_t type; + char *body; + int body_len; +#ifdef _RAF_SUPPORT + da_size_t received_len; +#endif + int status_code; + int error; +} http_raw_data_t; + +typedef void (*http_update_cb) (http_raw_data_t *data, void *user_param); + +typedef struct { + char *location_url; + http_state_t state; + pthread_mutex_t mutex_state; + pthread_mutex_t mutex_http; + pthread_cond_t cond_http; + http_msg_request_t *http_msg_request; + http_msg_response_t *http_msg_response; + http_method_t http_method; + http_msg_t *http_msg; + char *proxy_addr; + char *content_type_from_header; + char *file_name_from_header; + da_size_t content_len_from_header; + char *etag_from_header; + int error_code; // for error value for http abort. + da_size_t total_size; +#ifdef _RAF_SUPPORT + da_bool_t is_raf_mode_confirmed; +#endif + http_update_cb update_cb; +} http_info_t; + +typedef struct { + void *file_handle; + char *pure_file_name; + char *extension; + char *file_path; /* malloced in set_file_path_for_final_saving */ + char *mime_type;// For drm converting + char *buffer; + da_size_t buffer_len; + da_size_t file_size; /* http header's Content-Length has higher priority than DD's */ + da_size_t bytes_written_to_file; /* The file size to be written at actual file */ +#ifdef _RAF_SUPPORT + da_size_t file_size_of_temp_file; /* If the temporary file is existed, the file size of it */ +#endif + da_bool_t is_updated; /* The flag for updating progress event only if the data is wrriten to file not buffer */ +} file_info_t; + +typedef struct { + int da_id; + int tid; + pthread_t thread_id; + http_info_t *http_info; + file_info_t *file_info; + req_info_t *req_info; + da_cb_t cb_info; + da_bool_t is_cb_update; + int update_time; +} da_info_t; + +da_info_t *da_info_list[DA_MAX_ID]; + +#define GET_STATE_MUTEX(INFO) (INFO->mutex_state) +#define GET_STATE(INFO) (INFO->state) +#define CHANGE_STATE(STATE,INFO) {\ + DA_MUTEX_LOCK (&GET_STATE_MUTEX(INFO));\ + GET_STATE(INFO) = STATE;\ + DA_LOGV("Changed state[%d]", GET_STATE(INFO));\ + DA_MUTEX_UNLOCK (&GET_STATE_MUTEX(INFO));\ + } + +da_ret_t get_available_da_id(int *available_id); +da_ret_t copy_user_input_data(da_info_t *da_info, const char *url, + req_data_t *ext_data, da_cb_t *da_cb_data); +da_bool_t is_valid_download_id(int id); +void destroy_da_info(int id); +void destroy_da_info_list(void); +da_ret_t get_da_info_with_da_id(int id, da_info_t **out_info); +da_ret_t init_http_msg_t(http_msg_t **http_msg); +void destroy_http_msg_t(http_msg_t *http_msg); +void reset_http_info(http_info_t *http_info); +void reset_http_info_for_resume(http_info_t *http_info); +void destroy_http_info(http_info_t *http_info); +void destroy_file_info(file_info_t *file_info); + +#endif /* _DOWNLOAD_AGENT_INFO_H */ diff --git a/agent/include/download-agent-dl-mgr.h b/agent/include/download-agent-dl-mgr.h new file mode 100755 index 0000000..c6be7c7 --- /dev/null +++ b/agent/include/download-agent-dl-mgr.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Basic_H +#define _Download_Agent_Basic_H + +#include "download-agent-dl-info.h" + +da_ret_t start_download(da_info_t *da_info); +da_ret_t cancel_download(int dl_id, da_bool_t is_enable_cb); +da_ret_t suspend_download(int dl_id, da_bool_t is_enable_cb); +da_ret_t resume_download(int dl_id); + +#endif diff --git a/src/agent/include/download-agent-encoding.h b/agent/include/download-agent-encoding.h old mode 100644 new mode 100755 similarity index 52% rename from src/agent/include/download-agent-encoding.h rename to agent/include/download-agent-encoding.h index 9453edd..49e74e9 --- a/src/agent/include/download-agent-encoding.h +++ b/agent/include/download-agent-encoding.h @@ -1,25 +1,17 @@ /* - * Download Agent + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * @file download-agent-encoding.h - * @brief Utilities to manipulate encoding and charset - * @author Keunsoon Lee (keunsoon.lee@samsung.com) */ #ifndef _Download_Agent_Encoding_H @@ -28,7 +20,7 @@ #include "download-agent-type.h" da_bool_t is_base64_encoded_word(const char *in_str); -da_result_t decode_base64_encoded_str(const char *in_encoded_str, +da_ret_t decode_base64_encoded_str(const char *in_encoded_str, char **out_decoded_ascii_str); void decode_url_encoded_str(const char *in_encoded_str, char **out_str); diff --git a/agent/include/download-agent-file.h b/agent/include/download-agent-file.h new file mode 100755 index 0000000..2788fdd --- /dev/null +++ b/agent/include/download-agent-file.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_FILE_H +#define _DOWNLOAD_AGENT_FILE_H + +#include +#include +#include + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +#define DA_FILE_BUF_SIZE (1024*32) //bytes + +da_ret_t check_drm_convert(file_info_t *file_info); +da_bool_t is_file_exist(const char *file_path); +void get_file_size(char *file_path, da_size_t *out_file_size); +da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len); +da_ret_t file_write_complete(file_info_t *file_info); +#ifdef _RAF_SUPPORT +da_ret_t file_write_complete_for_raf(file_info_t *file_info); +#endif +da_ret_t start_file_writing(da_info_t *da_info); +da_ret_t start_file_append(file_info_t *file_info); +da_ret_t discard_download(file_info_t *file_info) ; +void clean_paused_file(file_info_t *file_info); +char *get_full_path_avoided_duplication(char *in_dir, + char *in_candidate_file_name, char *in_extension); +void remove_file(const char *file_path); +da_ret_t get_available_memory(char *dir_path, da_size_t len); +#endif diff --git a/agent/include/download-agent-http-mgr.h b/agent/include/download-agent-http-mgr.h new file mode 100755 index 0000000..95a0b3a --- /dev/null +++ b/agent/include/download-agent-http-mgr.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Http_Mgr_H +#define _Download_Agent_Http_Mgr_H + +#include + +#include "download-agent-type.h" +#include "download-agent-dl-mgr.h" + +#define DA_MAX_SESSION_INFO DA_MAX_DOWNLOAD_ID + +da_ret_t request_http_download(da_info_t *da_info); +da_ret_t request_to_cancel_http_download(da_info_t *da_info); +da_ret_t request_to_abort_http_download(da_info_t *da_info); +da_ret_t request_to_suspend_http_download(da_info_t *da_info); +da_ret_t request_to_resume_http_download(da_info_t *da_info); +da_bool_t is_stopped_state(da_info_t *da_info); + +#endif diff --git a/agent/include/download-agent-http-msg-handler.h b/agent/include/download-agent-http-msg-handler.h new file mode 100755 index 0000000..70abbda --- /dev/null +++ b/agent/include/download-agent-http-msg-handler.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Http_Msg_Handler_H +#define _Download_Agent_Http_Msg_Handler_H + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +// Reqeust Header +#define HTTP_FIELD_UAGENT "User-Agent" +#define HTTP_FIELD_HOST "Host" +#define HTTP_FIELD_UAPROF "X-Wap-Profile" +#define HTTP_FIELD_IF_MATCH "If-Match" +#define HTTP_FIELD_RANGE "Range" +#define HTTP_FIELD_IF_RANGE "If-Range" +#define HTTP_FIELD_ACCEPT_LANGUAGE "Accept-Language" +#define HTTP_FIELD_ACCEPT_CHARSET "Accept-Charset" + +// Response Header +#define HTTP_FIELD_CONTENT_LENGTH "Content-Length" +#define HTTP_FIELD_CONTENT_TYPE "Content-Type" +#define HTTP_FIELD_CONTENT_DISPOSITION "Content-Disposition" +#define HTTP_FIELD_LOCATION "Location" +#define HTTP_FIELD_DATA "Date" +#define HTTP_FIELD_ETAG "ETag" +#ifdef _RAF_SUPPORT +#define HTTP_FIELD_RAF_MODE "x-direct-write" +#endif + +#define HTTP_FIELD_END_OF_FIELD "\r\n" + +da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request); +void http_msg_request_destroy(http_msg_request_t **http_msg_request); +da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request, const char *url); +da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request, const char **url); +da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request, const char *field, const char *value); + +da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response); +void http_msg_response_destroy(http_msg_response_t **http_msg_response); +da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response, const char *field, const char *value); +/* Caution! Caller must free memory for every "char** out_xxx" for followings */ +da_bool_t http_msg_response_get_content_type(http_msg_response_t *http_msg_response, char **out_type); +void http_msg_response_set_content_type(http_msg_response_t *http_msg_response, const char *in_type); + +da_bool_t http_msg_response_get_content_length(http_msg_response_t *http_msg_response, da_size_t *out_length); +da_bool_t http_msg_response_get_content_disposition(http_msg_response_t *http_msg_response, char **out_disposition, char **out_file_name); +da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response, char **out_value); +da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response, char **out_value); +da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response, char **out_value); +#ifdef _RAF_SUPPORT +da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response, + char **out_value); +#endif +da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request, http_msg_iter_t *http_msg_iter); +da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response, http_msg_iter_t *http_msg_iter); +// should remove later +da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter, char **field, char **value); +da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter, char **out_field, http_header_t **out_header); +da_bool_t extract_attribute_from_header(char *szHeadStr, const char *szFindStr, char **ppRtnValue); +da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request, char **out_value); +da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request, char **out_value); + +#endif // _Download_Agent_Http_Msg_Handler_H diff --git a/agent/include/download-agent-interface.h b/agent/include/download-agent-interface.h new file mode 100755 index 0000000..f5ce653 --- /dev/null +++ b/agent/include/download-agent-interface.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_INTERFACE_H +#define _DOWNLOAD_AGENT_INTERFACE_H + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "download-agent-defs.h" +#include + +typedef struct { + int download_id; + char *file_type; + unsigned long long file_size; + char *tmp_saved_path; + char *content_name; + char *etag; +} download_info_t; + +typedef struct { + int download_id; + char *saved_path; + char *etag; + int err; + int http_status; +} finished_info_t; + +typedef struct { + const char **request_header; + int request_header_count; + const char *install_path; + const char *file_name; + const char *temp_file_path; + const char *etag; + const char *pkg_name; + int network_bonding; + void *user_req_data; + void *user_client_data; +} req_data_t; + +typedef void (*da_paused_cb) (int download_id, + void *user_param1, void *user_param2); +typedef void (*da_progress_cb) (int download_id, + unsigned long long received_size, + void *user_param1, void *user_param2); +typedef void (*da_started_cb) (download_info_t *download_info, + void *user_param1, void *user_param2); +typedef void (*da_finished_cb) (finished_info_t *finished_info, + void *user_param1, void *user_param2); + +typedef struct { + da_started_cb download_info_cb; + da_progress_cb progress_cb; + da_finished_cb finished_cb; + da_paused_cb paused_cb; +} da_cb_t; + +EXPORT_API int da_init(); +EXPORT_API int da_deinit(); + +EXPORT_API int da_start_download(const char *url, req_data_t *ext_data, + da_cb_t *da_cb_data, int *download_id); +EXPORT_API int da_cancel_download(int download_id); +EXPORT_API int da_cancel_download_without_update(int download_id); +EXPORT_API int da_suspend_download(int download_id); +EXPORT_API int da_suspend_download_without_update(int download_id); +EXPORT_API int da_resume_download(int download_id); +EXPORT_API int da_is_valid_download_id(int download_id); + +#ifdef __cplusplus +} +#endif + +#endif //_DOWNLOAD_AGENT_INTERFACE_H + + diff --git a/agent/include/download-agent-mime-util.h b/agent/include/download-agent-mime-util.h new file mode 100755 index 0000000..7f57899 --- /dev/null +++ b/agent/include/download-agent-mime-util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Mime_Table_H +#define _Download_Agent_Mime_Table_H + +#include "download-agent-type.h" + +#define NO_EXTENSION_NAME_STR "dat" + +#define DD_MIME_STR "application/vnd.oma.dd+xml" +#define DD_EXT_STR "*.dd" +#define DRM_MIME_MSG_STR "application/vnd.oma.drm.message" +#define DRM_EXT_STR "*.dm" +#define DRM_MIME_CONTENT_STR "application/vnd.oma.drm.content" + +typedef struct { + char *standard; + char *normal; +} Ext_translation_table; + +da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type); +da_bool_t da_get_extension_name_from_url(char *url, char **ext); +da_ret_t da_mime_get_ext_name(char *mime, char **ext); +da_bool_t da_get_file_name_from_url(char *url, char **name) ; +void delete_prohibited_char(char *szTarget, int str_len); +da_ret_t get_extension_from_mime_type(char *mime_type, char **extension); +#ifdef _ENABLE_OMA_DRM +da_bool_t is_content_drm_dcf(char *content_type); +da_bool_t is_content_drm_dm(char *content_type); +#endif + + + +#endif diff --git a/agent/include/download-agent-plugin-conf.h b/agent/include/download-agent-plugin-conf.h new file mode 100755 index 0000000..11e8095 --- /dev/null +++ b/agent/include/download-agent-plugin-conf.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Plugin_Conf_H +#define _Download_Agent_Plugin_Conf_H + +#include "download-agent-type.h" +#include "download-agent-interface.h" + +da_ret_t get_user_agent_string(char **uagent_str); +char *get_proxy_address(void); +#ifdef _RAF_SUPPORT +//test code +void get_smart_bonding_vconf(); +#endif + +#endif diff --git a/agent/include/download-agent-plugin-drm.h b/agent/include/download-agent-plugin-drm.h new file mode 100644 index 0000000..361f387 --- /dev/null +++ b/agent/include/download-agent-plugin-drm.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Plugin_Drm_H +#define _Download_Agent_Plugin_Drm_H + +#include "download-agent-type.h" + +da_bool_t EDRM_convert(const char *in_file_path, char **out_file_path); +da_ret_t EDRM_wm_get_license(char *rights_url, char **out_content_url); + +#endif diff --git a/agent/include/download-agent-plugin-libcurl.h b/agent/include/download-agent-plugin-libcurl.h new file mode 100644 index 0000000..67a4c53 --- /dev/null +++ b/agent/include/download-agent-plugin-libcurl.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _Download_Agent_Plugin_Libcurl_H +#define _Download_Agent_Plugin_Libcrul_H + +#include "download-agent-type.h" +#include "download-agent-dl-info.h" + +#define MAX_SESSION_COUNT DA_MAX_DOWNLOAD_REQ_AT_ONCE +#define MAX_TIMEOUT DA_MAX_TIME_OUT + +da_ret_t PI_http_start(da_info_t *da_info); +da_ret_t PI_http_disconnect(http_info_t *info); +da_ret_t PI_http_cancel(http_info_t *info); +da_ret_t PI_http_pause(http_info_t *info); +da_ret_t PI_http_unpause(http_info_t *info); +#ifdef _RAF_SUPPORT +da_ret_t PI_http_set_file_name_to_curl(http_msg_t *http_msg, char *file_path); +#endif + +#endif diff --git a/agent/include/download-agent-pthread.h b/agent/include/download-agent-pthread.h new file mode 100755 index 0000000..2748581 --- /dev/null +++ b/agent/include/download-agent-pthread.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_PTHREAD_H +#define _DOWNLOAD_AGENT_PTHREAD_H + +#include +#include +#include + +#include "download-agent-debug.h" + +#define DA_MUTEX_INIT(mutex_add, attr) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_init(mutex_add, attr);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_init FAIL with EINVAL.");\ + break;\ + }\ + else if (ENOMEM == ret){\ + DA_LOGE("pthread_mutex_init FAIL with ENOMEM.");\ + break;\ + }\ + else{\ + DA_LOGE("pthread_mutex_init FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_COND_INIT(cond_add, attr) do {\ + if (0 != pthread_cond_init(cond_add, attr)){\ + DA_LOGE("pthread_cond_init FAIL");\ + }\ +} while(0) + +#define DA_MUTEX_LOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_lock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_lock FAIL with EINVAL.");\ + break;\ + }\ + else if (EDEADLK == ret){\ + DA_LOGE("pthread_mutex_lock FAIL with EDEADLK.");\ + break;\ + }\ + else{\ + DA_LOGE("pthread_mutex_lock FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_MUTEX_UNLOCK(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_unlock(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret) {\ + DA_LOGE("pthread_mutex_unlock FAIL with EINVAL.");\ + break;\ + }\ + else if (EPERM == ret) {\ + DA_LOGE("pthread_mutex_unlock FAIL with EPERM.");\ + break;\ + }\ + else {\ + DA_LOGE("pthread_mutex_unlock FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} + +#define DA_COND_SIGNAL(cond_add) do {\ + if (0 != pthread_cond_signal(cond_add)) {\ + DA_LOGE("pthread_cond_signal FAIL");\ + }\ + } while(0) + +#define DA_COND_WAIT(cond_add, mutex_add) do {\ + if (0 != pthread_cond_wait(cond_add, mutex_add)){\ + DA_LOGE("pthread_cond_wait FAIL");\ + }\ + } while(0) + +#define DA_COND_TIMED_WAIT(cond_add, mutex_add, time) do {\ + if (0 != pthread_cond_timedwait(cond_add, mutex_add, time)){\ + DA_LOGE("pthread_cond_wait FAIL");\ + }\ + } while(0) + + +#define DA_COND_DESTROY(cond_add) do {\ + if (0 != pthread_cond_destroy(cond_add)){\ + DA_LOGE("pthread_cond_destroy FAIL");\ + }\ + } while(0) + +#define DA_MUTEX_DESTROY(mutex_add) {\ + int ret = 0;\ + do {\ + ret = pthread_mutex_destroy(mutex_add);\ + if (0 == ret){\ + break;\ + }\ + else if (EINVAL == ret){\ + DA_LOGE("pthread_mutex_destroy FAIL with EINVAL.");\ + break;\ + }\ + else if (EBUSY == ret){\ + DA_LOGE("pthread_mutex_destroy FAIL with EBUSY.");\ + break;\ + }\ + else {\ + DA_LOGE("pthread_mutex_destroy FAIL with %d.", ret);\ + break;\ + }\ + } while(1);\ +} +#endif diff --git a/agent/include/download-agent-type.h b/agent/include/download-agent-type.h new file mode 100755 index 0000000..e77c121 --- /dev/null +++ b/agent/include/download-agent-type.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DOWNLOAD_AGENT_TYPE_H +#define _DOWNLOAD_AGENT_TYPE_H + +#include "download-agent-defs.h" + +typedef int da_ret_t; +typedef int da_bool_t; +typedef unsigned long long da_size_t; + +#define IS_NOT_VALID_ID(x) (x <= DA_INVALID_ID) + +#define DA_MAX_URI_LEN 1024 +#define DA_MAX_FULL_PATH_LEN 356 // need configuration +#define DA_MAX_FILE_PATH_LEN 256 // need configuration +#define DA_MAX_STR_LEN 256 +#define DA_MAX_MIME_STR_LEN 256 +#define DA_MAX_PROXY_ADDR_LEN 64 // e.g. 100.200.300.400:10000 + +#define SCHEME_HTTP "http://" + +#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/usr/media/Downloads" + +#define DA_MAX_ID DA_MAX_DOWNLOAD_REQ_AT_ONCE + +#define SAVE_FILE_BUFFERING_SIZE_50KB (50*1024) + +#define NULL_CHECK(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return;\ + }\ +} + +#define NULL_CHECK_RET(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return DA_ERR_INVALID_ARGUMENT;\ + }\ +} + +#define NULL_CHECK_GOTO(DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + ret = DA_ERR_INVALID_ARGUMENT;\ + goto ERR;\ + }\ +} + +#define NULL_CHECK_RET_OPT(DATA, RET_DATA) {\ + if (!DATA) {\ + DA_LOGE("NULL CHECK!:%s",(#DATA));\ + return RET_DATA;\ + }\ +} + +#endif + diff --git a/debian/changelog b/debian/changelog deleted file mode 100755 index 5bf9374..0000000 --- a/debian/changelog +++ /dev/null @@ -1,8 +0,0 @@ -download-provider2 (0.0.1) unstable; urgency=low - - * Git: 165.213.180.234:/slp/pkgs/d/download-provider2 - * Tag: download-provider2_0.0.1 - - * initial making. - - -- Kwangmin Bang Thu, 15 Sep 2011 17:21:13 +0900 diff --git a/download-provider-service b/download-provider-service deleted file mode 100644 index 40fa113..0000000 --- a/download-provider-service +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -### A script for running download daemon in booting time. -#dlogutil -v long -f /var/log/download-capi.log -r 100 -n 10 TIZEN_N_URL_DOWNLOAD & -#dlogutil -v long -f /var/log/download-daemon.log -r 1000 -n 10 download-provider DownloadAgent & - -if [ -x /usr/bin/download-provider ]; then -/usr/bin/download-provider & -fi diff --git a/download-provider-w.manifest b/download-provider-w.manifest new file mode 100644 index 0000000..0877bb5 --- /dev/null +++ b/download-provider-w.manifest @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/download-provider.manifest b/download-provider.manifest index b8f2476..f7514e3 100644 --- a/download-provider.manifest +++ b/download-provider.manifest @@ -1,8 +1,39 @@ + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + diff --git a/download-provider.pc.in b/download-provider.pc.in index 5ec2085..72ea9e5 100644 --- a/download-provider.pc.in +++ b/download-provider.pc.in @@ -1,9 +1,6 @@ -# Package Information (download-provider daemon style) +# Package Information -prefix=/usr -includedir=${prefix}/include - -Name: Download Provider -Description: Download Provider Daemon +Name: @PROJECT_NAME@ +Description: @PACKAGE_DESCRIPTION@ Version: @VERSION@ -Cflags: -I${includedir}/download-provider +Cflags: -I/usr/include/download-provider diff --git a/dump-download-provider.sh b/dump-download-provider.sh new file mode 100644 index 0000000..e639496 --- /dev/null +++ b/dump-download-provider.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +PKG_NAME=download-provider + +DUMP_DIR=$1/$PKG_NAME +/bin/mkdir -p $DUMP_DIR + +# Download DB +DB_DIR=/opt/usr/data/download-provider/database +if [ "$DB_DIR" ] +then + /bin/echo "copy download DB ..." + /bin/cp -rf ${DB_DIR}* $DUMP_DIR +fi diff --git a/include/download-provider-config.h b/include/download-provider-config.h deleted file mode 100644 index ef73c3e..0000000 --- a/include/download-provider-config.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_CONFIG_H -#define DOWNLOAD_PROVIDER_CONFIG_H - -#include -#include - -#include - -#define DOWNLOAD_PROVIDER_IPC "/tmp/download-provider" -#define DOWNLOAD_PROVIDER_LOCK_PID "/tmp/download-provider.lock" - -#define DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL 5 -#define DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL 3600 - -#define DOWNLOAD_PROVIDER_DOWNLOADING_DB_NAME DATABASE_DIR"/"DATABASE_NAME - -#define MAX_CLIENT 64 // Backgound Daemon should has the limitation of resource. - -#define DOWNLOAD_PROVIDER_REQUESTID_LEN 20 - -#define DOWNLOAD_PROVIDER_HISTORY_DB_LIMIT_ROWS 1000 - -typedef struct { - pid_t pid; - uid_t uid; - gid_t gid; -} download_client_credential; - -typedef struct { - pthread_t thread_pid; - pthread_mutex_t client_mutex; - int clientfd; // socket for client - download_client_credential credentials; - ui_notification_h ui_notification_handle; // notification bar - service_h service_handle; // launch the special app from notification bar - int req_id; - download_request_info *requestinfo; - downloading_state_info *downloadinginfo; - download_content_info *downloadinfo; - char *tmp_saved_path; - download_states state; - download_error err; -} download_clientinfo; - -typedef struct { - download_clientinfo *clientinfo; -} download_clientinfo_slot; -#endif diff --git a/include/download-provider-db.h b/include/download-provider-db.h deleted file mode 100644 index a2ef14b..0000000 --- a/include/download-provider-db.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_DB_H -#define DOWNLOAD_PROVIDER_DB_H - -#include "download-provider-config.h" - -typedef struct { - download_states state; - int notification; - int retrycount; - int requestid; - char *packagename; - char *installpath; - char *filename; - char *createdate; - char *url; - char *mimetype; - char *etag; - char *saved_path; -} download_dbinfo; - -typedef struct { - unsigned int count; - download_dbinfo *item; -} download_dbinfo_list; - -typedef enum { - DOWNLOAD_DB_UNIQUEID = 0, - DOWNLOAD_DB_PACKAGENAME = 1, - DOWNLOAD_DB_NOTIFICATION = 2, - DOWNLOAD_DB_INSTALLPATH = 3, - DOWNLOAD_DB_FILENAME = 4, - DOWNLOAD_DB_RETRYCOUNT = 5, - DOWNLOAD_DB_STATE = 6, - DOWNLOAD_DB_URL = 7, - DOWNLOAD_DB_MIMETYPE = 10, - DOWNLOAD_DB_ETAG = 11, - DOWNLOAD_DB_SAVEDPATH = 12 -} download_db_column_type; - -int download_provider_db_requestinfo_new(download_clientinfo *clientinfo); -int download_provider_db_requestinfo_remove(int uniqueid); -int download_provider_db_requestinfo_update_column(download_clientinfo *clientinfo, - download_db_column_type type); -download_dbinfo_list *download_provider_db_get_list(int state); -download_dbinfo *download_provider_db_get_info(int requestid); -void download_provider_db_list_free(download_dbinfo_list *list); -void download_provider_db_info_free(download_dbinfo *info); -int download_provider_db_list_count(int state); -download_request_info *download_provider_db_get_requestinfo(download_dbinfo *dbinfo); -int download_provider_db_history_new(download_clientinfo *clientinfo); -int download_provider_db_history_remove(int uniqueid); -int download_provider_db_history_limit_rows(); -download_dbinfo *download_provider_db_history_get_info(int requestid); - -#endif diff --git a/include/download-provider-ipc.h b/include/download-provider-ipc.h deleted file mode 100644 index a38a965..0000000 --- a/include/download-provider-ipc.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_IPC_H -#define DOWNLOAD_PROVIDER_IPC_H - -#include "download-provider-config.h" - -int ipc_receive_header(int fd); -int ipc_send_stateinfo(download_clientinfo *clientinfo); -int ipc_send_downloadinfo(download_clientinfo *clientinfo); -int ipc_send_downloadinginfo(download_clientinfo *clientinfo); -int ipc_send_request_stateinfo(download_clientinfo *clientinfo); -int ipc_receive_request_msg(download_clientinfo *clientinfo); - -#endif diff --git a/include/download-provider-log.h b/include/download-provider-log.h deleted file mode 100644 index 3f78795..0000000 --- a/include/download-provider-log.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_LOG_H -#define DOWNLOAD_PROVIDER_LOG_H -#define DEBUG_MSG - -#ifdef DEBUG_MSG -#include -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "download-provider" -#define TRACE_DEBUG_MSG(format, ARG...) \ -{ \ -LOGE(format"[%s][%d]", ##ARG, __FUNCTION__, __LINE__); \ -} -#define TRACE_DEBUG_INFO_MSG(format, ARG...) \ -{ \ -LOGI(format"[%s][%d]", ##ARG, __FUNCTION__, __LINE__); \ -} -#else -#define TRACE_DEBUG_MSG(format, ARG...) ; -#endif -#endif diff --git a/include/download-provider-notification.h b/include/download-provider-notification.h deleted file mode 100644 index d464daf..0000000 --- a/include/download-provider-notification.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_NOTIFICATION_H -#define DOWNLOAD_PROVIDER_NOTIFICATION_H - -#include "download-provider-config.h" - -int set_downloadinginfo_appfw_notification(download_clientinfo *clientinfo); -int set_downloadedinfo_appfw_notification(download_clientinfo *clientinfo); -int destroy_appfw_notification(download_clientinfo *clientinfo); -void clear_downloadinginfo_appfw_notification(void); - -#endif diff --git a/include/download-provider-pthread.h b/include/download-provider-pthread.h deleted file mode 100644 index acbb361..0000000 --- a/include/download-provider-pthread.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_PTHREAD_H -#define DOWNLOAD_PROVIDER_PTHREAD_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#define CLIENT_MUTEX_INIT(mutex_add, attr) { \ - int ret = 0; \ - do { \ - ret = pthread_mutex_init(mutex_add, attr); \ - if (0 == ret) { \ - break; \ - } else if(EINVAL == ret) { \ - TRACE_DEBUG_MSG("ERR:pthread_mutex_init FAIL with EINVAL."); \ - break; \ - } else if(ENOMEM == ret) { \ - TRACE_DEBUG_MSG("ERR:pthread_mutex_init FAIL with ENOMEM."); \ - break; \ - } else { \ - TRACE_DEBUG_MSG("ERR:pthread_mutex_init FAIL with %d.", ret); \ - break; \ - } \ - }while(1); \ -} - -#define CLIENT_MUTEX_LOCK(mutex_add) {\ - int ret = 0;\ - do {\ - ret = pthread_mutex_lock(mutex_add);\ - if (0 == ret) {\ - break;\ - } else if (EINVAL == ret) {\ - TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EINVAL.");\ - break;\ - } else if (EDEADLK == ret) {\ - TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EDEADLK.");\ - break;\ - } else {\ - TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with %d.", ret);\ - break;\ - } \ - } while(1);\ -} - -#define CLIENT_MUTEX_UNLOCK(mutex_add) {\ - int ret = 0;\ - do {\ - ret = pthread_mutex_unlock(mutex_add);\ - if (0 == ret) {\ - break;\ - } else if (EINVAL == ret) {\ - TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EINVAL.");\ - break;\ - } else if (EDEADLK == ret) {\ - TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with EDEADLK.");\ - break;\ - } else {\ - TRACE_DEBUG_MSG("ERR:pthread_mutex_lock FAIL with %d.", ret);\ - break;\ - } \ - } while(1);\ -} - -#define CLIENT_MUTEX_DESTROY(mutex_add) { \ - int ret = 0; \ - do { \ - ret = pthread_mutex_destroy(mutex_add); \ - if (0 == ret) { \ - break; \ - } else if(EINVAL == ret) { \ - TRACE_DEBUG_MSG("ERR:pthread_mutex_destroy FAIL with EINVAL."); \ - break; \ - } else if(ENOMEM == ret) { \ - TRACE_DEBUG_MSG("ERR:pthread_mutex_destroy FAIL with ENOMEM."); \ - break; \ - } else { \ - TRACE_DEBUG_MSG("ERR:pthread_mutex_destroy FAIL with %d.", ret); \ - break; \ - } \ - }while(1); \ -} - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/download-provider-utils.h b/include/download-provider-utils.h deleted file mode 100644 index 99737a0..0000000 --- a/include/download-provider-utils.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_UTILS_H -#define DOWNLOAD_PROVIDER_UTILS_H - -#include "download-provider-config.h" - -int get_download_request_id(void); -void clear_clientinfoslot(download_clientinfo_slot *clientinfoslot); -void clear_clientinfo(download_clientinfo *clientinfo); -void clear_socket(download_clientinfo *clientinfo); -int get_downloading_count(download_clientinfo_slot *clientinfo_list); -int get_same_request_slot_index(download_clientinfo_slot *clientinfo_list, - int requestid); -int get_empty_slot_index(download_clientinfo_slot *clientinfo_list); -int get_pended_slot_index(download_clientinfo_slot *clientinfo_list); -int get_network_status(); - -#endif diff --git a/include/download-provider.h b/include/download-provider.h deleted file mode 100644 index a088a11..0000000 --- a/include/download-provider.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef DOWNLOAD_PROVIDER_H -#define DOWNLOAD_PROVIDER_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define DOWNLOAD_PROVIDER_IPC "/tmp/download-provider" - -#define DP_MAX_STR_LEN_64 64 -#define DP_MAX_STR_LEN 256 -#define DP_MAX_PATH_LEN DP_MAX_STR_LEN -#define DP_MAX_URL_LEN 2048 - - typedef enum { - DOWNLOAD_CONTROL_START = 1, - DOWNLOAD_CONTROL_STOP = 2, - DOWNLOAD_CONTROL_PAUSE = 3, - DOWNLOAD_CONTROL_RESUME = 4, - DOWNLOAD_CONTROL_GET_DOWNLOADING_INFO = 11, - DOWNLOAD_CONTROL_GET_STATE_INFO = 13, - DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO = 14, - DOWNLOAD_CONTROL_GET_REQUEST_STATE_INFO = 15 - } download_controls; - - typedef enum { - DOWNLOAD_STATE_NONE = 0, - DOWNLOAD_STATE_READY = 1, - DOWNLOAD_STATE_PENDED = 2, - DOWNLOAD_STATE_PAUSE_REQUESTED = 3, - DOWNLOAD_STATE_PAUSED = 4, - DOWNLOAD_STATE_DOWNLOADING = 5, - DOWNLOAD_STATE_INSTALLING = 6, - DOWNLOAD_STATE_FINISHED = 7, - DOWNLOAD_STATE_STOPPED = 10, - DOWNLOAD_STATE_FAILED = 11 - } download_states; - - typedef enum { - DOWNLOAD_ERROR_NONE = 0, - DOWNLOAD_ERROR_INVALID_PARAMETER = 1, - DOWNLOAD_ERROR_OUT_OF_MEMORY = 2, - DOWNLOAD_ERROR_IO_ERROR = 3, - DOWNLOAD_ERROR_NETWORK_UNREACHABLE = 4, - DOWNLOAD_ERROR_CONNECTION_TIMED_OUT = 5, - DOWNLOAD_ERROR_NO_SPACE = 6, - DOWNLOAD_ERROR_FILED_NOT_FOUND = 7, - DOWNLOAD_ERROR_INVALID_STATE = 8, - DOWNLOAD_ERROR_CONNECTION_FAILED = 9, - DOWNLOAD_ERROR_INVALID_URL = 10, - DOWNLOAD_ERROR_INVALID_DESTINATION = 11, - DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS = 12, - DOWNLOAD_ERROR_ALREADY_COMPLETED = 13, - DOWNLOAD_ERROR_INSTALL_FAIL = 20, - DOWNLOAD_ERROR_FAIL_INIT_AGENT = 100, - DOWNLOAD_ERROR_UNKOWN = 900 - } download_error; - - typedef struct { - unsigned int started; - unsigned int paused; - unsigned int completed; - unsigned int stopped; - unsigned int progress; - } callback_info; - - typedef struct { - unsigned int length; - char *str; - } download_flexible_string; - - typedef struct { - unsigned int rows; - download_flexible_string *str; - } download_flexible_double_string; - - typedef struct { - unsigned int received_size; - char saved_path[DP_MAX_PATH_LEN]; - } downloading_state_info; - - typedef struct { - download_states state; - download_error err; - } download_state_info; - - typedef struct { - unsigned int file_size; - char mime_type[DP_MAX_STR_LEN]; - char content_name[DP_MAX_STR_LEN]; - } download_content_info; - - typedef struct { - callback_info callbackinfo; - unsigned int notification; - int requestid; - download_flexible_string client_packagename; - download_flexible_string url; - download_flexible_string install_path; - download_flexible_string filename; - download_flexible_string service_data; - download_flexible_double_string headers; - } download_request_info; - - typedef struct { - download_state_info stateinfo; - int requestid; - } download_request_state_info; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/packaging/download-provider.spec b/packaging/download-provider.spec index 98bf889..b8303d7 100644 --- a/packaging/download-provider.spec +++ b/packaging/download-provider.spec @@ -1,27 +1,44 @@ - +%define _ux_define tizen2.3 Name: download-provider -Summary: download the contents in background. -Version: 0.0.5 -Release: 9 +Summary: Download the contents in background +Version: 2.1.23 +Release: 0 Group: Development/Libraries -License: Apache +License: Apache-2.0 Source0: %{name}-%{version}.tar.gz -Requires(post): /usr/bin/sqlite3 +Requires(post): sys-assert +Requires(post): libdevice-node +Requires(post): sqlite +Requires(post): connman BuildRequires: cmake -BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(libsoup-2.4) +BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(xdgmime) BuildRequires: pkgconfig(vconf) -BuildRequires: pkgconfig(db-util) BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(capi-appfw-app-manager) BuildRequires: pkgconfig(capi-appfw-application) BuildRequires: pkgconfig(capi-network-connection) +BuildRequires: pkgconfig(appsvc) +BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(capi-content-mime-type) +BuildRequires: pkgconfig(libsmack) +BuildRequires: gettext-devel +BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(capi-network-wifi-direct) +BuildRequires: pkgconfig(system-resource) +BuildRequires: model-build-features +BuildRequires: pkgconfig(storage) +%if "%{?tizen_profile_name}" == "wearable" +BuildRequires: pkgconfig(security-server) +%else if "%{?tizen_profile_name}" == "mobile" +BuildRequires: pkgconfig(notification) +%endif %description -Description: download the contents in background +Description: Download the contents in background %package devel Summary: download-provider @@ -29,125 +46,158 @@ Group: Development/Libraries Requires: %{name} = %{version}-%{release} %description devel -Description: download the contents in background (developement files) +Description: Download the contents in background (development files) %prep %setup -q -cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} +%define _data_install_path /opt/usr/data/%{name} +%define _resource_install_path /usr/share/%{name} +%define _imagedir %{_resource_install_path}/images +%define _localedir %{_resource_install_path}/locales +%define _databasedir %{_data_install_path}/database +%define _database_client_dir %{_databasedir}/clients +%define _notifydir %{_data_install_path}/notify +%define _ipc_socket /opt/data/%{name}/%{name}.sock +%define _licensedir /usr/share/license +%define _logdump_script_dir /opt/etc/dump.d/module.d +%define _http_lib libcurl + +%define download_booster OFF +%define sys_resource OFF +%define support_oma_drm OFF +%define wifi_direct ON +%define support_security_privilege OFF +%define support_companion_mode OFF +%define support_notification ON +%define _manifest_name %{name}.manifest + +%if 0%{?model_build_feature_wlan_p2p_disable } +%define wifi_direct OFF +%endif +%if "%{?tizen_profile_name}" == "wearable" +%define download_booster OFF +%define support_notification OFF +%define _manifest_name %{name}-w.manifest +%endif + +%define cmake \ + CFLAGS="${CFLAGS:-%optflags} -fPIC -D_REENTRANT -fvisibility=hidden"; export CFLAGS \ + FFLAGS="${FFLAGS:-%optflags} -fPIC -fvisibility=hidden"; export FFLAGS \ + LDFLAGS+=" -Wl,--as-needed -Wl,--hash-style=both"; export LDFLAGS \ + %__cmake \\\ + -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \\\ + -DBIN_INSTALL_DIR:PATH=%{_bindir} \\\ + -DLIB_INSTALL_DIR:PATH=%{_libdir} \\\ + -DINCLUDE_INSTALL_DIR:PATH=%{_includedir} \\\ + -DPKG_NAME=%{name} \\\ + -DPKG_VERSION=%{version} \\\ + -DPKG_RELEASE=%{release} \\\ + -DIPC_SOCKET:PATH=%{_ipc_socket} \\\ + -DPROVIDER_DIR:PATH=%{_data_install_path} \\\ + -DNOTIFY_DIR:PATH=%{_notifydir} \\\ + -DDATABASE_DIR:PATH=%{_databasedir} \\\ + -DDATABASE_CLIENT_DIR:PATH=%{_database_client_dir} \\\ + -DIMAGE_DIR:PATH=%{_imagedir} \\\ + -DLOCALE_DIR:PATH=%{_localedir} \\\ + -DLICENSE_DIR:PATH=%{_licensedir} \\\ + %if "%{?wifi_direct}" == "ON" \ + -DSUPPORT_WIFI_DIRECT:BOOL=ON \\\ + %else \ + -DSUPPORT_WIFI_DIRECT:BOOL=OFF \\\ + %endif \ + %if "%{?sys_resource}" == "ON" \ + -DSUPPORT_SYS_RESOURCE:BOOL=ON \\\ + %else \ + -DSUPPORT_SYS_RESOURCE:BOOL=OFF \\\ + %endif \ + %if "%{?download_booster}" == "ON" \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=ON \\\ + %else \ + -DSUPPORT_DOWNLOAD_BOOSTER:BOOL=OFF \\\ + %endif \ + %if "%{?support_notification}" == "ON" \ + -DSUPPORT_NOTIFICATION:BOOL=ON \\\ + %else \ + -DSUPPORT_NOTIFICATION:BOOL=OFF \\\ + %endif \ + -DSUPPORT_LOG_MESSAGE:BOOL=ON \\\ + %if "%{?support_oma_drm}" == "ON" \ + -DSUPPORT_OMA_DRM:BOOL=ON \\\ + %else \ + -DSUPPORT_OMA_DRM:BOOL=OFF \\\ + %endif \ + %if "%{?support_security_privilege}" == "ON" \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=ON \\\ + %else \ + -DSUPPORT_SECURITY_PRIVILEGE:BOOL=OFF \\\ + %endif \ + %if "%{?support_companion_mode}" == "ON" \ + -DSUPPORT_COMPANION_MODE:BOOL=ON \\\ + %else \ + -DSUPPORT_COMPANION_MODE:BOOL=OFF \\\ + %endif \ + %if "%{?_ux_define}" == "tizen2.3" \ + -DTIZEN_2_3_UX:BOOL=ON \\\ + %endif \ + -DCMAKE_LOG_DUMP_SCRIPT_DIR=%{_logdump_script_dir} \\\ + -DHTTP_LIB=%{_http_lib} \\\ + %if "%{?_lib}" == "lib64" \ + %{?_cmake_lib_suffix64} \\\ + %endif \ + %{?_cmake_skip_rpath} \\\ + -DBUILD_SHARED_LIBS:BOOL=ON %build +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +%cmake . make %{?jobs:-j%jobs} %install rm -rf %{buildroot} %make_install - -mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc3.d -ln -s %{_sysconfdir}/rc.d/init.d/download-provider-service %{buildroot}%{_sysconfdir}/rc.d/rc3.d/S70download-provider-service -mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc5.d -ln -s %{_sysconfdir}/rc.d/init.d/download-provider-service %{buildroot}%{_sysconfdir}/rc.d/rc5.d/S70download-provider-service - -mkdir -p %{buildroot}/opt/data/download-provider +mkdir -p %{buildroot}%{_licensedir} +mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants +mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants +ln -s ../download-provider.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/ +ln -s ../download-provider.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/ %post -mkdir -p /opt/dbspace/ -if [ ! -f /opt/dbspace/.download-provider.db ]; -then - sqlite3 /opt/dbspace/.download-provider.db 'PRAGMA journal_mode=PERSIST; - CREATE TABLE downloading (id INTEGER PRIMARY KEY AUTOINCREMENT, uniqueid INTEGER UNIQUE, packagename TEXT, notification INTEGER, installpath TEXT, filename TEXT, creationdate TEXT, retrycount INTEGER, state INTEGER, url TEXT, mimetype TEXT, etag TEXT, savedpath TEXT);' - sqlite3 /opt/dbspace/.download-provider.db 'PRAGMA journal_mode=PERSIST; - CREATE TABLE history (id INTEGER PRIMARY KEY AUTOINCREMENT, uniqueid INTEGER UNIQUE, packagename TEXT, filename TEXT, creationdate TEXT, state INTEGER, mimetype TEXT, savedpath TEXT);' -fi +#make notify dir in post section for smack +mkdir -p %{_notifydir} +chsmack -a 'download-provider::ipc' %{_notifydir} +chsmack -t %{_notifydir} +mkdir -p --mode=0700 %{_databasedir} +chsmack -a 'download-provider' %{_databasedir} +mkdir -p --mode=0700 %{_database_client_dir} +chsmack -a 'download-provider' %{_database_client_dir} %files %defattr(-,root,root,-) -%dir /opt/data/download-provider -/opt/data/download-provider/*.png -%{_libdir}/libdownloadagent.so.0.0.1 -%{_libdir}/libdownloadagent.so -%{_bindir}/download-provider -%{_sysconfdir}/rc.d/init.d/download-provider-service -%{_sysconfdir}/rc.d/rc3.d/S70download-provider-service -%{_sysconfdir}/rc.d/rc5.d/S70download-provider-service +%manifest %{_manifest_name} +%{_imagedir}/*.png +%{_localedir}/*/*/download-provider.mo +%{_libdir}/libdownloadagent2.so.0.1.0 +%{_libdir}/libdownloadagent2.so +%{_libdir}/systemd/system/download-provider.service +%{_libdir}/systemd/system/graphical.target.wants/download-provider.service +%{_libdir}/systemd/system/download-provider.socket +%{_libdir}/systemd/system/sockets.target.wants/download-provider.socket +%{_libdir}/libdownload-provider-interface.so.%{version} +%{_libdir}/libdownload-provider-interface.so.0 +%{_bindir}/%{name} +%{_licensedir}/%{name} +%attr(0544,root,root) %{_logdump_script_dir}/dump-%{name}.sh %files devel %defattr(-,root,root,-) -%{_libdir}/libdownloadagent.so.0.0.1 -%{_libdir}/libdownloadagent.so -%{_bindir}/download-provider +%{_libdir}/libdownloadagent2.so.0.1.0 +%{_libdir}/libdownloadagent2.so +%{_libdir}/libdownload-provider-interface.so %{_includedir}/download-provider/download-provider.h +%{_includedir}/download-provider/download-provider-interface.h +%{_bindir}/%{name} %{_libdir}/pkgconfig/download-provider.pc - -%changelog -* Fri Sep 07 2012 Kwangmin Bang -- add LICENSE -- Add to search download id from history db - -* Thu Sep 06 2012 Kwangmin Bang -- start to download again even if already finished -- change thread style -- arrange the request priority -- change data type -- wait till getting the response from client - -* Mon Sep 03 2012 Kwangmin Bang -- fix timeout error - -* Mon Sep 03 2012 Kwangmin Bang -- free slot after getting event from url-download -- fix INTEGER OVERFLOW - -* Thu Aug 30 2012 Kwangmin Bang -- initialize mutex for auto-redownloading -- support Pause/Resume with new connection -- fix the memory leak - -* Mon Aug 27 2012 Kwangmin Bang -- Change the ownership of downloaded file -- Add detached option when pthread is created -- fix the failure getting history info from database -- fix first timeout takes a long time -- fix wrong checking of network status -- fix the crash by double free -- divide log level -- Resolve prevent defects for agent module -- Resolve a bug to join domain in case of playready - -* Tue Aug 23 2012 Kwangmin Bang -- event thread does not deal in some state -- fix the lockup by mutex and the crash by invaild socket event - -* Tue Aug 22 2012 Jungki Kwak -- Fix the crash when use notification -- One thread model for socket -- Fix the defects found by prevent tool -- Remove mutex lock/unlock in case of invalid id -- Support the status of download in case of getting new connection with requestid -- Clear db and register notification when stopped the download -- Update notification function -- Enable to set the defined file name by user - -* Tue Aug 17 2012 Jungki Kwak -- Enable to use destination path -- Add to handle invalid id - -* Tue Aug 16 2012 Jungki Kwak -- Change socket close timing - -* Mon Aug 13 2012 Kwangmin Bang -- Disable default dlog in launching script. - -* Tue Aug 09 2012 Jungki Kwak -- The function to init dbus glib is removed - -* Tue Aug 08 2012 Jungki Kwak -- The function to init dbus glib is added for connection network CAPI - -* Tue Aug 07 2012 Jungki Kwak -- Change the name of temp direcoty. -- When add requestinfo to slot, save it to DB. - -* Mon Aug 06 2012 Jungki Kwak -- Initial version is updated. - +%{_libdir}/pkgconfig/download-provider-interface.pc diff --git a/po/redwood/CMakeLists.txt b/po/redwood/CMakeLists.txt new file mode 100644 index 0000000..706d725 --- /dev/null +++ b/po/redwood/CMakeLists.txt @@ -0,0 +1,27 @@ +# for i18n + +SET(POFILES az.po bg.po ca.po cs.po da.po de.po el_GR.po en.po en_US.po es_ES.po + es_US.po et.po eu.po fi.po fr_CA.po fr.po gl.po hr.po hu.po hy.po is.po + it_IT.po ka.po kk.po ko_KR.po lt.po lv.po mn_MN.po nb.po nl.po pl.po + pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po tr_TR.po uk.po uz.po) + +SET(MSGFMT "/usr/bin/msgfmt") + +FOREACH(pofile ${POFILES}) + SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile}) + MESSAGE("PO: ${pofile}") + GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE) + GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE) + SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo) + ADD_CUSTOM_COMMAND( + OUTPUT ${moFile} + COMMAND ${MSGFMT} -o ${moFile} ${absPofile} + DEPENDS ${absPofile} + ) + INSTALL(FILES ${moFile} + DESTINATION ${LOCALE_DIR}/${lang}/LC_MESSAGES RENAME ${PKG_NAME}.mo) + SET(moFiles ${moFiles} ${moFile}) +ENDFOREACH(pofile) + +MESSAGE(".mo files: ${moFiles}") +ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) diff --git a/po/redwood/az.po b/po/redwood/az.po new file mode 100644 index 0000000..f8d4868 --- /dev/null +++ b/po/redwood/az.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yükləmə tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yükləmə alınmadı" + diff --git a/po/redwood/bg.po b/po/redwood/bg.po new file mode 100644 index 0000000..4b2b9cb --- /dev/null +++ b/po/redwood/bg.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Изтеглянето завършено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Изтеглянето неуспешно" + diff --git a/po/redwood/ca.po b/po/redwood/ca.po new file mode 100644 index 0000000..e4cb32e --- /dev/null +++ b/po/redwood/ca.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descàrrega completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descàrrega fallida" + diff --git a/po/redwood/cs.po b/po/redwood/cs.po new file mode 100644 index 0000000..7c33b8b --- /dev/null +++ b/po/redwood/cs.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Stahování dokončeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Stažení se nezdařilo" + diff --git a/po/redwood/da.po b/po/redwood/da.po new file mode 100644 index 0000000..1cbbbec --- /dev/null +++ b/po/redwood/da.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Overførsel fuldført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Overførsel mislykkedes" + diff --git a/po/redwood/de.po b/po/redwood/de.po new file mode 100644 index 0000000..8301d76 --- /dev/null +++ b/po/redwood/de.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download beendet" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download fehlgeschlagen" + diff --git a/po/redwood/el_GR.po b/po/redwood/el_GR.po new file mode 100644 index 0000000..f96c0a1 --- /dev/null +++ b/po/redwood/el_GR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Η λήψη ολοκληρώθηκε" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Αποτυχία λήψης" + diff --git a/po/redwood/en.po b/po/redwood/en.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/redwood/en.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/redwood/en_US.po b/po/redwood/en_US.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/redwood/en_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/redwood/es_ES.po b/po/redwood/es_ES.po new file mode 100644 index 0000000..300e275 --- /dev/null +++ b/po/redwood/es_ES.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error de descarga" + diff --git a/po/redwood/es_US.po b/po/redwood/es_US.po new file mode 100644 index 0000000..6be685a --- /dev/null +++ b/po/redwood/es_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error al descargar" + diff --git a/po/redwood/et.po b/po/redwood/et.po new file mode 100644 index 0000000..6ffe386 --- /dev/null +++ b/po/redwood/et.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Allalaadimine on lõpule viidud" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Allalaadimine nurjus" + diff --git a/po/redwood/eu.po b/po/redwood/eu.po new file mode 100644 index 0000000..b9db71f --- /dev/null +++ b/po/redwood/eu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Deskarga osatuta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Deskargak huts egin du" + diff --git a/po/redwood/fi.po b/po/redwood/fi.po new file mode 100644 index 0000000..7929571 --- /dev/null +++ b/po/redwood/fi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lataus valmis" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lataus epäonnistui" + diff --git a/po/redwood/fr.po b/po/redwood/fr.po new file mode 100644 index 0000000..f1e8884 --- /dev/null +++ b/po/redwood/fr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Echec du téléchargement" + diff --git a/po/redwood/fr_CA.po b/po/redwood/fr_CA.po new file mode 100644 index 0000000..608ae3d --- /dev/null +++ b/po/redwood/fr_CA.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Échec du téléchargement" + diff --git a/po/redwood/gl.po b/po/redwood/gl.po new file mode 100644 index 0000000..8527d75 --- /dev/null +++ b/po/redwood/gl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Erro na descarga" + diff --git a/po/redwood/hr.po b/po/redwood/hr.po new file mode 100644 index 0000000..0f225a4 --- /dev/null +++ b/po/redwood/hr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Skidanje dovrÅ¡eno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Skidanje neuspjeÅ¡no" + diff --git a/po/redwood/hu.po b/po/redwood/hu.po new file mode 100644 index 0000000..847e5af --- /dev/null +++ b/po/redwood/hu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "A letöltés befejeződött" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sikertelen letöltés" + diff --git a/po/redwood/hy.po b/po/redwood/hy.po new file mode 100644 index 0000000..8636b2b --- /dev/null +++ b/po/redwood/hy.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ներբեռնումն ավարտվեց" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ներբեռնումը ձախողվեց" + diff --git a/po/redwood/is.po b/po/redwood/is.po new file mode 100644 index 0000000..3bb7f29 --- /dev/null +++ b/po/redwood/is.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Niðurhali lokið" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Niðurhal mistókst" + diff --git a/po/redwood/it_IT.po b/po/redwood/it_IT.po new file mode 100644 index 0000000..51a407e --- /dev/null +++ b/po/redwood/it_IT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download completato" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download non riuscito" + diff --git a/po/redwood/ka.po b/po/redwood/ka.po new file mode 100644 index 0000000..83aea79 --- /dev/null +++ b/po/redwood/ka.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ჩამოტვირთვა დასრულდა" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ვერ ჩამოიტვირთა" + diff --git a/po/redwood/kk.po b/po/redwood/kk.po new file mode 100644 index 0000000..bd25ab4 --- /dev/null +++ b/po/redwood/kk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Жүктеу аяқталды" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Жүктеу орындалмады" + diff --git a/po/redwood/ko_KR.po b/po/redwood/ko_KR.po new file mode 100644 index 0000000..80d1e37 --- /dev/null +++ b/po/redwood/ko_KR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "다운로드 완료" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "다운로드 안 됨" + diff --git a/po/redwood/lt.po b/po/redwood/lt.po new file mode 100644 index 0000000..d08e1d5 --- /dev/null +++ b/po/redwood/lt.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Atsisiuntimas baigtas" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Atsisiųsti nepavyko" + diff --git a/po/redwood/lv.po b/po/redwood/lv.po new file mode 100644 index 0000000..323c609 --- /dev/null +++ b/po/redwood/lv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lejupielāde pabeigta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lejupielāde neizdevās" + diff --git a/po/redwood/mn_MN.po b/po/redwood/mn_MN.po new file mode 100644 index 0000000..7060f68 --- /dev/null +++ b/po/redwood/mn_MN.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Татан авалт дууссан" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Татаж авч чадсангүй" + diff --git a/po/redwood/nb.po b/po/redwood/nb.po new file mode 100644 index 0000000..49448f5 --- /dev/null +++ b/po/redwood/nb.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Nedlasting fullført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Nedlastingen mislyktes" + diff --git a/po/redwood/nl.po b/po/redwood/nl.po new file mode 100644 index 0000000..1195f04 --- /dev/null +++ b/po/redwood/nl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Downloaden voltooid" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Downloaden mislukt" + diff --git a/po/redwood/pl.po b/po/redwood/pl.po new file mode 100644 index 0000000..9e52a17 --- /dev/null +++ b/po/redwood/pl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Pobieranie zakończone" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Pobieranie nie powiodło się" + diff --git a/po/redwood/pt_BR.po b/po/redwood/pt_BR.po new file mode 100644 index 0000000..0fdce74 --- /dev/null +++ b/po/redwood/pt_BR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download concluído" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Falha no download" + diff --git a/po/redwood/pt_PT.po b/po/redwood/pt_PT.po new file mode 100644 index 0000000..c934937 --- /dev/null +++ b/po/redwood/pt_PT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Transferência concluída" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "A transferência falhou" + diff --git a/po/redwood/ro.po b/po/redwood/ro.po new file mode 100644 index 0000000..820ab33 --- /dev/null +++ b/po/redwood/ro.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descărcare finalizată" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descărcarea nu a reuşit" + diff --git a/po/redwood/ru_RU.po b/po/redwood/ru_RU.po new file mode 100644 index 0000000..e3cb63a --- /dev/null +++ b/po/redwood/ru_RU.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Загрузка завершена" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Сбой загрузки" + diff --git a/po/redwood/sk.po b/po/redwood/sk.po new file mode 100644 index 0000000..6d92c75 --- /dev/null +++ b/po/redwood/sk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "SÅ¥ahovanie je dokončené" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "SÅ¥ahovanie zlyhalo" + diff --git a/po/redwood/sl.po b/po/redwood/sl.po new file mode 100644 index 0000000..1c256ab --- /dev/null +++ b/po/redwood/sl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Prenos je končan" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Prenos ni uspel" + diff --git a/po/redwood/sr.po b/po/redwood/sr.po new file mode 100644 index 0000000..2e6331a --- /dev/null +++ b/po/redwood/sr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Preuzimanje zavrÅ¡eno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "NeuspeÅ¡no preuzimanje" + diff --git a/po/redwood/sv.po b/po/redwood/sv.po new file mode 100644 index 0000000..e792e63 --- /dev/null +++ b/po/redwood/sv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Hämtningen är klar" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Hämtningen misslyckades" + diff --git a/po/redwood/tr_TR.po b/po/redwood/tr_TR.po new file mode 100644 index 0000000..73277df --- /dev/null +++ b/po/redwood/tr_TR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ä°ndirme tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ä°ndirme başarısız" + diff --git a/po/redwood/uk.po b/po/redwood/uk.po new file mode 100644 index 0000000..ad32cd3 --- /dev/null +++ b/po/redwood/uk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Завантаження завершено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Збій завантаження" + diff --git a/po/redwood/uz.po b/po/redwood/uz.po new file mode 100644 index 0000000..ff9b724 --- /dev/null +++ b/po/redwood/uz.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yuklab olish yakunlandi" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yuklab olib bo‘lmadi" + diff --git a/po/tizen2.3/CMakeLists.txt b/po/tizen2.3/CMakeLists.txt new file mode 100644 index 0000000..1ff1ce8 --- /dev/null +++ b/po/tizen2.3/CMakeLists.txt @@ -0,0 +1,30 @@ +# for i18n + +SET(POFILES + ar.po az.po bg.po ca.po cs.po da.po de.po el_GR.po en.po + en_PH.po en_US.po es_ES.po es_US.po et.po eu.po fi.po fr.po + fr_CA.po ga.po gl.po hi.po hr.po hu.po hy.po is.po it_IT.po + ja_JP.po ka.po kk.po ko_KR.po lt.po lv.po mk.po nb.po nl.po + pl.po pt_BR.po pt_PT.po ro.po ru_RU.po sk.po sl.po sr.po sv.po + tr_TR.po uk.po uz.po zh_CN.po zh_HK.po zh_TW.po) + +SET(MSGFMT "/usr/bin/msgfmt") + +FOREACH(pofile ${POFILES}) + SET(pofile ${CMAKE_CURRENT_SOURCE_DIR}/${pofile}) + MESSAGE("PO: ${pofile}") + GET_FILENAME_COMPONENT(absPofile ${pofile} ABSOLUTE) + GET_FILENAME_COMPONENT(lang ${absPofile} NAME_WE) + SET(moFile ${CMAKE_CURRENT_BINARY_DIR}/${lang}.mo) + ADD_CUSTOM_COMMAND( + OUTPUT ${moFile} + COMMAND ${MSGFMT} -o ${moFile} ${absPofile} + DEPENDS ${absPofile} + ) + INSTALL(FILES ${moFile} + DESTINATION ${LOCALE_DIR}/${lang}/LC_MESSAGES RENAME ${PKG_NAME}.mo) + SET(moFiles ${moFiles} ${moFile}) +ENDFOREACH(pofile) + +MESSAGE(".mo files: ${moFiles}") +ADD_CUSTOM_TARGET(po ALL DEPENDS ${moFiles}) diff --git a/po/tizen2.3/ar.po b/po/tizen2.3/ar.po new file mode 100644 index 0000000..1bf0a3c --- /dev/null +++ b/po/tizen2.3/ar.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "تم التنزيل" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "فشل التنزيل" + diff --git a/po/tizen2.3/az.po b/po/tizen2.3/az.po new file mode 100644 index 0000000..f8d4868 --- /dev/null +++ b/po/tizen2.3/az.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yükləmə tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yükləmə alınmadı" + diff --git a/po/tizen2.3/bg.po b/po/tizen2.3/bg.po new file mode 100644 index 0000000..4b2b9cb --- /dev/null +++ b/po/tizen2.3/bg.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Изтеглянето завършено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Изтеглянето неуспешно" + diff --git a/po/tizen2.3/ca.po b/po/tizen2.3/ca.po new file mode 100644 index 0000000..e4cb32e --- /dev/null +++ b/po/tizen2.3/ca.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descàrrega completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descàrrega fallida" + diff --git a/po/tizen2.3/cs.po b/po/tizen2.3/cs.po new file mode 100644 index 0000000..7c33b8b --- /dev/null +++ b/po/tizen2.3/cs.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Stahování dokončeno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Stažení se nezdařilo" + diff --git a/po/tizen2.3/da.po b/po/tizen2.3/da.po new file mode 100644 index 0000000..1cbbbec --- /dev/null +++ b/po/tizen2.3/da.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Overførsel fuldført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Overførsel mislykkedes" + diff --git a/po/tizen2.3/de.po b/po/tizen2.3/de.po new file mode 100644 index 0000000..8301d76 --- /dev/null +++ b/po/tizen2.3/de.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download beendet" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download fehlgeschlagen" + diff --git a/po/tizen2.3/el_GR.po b/po/tizen2.3/el_GR.po new file mode 100644 index 0000000..f96c0a1 --- /dev/null +++ b/po/tizen2.3/el_GR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Η λήψη ολοκληρώθηκε" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Αποτυχία λήψης" + diff --git a/po/tizen2.3/en.po b/po/tizen2.3/en.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/en_PH.po b/po/tizen2.3/en_PH.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en_PH.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/en_US.po b/po/tizen2.3/en_US.po new file mode 100644 index 0000000..0bcc00f --- /dev/null +++ b/po/tizen2.3/en_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download complete" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download failed" + diff --git a/po/tizen2.3/es_ES.po b/po/tizen2.3/es_ES.po new file mode 100644 index 0000000..300e275 --- /dev/null +++ b/po/tizen2.3/es_ES.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error de descarga" + diff --git a/po/tizen2.3/es_US.po b/po/tizen2.3/es_US.po new file mode 100644 index 0000000..6be685a --- /dev/null +++ b/po/tizen2.3/es_US.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Error al descargar" + diff --git a/po/tizen2.3/et.po b/po/tizen2.3/et.po new file mode 100644 index 0000000..6ffe386 --- /dev/null +++ b/po/tizen2.3/et.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Allalaadimine on lõpule viidud" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Allalaadimine nurjus" + diff --git a/po/tizen2.3/eu.po b/po/tizen2.3/eu.po new file mode 100644 index 0000000..b9db71f --- /dev/null +++ b/po/tizen2.3/eu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Deskarga osatuta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Deskargak huts egin du" + diff --git a/po/tizen2.3/fi.po b/po/tizen2.3/fi.po new file mode 100644 index 0000000..7929571 --- /dev/null +++ b/po/tizen2.3/fi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lataus valmis" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lataus epäonnistui" + diff --git a/po/tizen2.3/fr.po b/po/tizen2.3/fr.po new file mode 100644 index 0000000..f1e8884 --- /dev/null +++ b/po/tizen2.3/fr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Echec du téléchargement" + diff --git a/po/tizen2.3/fr_CA.po b/po/tizen2.3/fr_CA.po new file mode 100644 index 0000000..608ae3d --- /dev/null +++ b/po/tizen2.3/fr_CA.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Téléchargement terminé" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Échec du téléchargement" + diff --git a/po/tizen2.3/ga.po b/po/tizen2.3/ga.po new file mode 100644 index 0000000..f8651ef --- /dev/null +++ b/po/tizen2.3/ga.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Íoslódáilte" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Theip ar íoslódáil" + diff --git a/po/tizen2.3/gl.po b/po/tizen2.3/gl.po new file mode 100644 index 0000000..8527d75 --- /dev/null +++ b/po/tizen2.3/gl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descarga completa" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Erro na descarga" + diff --git a/po/tizen2.3/hi.po b/po/tizen2.3/hi.po new file mode 100644 index 0000000..36382aa --- /dev/null +++ b/po/tizen2.3/hi.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "डाउनलोड पूर्ण" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "डाउनलोड विफल" + diff --git a/po/tizen2.3/hr.po b/po/tizen2.3/hr.po new file mode 100644 index 0000000..0f225a4 --- /dev/null +++ b/po/tizen2.3/hr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Skidanje dovrÅ¡eno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Skidanje neuspjeÅ¡no" + diff --git a/po/tizen2.3/hu.po b/po/tizen2.3/hu.po new file mode 100644 index 0000000..847e5af --- /dev/null +++ b/po/tizen2.3/hu.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "A letöltés befejeződött" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Sikertelen letöltés" + diff --git a/po/tizen2.3/hy.po b/po/tizen2.3/hy.po new file mode 100644 index 0000000..8636b2b --- /dev/null +++ b/po/tizen2.3/hy.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ներբեռնումն ավարտվեց" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ներբեռնումը ձախողվեց" + diff --git a/po/tizen2.3/is.po b/po/tizen2.3/is.po new file mode 100644 index 0000000..3bb7f29 --- /dev/null +++ b/po/tizen2.3/is.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Niðurhali lokið" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Niðurhal mistókst" + diff --git a/po/tizen2.3/it_IT.po b/po/tizen2.3/it_IT.po new file mode 100644 index 0000000..51a407e --- /dev/null +++ b/po/tizen2.3/it_IT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download completato" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Download non riuscito" + diff --git a/po/tizen2.3/ja_JP.po b/po/tizen2.3/ja_JP.po new file mode 100644 index 0000000..b466c9b --- /dev/null +++ b/po/tizen2.3/ja_JP.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ダウンロード完了" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ダウンロード失敗" + diff --git a/po/tizen2.3/ka.po b/po/tizen2.3/ka.po new file mode 100644 index 0000000..83aea79 --- /dev/null +++ b/po/tizen2.3/ka.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "ჩამოტვირთვა დასრულდა" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "ვერ ჩამოიტვირთა" + diff --git a/po/tizen2.3/kk.po b/po/tizen2.3/kk.po new file mode 100644 index 0000000..bd25ab4 --- /dev/null +++ b/po/tizen2.3/kk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Жүктеу аяқталды" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Жүктеу орындалмады" + diff --git a/po/tizen2.3/ko_KR.po b/po/tizen2.3/ko_KR.po new file mode 100644 index 0000000..80d1e37 --- /dev/null +++ b/po/tizen2.3/ko_KR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "다운로드 완료" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "다운로드 안 됨" + diff --git a/po/tizen2.3/lt.po b/po/tizen2.3/lt.po new file mode 100644 index 0000000..d08e1d5 --- /dev/null +++ b/po/tizen2.3/lt.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Atsisiuntimas baigtas" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Atsisiųsti nepavyko" + diff --git a/po/tizen2.3/lv.po b/po/tizen2.3/lv.po new file mode 100644 index 0000000..323c609 --- /dev/null +++ b/po/tizen2.3/lv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Lejupielāde pabeigta" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Lejupielāde neizdevās" + diff --git a/po/tizen2.3/mk.po b/po/tizen2.3/mk.po new file mode 100644 index 0000000..0ef6f04 --- /dev/null +++ b/po/tizen2.3/mk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Преземањето заврши" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Преземањето не успеа" + diff --git a/po/tizen2.3/nb.po b/po/tizen2.3/nb.po new file mode 100644 index 0000000..49448f5 --- /dev/null +++ b/po/tizen2.3/nb.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Nedlasting fullført" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Nedlastingen mislyktes" + diff --git a/po/tizen2.3/nl.po b/po/tizen2.3/nl.po new file mode 100644 index 0000000..1195f04 --- /dev/null +++ b/po/tizen2.3/nl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Downloaden voltooid" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Downloaden mislukt" + diff --git a/po/tizen2.3/pl.po b/po/tizen2.3/pl.po new file mode 100644 index 0000000..9e52a17 --- /dev/null +++ b/po/tizen2.3/pl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Pobieranie zakończone" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Pobieranie nie powiodło się" + diff --git a/po/tizen2.3/pt_BR.po b/po/tizen2.3/pt_BR.po new file mode 100644 index 0000000..0fdce74 --- /dev/null +++ b/po/tizen2.3/pt_BR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Download concluído" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Falha no download" + diff --git a/po/tizen2.3/pt_PT.po b/po/tizen2.3/pt_PT.po new file mode 100644 index 0000000..c934937 --- /dev/null +++ b/po/tizen2.3/pt_PT.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Transferência concluída" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "A transferência falhou" + diff --git a/po/tizen2.3/ro.po b/po/tizen2.3/ro.po new file mode 100644 index 0000000..820ab33 --- /dev/null +++ b/po/tizen2.3/ro.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Descărcare finalizată" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Descărcarea nu a reuşit" + diff --git a/po/tizen2.3/ru_RU.po b/po/tizen2.3/ru_RU.po new file mode 100644 index 0000000..e3cb63a --- /dev/null +++ b/po/tizen2.3/ru_RU.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Загрузка завершена" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Сбой загрузки" + diff --git a/po/tizen2.3/sk.po b/po/tizen2.3/sk.po new file mode 100644 index 0000000..6d92c75 --- /dev/null +++ b/po/tizen2.3/sk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "SÅ¥ahovanie je dokončené" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "SÅ¥ahovanie zlyhalo" + diff --git a/po/tizen2.3/sl.po b/po/tizen2.3/sl.po new file mode 100644 index 0000000..1c256ab --- /dev/null +++ b/po/tizen2.3/sl.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Prenos je končan" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Prenos ni uspel" + diff --git a/po/tizen2.3/sr.po b/po/tizen2.3/sr.po new file mode 100644 index 0000000..2e6331a --- /dev/null +++ b/po/tizen2.3/sr.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Preuzimanje zavrÅ¡eno" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "NeuspeÅ¡no preuzimanje" + diff --git a/po/tizen2.3/sv.po b/po/tizen2.3/sv.po new file mode 100644 index 0000000..e792e63 --- /dev/null +++ b/po/tizen2.3/sv.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Hämtningen är klar" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Hämtningen misslyckades" + diff --git a/po/tizen2.3/tr_TR.po b/po/tizen2.3/tr_TR.po new file mode 100644 index 0000000..73277df --- /dev/null +++ b/po/tizen2.3/tr_TR.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Ä°ndirme tamamlandı" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Ä°ndirme başarısız" + diff --git a/po/tizen2.3/uk.po b/po/tizen2.3/uk.po new file mode 100644 index 0000000..ad32cd3 --- /dev/null +++ b/po/tizen2.3/uk.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Завантаження завершено" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Збій завантаження" + diff --git a/po/tizen2.3/uz.po b/po/tizen2.3/uz.po new file mode 100644 index 0000000..ff9b724 --- /dev/null +++ b/po/tizen2.3/uz.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "Yuklab olish yakunlandi" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "Yuklab olib bo‘lmadi" + diff --git a/po/tizen2.3/zh_CN.po b/po/tizen2.3/zh_CN.po new file mode 100644 index 0000000..f5e03c8 --- /dev/null +++ b/po/tizen2.3/zh_CN.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下载完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下载失败" + diff --git a/po/tizen2.3/zh_HK.po b/po/tizen2.3/zh_HK.po new file mode 100644 index 0000000..ef7afd3 --- /dev/null +++ b/po/tizen2.3/zh_HK.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下載完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下載失敗" + diff --git a/po/tizen2.3/zh_TW.po b/po/tizen2.3/zh_TW.po new file mode 100644 index 0000000..ef7afd3 --- /dev/null +++ b/po/tizen2.3/zh_TW.po @@ -0,0 +1,6 @@ +msgid "IDS_DM_HEADER_DOWNLOAD_COMPLETE" +msgstr "下載完成" + +msgid "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB" +msgstr "下載失敗" + diff --git a/provider-interface/CMakeLists.txt b/provider-interface/CMakeLists.txt new file mode 100755 index 0000000..70792e7 --- /dev/null +++ b/provider-interface/CMakeLists.txt @@ -0,0 +1,49 @@ + +## PROJECT NAME +PROJECT(download-provider-interface C) +SET(PACKAGE_DESCRIPTION "Interface supported by download-provider") + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Debug") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +SET(PC_REQUIRED "glib-2.0 gobject-2.0 dlog capi-base-common capi-appfw-app-manager capi-appfw-application bundle") + +INCLUDE(FindPkgConfig) + +pkg_check_modules(provider_interface_pkgs REQUIRED ${PC_REQUIRED}) + +FOREACH(flag ${provider_interface_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +## INCLUDES +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/provider/include) + +SET(PROVIDER_INTERFACE_LINK_LIBRARIES + ${GLIB-2_LIBRARIES} + ${GOBJECT-2_LIBRARIES} + pthread + ) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall") + +ADD_DEFINITIONS(-DDOWNLOAD_PROVIDER_LOG_TAG=\"DOWNLOAD_PROVIDER_INTERFACE\") + +ADD_LIBRARY(${PROJECT_NAME} SHARED + ${CMAKE_SOURCE_DIR}/provider/download-provider-utils.c + ${CMAKE_SOURCE_DIR}/provider/download-provider-ipc.c + ${CMAKE_SOURCE_DIR}/provider/download-provider-pthread.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.c ) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${provider_interface_pkgs_LDFLAGS} ${PROVIDER_INTERFACE_LINK_LIBRARIES}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${PKG_VERSION}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION 0) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}.h DESTINATION ${INCLUDE_INSTALL_DIR}/${PKG_NAME}) +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/provider-interface/download-provider-interface.c b/provider-interface/download-provider-interface.c new file mode 100755 index 0000000..8b0790e --- /dev/null +++ b/provider-interface/download-provider-interface.c @@ -0,0 +1,1560 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include // for notification bundle +#include +#include + +#ifdef SUPPORT_CHECK_IPC +#include +#endif + +#define DP_CHECK_CONNECTION do {\ + int dp_errorcode = __check_connections();\ + if (dp_errorcode != DP_ERROR_NONE) {\ + CLIENT_MUTEX_UNLOCK(&g_function_mutex);\ + return __dp_interface_convert_errorcode(dp_errorcode);\ + }\ +} while(0) + +#define DP_PRE_CHECK_ID do {\ + if (id <= 0) {\ + TRACE_ERROR("[CHECK ID] (%d)", id);\ + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER;\ + }\ +} while(0) + +// define type +typedef struct { + int channel; // query & response + int notify; // event from provider +} dp_interface_ipc; + +typedef struct { + int id; + dp_interface_state_changed_cb state; + void *state_data; + dp_interface_progress_cb progress; + void *progress_data; +} dp_interface_slot; + +// declare the variables +dp_interface_ipc *g_dp_client = NULL; +dp_interface_slot g_interface_slots[MAX_DOWNLOAD_HANDLE]; +static pthread_mutex_t g_function_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_clear_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t g_dp_event_thread_id = 0; + +//////////// defines functions ///////////////// + + +static int __dp_interface_convert_state(int state) +{ + switch (state) { + case DP_STATE_READY: + TRACE_DEBUG("READY"); + return DOWNLOAD_ADPATOR_STATE_READY; + case DP_STATE_CONNECTING: + TRACE_DEBUG("CONNECTING/QUEUED"); + return DOWNLOAD_ADPATOR_STATE_QUEUED; + case DP_STATE_QUEUED: + TRACE_DEBUG("QUEUED"); + return DOWNLOAD_ADPATOR_STATE_QUEUED; + case DP_STATE_DOWNLOADING: + TRACE_DEBUG("DOWNLOADING"); + return DOWNLOAD_ADPATOR_STATE_DOWNLOADING; + case DP_STATE_PAUSED: + TRACE_DEBUG("PAUSED"); + return DOWNLOAD_ADPATOR_STATE_PAUSED; + case DP_STATE_COMPLETED: + TRACE_DEBUG("COMPLETED"); + return DOWNLOAD_ADPATOR_STATE_COMPLETED; + case DP_STATE_CANCELED: + TRACE_DEBUG("CANCELED"); + return DOWNLOAD_ADPATOR_STATE_CANCELED; + case DP_STATE_FAILED: + TRACE_DEBUG("FAILED"); + return DOWNLOAD_ADPATOR_STATE_FAILED; + default: + break; + } + return DOWNLOAD_ADPATOR_STATE_NONE; +} + +static int __dp_interface_convert_errorcode(int errorcode) +{ + switch (errorcode) { + case DP_ERROR_NONE: + return DOWNLOAD_ADAPTOR_ERROR_NONE; + case DP_ERROR_INVALID_PARAMETER: + TRACE_DEBUG("ERROR_INVALID_PARAMETER"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + case DP_ERROR_OUT_OF_MEMORY: + TRACE_DEBUG("ERROR_OUT_OF_MEMORY"); + return DOWNLOAD_ADAPTOR_ERROR_OUT_OF_MEMORY; + case DP_ERROR_IO_EAGAIN: + TRACE_DEBUG("ERROR_IO_ERROR(EAGAIN)"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_IO_EINTR: + TRACE_DEBUG("ERROR_IO_ERROR(EINTR)"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_IO_ERROR: + TRACE_DEBUG("ERROR_IO_ERROR"); + return DOWNLOAD_ADAPTOR_ERROR_IO_ERROR; + case DP_ERROR_NETWORK_UNREACHABLE: + TRACE_DEBUG("ERROR_NETWORK_UNREACHABLE"); + return DOWNLOAD_ADAPTOR_ERROR_NETWORK_UNREACHABLE; + case DP_ERROR_NO_SPACE: + TRACE_DEBUG("ERROR_NO_SPACE"); + return DOWNLOAD_ADAPTOR_ERROR_NO_SPACE; + case DP_ERROR_FIELD_NOT_FOUND: + TRACE_DEBUG("ERROR_FIELD_NOT_FOUND"); + return DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND; + case DP_ERROR_INVALID_STATE: + TRACE_DEBUG("ERROR_INVALID_STATE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_CONNECTION_FAILED: + case DP_ERROR_NETWORK_ERROR: + TRACE_DEBUG("ERROR_CONNECTION_TIMED_OUT/CONNECTION_FAILED"); + return DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT; + case DP_ERROR_INVALID_URL: + TRACE_DEBUG("ERROR_INVALID_URL"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_URL; + case DP_ERROR_INVALID_DESTINATION: + TRACE_DEBUG("ERROR_INVALID_DESTINATION"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION; + case DP_ERROR_PERMISSION_DENIED: + TRACE_DEBUG("ERROR_PERMISSION_DENIED"); + return DOWNLOAD_ADAPTOR_ERROR_PERMISSION_DENIED; + case DP_ERROR_QUEUE_FULL: + TRACE_DEBUG("ERROR_QUEUE_FULL"); + return DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL; + case DP_ERROR_ALREADY_COMPLETED: + TRACE_DEBUG("ERROR_ALREADY_COMPLETED"); + return DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED; + case DP_ERROR_FILE_ALREADY_EXISTS: + TRACE_DEBUG("ERROR_FILE_ALREADY_EXISTS"); + return DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS; + case DP_ERROR_TOO_MANY_DOWNLOADS: + TRACE_DEBUG("ERROR_TOO_MANY_DOWNLOADS"); + return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + case DP_ERROR_NO_DATA: + TRACE_DEBUG("ERROR_NO_DATA"); + return DOWNLOAD_ADAPTOR_ERROR_NO_DATA; + case DP_ERROR_UNHANDLED_HTTP_CODE: + TRACE_DEBUG("ERROR_UNHANDLED_HTTP_CODE"); + return DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE; + case DP_ERROR_CANNOT_RESUME: + TRACE_DEBUG("ERROR_CANNOT_RESUME"); + return DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME; + case DP_ERROR_ID_NOT_FOUND: + TRACE_DEBUG("ERROR_ID_NOT_FOUND"); + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + case DP_ERROR_UNKNOWN: + TRACE_DEBUG("ERROR_INVALID_STATE/UNKNOWN"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE; + case DP_ERROR_INVALID_NETWORK_TYPE: + TRACE_DEBUG("ERROR_INVALID_NETWORK_TYPE"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE; + default: + break; + } + return DOWNLOAD_ADAPTOR_ERROR_NONE; +} + +static int __get_my_slot_index(int id) +{ + int i = 0; + // search same info in array. + for (; i < MAX_DOWNLOAD_HANDLE; i++) + if (g_interface_slots[i].id == id) + return i; + return -1; +} + +static int __get_empty_slot_index() +{ + int i = 0; + for (; i < MAX_DOWNLOAD_HANDLE; i++) + if (g_interface_slots[i].id <= 0) + return i; + return -1; +} + +static int __create_socket() +{ + int sockfd = -1; + struct sockaddr_un clientaddr; + + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + TRACE_STRERROR("[CRITICAL] socket system error"); + return -1; + } + + bzero(&clientaddr, sizeof clientaddr); + clientaddr.sun_family = AF_UNIX; + memset(clientaddr.sun_path, 0x00, sizeof(clientaddr.sun_path)); + strncpy(clientaddr.sun_path, IPC_SOCKET, strlen(IPC_SOCKET)); + clientaddr.sun_path[strlen(IPC_SOCKET)] = '\0'; + if (connect(sockfd, + (struct sockaddr*)&clientaddr, sizeof(clientaddr)) < 0) { + close(sockfd); + if (errno == EACCES || errno == EPERM) { + TRACE_STRERROR("check permission"); + return -DP_ERROR_PERMISSION_DENIED; + } + return -1; + } + TRACE_DEBUG("sockfd [%d]", sockfd); + return sockfd; +} + +static void __clear_interface() +{ + TRACE_DEBUG(""); + CLIENT_MUTEX_LOCK(&g_clear_mutex); + if (g_dp_client != NULL) { + if (g_dp_client->channel >= 0) + close(g_dp_client->channel); + g_dp_client->channel= -1; + if (g_dp_client->notify >= 0) + close(g_dp_client->notify); + g_dp_client->notify = -1; + free(g_dp_client); + g_dp_client = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); +} + +static int __bp_disconnect(const char *funcname) +{ + TRACE_DEBUG("%s", funcname); + if (g_dp_event_thread_id > 0 && + pthread_kill(g_dp_event_thread_id, 0) != ESRCH) { + if (pthread_cancel(g_dp_event_thread_id) != 0) { + TRACE_STRERROR("pthread:%d", (int)g_dp_event_thread_id); + } + g_dp_event_thread_id = 0; + } + __clear_interface(); + return DP_ERROR_NONE; +} + +// listen ASYNC state event, no timeout +static void *__dp_event_manager(void *arg) +{ + if (g_dp_client == NULL) { + TRACE_STRERROR("[CRITICAL] INTERFACE null"); + return 0; + } + + size_t path_size = sizeof(NOTIFY_DIR) + 11; + char notify_fifo[path_size]; + snprintf((char *)¬ify_fifo, path_size,"%s/%d", NOTIFY_DIR, getpid()); + TRACE_DEBUG("IPC ESTABILISH %s", notify_fifo); + g_dp_client->notify = open(notify_fifo, O_RDONLY, 0600); + if (g_dp_client->notify < 0) { + TRACE_STRERROR("[CRITICAL] failed to ESTABILISH IPC %s", notify_fifo); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; + } + + // deferred wait to cancal until next function called. + // ex) function : select, read in this thread + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while(g_dp_client != NULL && g_dp_client->notify >= 0) { + + if (g_dp_event_thread_id <= 0 || + pthread_self() != g_dp_event_thread_id) { + TRACE_ERROR("competitive threads self:%0x global:%0x", + pthread_self(), g_dp_event_thread_id); + // another thread may work. just terminate + break; + } + + // blocking fifo. + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + if (dp_ipc_read(g_dp_client->notify, &eventinfo, + sizeof(dp_ipc_event_fmt), __FUNCTION__) <= 0 || + (eventinfo.id <= 0 && + eventinfo.errorcode == DP_ERROR_CLIENT_DOWN)) { + TRACE_INFO("expelled by provider"); + g_dp_event_thread_id = 0; + CLIENT_MUTEX_LOCK(&g_function_mutex); + __clear_interface(); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return 0; + } + + int index = -1; + if ((index = __get_my_slot_index(eventinfo.id)) < 0) { + TRACE_ERROR("[CRITICAL] not found slot id:%d", eventinfo.id); + continue; + } + + // begin protect callback sections & thread safe + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + + if (eventinfo.state == DP_STATE_DOWNLOADING && + eventinfo.received_size > 0) { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].progress != NULL) { + // progress event + g_interface_slots[index].progress(eventinfo.id, + eventinfo.received_size, + g_interface_slots[index].progress_data); + } + } else { + if (eventinfo.id == g_interface_slots[index].id && + g_interface_slots[index].state != NULL) { + // state event + g_interface_slots[index].state(eventinfo.id, + __dp_interface_convert_state(eventinfo.state), + g_interface_slots[index].state_data); + } + } + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + } // while + + g_dp_event_thread_id = 0; // set 0 to not call pthread_cancel + TRACE_DEBUG("thread end by itself"); + return 0; +} + + + + + + +////////////////// new download-provider /////////////////////////////// +////////////////// created on 7 November, 2013 ///////////////////////// + +#define DP_CHECK_IPC_SOCK (g_dp_client == NULL ? -1 : g_dp_client->channel) + +static void __dp_ipc_clear_garbage(int sock, const size_t length) +{ + if (length > 0) { + char garbage[length]; + if (read(sock, &garbage, length) == 0) { + TRACE_ERROR("sock:%d closed peer", sock); + } + } +} + +static int __dp_ipc_response(int sock, int download_id, short section, + unsigned property, size_t *size) +{ + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL || ipc_info->section != section || + ipc_info->property != property || + (download_id >= 0 && ipc_info->id != download_id)) { + TRACE_STRERROR("socket read ipcinfo"); + free(ipc_info); + return DP_ERROR_IO_ERROR; + } + int errorcode = ipc_info->errorcode; + if (size != NULL) + *size = ipc_info->size; + free(ipc_info); + return errorcode; +} + +static int __connect_to_provider() +{ + int errorcode = DP_ERROR_NONE; + + CLIENT_MUTEX_LOCK(&g_clear_mutex); + + if (g_dp_client == NULL) { + g_dp_client = + (dp_interface_ipc *)calloc(1, sizeof(dp_interface_ipc)); + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + TRACE_ERROR("failed to ignore SIGPIPE signal"); + } + } + + if (g_dp_client != NULL) { + + int connect_retry = 3; + g_dp_client->channel = -1; + while(g_dp_client->channel < 0 && connect_retry-- > 0) { + int ret = __create_socket(); + if (ret == -1) { + TRACE_STRERROR("failed to connect to provider(remains:%d)", connect_retry); + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 20000000; + nanosleep(&ts, NULL); + } else if (ret >= 0) { + struct timeval tv_timeo = { 1, 500000 }; // 1.5 second + g_dp_client->channel = ret; + if (setsockopt(g_dp_client->channel, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo)) < 0) { + TRACE_STRERROR("[CRITICAL] setsockopt SO_RCVTIMEO"); + } + } else { + errorcode = -ret; + TRACE_STRERROR("check error:%d", errorcode); + goto EXIT_CONNECT; + } + } + if (g_dp_client->channel < 0) { + TRACE_STRERROR("[CRITICAL] connect system error"); + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } + + if (dp_ipc_query(g_dp_client->channel, -1, DP_SEC_INIT, + DP_PROP_NONE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } +#ifndef SO_PEERCRED + dp_credential cred; + cred.pid = getpid(); + cred.uid = getuid(); + cred.gid = getgid(); + // send PID. Not support SO_PEERCRED + if (dp_ipc_write(g_dp_client->channel, + &cred, sizeof(dp_credential)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + goto EXIT_CONNECT; + } +#endif + + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + // Commented by justine.bang + // Above ipc_query call try to wake up download-provider. + // But, we can sometimes meet EINTR, EAGAIN or EINPROGRESS signal if systemd is slow. + // So, If meet EINTR ,EAGAIN or EINPROGRESS in this line, it's better to wait response from download-provider one more time. + if (errorcode == DP_ERROR_IO_ERROR && (errno == EINTR || errno == EAGAIN || errno == EINPROGRESS)) { + errorcode = __dp_ipc_response(g_dp_client->channel, + -1, DP_SEC_INIT, DP_PROP_NONE, NULL); + } + + if (errorcode == DP_ERROR_NONE && g_dp_event_thread_id <= 0) { + if (pthread_create(&g_dp_event_thread_id, NULL, + __dp_event_manager, g_dp_client) != 0) { + TRACE_STRERROR("failed to create event-manager"); + errorcode = DP_ERROR_IO_ERROR; + } else { + pthread_detach(g_dp_event_thread_id); + } + } + + } + +EXIT_CONNECT: + CLIENT_MUTEX_UNLOCK(&g_clear_mutex); + if (errorcode != DP_ERROR_NONE) + __bp_disconnect(__FUNCTION__); + + return errorcode; +} + +static dp_error_type __check_connections() +{ + int ret = 0; + + if (g_dp_client == NULL) + if ((ret = __connect_to_provider()) != DP_ERROR_NONE) + return ret; + + if (g_dp_client == NULL || g_dp_client->channel < 0) { + TRACE_ERROR("[CHECK IPC]"); + return DP_ERROR_IO_ERROR; + } + return DP_ERROR_NONE; +} + +static int __dp_ipc_set_binary(const int id, const unsigned property, + const bundle_raw *string, const size_t length, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + if (string == NULL || length <= 0) { + TRACE_ERROR("%s check binary (%d)", funcname, length); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_SET, property, DP_ERROR_NONE, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(unsigned char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, DP_SEC_SET, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +static int __dp_ipc_set_string(const int id, const short section, const unsigned property, + const char *string, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (string == NULL || (length = strlen(string)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("%s check string (%d:%s)", funcname, length, string); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void*)string, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +static int __dp_ipc_get_string(const int id, const unsigned property, + char **string, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + if (string == NULL) { + TRACE_ERROR("%s check buffer", funcname); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t string_length = 0; + *string = NULL; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, funcname) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command and int & return errorcode +static int __dp_ipc_set_int(const int id, const unsigned section, const unsigned property, + const int value, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + if (dp_ipc_write(sock, (void *)&value, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command & return errorcode and int +static int __dp_ipc_get_int(const int id, const unsigned property, + int *value, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + if (value == NULL) { + TRACE_ERROR("%s check buffer", funcname); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, value, extra_size, funcname) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +// send command & return errorcode. +int __dp_ipc_echo(const int id, const short section, + const unsigned property, const char *funcname) +{ + int errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", funcname, sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(funcname); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +/////////////////////// APIs ///////////////////////////////// + +int dp_interface_create(int *id) +{ + int errorcode = DP_ERROR_NONE; + int index = -1; + + if (id == NULL) { + TRACE_ERROR("[CHECK id variable]"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + CLIENT_MUTEX_LOCK(&g_function_mutex); + + if ((index = __get_empty_slot_index()) < 0) { + TRACE_ERROR + ("[ERROR] TOO_MANY_DOWNLOADS[%d]", MAX_DOWNLOAD_HANDLE); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + + DP_CHECK_CONNECTION; + + dp_ipc_fmt *ipc_info = NULL; + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, -1, DP_SEC_CONTROL, DP_PROP_CREATE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + ipc_info = dp_ipc_get_fmt(sock); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] IPC INFO is NULL"); + errorcode = DP_ERROR_IO_ERROR; + } else if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE || + ipc_info->size != 0) { + TRACE_ERROR("sock:%d id:%d section:%d property:%d size:%d", + sock, ipc_info->id, ipc_info->section, ipc_info->property, + ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("download_id:%d", ipc_info->id); + if (errorcode == DP_ERROR_NONE && ipc_info->id > 0) { + *id = ipc_info->id; + g_interface_slots[index].id = ipc_info->id; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + } + } + free(ipc_info); + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_destroy(const int id) +{ + int index = -1; + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + if ((index = __get_my_slot_index(id)) >= 0) { + g_interface_slots[index].id = 0; + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_DESTROY, __FUNCTION__); +} + +int dp_interface_start(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_START, __FUNCTION__); +} + +int dp_interface_pause(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_PAUSE, __FUNCTION__); +} + +int dp_interface_cancel(const int id) +{ + return __dp_ipc_echo(id, DP_SEC_CONTROL, DP_PROP_CANCEL, __FUNCTION__); +} + +int dp_interface_set_url(const int id, const char *url) +{ + if (url == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_URL, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_URL, url, __FUNCTION__); +} + +int dp_interface_get_url(const int id, char **url) +{ + return __dp_ipc_get_string(id, DP_PROP_URL, url, __FUNCTION__); +} + +int dp_interface_set_destination(const int id, const char *path) +{ + if (path == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_DESTINATION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_DESTINATION, path, __FUNCTION__); +} + +int dp_interface_get_destination(const int id, char **path) +{ + return __dp_ipc_get_string(id, DP_PROP_DESTINATION, path, __FUNCTION__); +} + +int dp_interface_set_file_name(const int id, const char *file_name) +{ + if (file_name == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_FILENAME, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_FILENAME, file_name, __FUNCTION__); +} + +int dp_interface_get_file_name(const int id, char **file_name) +{ + return __dp_ipc_get_string(id, DP_PROP_FILENAME, file_name, __FUNCTION__); +} + +int dp_interface_get_downloaded_file_path(const int id, char **path) +{ + return __dp_ipc_get_string(id, DP_PROP_SAVED_PATH, path, __FUNCTION__); +} + +int dp_interface_get_temp_path(const int id, char **temp_path) +{ + return __dp_ipc_get_string(id, DP_PROP_TEMP_SAVED_PATH, temp_path, __FUNCTION__); +} + +int dp_interface_get_content_name(const int id, char **content_name) +{ + return __dp_ipc_get_string(id, DP_PROP_CONTENT_NAME, content_name, __FUNCTION__); +} + +int dp_interface_get_etag(const int id, char **etag) +{ + return __dp_ipc_get_string(id, DP_PROP_ETAG, etag, __FUNCTION__); +} + +int dp_interface_set_temp_file_path(const int id, const char *path) +{ + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_TEMP_SAVED_PATH, path, __FUNCTION__); +} + +int dp_interface_set_network_type(const int id, int net_type) +{ + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_TYPE, + net_type, __FUNCTION__); +} + +int dp_interface_get_network_type(const int id, int *net_type) +{ + if (net_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NETWORK_TYPE, net_type, __FUNCTION__); +} + +int dp_interface_get_network_bonding(const int id, int *enable) +{ + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NETWORK_BONDING, enable, __FUNCTION__); +} + +int dp_interface_set_network_bonding(const int id, int enable) +{ + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NETWORK_BONDING, + enable, __FUNCTION__); +} + +int dp_interface_set_state_changed_cb(const int id, + dp_interface_state_changed_cb callback, void *user_data) +{ + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_STATE_CALLBACK, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index < 0) { + index = __get_empty_slot_index(); + if (index >= 0) { + g_interface_slots[index].id = id; + } else { + TRACE_ERROR("too many download limit:%d", + MAX_DOWNLOAD_HANDLE); + errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + } + if (index >= 0) { + g_interface_slots[index].state = callback; + g_interface_slots[index].state_data = user_data; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + } + return errorcode; +} + +int dp_interface_unset_state_changed_cb(const int id) +{ + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].state = NULL; + g_interface_slots[index].state_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_STATE_CALLBACK, __FUNCTION__); +} + +int dp_interface_set_progress_cb(const int id, + dp_interface_progress_cb callback, void *user_data) +{ + int errorcode = __dp_ipc_echo(id, DP_SEC_SET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index < 0) { + index = __get_empty_slot_index(); + if (index >= 0) { + g_interface_slots[index].id = id; + } else { + TRACE_ERROR("too many download limit:%d", + MAX_DOWNLOAD_HANDLE); + errorcode = DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS; + } + } + if (index >= 0) { + g_interface_slots[index].progress = callback; + g_interface_slots[index].progress_data = user_data; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + } + return errorcode; +} + +int dp_interface_unset_progress_cb(const int id) +{ + CLIENT_MUTEX_LOCK(&g_function_mutex); + int index = __get_my_slot_index(id); + if (index >= 0) { + g_interface_slots[index].progress = NULL; + g_interface_slots[index].progress_data = NULL; + } + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + if (index < 0) + return DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND; + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_PROGRESS_CALLBACK, __FUNCTION__); +} + +int dp_interface_get_state(const int id, int *state) +{ + if (state == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int dp_state = DP_STATE_NONE; + int errorcode = __dp_ipc_get_int(id, DP_PROP_STATE, &dp_state, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) + *state = __dp_interface_convert_state(dp_state); + return errorcode; +} + +int dp_interface_get_content_size(const int id, + unsigned long long *content_size) +{ + int errorcode = DP_ERROR_NONE; + + if (content_size == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("%s check ipc sock:%d", __FUNCTION__, sock); + } else { + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, DP_SEC_GET, DP_PROP_TOTAL_FILE_SIZE, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(unsigned long long)) { + if (dp_ipc_read(sock, content_size, extra_size, __FUNCTION__) < 0) + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_mime_type(const int id, char **mime_type) +{ + if (mime_type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_MIME_TYPE, mime_type, + __FUNCTION__); +} + +int dp_interface_set_auto_download(const int id, int enable) +{ + short section = DP_SEC_SET; + if (enable <= 0) + section = DP_SEC_UNSET; + return __dp_ipc_echo(id, section, DP_PROP_AUTO_DOWNLOAD, __FUNCTION__); +} + +int dp_interface_get_auto_download(const int id, int *enable) +{ + if (enable == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_AUTO_DOWNLOAD, enable, __FUNCTION__); +} + +int dp_interface_get_error(const int id, int *error) +{ + if (error == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DP_ERROR_NONE; + int ret = __dp_ipc_get_int(id, DP_PROP_ERROR, &errorcode, __FUNCTION__); + if (ret == DOWNLOAD_ADAPTOR_ERROR_NONE) + *error = __dp_interface_convert_errorcode(errorcode); + return ret; +} + +int dp_interface_get_http_status(const int id, int *http_status) +{ + if (http_status == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_HTTP_STATUS, http_status, + __FUNCTION__); +} + +int dp_interface_set_notification_title(const int id, const char *title) +{ + if (title == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_SUBJECT, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} + +int dp_interface_get_notification_title(const int id, char **title) +{ + if (title == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_SUBJECT, title, __FUNCTION__); +} + +int dp_interface_set_notification_description(const int id, const char *description) +{ + if (description == NULL) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_DESCRIPTION, __FUNCTION__); + return __dp_ipc_set_string(id, DP_SEC_SET, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); +} + +int dp_interface_get_notification_description(const int id, char **description) +{ + if (description == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_string(id, DP_PROP_NOTIFICATION_DESCRIPTION, description, __FUNCTION__); +} + +int dp_interface_set_notification_type(const int id, int type) +{ + if (type == DP_NOTIFICATION_TYPE_NONE) + return __dp_ipc_echo(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_TYPE, __FUNCTION__); + return __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_get_notification_type(const int id, int *type) +{ + if (type == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + return __dp_ipc_get_int(id, DP_PROP_NOTIFICATION_TYPE, type, __FUNCTION__); +} + +int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (bundle_param == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + int result = bundle_encode_raw(bundle_param, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + } + return errorcode; +} + +int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param) +{ + if (bundle_param == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_BUNDLE_TYPE_ONGOING && + type != DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE && + type != DP_NOTIFICATION_BUNDLE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + *bundle_param = bundle_decode_raw(recv_raws, extra_size); + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_set_notification_service_handle(const int id, const int type, void *handle) +{ + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + if (handle == NULL) { // unset + return __dp_ipc_set_int(id, DP_SEC_UNSET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + } else { // set + int length = 0; + bundle_raw *raw_buffer = NULL; + bundle *bundle_data = NULL; + int result = app_control_export_as_bundle((app_control_h) handle, &bundle_data); + if (result == APP_CONTROL_ERROR_NONE) { + result = bundle_encode_raw(bundle_data, &raw_buffer, &length); + if (result == 0 && length > 0) { + errorcode = __dp_ipc_set_int(id, DP_SEC_SET, DP_PROP_NOTIFICATION_RAW, type, __FUNCTION__); + if (errorcode == DOWNLOAD_ADAPTOR_ERROR_NONE) { + errorcode = __dp_ipc_set_binary(id, DP_PROP_NOTIFICATION_RAW, raw_buffer, (size_t)length, __FUNCTION__); + } + } else { + TRACE_ERROR("failed to encode raws error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to encode service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (raw_buffer != NULL) + bundle_free_encoded_rawdata(&raw_buffer); + if (bundle_data != NULL) + bundle_free(bundle_data); + } + return errorcode; +} + +int dp_interface_get_notification_service_handle(const int id, const int type, void **handle) +{ + bundle *bundle_data = NULL; + if (handle == NULL) { + TRACE_ERROR("check buffer"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + int errorcode = DOWNLOAD_ADAPTOR_ERROR_NONE; + if (type != DP_NOTIFICATION_SERVICE_TYPE_ONGOING && + type != DP_NOTIFICATION_SERVICE_TYPE_COMPLETE && + type != DP_NOTIFICATION_SERVICE_TYPE_FAILED) { + TRACE_ERROR("check type:%d id:%d", type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + return errorcode; + } + + // send type, get errorcode with extra_size, get bundle binary + + errorcode = DP_ERROR_NONE; + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + const unsigned section = DP_SEC_GET; + const unsigned property = DP_PROP_NOTIFICATION_RAW; + size_t extra_size = 0; + + int sock = DP_CHECK_IPC_SOCK; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void *)&type, sizeof(int)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + } + } + if (errorcode == DP_ERROR_NONE && extra_size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(extra_size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, extra_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, extra_size); + } else { + if (dp_ipc_read(sock, recv_raws, extra_size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_raws); + } else { + TRACE_DEBUG("sock:%d length:%d raws", sock, extra_size); + + bundle_data = bundle_decode_raw(recv_raws, extra_size); + if (bundle_data) { + int result = 0; + result = app_control_create((app_control_h *)handle); + if (result == APP_CONTROL_ERROR_NONE) { + result = app_control_import_from_bundle((app_control_h)*handle, bundle_data); + if (result != APP_CONTROL_ERROR_NONE) { + TRACE_ERROR("failed to import service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + } else { + TRACE_ERROR("failed to create service handle error:%d type:%d id:%d", result, type, id); + errorcode = DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + bundle_free(bundle_data); + } + free(recv_raws); + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_add_http_header_field(const int id, const char *field, + const char *value) +{ + // cmd + field string + value string + // wait response + int errorcode = DP_ERROR_NONE; + size_t field_length = 0; + size_t value_length = 0; + if (field == NULL || (field_length = strlen(field)) <= 0 || + field_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", field_length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL || (value_length = strlen(value)) <= 0 || + value_length > DP_MAX_STR_LEN) { + TRACE_ERROR("check value (%d:%s)", value_length, value); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_SET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, field_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + if (errorcode == DP_ERROR_NONE) { + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)value, value_length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + errorcode = __dp_ipc_response(sock, id, section, property, NULL); + } + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_http_header_field(const int id, const char *field, + char **value) +{ + // cmd + field string + // wait response + value string + int errorcode = DP_ERROR_NONE; + size_t length = 0; + if (field == NULL || (length = strlen(field)) <= 0 || + length > DP_MAX_STR_LEN) { + TRACE_ERROR("check field (%d:%s)", length, field); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (value == NULL) { + TRACE_ERROR("check pointer for value"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADER; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + if (dp_ipc_write(sock, (void*)field, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + size_t string_length = 0; + *value = NULL; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + if (errorcode == DP_ERROR_NONE) { + if (string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length); + errorcode = DP_ERROR_OUT_OF_MEMORY; + __dp_ipc_clear_garbage(sock, string_length); + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + *value = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + } + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_get_http_header_field_list(const int id, char ***fields, + int *length) +{ + // cmd + // wait response + // wait size + // wait strings + int errorcode = DP_ERROR_NONE; + if (fields == NULL) { + TRACE_ERROR("check pointer for fields"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + if (length == NULL) { + TRACE_ERROR("check pointer for length"); + return DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER; + } + + DP_PRE_CHECK_ID; + CLIENT_MUTEX_LOCK(&g_function_mutex); + DP_CHECK_CONNECTION; + + int sock = DP_CHECK_IPC_SOCK; + short section = DP_SEC_GET; + unsigned property = DP_PROP_HTTP_HEADERS; + if (dp_ipc_query(sock, id, section, property, DP_ERROR_NONE, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", sock); + } else { + + int array_size = 0; + size_t extra_size = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &extra_size); + if (errorcode == DP_ERROR_NONE) { + if (extra_size == sizeof(int)) { + if (dp_ipc_read(sock, &array_size, extra_size, __FUNCTION__) < 0) { + errorcode = DP_ERROR_IO_ERROR; + } else { + if (array_size <= 0) { + errorcode = DP_ERROR_NO_DATA; + *length = 0; + } else { + int i = 0; + char **recv_strings = NULL; + recv_strings = (char **)calloc(array_size, sizeof(char *)); + if (recv_strings == NULL) { + TRACE_STRERROR("check memory size:%d", array_size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + *length = 0; + } else { + // get strings. + for (; i < array_size; i++) { + size_t string_length = 0; + errorcode = __dp_ipc_response(sock, id, section, property, &string_length); + recv_strings[i] = NULL; + if (errorcode == DP_ERROR_NONE && string_length > 0) { + char *recv_str = (char *)calloc((string_length + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("check memory length:%d", string_length * sizeof(char)); + errorcode = DP_ERROR_OUT_OF_MEMORY; + break; + } else { + if (dp_ipc_read(sock, recv_str, string_length, __FUNCTION__) <= 0) { + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[string_length] = '\0'; + recv_strings[i] = recv_str; + } + } + } + } + *fields = recv_strings; + } + if (errorcode != DP_ERROR_NONE) { // if error, free all allocated memories + int j = 0; + for (; j < i; j++) { + free(recv_strings[j]); + } + free(recv_strings); + *length = 0; + *fields = NULL; + if (errorcode != DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); // clear IPC, can not expect the size of futher packets + } + *length = i; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + } + + + } + if (errorcode == DP_ERROR_IO_ERROR) + __bp_disconnect(__FUNCTION__); + CLIENT_MUTEX_UNLOCK(&g_function_mutex); + return __dp_interface_convert_errorcode(errorcode); +} + +int dp_interface_remove_http_header_field(const int id, + const char *field) +{ + return __dp_ipc_set_string(id, DP_SEC_UNSET, DP_PROP_HTTP_HEADER, field, __FUNCTION__); +} diff --git a/provider-interface/download-provider-interface.pc.in b/provider-interface/download-provider-interface.pc.in new file mode 100644 index 0000000..35e1cc9 --- /dev/null +++ b/provider-interface/download-provider-interface.pc.in @@ -0,0 +1,8 @@ +# Package Information + +Name: @PROJECT_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L/usr/lib -l@PROJECT_NAME@ +Cflags: -I/usr/include/@PKG_NAME@ diff --git a/provider-interface/include/download-provider-interface.h b/provider-interface/include/download-provider-interface.h new file mode 100755 index 0000000..e9d3d59 --- /dev/null +++ b/provider-interface/include/download-provider-interface.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DOWNLOAD_PROVIDER_INTERFACE_H__ +#define __DOWNLOAD_PROVIDER_INTERFACE_H__ + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +// sync with url-download +typedef enum +{ + DOWNLOAD_ADPATOR_STATE_NONE, + DOWNLOAD_ADPATOR_STATE_READY, + DOWNLOAD_ADPATOR_STATE_QUEUED, + DOWNLOAD_ADPATOR_STATE_DOWNLOADING, + DOWNLOAD_ADPATOR_STATE_PAUSED, + DOWNLOAD_ADPATOR_STATE_COMPLETED, + DOWNLOAD_ADPATOR_STATE_FAILED, + DOWNLOAD_ADPATOR_STATE_CANCELED, +} download_adaptor_state_e; + +typedef enum +{ + DOWNLOAD_ADAPTOR_NETWORK_DATA_NETWORK, + DOWNLOAD_ADAPTOR_NETWORK_WIFI, + DOWNLOAD_ADAPTOR_NETWORK_WIFI_DIRECT, + DOWNLOAD_ADAPTOR_NETWORK_ALL +} download_adaptor_network_type_e ; + +typedef enum +{ + DOWNLOAD_ADAPTOR_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + DOWNLOAD_ADAPTOR_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + DOWNLOAD_ADAPTOR_ERROR_NETWORK_UNREACHABLE = TIZEN_ERROR_NETWORK_UNREACHABLE, /**< Network is unreachable */ + DOWNLOAD_ADAPTOR_ERROR_CONNECTION_TIMED_OUT = TIZEN_ERROR_CONNECTION_TIME_OUT, /**< Http session time-out */ + DOWNLOAD_ADAPTOR_ERROR_NO_SPACE = TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE, /**< No space left on device */ + DOWNLOAD_ADAPTOR_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ + DOWNLOAD_ADAPTOR_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_STATE = TIZEN_ERROR_DOWNLOAD | 0x21, /**< Invalid state */ + DOWNLOAD_ADAPTOR_ERROR_CONNECTION_FAILED = TIZEN_ERROR_DOWNLOAD | 0x22, /**< Connection failed */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_URL = TIZEN_ERROR_DOWNLOAD | 0x24, /**< Invalid URL */ + DOWNLOAD_ADAPTOR_ERROR_INVALID_DESTINATION = TIZEN_ERROR_DOWNLOAD | 0x25, /**< Invalid destination */ + DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_DOWNLOADS = TIZEN_ERROR_DOWNLOAD | 0x26, /**< Full of available simultaneous downloads */ + DOWNLOAD_ADAPTOR_ERROR_QUEUE_FULL = TIZEN_ERROR_DOWNLOAD | 0x27, /**< Full of available downloading items from server*/ + DOWNLOAD_ADAPTOR_ERROR_ALREADY_COMPLETED = TIZEN_ERROR_DOWNLOAD | 0x28, /**< The download is already completed */ + DOWNLOAD_ADAPTOR_ERROR_FILE_ALREADY_EXISTS = TIZEN_ERROR_DOWNLOAD | 0x29, /**< It is failed to rename the downloaded file */ + DOWNLOAD_ADAPTOR_ERROR_CANNOT_RESUME = TIZEN_ERROR_DOWNLOAD | 0x2a, /**< It cannot resume */ + DOWNLOAD_ADAPTOR_ERROR_FIELD_NOT_FOUND = TIZEN_ERROR_DOWNLOAD | 0x2b, /**< Specified field not found */ + DOWNLOAD_ADAPTOR_ERROR_TOO_MANY_REDIRECTS = TIZEN_ERROR_DOWNLOAD | 0x30, /**< In case of too may redirects from http response header*/ + DOWNLOAD_ADAPTOR_ERROR_UNHANDLED_HTTP_CODE = TIZEN_ERROR_DOWNLOAD | 0x31, /**< The download cannot handle the http status value */ + DOWNLOAD_ADAPTOR_ERROR_REQUEST_TIMEOUT = TIZEN_ERROR_DOWNLOAD | 0x32, /**< There are no action after client create a download id*/ + DOWNLOAD_ADAPTOR_ERROR_RESPONSE_TIMEOUT = TIZEN_ERROR_DOWNLOAD | 0x33, /**< It does not call start API in some time although the download is created*/ + DOWNLOAD_ADAPTOR_ERROR_SYSTEM_DOWN = TIZEN_ERROR_DOWNLOAD | 0x34, /**< There are no response from client after rebooting download daemon*/ + DOWNLOAD_ADAPTOR_ERROR_ID_NOT_FOUND = TIZEN_ERROR_DOWNLOAD | 0x35, /**< The download id is not existed in download service module*/ + DOWNLOAD_ADAPTOR_ERROR_INVALID_NETWORK_TYPE = TIZEN_ERROR_DOWNLOAD | 0x36, /**< error when setting network bonding and network all is not set */ + DOWNLOAD_ADAPTOR_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data because the set API is not called */ + DOWNLOAD_ADAPTOR_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR /**< Internal I/O error */ +} download_adaptor_error_e; + +// sync types with url-download.. +typedef void (*dp_interface_state_changed_cb) (int id, int state, void *user_data); +typedef void (*dp_interface_progress_cb) (int id, unsigned long long received, void *user_data); + +EXPORT_API int dp_interface_set_state_changed_cb + (const int id, dp_interface_state_changed_cb callback, void *user_data); +EXPORT_API int dp_interface_unset_state_changed_cb(int id); +EXPORT_API int dp_interface_set_progress_cb + (const int id, dp_interface_progress_cb callback, void *user_data); +EXPORT_API int dp_interface_unset_progress_cb(const int id); + +EXPORT_API int dp_interface_create(int *id); +EXPORT_API int dp_interface_destroy(const int id); + +EXPORT_API int dp_interface_start(const int id); +EXPORT_API int dp_interface_pause(const int id); +EXPORT_API int dp_interface_cancel(const int id); + +EXPORT_API int dp_interface_set_url(const int id, const char *url); +EXPORT_API int dp_interface_set_destination(const int id, const char *path); +EXPORT_API int dp_interface_set_file_name(const int id, const char *file_name); +EXPORT_API int dp_interface_set_network_type(const int id, int net_type); +EXPORT_API int dp_interface_set_network_bonding(const int id, int enable); +EXPORT_API int dp_interface_set_auto_download(const int id, int enable); +EXPORT_API int dp_interface_get_url(const int id, char **url); +EXPORT_API int dp_interface_get_network_type(const int id, int *net_type); +EXPORT_API int dp_interface_get_network_bonding(const int id, int *enable); +EXPORT_API int dp_interface_get_destination(const int id, char **path); +EXPORT_API int dp_interface_get_file_name(const int id, char **file_name); +EXPORT_API int dp_interface_get_downloaded_file_path(const int id, char **path); +EXPORT_API int dp_interface_get_mime_type(const int id, char **mime_type); +EXPORT_API int dp_interface_get_auto_download(const int id, int *enable); +EXPORT_API int dp_interface_get_state(const int id, int *state); +EXPORT_API int dp_interface_get_temp_path(const int id, char **temp_path); +EXPORT_API int dp_interface_get_content_name(const int id, char **content_name); +EXPORT_API int dp_interface_get_content_size(const int id, unsigned long long *content_size); +EXPORT_API int dp_interface_get_error(const int id, int *error); +EXPORT_API int dp_interface_get_http_status(const int id, int *http_status); +EXPORT_API int dp_interface_get_etag(const int id, char **etag); +EXPORT_API int dp_interface_set_temp_file_path(const int id, const char *path); + +EXPORT_API int dp_interface_add_http_header_field(const int id, const char *field, const char *value); +EXPORT_API int dp_interface_get_http_header_field(const int id, const char *field, char **value); +EXPORT_API int dp_interface_get_http_header_field_list(const int id, char ***fields, int *length); +EXPORT_API int dp_interface_remove_http_header_field(const int id, const char *field); + +EXPORT_API int dp_interface_set_notification_bundle(const int id, const int type, void *bundle_param); +EXPORT_API int dp_interface_get_notification_bundle(const int id, const int type, void **bundle_param); +EXPORT_API int dp_interface_set_notification_service_handle(const int id, const int type, void *handle); +EXPORT_API int dp_interface_get_notification_service_handle(const int id, const int type, void **handle); +EXPORT_API int dp_interface_set_notification_title(const int id, const char *title); +EXPORT_API int dp_interface_get_notification_title(const int id, char **title); +EXPORT_API int dp_interface_set_notification_description(const int id, const char *description); +EXPORT_API int dp_interface_get_notification_description(const int id, char **description); +EXPORT_API int dp_interface_set_notification_type(const int id, int type); +EXPORT_API int dp_interface_get_notification_type(const int id, int *type); +#ifdef __cplusplus +} +#endif + +#endif /* __DOWNLOAD_PROVIDER_INTERFACE_H__ */ diff --git a/provider/CMakeLists.txt b/provider/CMakeLists.txt new file mode 100755 index 0000000..c4060c8 --- /dev/null +++ b/provider/CMakeLists.txt @@ -0,0 +1,122 @@ + +## PROJECT NAME +PROJECT(${PKG_NAME} C) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Debug") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE(FindPkgConfig) + +pkg_check_modules(dp2_pkgs REQUIRED glib-2.0 + gobject-2.0 + sqlite3 + capi-appfw-app-manager + capi-network-connection + capi-content-mime-type + appsvc + bundle + libsmack + dlog + libsystemd-daemon) + +FOREACH(flag ${dp2_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +IF(SUPPORT_WIFI_DIRECT) +MESSAGE("WIFI direct:On") +pkg_check_modules(dp2_wifi_direct_pkgs REQUIRED + capi-network-wifi-direct) +FOREACH(flag ${dp2_wifi_direct_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ELSE (SUPPORT_WIFI_DIRECT) +MESSAGE("WIFI direct:Off") +ENDIF(SUPPORT_WIFI_DIRECT) + +IF(SUPPORT_SECURITY_PRIVILEGE) +pkg_check_modules(dp2_security_privilege_pkgs REQUIRED security-server) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${dp2_security_privilege_pkgs_CFLAGS}") +ENDIF(SUPPORT_SECURITY_PRIVILEGE) + +IF(SUPPORT_NOTIFICATION) +MESSAGE("Notification:On") +pkg_check_modules(dp2_noti_pkgs REQUIRED + notification) +FOREACH(flag ${dp2_noti_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ADD_DEFINITIONS(-DSUPPORT_NOTIFICATION) +ELSE (SUPPORT_NOTIFICATION) +MESSAGE("Notification:Off") +ENDIF(SUPPORT_NOTIFICATION) + +IF(SUPPORT_COMPANION_MODE) +MESSAGE("Companion:On") +pkg_check_modules(dp2_companion_pkgs REQUIRED + sap-client-stub-api) +FOREACH(flag ${dp2_companion_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +ADD_DEFINITIONS(-DSUPPORT_COMPANION_MODE) +ELSE (SUPPORT_COMPANION_MODE) +MESSAGE("Companion:Off") +ENDIF(SUPPORT_COMPANION_MODE) + +## INCLUDES +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/agent/include) + +set(DP2_LINK_LIBRARIES ${GLIB-2_LIBRARIES} + ${GOBJECT-2_LIBRARIES} + pthread + capi-appfw-app-manager + ) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -Wall -fPIE") + +IF(DEFINED IMAGE_DIR) + ADD_DEFINITIONS(-DIMAGE_DIR=\"${IMAGE_DIR}\") +ENDIF(DEFINED IMAGE_DIR) + +IF(DEFINED PROVIDER_DIR) + ADD_DEFINITIONS(-DPROVIDER_DIR=\"${PROVIDER_DIR}\") +ENDIF(DEFINED PROVIDER_DIR) + +IF(DEFINED DATABASE_CLIENT_DIR) + ADD_DEFINITIONS(-DDATABASE_CLIENT_DIR=\"${DATABASE_CLIENT_DIR}\") +ENDIF(DEFINED DATABASE_CLIENT_DIR) + +IF(DEFINED DATABASE_DIR) + ADD_DEFINITIONS(-DDATABASE_DIR=\"${DATABASE_DIR}\") +ENDIF(DEFINED DATABASE_DIR) + +IF(DEFINED LOCALE_DIR) + ADD_DEFINITIONS(-DPKG_NAME=\"${PKG_NAME}\") + ADD_DEFINITIONS(-DLOCALE_DIR=\"${LOCALE_DIR}\") +ENDIF(DEFINED LOCALE_DIR) + +ADD_DEFINITIONS(-DDOWNLOAD_PROVIDER_LOG_TAG=\"DOWNLOAD_PROVIDER\") + +ADD_EXECUTABLE(${PROJECT_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-pthread.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-ipc.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-utils.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notify.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-smack.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-network.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-db.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-plugin-download-agent.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-queue.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-queue-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-client.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-client-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification-manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-main.c ) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dp2_pkgs_LDFLAGS} ${DP2_LINK_LIBRARIES} ${dp2_noti_pkgs_LDFLAGS} ${dp2_companion_pkgs_LDFLAGS} ${dp2_wifi_direct_pkgs_LDFLAGS} ${dp2_security_privilege_pkgs_LDFLAGS} -ldl -pie) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BIN_INSTALL_DIR}) + +INSTALL(FILES include/download-provider.h DESTINATION ${INCLUDE_INSTALL_DIR}/${PKG_NAME}) diff --git a/provider/download-provider-client-manager.c b/provider/download-provider-client-manager.c new file mode 100644 index 0000000..28ecaf3 --- /dev/null +++ b/provider/download-provider-client-manager.c @@ -0,0 +1,741 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int g_dp_sock = -1; +dp_client_slots_fmt *g_dp_client_slots = NULL; +static void *g_db_handle = 0; +static pthread_mutex_t g_db_mutex = PTHREAD_MUTEX_INITIALIZER; + +void dp_terminate(int signo) +{ + TRACE_DEBUG("Received SIGTERM:%d", signo); + close(g_dp_sock); + g_dp_sock = -1; +} + +void dp_broadcast_signal() +{ + TRACE_INFO("broadcast"); + // announce to all thread for clients + // signo 10 : ip changed + if (g_dp_client_slots != NULL) { + int i = 0; + for (; i < DP_MAX_CLIENTS; i++) { + if (g_dp_client_slots[i].thread > 0 && + pthread_kill(g_dp_client_slots[i].thread, 0) != ESRCH) + pthread_kill(g_dp_client_slots[i].thread, SIGUSR1); + } + } + +} + +char *dp_db_get_client_smack_label(const char *pkgname) +{ + char *smack_label = NULL; + unsigned length = 0; + int errorcode = DP_ERROR_NONE; + + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_get_client_property_string(g_db_handle, pkgname, DP_DB_COL_SMACK_LABEL, (unsigned char **)&smack_label, &length, &errorcode) < 0) { + TRACE_SECURE_ERROR("failed to get smack label for %s", pkgname); + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + + return smack_label; +} + +static int __dp_db_open_client_manager() +{ + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_open_client_manager(&g_db_handle) < 0) { + TRACE_ERROR("[CRITICAL] can not open SQL"); + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + return -1; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + return 0; +} + +static void __dp_db_free_client_manager() +{ + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (g_db_handle != 0) { + TRACE_SECURE_DEBUG("TRY to close [%s]", DP_DBFILE_CLIENTS); + dp_db_close(g_db_handle); + g_db_handle = 0; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); +} + +static int __dp_accept_socket_new() +{ + int fd_base, listen_fds = sd_listen_fds(1); + TRACE_DEBUG("sd_listen_fds:%d", listen_fds); + for (fd_base = 0 ; fd_base < listen_fds; fd_base++) { + if (sd_is_socket_unix(fd_base + SD_LISTEN_FDS_START, SOCK_STREAM, 1, IPC_SOCKET, 0) >= 0) { + TRACE_INFO("listen systemd socket:%d", fd_base + SD_LISTEN_FDS_START); + return fd_base + SD_LISTEN_FDS_START; + } + } + return -1; +} + +int dp_client_slot_free(dp_client_slots_fmt *slot) +{ + if (slot->client.channel >= 0) { + close(slot->client.channel); + slot->client.channel = -1; + } + if (slot->client.dbhandle != 0) { + dp_db_close(slot->client.dbhandle); + slot->client.dbhandle = 0; + } + // free all requests + // remove notify fifo + if (slot->client.notify >= 0) { + close(slot->client.notify); + slot->client.notify = -1; + } + dp_notify_deinit(slot->credential.pid); + // kill thread + if (slot->thread != 0) + pthread_cancel(slot->thread); + slot->thread = 0; + if (slot->pkgname != NULL) { + TRACE_SECURE_DEBUG("TRY to close [%s]", slot->pkgname); + free(slot->pkgname); + slot->pkgname = NULL; + } + return 0; +} + +// precondition : all slots are empty +static int __dp_manage_client_requests(dp_client_slots_fmt *clients) +{ + int errorcode = DP_ERROR_NONE; + int i = 0; + int slot_index = 0; + + dp_notification_manager_kill(); + dp_queue_manager_kill(); + + // get all clients info from clients database. + + int *ids = (int *)calloc(DP_MAX_CLIENTS, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + return -1; + } + // getting ids of clients + int rows_count = dp_db_get_ids(g_db_handle, DP_TABLE_CLIENTS, NULL, ids, NULL, DP_MAX_CLIENTS, DP_DB_COL_ACCESS_TIME, "ASC", &errorcode); + for (; i < rows_count; i++) { + char *pkgname = NULL; + unsigned length = 0; + errorcode = DP_ERROR_NONE; + if (dp_db_get_property_string(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE, (unsigned char **)&pkgname, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get pkgname for id:%d", ids[i]); + continue; + } + + if (pkgname != NULL) { + if (dp_db_remove_database(pkgname, time(NULL), DP_CARE_CLIENT_INFO_PERIOD * 3600) == 0) { // old database + // remove info from client database; + if (dp_db_delete(g_db_handle, ids[i], DP_TABLE_CLIENTS, &errorcode) == 0) { + TRACE_SECURE_ERROR("clear info for %s", pkgname); + // remove database file + } + TRACE_SECURE_INFO("remove database for %s", pkgname); + free(pkgname); + continue; + } + + dp_credential credential; + credential.pid = 0; + if (dp_db_get_property_int(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_UID, &credential.uid, &errorcode) < 0 || + dp_db_get_property_int(g_db_handle, ids[i], DP_TABLE_CLIENTS, DP_DB_COL_GID, &credential.gid, &errorcode) < 0) { + TRACE_SECURE_ERROR("failed to get credential for %s", pkgname); + free(pkgname); + continue; + } + if (dp_mutex_init(&clients[slot_index].mutex, NULL) != 0) { + TRACE_SECURE_ERROR("failed to initialize mutex for %s", pkgname); + free(pkgname); + continue; + } + // open database of a clients + if (dp_db_open_client_v2(&clients[slot_index].client.dbhandle, pkgname) < 0) { + TRACE_SECURE_ERROR("failed to open database for %s", pkgname); + // remove this client from clients database + if (dp_db_delete(g_db_handle, ids[i], DP_TABLE_CLIENTS, &errorcode) == 0) { + TRACE_SECURE_ERROR("clear info for %s", pkgname); + // remove database file + if (dp_db_remove_database(pkgname, time(NULL), 0) == 0) { + TRACE_SECURE_INFO("remove database for %s", pkgname); + } else { + TRACE_SECURE_ERROR("failed to remove database for %s", pkgname); + } + } + free(pkgname); + continue; + } + + // get ids if state is QUEUED, CONNECTING or DOWNLOADING with auto_download + int *request_ids = (int *)calloc(DP_MAX_REQUEST, sizeof(int)); + if (request_ids == NULL) { + TRACE_SECURE_ERROR("failed to allocate the requests for %s", pkgname); + free(pkgname); + continue; + } + int request_count = dp_db_get_crashed_ids(clients[slot_index].client.dbhandle, DP_TABLE_LOGGING, request_ids, DP_MAX_REQUEST, &errorcode); + TRACE_DEBUG("client: %s requests:%d", pkgname, request_count); + int ids_i = 0; + if (request_count > 0) { + clients[slot_index].pkgname = pkgname; + clients[slot_index].client.channel = -1; + clients[slot_index].client.notify = -1; + clients[slot_index].credential.pid = credential.pid; + clients[slot_index].credential.uid = credential.uid; + clients[slot_index].credential.gid = credential.gid; + for (ids_i = 0; ids_i < request_count; ids_i++) { + // loading requests from client's database... attach to client.requests + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory download-id:%d", request_ids[ids_i]); + break; + } + request->id = request_ids[ids_i]; + request->agent_id = -1; + request->state = DP_STATE_QUEUED; + request->error = DP_ERROR_NONE; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &request->network_type, &errorcode) < 0) { + TRACE_ERROR("failed to get network type for id:%d", request->id); + request->network_type = DP_NETWORK_WIFI; + } + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_LOGGING, DP_DB_COL_STARTCOUNT, &request->startcount, &errorcode) < 0) { + TRACE_ERROR("failed to get start count for id:%d", request->id); + request->startcount = 0; + } + request->startcount++; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, &request->noti_type, &errorcode) < 0) { + TRACE_ERROR("failed to get notification type for id:%d", request->id); + } + if (request->noti_type == DP_NOTIFICATION_TYPE_NONE) { + TRACE_INFO("enable notification for id:%d", request->id); + request->noti_type = DP_NOTIFICATION_TYPE_COMPLETE_ONLY; + } + request->progress_lasttime = 0; + request->received_size = 0; // ? + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; // ? + if (dp_db_get_property_int(clients[slot_index].client.dbhandle, request->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, &request->noti_priv_id, &errorcode) < 0) { + TRACE_ERROR("failed to get notification noti_priv_id for id:%d", request->id); + request->noti_priv_id = -1; + } + + dp_request_create(&clients[slot_index].client, request); + + if (dp_db_update_logging(clients[slot_index].client.dbhandle, request->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log download-id:%d", request->id); + errorcode = DP_ERROR_DISK_BUSY; + break; + } + if (dp_queue_manager_push_queue((void *)&clients[slot_index], (void *)request) < 0) { + errorcode = DP_ERROR_QUEUE_FULL; + TRACE_INFO("failed to push to queue for id:%d", request->id); + dp_request_destroy(&(clients[slot_index].client), NULL, request); + break; + } + // notification + if (dp_notification_manager_push_notification((void *)&clients[slot_index], (void *)request, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + + } + + slot_index++; + + } else { + free(pkgname); + } + free(request_ids); + } + } + free(ids); + TRACE_DEBUG("slot_index:%d", slot_index); + if (slot_index > 0) + dp_queue_manager_wake_up(); + return slot_index; +} + +static int __dp_client_run(int clientfd, dp_client_slots_fmt *slot, + dp_credential credential) +{ + int errorcode = DP_ERROR_NONE; + // make notify fifo + slot->client.notify = dp_notify_init(credential.pid); + if (slot->client.notify < 0) { + TRACE_STRERROR("failed to open fifo slot:%d", clientfd); + errorcode = DP_ERROR_IO_ERROR; + } else { + char *smack_label = NULL; + if (dp_smack_is_mounted() == 1) { + smack_label = dp_smack_get_label_from_socket(clientfd); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("smack_new_label_from_socket"); + } + } + // save client info to database + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_update_client_info(g_db_handle, + slot->pkgname, smack_label, + credential.uid, credential.gid, &errorcode) < 0) { + TRACE_ERROR("check error:%s", dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + free(smack_label); + } + if (errorcode == DP_ERROR_NONE) { + + // create a thread for client + if (pthread_create(&slot->thread, NULL, + dp_client_request_thread, (void *)slot) != 0) { + TRACE_ERROR("failed to create client thread slot:%d", clientfd); + errorcode = DP_ERROR_OUT_OF_MEMORY; + slot->thread = 0; + dp_client_slot_free(slot); // => make pkgname as NULL + } else { + pthread_detach(slot->thread); + TRACE_SECURE_INFO("accept client[%s] pid:%d sock:%d", + slot->pkgname, credential.pid, clientfd); + slot->client.channel = clientfd; + slot->credential.pid = credential.pid; + slot->credential.uid = credential.uid; + slot->credential.gid = credential.gid; + } + } + return errorcode; +} + + +static int __dp_client_new(int clientfd, dp_client_slots_fmt *clients, + dp_credential credential) +{ + // search in clients list. + // if same pkgname. update it. + // search same pkg or pid in clients + int errorcode = DP_ERROR_NONE; + int i = 0; + int pkg_len = 0; + char *pkgname = NULL; + + // getting the package name via pid + if (app_manager_get_package(credential.pid, &pkgname) != + APP_MANAGER_ERROR_NONE) + TRACE_ERROR("[CRITICAL] app_manager_get_package"); + + //// TEST CODE ... to allow sample client ( no package name ). + if (pkgname == NULL) { + //pkgname = dp_strdup("unknown_app"); + char *temp_pkgname = (char *)calloc(41, sizeof(char)); + if (temp_pkgname == NULL || + snprintf(temp_pkgname, 41,"unknown_app_%d", credential.pid) < 0) { + pkgname = dp_strdup("unknown_app"); + } else { + pkgname = temp_pkgname; + } + } + + if (pkgname == NULL) { + TRACE_ERROR("[CRITICAL] app_manager_get_package"); + return DP_ERROR_INVALID_PARAMETER; + } + if ((pkg_len = strlen(pkgname)) <= 0) { + TRACE_ERROR("[CRITICAL] pkgname:%s", pkgname); + free(pkgname); + return DP_ERROR_INVALID_PARAMETER; + } + +#ifdef SUPPORT_SECURITY_PRIVILEGE + int result = security_server_check_privilege_by_sockfd(clientfd, SECURITY_PRIVILEGE_INTERNET, "w"); + if (result != SECURITY_SERVER_API_SUCCESS) { + TRACE_ERROR("check privilege permission:%d", result); + return DP_ERROR_PERMISSION_DENIED; + } +#endif + + // EINVAL: empty slot + // EBUSY : occupied slot + // locked & thread == 0 : downloading without client <= check target + // thread == 0, requests == NULL : clear target + + // Have this client ever been connected before ? + for (i = 0; i < DP_MAX_CLIENTS; i++) { + + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked != 0) { // empty or used by other thread. it would be same client, but it's busy + continue; + } + TRACE_DEBUG("locked slot:%d", i); + if (locked == 0 && clients[i].thread == 0) { // this slot has run without the client + if (clients[i].pkgname != NULL) { + // check package name. + TRACE_DEBUG("check client[%s] slot:%d", clients[i].pkgname, i); + int cname_len = strlen(clients[i].pkgname); + if (pkg_len == cname_len && + strncmp(clients[i].pkgname, pkgname, pkg_len) == 0) { + TRACE_SECURE_INFO("update client[%s] slot:%d pid:%d sock:%d", + pkgname, i, credential.pid, clientfd); + if (clients[i].client.channel >= 0 && + clients[i].client.channel != clientfd) { + dp_ipc_socket_free(clients[i].client.channel); + if (clients[i].client.notify >= 0) + close(clients[i].client.notify); + dp_notify_deinit(clients[i].credential.pid); + } + errorcode = __dp_client_run(clientfd, &clients[i], credential); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + if (errorcode != DP_ERROR_NONE) + dp_mutex_destroy(&clients[i].mutex); + free(pkgname); + return errorcode; + } + } + if (clients[i].client.requests == NULL) { // clear + dp_client_slot_free(&clients[i]); + dp_mutex_destroy(&clients[i].mutex); + continue; + } + } + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + + TRACE_DEBUG("search empty client[%s] slot:%d", pkgname, i); + // search empty slot + for (i = 0; i < DP_MAX_CLIENTS; i++) { + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EINVAL) { + if (dp_mutex_init(&clients[i].mutex, NULL) == 0) { + CLIENT_MUTEX_LOCK(&clients[i].mutex); + TRACE_DEBUG("found empty client[%s] slot:%d", pkgname, i); + clients[i].pkgname = pkgname; + clients[i].client.dbhandle = 0; + clients[i].client.requests = NULL; + errorcode = __dp_client_run(clientfd, &clients[i], credential); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + if (errorcode != DP_ERROR_NONE) + dp_mutex_destroy(&clients[i].mutex); + return errorcode; + } + } + if (locked == 0) + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + + TRACE_SECURE_INFO("busy client[%s] pid:%d sock:%d", pkgname, + credential.pid, clientfd); + free(pkgname); + return DP_ERROR_TOO_MANY_DOWNLOADS; +} + +void *dp_client_manager(void *arg) +{ + fd_set rset, eset, listen_fdset, except_fdset; + struct timeval timeout; // for timeout of select + socklen_t clientlen; + struct sockaddr_un clientaddr; + dp_credential credential; + unsigned i; + int errorcode = DP_ERROR_NONE; + GMainLoop *event_loop = (GMainLoop *)arg; + + g_dp_sock = __dp_accept_socket_new(); + if (g_dp_sock < 0) { + TRACE_STRERROR("failed to open listen socket"); + g_main_loop_quit(event_loop); + return 0; + } + + if (signal(SIGTERM, dp_terminate) == SIG_ERR || + signal(SIGPIPE, SIG_IGN) == SIG_ERR || + signal(SIGINT, dp_terminate) == SIG_ERR) { + TRACE_ERROR("failed to register signal callback"); + g_main_loop_quit(event_loop); + return 0; + } + + dp_notification_clear_ongoings(); + +#ifdef PROVIDER_DIR + dp_rebuild_dir(PROVIDER_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +#endif +#ifdef DATABASE_DIR + dp_rebuild_dir(DATABASE_DIR, S_IRWXU); +#endif +#ifdef DATABASE_CLIENT_DIR + dp_rebuild_dir(DATABASE_CLIENT_DIR, S_IRWXU); +#endif +#ifdef NOTIFY_DIR + dp_rebuild_dir(NOTIFY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +#endif + + if (__dp_db_open_client_manager() < 0) { + TRACE_STRERROR("failed to open database for client-manager"); + g_main_loop_quit(event_loop); + return 0; + } + + dp_client_slots_fmt *clients = + (dp_client_slots_fmt *)calloc(DP_MAX_CLIENTS, + sizeof(dp_client_slots_fmt)); + if (clients == NULL) { + TRACE_ERROR("failed to allocate client slots"); + g_main_loop_quit(event_loop); + return 0; + } + g_dp_client_slots = clients; + for (i = 0; i < DP_MAX_CLIENTS; i++) { + dp_mutex_destroy(&clients[i].mutex); // clear mutex init + } + + int maxfd = g_dp_sock; + FD_ZERO(&listen_fdset); + FD_ZERO(&except_fdset); + FD_SET(g_dp_sock, &listen_fdset); + FD_SET(g_dp_sock, &except_fdset); + + while (g_dp_sock >= 0) { + + int clientfd = -1; + + // initialize timeout structure for calling timeout exactly + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_MANAGER_INTERVAL; + credential.pid = -1; + credential.uid = -1; + credential.gid = -1; + + rset = listen_fdset; + eset = except_fdset; + + if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) { + TRACE_STRERROR("interrupted by terminating"); + break; + } + + if (g_dp_sock < 0) { + TRACE_DEBUG("queue-manager is closed by other thread"); + break; + } + + if (FD_ISSET(g_dp_sock, &eset) > 0) { + TRACE_STRERROR("exception of socket"); + break; + } else if (FD_ISSET(g_dp_sock, &rset) > 0) { + + // Anyway accept client. + clientlen = sizeof(clientaddr); + clientfd = accept(g_dp_sock, (struct sockaddr *)&clientaddr, + &clientlen); + if (clientfd < 0) { + TRACE_STRERROR("too many client ? accept failure"); + // provider need the time of refresh. + break; + } + + // blocking & timeout to prevent the lockup by client. + struct timeval tv_timeo = {1, 500000}; // 1.5 sec + if (setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, + sizeof(tv_timeo)) < 0) { + TRACE_ERROR("failed to set timeout in blocking socket"); + close(clientfd); + continue; + } + + dp_ipc_fmt ipc_info; + memset(&ipc_info, 0x00, sizeof(dp_ipc_fmt)); + if (read(clientfd, &ipc_info, sizeof(dp_ipc_fmt)) <= 0 || + ipc_info.section == DP_SEC_NONE || + ipc_info.property != DP_PROP_NONE || + ipc_info.id != -1 || + ipc_info.size != 0) { + TRACE_ERROR("peer terminate ? ignore this connection"); + close(clientfd); + continue; + } + +#ifdef SO_PEERCRED // getting the info of client + socklen_t cr_len = sizeof(credential); + if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED, + &credential, &cr_len) < 0) { + TRACE_ERROR("failed to cred from sock:%d", clientfd); + close(clientfd); + continue; + } +#else // In case of not supported SO_PEERCRED + if (read(clientfd, &credential, sizeof(dp_credential)) <= 0) { + TRACE_ERROR("failed to cred from client:%d", clientfd); + close(clientfd); + continue; + } +#endif + + CLIENT_MUTEX_LOCK(&g_db_mutex); + if (dp_db_check_connection(g_db_handle) < 0) { + TRACE_ERROR("check database, provider can't work anymore"); + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + close(clientfd); + break; + } + CLIENT_MUTEX_UNLOCK(&g_db_mutex); + + if (ipc_info.section == DP_SEC_INIT) { + + // new client + errorcode = __dp_client_new(clientfd, clients, credential); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + if (dp_ipc_query(clientfd, -1, DP_SEC_INIT, DP_PROP_NONE, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", clientfd); + } + if (errorcode == DP_ERROR_NONE) { + // write client info into database + + } else { + TRACE_ERROR("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + clientfd, ipc_info.id, + dp_print_section(ipc_info.section), + dp_print_property(ipc_info.property), + dp_print_errorcode(ipc_info.errorcode), + ipc_info.size); + close(clientfd); // ban this client + } + + } else { + + // take care zombie client, slots + unsigned connected_clients = 0; + int i = 0; + for (; i < DP_MAX_CLIENTS; i++) { + + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EINVAL) { // not initialized + continue; + } else if (locked == EBUSY) { // already locked + connected_clients++; + continue; + } + + if (locked == 0) { // locked + + // if no client thread, requests should be checked here + // if no queued, connecting or downloading, close the slot + if (clients[i].pkgname != NULL) { + if (clients[i].thread == 0) { + dp_client_clear_requests(&clients[i]); + if (clients[i].client.requests == NULL) { + dp_client_slot_free(&clients[i]); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + dp_mutex_destroy(&clients[i].mutex); + continue; + } + } + connected_clients++; + } + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + } + } + TRACE_DEBUG("%d clients are active now", connected_clients); + // terminating download-provider if no clients. + if (connected_clients == 0) { + if (__dp_manage_client_requests(clients) <= 0) // if no crashed job + break; + } else { + dp_queue_manager_wake_up(); + dp_notification_manager_wake_up(); + } + } + + } + if (g_dp_sock >= 0) + close(g_dp_sock); + g_dp_sock = -1; + + dp_queue_manager_kill(); + dp_notification_clear_ongoings(); + dp_notification_manager_kill(); + + __dp_db_free_client_manager(); + + // kill other clients + TRACE_DEBUG("try to deallocate the resources for all clients"); + for (i = 0; i < DP_MAX_CLIENTS; i++) { + int locked = CLIENT_MUTEX_TRYLOCK(&clients[i].mutex); + if (locked == EBUSY) { // already locked + CLIENT_MUTEX_LOCK(&clients[i].mutex); + } else if (locked == EINVAL) { // not initialized, empty slot + continue; + } + dp_client_slot_free(&clients[i]); + CLIENT_MUTEX_UNLOCK(&clients[i].mutex); + dp_mutex_destroy(&clients[i].mutex); + } + free(clients); + // free all resources + + TRACE_INFO("client-manager's working is done"); + g_main_loop_quit(event_loop); + return 0; +} diff --git a/provider/download-provider-client.c b/provider/download-provider-client.c new file mode 100644 index 0000000..53c5909 --- /dev/null +++ b/provider/download-provider-client.c @@ -0,0 +1,2110 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *dp_print_state(int state) +{ + switch(state) + { + case DP_STATE_NONE : + return "NONE"; + case DP_STATE_READY : + return "READY"; + case DP_STATE_QUEUED : + return "QUEUED"; + case DP_STATE_CONNECTING : + return "CONNECTING"; + case DP_STATE_DOWNLOADING : + return "DOWNLOADING"; + case DP_STATE_PAUSED : + return "PAUSED"; + case DP_STATE_COMPLETED : + return "COMPLETED"; + case DP_STATE_CANCELED : + return "CANCELED"; + case DP_STATE_FAILED : + return "FAILED"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_errorcode(int errorcode) +{ + switch(errorcode) + { + case DP_ERROR_NONE : + return "NONE"; + case DP_ERROR_INVALID_PARAMETER : + return "INVALID_PARAMETER"; + case DP_ERROR_OUT_OF_MEMORY : + return "OUT_OF_MEMORY"; + case DP_ERROR_IO_ERROR : + return "IO_ERROR"; + case DP_ERROR_NETWORK_UNREACHABLE : + return "NETWORK_UNREACHABLE"; + case DP_ERROR_CONNECTION_TIMED_OUT : + return "CONNECTION_TIMED_OUT"; + case DP_ERROR_NO_SPACE : + return "NO_SPACE"; + case DP_ERROR_FIELD_NOT_FOUND : + return "FIELD_NOT_FOUND"; + case DP_ERROR_INVALID_STATE : + return "INVALID_STATE"; + case DP_ERROR_CONNECTION_FAILED : + return "CONNECTION_FAILED"; + case DP_ERROR_INVALID_URL : + return "INVALID_URL"; + case DP_ERROR_INVALID_DESTINATION : + return "INVALID_DESTINATION"; + case DP_ERROR_QUEUE_FULL : + return "QUEUE_FULL"; + case DP_ERROR_ALREADY_COMPLETED : + return "ALREADY_COMPLETED"; + case DP_ERROR_FILE_ALREADY_EXISTS : + return "FILE_ALREADY_EXISTS"; + case DP_ERROR_TOO_MANY_DOWNLOADS : + return "TOO_MANY_DOWNLOADS"; + case DP_ERROR_NO_DATA : + return "NO_DATA"; + case DP_ERROR_UNHANDLED_HTTP_CODE : + return "UNHANDLED_HTTP_CODE"; + case DP_ERROR_CANNOT_RESUME : + return "CANNOT_RESUME"; + case DP_ERROR_PERMISSION_DENIED : + return "PERMISSION_DENIED"; + case DP_ERROR_RESPONSE_TIMEOUT : + return "RESPONSE_TIMEOUT"; + case DP_ERROR_REQUEST_TIMEOUT : + return "REQUEST_TIMEOUT"; + case DP_ERROR_SYSTEM_DOWN : + return "SYSTEM_DOWN"; + case DP_ERROR_CLIENT_DOWN : + return "CLIENT_DOWN"; + case DP_ERROR_DISK_BUSY: + return "DISK_BUSY"; + case DP_ERROR_ID_NOT_FOUND : + return "ID_NOT_FOUND"; + default : + break; + } + return "UNKNOWN"; +} + +char *dp_print_section(short section) +{ + switch (section) { + case DP_SEC_NONE: + return "NONE"; + case DP_SEC_INIT: + return "INIT"; + case DP_SEC_DEINIT: + return "DEINIT"; + case DP_SEC_CONTROL: + return "CONTROL"; + case DP_SEC_GET: + return "GET"; + case DP_SEC_SET: + return "SET"; + case DP_SEC_UNSET: + return "UNSET"; + default: + break; + } + return "UNKNOWN"; +} + +char *dp_print_property(unsigned property) +{ + switch (property) { + case DP_PROP_NONE: + return "NONE"; + case DP_PROP_CREATE: + return "CREATE"; + case DP_PROP_START: + return "START"; + case DP_PROP_PAUSE: + return "PAUSE"; + case DP_PROP_CANCEL: + return "CANCEL"; + case DP_PROP_DESTROY: + return "DESTROY"; + case DP_PROP_URL: + return "URL"; + case DP_PROP_DESTINATION: + return "DESTINATION"; + case DP_PROP_FILENAME: + return "FILENAME"; + case DP_PROP_STATE_CALLBACK: + return "STATE_CB"; + case DP_PROP_PROGRESS_CALLBACK: + return "PROGRESS_CB"; + case DP_PROP_AUTO_DOWNLOAD: + return "AUTO_DOWNLOAD"; + case DP_PROP_NETWORK_TYPE: + return "NETWORK_TYPE"; + case DP_PROP_NETWORK_BONDING: + return "NETWORK_BONDING"; + case DP_PROP_SAVED_PATH: + return "SAVED_PATH"; + case DP_PROP_TEMP_SAVED_PATH: + return "TEMP_SAVED_PATH"; + case DP_PROP_MIME_TYPE: + return "MIME_TYPE"; + case DP_PROP_RECEIVED_SIZE: + return "RECEIVED_SIZE"; + case DP_PROP_TOTAL_FILE_SIZE: + return "TOTAL_FILE_SIZE"; + case DP_PROP_CONTENT_NAME: + return "CONTENT_NAME"; + case DP_PROP_HTTP_STATUS: + return "HTTP_STATUS"; + case DP_PROP_ETAG: + return "ETAG"; + case DP_PROP_STATE: + return "STATE"; + case DP_PROP_ERROR: + return "ERROR"; + case DP_PROP_NOTIFICATION_RAW: + return "NOTIFICATION_RAW"; + case DP_PROP_NOTIFICATION_SUBJECT: + return "NOTIFICATION_SUBJECT"; + case DP_PROP_NOTIFICATION_DESCRIPTION: + return "NOTIFICATION_DESCRIPTION"; + case DP_PROP_NOTIFICATION_TYPE: + return "NOTIFICATION_TYPE"; + case DP_PROP_HTTP_HEADERS: + return "HTTP_HEADERS"; + case DP_PROP_HTTP_HEADER: + return "HTTP_HEADER"; + default: + break; + } + return "UNKNOWN"; +} + +static int __dp_get_download_id(dp_client_fmt *client) +{ + int download_id = -1; + static int last_download_id = 0; + int check_duplicate = 0; + int errorcode = DP_ERROR_NONE; + + do { + do { + struct timeval tval; + int cipher = 1; + int c = 0; + + download_id = -1; + gettimeofday(&tval, NULL); + + int usec = tval.tv_usec; + for (c = 0; ; c++, cipher++) { + if ((usec /= 10) <= 0) + break; + } + if (tval.tv_usec == 0) + tval.tv_usec = (tval.tv_sec & 0x0fff); + int disit_unit = 10; + for (c = 0; c < cipher - 3; c++) + disit_unit = disit_unit * 10; + download_id = tval.tv_sec + ((tval.tv_usec << 2) * 100) + + ((tval.tv_usec >> (cipher - 1)) * disit_unit) + + ((tval.tv_usec + (tval.tv_usec % 10)) & 0x0fff); + } while (last_download_id == download_id); + last_download_id = download_id; + check_duplicate = dp_db_check_duplicated_int(client->dbhandle, + DP_TABLE_LOGGING, DP_DB_COL_ID, download_id, &errorcode); + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("ERROR [%d]", errorcode); + } + } while (check_duplicate != 0); // means duplicated id + return download_id; +} + +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request) +{ + // new request + // find the tail of linked list & check limitation + int i = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (tailp == NULL) + break; + TRACE_DEBUG("link %d info: id:%d access-time:%d", i, tailp->id, tailp->access_time); + prevp = tailp; + tailp = tailp->next; + } + request->next = NULL; + if (prevp == NULL) // it's first link + client->requests = request; + else + prevp->next = request; // attach at the tail + + TRACE_DEBUG("sock:%d download-id:%d", client->channel, request->id); +} + +static int __dp_request_create(dp_client_fmt *client, dp_ipc_fmt *ipc_info) +{ + int errorcode = DP_ERROR_NONE; + + int download_id = __dp_get_download_id(client); + + // allocation new request. + dp_request_fmt *request = (dp_request_fmt *) calloc(1, sizeof(dp_request_fmt)); + if (request == NULL) { + TRACE_ERROR("check memory sock:%d download-id:%d", client->channel, download_id); + return DP_ERROR_OUT_OF_MEMORY; + } + + if (dp_db_new_logging(client->dbhandle, download_id, DP_STATE_READY, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("new log sock:%d download-id:%d", client->channel, download_id); + free(request); + return DP_ERROR_DISK_BUSY; + } + + request->id = download_id; + request->agent_id = -1; + request->state = DP_STATE_READY; + request->error = DP_ERROR_NONE; + request->network_type = DP_NETWORK_ALL; + request->access_time = (int)time(NULL); + request->state_cb = 0; + request->progress_cb = 0; + request->startcount = 0; + request->noti_type = DP_NOTIFICATION_TYPE_NONE; + request->progress_lasttime = 0; + request->received_size = 0; + request->content_type = DP_CONTENT_UNKNOWN; + request->file_size = 0; + request->noti_priv_id = -1; + + dp_request_create(client, request); + ipc_info->id = download_id; + return errorcode; +} + +void dp_request_free(dp_request_fmt *request) +{ + // free notification handle here + TRACE_DEBUG("destory id:%d", request->id); + free(request); +} + +void dp_client_clear_requests(void *slotp) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)slotp; + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return ; + } + dp_client_fmt *client = &slot->client; + if (client == NULL) { + TRACE_ERROR("check client memory"); + return ; + } + + int now_time = (int)time(NULL); + int i = 0; + unsigned queued_count = 0; + unsigned ongoing_count = 0; + dp_request_fmt *tailp = client->requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + + unsigned can_unload = 0; + if (tailp->id <= 0 || tailp->state == DP_STATE_NONE) { + TRACE_ERROR("id:%d unexpected request (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } else if (tailp->access_time > 0 && + (now_time - tailp->access_time) > DP_CARE_CLIENT_CLEAR_INTERVAL) { + // check accesstime. if difference is bigger than DP_CARE_CLIENT_CLEAR_INTERVAL, clear. + + if (tailp->state == DP_STATE_READY || + tailp->state == DP_STATE_COMPLETED || + tailp->state == DP_STATE_CANCELED || + tailp->state == DP_STATE_FAILED) { + can_unload = 1; + } else if (tailp->state == DP_STATE_CONNECTING) { // it take 120 sec over to connect. it means zombie. + TRACE_ERROR("id:%d connection timeout (%ld/%ld)", tailp->id, tailp->access_time, now_time); + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + tailp->state = DP_STATE_FAILED; + tailp->error = DP_ERROR_CONNECTION_TIMED_OUT; + if (tailp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + tailp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, tailp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", tailp->id); + } + } + } + } else if (tailp->state == DP_STATE_PAUSED && + dp_is_alive_download(tailp->agent_id) == 0) { + // paused & agent_id not exist.... unload from memory. + TRACE_ERROR("id:%d hanged as paused (%ld/%ld)", tailp->id, tailp->access_time, now_time); + can_unload = 1; + } + + if (can_unload == 1) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d clear: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } else { + ongoing_count++; + } + + if (tailp->state == DP_STATE_QUEUED) + queued_count++; + + prevp = tailp; + tailp = tailp->next; + } + TRACE_DEBUG("info requests:%d queued:%d", ongoing_count, queued_count); + if (queued_count > 0) + dp_queue_manager_wake_up(); +} + +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + + if (requestp != NULL && client->requests != NULL) { + if (requestp == client->requests) { + // cancel downloading ... after checking status + client->requests = requestp->next; + dp_request_free(requestp); + } else { + int i = 1; + dp_request_fmt *prevp = client->requests; + dp_request_fmt *removep = client->requests->next; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (removep == NULL) { + errorcode = DP_ERROR_ID_NOT_FOUND; + break; + } + if (removep == requestp) { + // cancel downloading ... after checking status + prevp->next = removep->next; + dp_request_free(removep); + break; + } + prevp = removep; + removep = removep->next; + } + } + } + + TRACE_DEBUG("sock:%d id:%d errorcode:%s", client->channel, + (ipc_info) ? ipc_info->id : -1, dp_print_errorcode(errorcode)); + + return errorcode; +} + +static int __dp_request_read_int(int sock, dp_ipc_fmt *ipc_info, int *value) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size == sizeof(int)) { + if (dp_ipc_read(sock, value, ipc_info->size, __FUNCTION__) < 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_string(int sock, dp_ipc_fmt *ipc_info, void *string, size_t length, int errorvalue) +{ + int errorcode = DP_ERROR_NONE; + + if (length == 0 && errorvalue == DP_ERROR_NONE) + errorvalue = DP_ERROR_NO_DATA; + + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, length * sizeof(char)) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, string, sizeof(char) * length) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, length); + } + } + return errorcode; +} + +static int __dp_request_read_string(int sock, dp_ipc_fmt *ipc_info, char **string) +{ + int errorcode = DP_ERROR_NONE; + if (ipc_info->size > 0) { + char *recv_str = (char *)calloc((ipc_info->size + (size_t)1), sizeof(char)); + if (recv_str == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(sock, recv_str, ipc_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", sock, ipc_info->size); + errorcode = DP_ERROR_IO_ERROR; + free(recv_str); + } else { + recv_str[ipc_info->size] = '\0'; + TRACE_DEBUG("sock:%d length:%d string:%s", sock, ipc_info->size, recv_str); + *string = recv_str; + } + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; +} + +static int __dp_request_feedback_int(int sock, dp_ipc_fmt *ipc_info, void *value, int errorvalue, size_t extra_size) +{ + int errorcode = DP_ERROR_NONE; + if (errorvalue != DP_ERROR_NONE) + extra_size = 0; + if (dp_ipc_query(sock, ipc_info->id, ipc_info->section, ipc_info->property, errorvalue, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + if (errorvalue == DP_ERROR_NONE && errorcode == DP_ERROR_NONE) { + if (dp_ipc_write(sock, value, extra_size) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("sock:%d check ipc length:%d", sock, extra_size); + } + } + return errorcode; +} + +static int __dp_request_get_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + int errorcode = DP_ERROR_NONE; + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_DESTINATION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_FILENAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->state_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + int callback = 0; + if (requestp != NULL) { + callback = requestp->progress_cb; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, &callback, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&callback, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + int autodownload = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, &autodownload, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&autodownload, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int network = 0; + if (requestp != NULL) { + network = requestp->network_type; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, &network, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int network_bonding = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, &network_bonding, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&network_bonding, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_MIME_TYPE: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_RECEIVED_SIZE: + { + unsigned long long recv_size = 0; + if (requestp != NULL) { + recv_size = requestp->received_size; + } else { + errorcode = DP_ERROR_INVALID_STATE; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&recv_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_TOTAL_FILE_SIZE: + { + unsigned long long file_size = 0; + if (requestp != NULL) { + file_size = requestp->file_size; + } else { + // load content_size(INT64) from database; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, &file_size, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&file_size, errorcode, sizeof(unsigned long long)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_CONTENT_NAME: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_HTTP_STATUS: + { + int httpstatus = 0; + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, &httpstatus, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&httpstatus, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ETAG: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_STATE: + { + int state = DP_STATE_NONE; + if (requestp != NULL) { + state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &state, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&state, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_ERROR: + { + int errorvalue = DP_ERROR_NONE; + if (requestp != NULL) { + errorvalue = requestp->error; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_ERRORCODE, &errorvalue, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&errorvalue, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = 0; + if (requestp != NULL) { + noti_type = requestp->noti_type; + // if already notification, unregister from notification bar. + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, ¬i_type, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)¬i_type, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(string); + break; + } + case DP_PROP_NOTIFICATION_RAW: // read type, send raw binary for type + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + + if (raw_column == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid type %d type:%d", dp_print_property(ipc_info->property), bundle_type); + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + } + if (errorcode == DP_ERROR_NONE) { + unsigned char *raws_buffer = NULL; + unsigned length = 0; + // get blob binary from database by raw_column + if (dp_db_get_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, raws_buffer, (size_t)length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(raws_buffer); + } + break; + } + case DP_PROP_HTTP_HEADERS: + { + // 1. response + // 2. send the number of header fields by id + // 3. send response & field string for each fields + int field_count = dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, ipc_info->id, &errorcode); + if (field_count < 0 ) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + field_count = 0; + } + int result = __dp_request_feedback_int(client->channel, ipc_info, (void *)&field_count, errorcode, sizeof(int)); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } else if (field_count > 0) { + // get fields from database. + int *ids = (int *)calloc(field_count, sizeof(int)); + if (ids == NULL) { + TRACE_ERROR("failed to allocate the clients"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + // getting ids of clients + int i = 0; + int rows_count = dp_db_get_cond_ids(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, DP_DB_COL_ID, ipc_info->id, ids, field_count, &errorcode); + for (; i < rows_count; i++) { + char *string = NULL; + unsigned length = 0; + if (dp_db_get_cond_string(client->dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ROW_ID, ids[i], DP_DB_COL_HEADER_FIELD, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %d", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + free(string); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + break; + } + } + } + } + + break; + } + case DP_PROP_HTTP_HEADER: + { + // 1. read field string + // 2. response with extra size + // 3. send string. + char *header_field = NULL; + char *string = NULL; + unsigned length = 0; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + if (dp_db_get_header_value(client->dbhandle, ipc_info->id, header_field, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_NO_DATA; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + int result = __dp_request_feedback_string(client->channel, ipc_info, string, length, errorcode); + if (result == DP_ERROR_IO_ERROR) { + errorcode = DP_ERROR_IO_ERROR; + TRACE_ERROR("check ipc sock:%d", client->channel); + } + free(header_field); + free(string); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static int __dp_request_set_info(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // if completed or downloading, invalid state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + // should the state be checked ? + TRACE_DEBUG("state:%s set property:%s", dp_print_state(download_state), dp_print_property(ipc_info->property)); + + switch (ipc_info->property) { + case DP_PROP_URL: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_DESTINATION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_smack_is_mounted() == 1) { + // check here destination is available. with checking smack + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("[SMACK][%d] no label", ipc_info->id); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else if (dp_is_valid_dir(recv_str) != 0) { + errorcode = DP_ERROR_INVALID_DESTINATION; + } else if (dp_smack_is_valid_dir(slot->credential.uid, slot->credential.gid, smack_label, recv_str) != 0) { + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(smack_label); + } + if (errorcode == DP_ERROR_NONE && + dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_TEMP_SAVED_PATH: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_FILENAME: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_STATE_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->state_cb = 1; + } + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + // check state here + // DP_ERROR_INVALID_STATE if downloading or finished + // update database here + if (requestp != NULL) { + requestp->progress_cb = 1; + } + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 1 in database + int enable_cb = 1; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int <= DP_NETWORK_OFF || + recv_int > DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // update in database + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else { + requestp->network_type = recv_int; + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // pause & push queue + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } else { + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } + } + } + } + } + int enable_cb = recv_int; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NETWORK_BONDING: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (errorcode == DP_ERROR_NONE) { + if(requestp != NULL && requestp->network_type != DP_NETWORK_ALL) { + errorcode = DP_ERROR_INVALID_NETWORK_TYPE; + TRACE_ERROR("[ERROR] wrong network type"); + } else if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (void *)&recv_int, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int recv_int = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &recv_int); + if (recv_int == DP_NOTIFICATION_TYPE_NONE || + recv_int == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + recv_int == DP_NOTIFICATION_TYPE_ALL) { + // check state request->state == DP_STATE_COMPLETED + // DP_ERROR_INVALID_STATE + // update notificatio type in database + int noti_type = recv_int; + if (requestp != NULL) { + if (recv_int < requestp->noti_type) { + // if already notification, unregister from notification bar. + if (recv_int == DP_NOTIFICATION_TYPE_NONE) { + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to clear notification %s", dp_print_property(ipc_info->property)); + } + } + if (dp_notification_manager_clear_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to clear ongoing %s", dp_print_property(ipc_info->property)); + } + } + requestp->noti_type = recv_int; + } + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + char *recv_str = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &recv_str); + if (errorcode == DP_ERROR_NONE) { + if (recv_str == NULL) { + errorcode = DP_ERROR_INVALID_PARAMETER; + } else { + // write to database here + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (void *)recv_str, ipc_info->size, 2, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + free(recv_str); + } + } + break; + } + case DP_PROP_NOTIFICATION_RAW: // bundle_type(db column) + bundle_binary + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + else + errorcode = DP_ERROR_INVALID_PARAMETER; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + if (errorcode == DP_ERROR_NONE) { + dp_ipc_fmt *raw_info = dp_ipc_get_fmt(client->channel); + if (raw_info == NULL || raw_info->section != ipc_info->section || + raw_info->property != ipc_info->property || + (raw_info->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion waiting raw binary in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } + if (raw_info != NULL && raw_info->size > 0) { + unsigned char *recv_raws = (unsigned char *)calloc(raw_info->size, sizeof(unsigned char)); + if (recv_raws == NULL) { + TRACE_STRERROR("sock:%d check memory length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } else { + if (dp_ipc_read(client->channel, recv_raws, raw_info->size, __FUNCTION__) <= 0) { + TRACE_ERROR("sock:%d check ipc length:%d", client->channel, raw_info->size); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d length:%d raws", client->channel, raw_info->size); + // save to database + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, (void *)recv_raws, raw_info->size, 3, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + free(recv_raws); + } + } else { + errorcode = DP_ERROR_IO_ERROR; + } + free(raw_info); + } + break; + } + case DP_PROP_HTTP_HEADER: // a request can have one or more fields, a fields can have only one value. + { + char *header_field = NULL; + char *header_value = NULL; + // 1. read field string + // 2. response after checking sql status + // 3. read query IPC for checking IPC + // 4. read value string + // 5. response + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + // check sql + int check_field = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode); + if (check_field < 0) { + errorcode = DP_ERROR_DISK_BUSY; + } else { + errorcode = DP_ERROR_NONE; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, ipc_info->section, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } else { + dp_ipc_fmt *header_ipc = dp_ipc_get_fmt(client->channel); + if (header_ipc == NULL || header_ipc->section != ipc_info->section || + header_ipc->property != ipc_info->property || + (header_ipc->id != ipc_info->id)) { + TRACE_ERROR("there is a confusion during waiting http string in %s section", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_read_string(client->channel, header_ipc, &header_value); + if (errorcode == DP_ERROR_NONE && header_value != NULL) { + if (check_field == 0) { // insert + if (dp_db_new_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { // update + if (dp_db_update_header(client->dbhandle, ipc_info->id, header_field, header_value, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_value == NULL) { + TRACE_ERROR("failed to set %s, do you want to run as unset?", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + } + free(header_ipc); + } + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + free(header_value); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_request_unset_info(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + switch (ipc_info->property) { + case DP_PROP_URL: + // it would be run like cancel operation + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_URL, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_DESTINATION: + // if downloading, change destination to da_agent + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_FILENAME: + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + case DP_PROP_STATE_CALLBACK: + { + if (requestp != NULL) { + requestp->state_cb = 0; + } + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_STATE_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_PROGRESS_CALLBACK: + { + if (requestp != NULL) { + requestp->progress_cb = 0; + } + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_PROGRESS_EVENT, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_AUTO_DOWNLOAD: + { + // update autodownload property as 0 in database + int enable_cb = 0; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_AUTO_DOWNLOAD, (void *)&enable_cb, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NETWORK_TYPE: + { + // check state here + // update database here + if (requestp != NULL) { + requestp->network_type = DP_NETWORK_OFF; + } + int enable_cb = DP_NETWORK_OFF; + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_TYPE, (void *)&enable_cb, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_TYPE: + { + int noti_type = DP_NOTIFICATION_TYPE_NONE; + if (requestp != NULL) { + requestp->noti_type = noti_type; + } + if (dp_db_replace_property(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_TYPE, (void *)¬i_type, ipc_info->size, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_DISK_BUSY; + } + break; + } + case DP_PROP_NOTIFICATION_SUBJECT: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_DESCRIPTION: + { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + break; + } + case DP_PROP_NOTIFICATION_RAW: + { + int bundle_type = -1; + errorcode = __dp_request_read_int(client->channel, ipc_info, &bundle_type); + TRACE_DEBUG("read %s type:%d", dp_print_property(ipc_info->property), bundle_type); + char *raw_column = NULL; + if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_ONGOING) + raw_column = DP_DB_COL_NOTI_RAW_ONGOING; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE) + raw_column = DP_DB_COL_NOTI_RAW_COMPLETE; + else if (bundle_type == DP_NOTIFICATION_BUNDLE_TYPE_FAILED) + raw_column = DP_DB_COL_NOTI_RAW_FAIL; + if (raw_column != NULL) { + if (dp_db_unset_property_string(client->dbhandle, ipc_info->id, DP_TABLE_NOTIFICATION, raw_column, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s", dp_print_property(ipc_info->property)); + } + } else { + TRACE_ERROR("invalid param set: %s type:%d", dp_print_property(ipc_info->property), bundle_type); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + break; + } + case DP_PROP_HTTP_HEADER: // unset value by field + { + char *header_field = NULL; + errorcode = __dp_request_read_string(client->channel, ipc_info, &header_field); + if (errorcode == DP_ERROR_NONE && header_field != NULL) { + int is_present = dp_db_check_duplicated_string(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, 0, header_field, &errorcode); + if (is_present < 0) + errorcode = DP_ERROR_DISK_BUSY; + else if (is_present == 0) + errorcode = DP_ERROR_FIELD_NOT_FOUND; + else if (dp_db_cond_delete(client->dbhandle, ipc_info->id, DP_TABLE_HEADERS, DP_DB_COL_HEADER_FIELD, header_field, 2, &errorcode) < 0) { + TRACE_ERROR("failed to unset %s for %s", dp_print_property(ipc_info->property), header_field); + errorcode = DP_ERROR_DISK_BUSY; + } + } else { + if (errorcode != DP_ERROR_NONE) { + TRACE_ERROR("failed to set %s, error:%s", dp_print_property(ipc_info->property), dp_print_errorcode(errorcode)); + } + if (header_field == NULL) { + TRACE_ERROR("failed to set %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_INVALID_PARAMETER; + } + } + free(header_field); + break; + } + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_UNSET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; +} + +static int __dp_call_cancel_agent(dp_request_fmt *request) +{ + int ret = -1; + if (request != NULL) { + if (request->agent_id >= 0) { + TRACE_INFO("cancel download(%d) id: %d state:%s", request->agent_id, + request->id, dp_print_state(request->state)); + if (dp_cancel_agent_download_without_update(request->agent_id) == 0) + ret = 0; + } else { + TRACE_ERROR("invalid agent-id:%d id:%d", request->agent_id, + request->id); + } + } + return ret; +} + +static int __dp_request_controls(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + if (ipc_info->property == DP_PROP_CREATE) { + // check packets again + if (ipc_info->size != 0 || ipc_info->id != -1) { + errorcode = DP_ERROR_IO_ERROR; + } else { + errorcode = __dp_request_create(client, ipc_info); + } + } else { + + // get now state. + int download_state = DP_STATE_NONE; + if (requestp != NULL) { + download_state = requestp->state; + } else { + if (dp_db_get_property_int(client->dbhandle, ipc_info->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("failed to get %s", dp_print_property(ipc_info->property)); + errorcode = DP_ERROR_ID_NOT_FOUND; + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_SET, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + return errorcode; + } + } + TRACE_DEBUG("id:%d state:%s set property:%s", ipc_info->id, dp_print_state(download_state), dp_print_property(ipc_info->property)); + + if (ipc_info->property == DP_PROP_START) { + + if (download_state == DP_STATE_COMPLETED || + download_state == DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { + + if (requestp == NULL) { // load from databse + // check state + // load and add new request to client->requests. + } + if (requestp == NULL) { + TRACE_ERROR("failed to load id:%d from database sock:%d", ipc_info->id, client->channel); + errorcode = DP_ERROR_DISK_BUSY; + } + if (errorcode == DP_ERROR_NONE) { + // update database + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_QUEUED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + requestp->state = DP_STATE_QUEUED; + requestp->error = DP_ERROR_NONE; + // if it's the first request for this client-> push a request at the head of queue. + // check count queued, connecting.downloading in requets of client + // else push at the tail of queue. + // push to queue + if (dp_queue_manager_push_queue(slot, requestp) < 0) { + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } + requestp->state = DP_STATE_FAILED; + requestp->error = DP_ERROR_QUEUE_FULL; + errorcode = DP_ERROR_QUEUE_FULL; + } else { // push ok + dp_queue_manager_wake_up(); + // notification + if (requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION_ONGOING) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + TRACE_DEBUG("id:%d check start error:%s", ipc_info->id, dp_print_errorcode(errorcode)); + } + + } else if (ipc_info->property == DP_PROP_PAUSE) { + + if (download_state > DP_STATE_DOWNLOADING) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_PAUSED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_pause API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download_without_update(requestp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_PAUSED; + requestp->error = DP_ERROR_NONE; + } + } + } + + } else if (ipc_info->property == DP_PROP_CANCEL) { + + if (download_state > DP_STATE_COMPLETED) { + errorcode = DP_ERROR_INVALID_STATE; + } else { // change state regardless it's on memory or not. + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + errorcode = DP_ERROR_DISK_BUSY; + } else { + // call da_cancel API + if (requestp != NULL) { + // pop from queue. if state is queued. + if (requestp->state == DP_STATE_QUEUED) { + dp_queue_manager_clear_queue(requestp); + } else if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->agent_id = -1; + requestp->state = DP_STATE_CANCELED; + requestp->error = DP_ERROR_NONE; + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + } + } + + } else if (ipc_info->property == DP_PROP_DESTROY) { + + // check state + // pop from queue. if state is queued. + if (requestp != NULL) { + if (requestp->state == DP_STATE_QUEUED) + dp_queue_manager_clear_queue(requestp); + if (requestp->state == DP_STATE_CONNECTING || + requestp->state == DP_STATE_DOWNLOADING) { + // update state property database; + if (dp_db_update_logging(client->dbhandle, ipc_info->id, DP_STATE_CANCELED, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", client->channel, ipc_info->id); + } else { + // call da_cancel API + if (__dp_call_cancel_agent(requestp) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", requestp->agent_id, ipc_info->id); + } + } + requestp->state = DP_STATE_CANCELED; + } + if (requestp->state == DP_STATE_QUEUED || requestp->state == DP_STATE_CANCELED) { + + if (requestp->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + requestp->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, requestp, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", ipc_info->id); + } + } + } + requestp->agent_id = -1; + } + errorcode = dp_request_destroy(client, ipc_info, requestp); + + } else { + errorcode = DP_ERROR_INVALID_PARAMETER; + TRACE_ERROR("invalid param - id:%d set property:%s", ipc_info->id, dp_print_property(ipc_info->property)); + } + } + + // feedback + if (dp_ipc_query(client->channel, ipc_info->id, DP_SEC_CONTROL, + ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + } + + // workaround. client still request the feedback by cancelation + if (ipc_info->property == DP_PROP_CANCEL || + ipc_info->property == DP_PROP_PAUSE) { + if (requestp != NULL && requestp->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, ipc_info->id, requestp->state, errorcode, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", ipc_info->id); + requestp->state_cb = 0; + } + } + } + + return errorcode; +} + +static int __dp_client_requests(dp_client_slots_fmt *slot, dp_ipc_fmt *ipc_info) +{ + if (slot == NULL) { + TRACE_ERROR("check slot memory"); + return DP_ERROR_INVALID_PARAMETER; + } + dp_client_fmt *client = &slot->client; + if (client == NULL || ipc_info == NULL) { + TRACE_ERROR("check client or ipc info."); + return DP_ERROR_INVALID_PARAMETER; + } + + int errorcode = DP_ERROR_NONE; + + // check id except create command /////////// DP_ERROR_ID_NOT_FOUND + dp_request_fmt *requestp = NULL; + if (ipc_info->section != DP_SEC_CONTROL || + ipc_info->property != DP_PROP_CREATE) { + // check on requests + int i = 0; + requestp = client->requests; + errorcode = DP_ERROR_ID_NOT_FOUND; + for (; i < MAX_DOWNLOAD_HANDLE; i++) { + if (requestp == NULL) + break; + //TRACE_DEBUG("link %d info: id:%d access-time:%d", i, requestp->id, requestp->access_time); + if (requestp->id == ipc_info->id) { + errorcode = DP_ERROR_NONE; + break; + } + requestp = requestp->next; + } + if (errorcode == DP_ERROR_ID_NOT_FOUND) { + // check in database + if (dp_db_check_duplicated_int(client->dbhandle, DP_TABLE_LOGGING, DP_DB_COL_ID, ipc_info->id, &errorcode) > 0) { + //TRACE_DEBUG("found %d from database", ipc_info->id); + errorcode = DP_ERROR_NONE; + } + } + } + + // Check size for prevent + if (ipc_info->size > 4294967295U) { + TRACE_ERROR("Check socket. Invalid size value. sock:%d", client->channel); + return DP_ERROR_IO_ERROR; + } + if (errorcode != DP_ERROR_NONE) { // prechecking + TRACE_ERROR("precheck errorcode:%s sock:%d id:%d section:%s property:%s", + dp_print_errorcode(errorcode), + client->channel, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property)); + + // clear followed packets. + if (ipc_info->size > 0) { + char garbage[ipc_info->size]; + if (read(client->channel, &garbage, ipc_info->size) == 0) { + TRACE_ERROR("sock:%d closed peer", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + } + + if (dp_ipc_query(client->channel, ipc_info->id, + ipc_info->section, ipc_info->property, errorcode, 0) < 0) { + TRACE_ERROR("check ipc sock:%d", client->channel); + errorcode = DP_ERROR_IO_ERROR; + } + return errorcode; + } + + switch (ipc_info->section) { + case DP_SEC_CONTROL: + errorcode = __dp_request_controls(slot, ipc_info, requestp); + break; + case DP_SEC_GET: + errorcode = __dp_request_get_info(client, ipc_info, requestp); + break; + case DP_SEC_SET: + errorcode = __dp_request_set_info(slot, ipc_info, requestp); + break; + case DP_SEC_UNSET: + errorcode = __dp_request_unset_info(client, ipc_info, requestp); + break; + default: + errorcode = DP_ERROR_INVALID_PARAMETER; + break; + } + return errorcode; +} + +static void __dp_client_stop_all_requests(dp_client_slots_fmt *slot) +{ + unsigned push_count = 0; + int errorcode = DP_ERROR_NONE; + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + for (; tailp != NULL; i++) { + TRACE_DEBUG("request %d stop id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + int state = tailp->state; + if (state == DP_STATE_CONNECTING) { + if (dp_cancel_agent_download_without_update(tailp->agent_id) < 0) { + TRACE_ERROR("failed to cancel download(%d) id:%d", tailp->agent_id, tailp->id); + } + } else if (state == DP_STATE_DOWNLOADING) { + if (dp_pause_agent_download(tailp->agent_id) < 0) { + TRACE_ERROR("failed to pause download(%d) id:%d", tailp->agent_id, tailp->id); + } + } + if (state == DP_STATE_DOWNLOADING || state == DP_STATE_CONNECTING) { + tailp->state = DP_STATE_QUEUED; + // This is error code for checking the reason when changing ip configuration process + tailp->error = DP_ERROR_IO_EAGAIN; + // push to queue now + // in da callback, check DP_ERROR_IO_EAGAIN, then ignore. + if (dp_db_update_logging(slot->client.dbhandle, tailp->id, tailp->state, DP_ERROR_NONE, &errorcode) < 0) { + TRACE_ERROR("update log sock:%d download-id:%d", slot->client.channel, tailp->id); + } + if (dp_queue_manager_push_queue(slot, tailp) < 0) { + TRACE_ERROR("Fail to push queueg sock:%d download-id:%d", slot->client.channel, tailp->id); + // FIXME later : error case. How can handle this item? + } else { + push_count++; + } + } + tailp = tailp->next; + } + if (push_count > 0) + dp_queue_manager_wake_up(); +} + +void dp_client_sig_handler(int signo) +{ + TRACE_INFO("thread:%0x signal:%d", pthread_self(), signo); +} + +void *dp_client_request_thread(void *arg) +{ + dp_client_slots_fmt *slot = (dp_client_slots_fmt *)arg; + if (slot == NULL) { + TRACE_ERROR("slot null, can not launch the thread for client"); + return 0; + } + + // wait detaching thread + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("slot %p thread:%0x", slot, slot->thread); + + struct sigaction act = {{0},}; + sigset_t newmask; + sigemptyset(&newmask); + sigaddset(&newmask, SIGUSR1); + act.sa_handler = dp_client_sig_handler; + sigaction(SIGUSR1, &act, NULL); + + fd_set imask, emask; + int errorcode = DP_ERROR_NONE; + dp_client_fmt *client = &slot->client; + int client_sock = client->channel; + struct timeval timeout; // for timeout of select + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + while (slot != NULL && client_sock >= 0 && + client_sock == slot->client.channel) { + + memset(&timeout, 0x00, sizeof(struct timeval)); + timeout.tv_sec = DP_CARE_CLIENT_REQUEST_INTERVAL; + FD_ZERO(&imask ); + FD_ZERO(&emask ); + FD_SET(client_sock, &imask); + FD_SET(client_sock, &emask); + if (select(client_sock + 1, &imask, 0, &emask, &timeout) < 0 ) { + if (slot != NULL && slot->client.channel >= 0) { + TRACE_INFO("broadcast by client-manager"); + CLIENT_MUTEX_LOCK(&slot->mutex); + // check all requests + __dp_client_stop_all_requests(slot); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + continue; + } else { + TRACE_STRERROR("interrupted by client-manager sock:%d", client_sock); + break; + } + } + if (FD_ISSET(client_sock, &imask) > 0) { + + CLIENT_MUTEX_LOCK(&slot->mutex); + + if (client->dbhandle == 0 || dp_db_check_connection(client->dbhandle) < 0) { + if (dp_db_open_client(&client->dbhandle, slot->pkgname) < 0) { + TRACE_ERROR("failed to open database for sock:%d", client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + } + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + client->access_time = (int)time(NULL); + + // read ipc_fmt first. below func will deal followed packets + dp_ipc_fmt *ipc_info = dp_ipc_get_fmt(client_sock); + if (ipc_info == NULL) { + TRACE_STRERROR("sock:%d maybe closed", client_sock); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_DEBUG("sock:%d id:%d section:%s property:%s errorcode:%s size:%d", + client_sock, ipc_info->id, + dp_print_section(ipc_info->section), + dp_print_property(ipc_info->property), + dp_print_errorcode(ipc_info->errorcode), + ipc_info->size); + + // JOB + errorcode = __dp_client_requests(slot, ipc_info); + } + free(ipc_info); + + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + if (errorcode == DP_ERROR_IO_ERROR || + errorcode == DP_ERROR_OUT_OF_MEMORY || + errorcode == DP_ERROR_INVALID_PARAMETER) { + TRACE_ERROR("disconnect client errorcode:%s sock:%d", + dp_print_errorcode(errorcode), client_sock); + break; + } + + } else if (FD_ISSET(client_sock, &emask) > 0) { + TRACE_ERROR("[EXCEPTION]"); + break; + } else { + + // timeout + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) == 0) { + // 1. clear zombie requests. clean requests finished. paused or ready for long time + dp_client_clear_requests(slot); + + int sql_errorcode = DP_ERROR_NONE; + + // 2. maintain only 1000 rows for each client + if (dp_db_limit_rows(client->dbhandle, DP_TABLE_LOGGING, DP_LOG_DB_LIMIT_ROWS, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 3. maintain for 48 hours + if (dp_db_limit_time(client->dbhandle, DP_TABLE_LOGGING, DP_CARE_CLIENT_INFO_PERIOD, &sql_errorcode) < 0) { + TRACE_INFO("limit rows error:%s", dp_print_errorcode(sql_errorcode)); + } + // 4. if no requests, exit by itself. + if (slot->client.requests == NULL) { + TRACE_DEBUG("no requests"); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + break; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + + FD_CLR(client_sock, &imask); + FD_CLR(client_sock, &emask); + + // if no requests, clear slot after disconnect with client. + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + + slot->thread = 0;// to prevent kill thread twice + + int i = 0; + dp_request_fmt *tailp = slot->client.requests; + dp_request_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->state != DP_STATE_QUEUED && + tailp->state != DP_STATE_CONNECTING && + tailp->state != DP_STATE_DOWNLOADING) { + dp_request_fmt *removep = tailp; + if (prevp == NULL) // first request. + client->requests = tailp->next; + else + prevp->next = tailp->next; + tailp = tailp->next; + TRACE_DEBUG("request %d remove: id:%d state:%s", i, removep->id, dp_print_state(removep->state)); + dp_request_free(removep); + continue; + } + TRACE_DEBUG("request %d remain: id:%d state:%s", i, tailp->id, dp_print_state(tailp->state)); + prevp = tailp; + tailp = tailp->next; + + } + // if no requests after clear finished requests. + if (slot->client.requests == NULL) { + dp_client_slot_free(slot); + } else { + if (slot->client.notify >= 0) + close(slot->client.notify); + dp_notify_deinit(slot->credential.pid); + slot->client.notify = -1; + if (slot->client.channel > 0) + close(slot->client.channel); + slot->client.channel = -1; + } + TRACE_INFO("thread done slot %p thread:%0x sock:%d", slot, slot->thread, client_sock); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return 0; +} + diff --git a/provider/download-provider-db.c b/provider/download-provider-db.c new file mode 100755 index 0000000..d05eabd --- /dev/null +++ b/provider/download-provider-db.c @@ -0,0 +1,1322 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#include +//#include +#include +#include // alloc +//#include // unlink + +#include + +#include "download-provider.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#include "download-provider-log.h" +#include "download-provider-utils.h" + + +static void __basic_property(sqlite3 *handle) +{ + if (sqlite3_exec(handle, "PRAGMA journal_mode=PERSIST;", 0, 0, 0) != SQLITE_OK) + TRACE_ERROR("check property journal_mode:PERSIST"); + if (sqlite3_exec(handle, "PRAGMA foreign_keys=ON;", 0, 0, 0) != SQLITE_OK) + TRACE_ERROR("check property foreign_keys:ON"); +} + +static void __dp_finalize(sqlite3_stmt *stmt) +{ + if (stmt != 0) { + if (sqlite3_finalize(stmt) != SQLITE_OK) { + sqlite3 *handle = sqlite3_db_handle(stmt); + TRACE_ERROR("sqlite3_finalize:%s", sqlite3_errmsg(handle)); + } + } +} + +static int __check_table(sqlite3 *handle, char *table) +{ + sqlite3_stmt *stmt = NULL; + + if (handle == 0 || table == NULL) { + TRACE_ERROR("check handle or table:%s", table); + return -1; + } + + char *query = sqlite3_mprintf("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'", table); + if (query == NULL) { + TRACE_ERROR("failed to make query statement"); + return -1; + } + int ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + int result = 0; + if (ret != SQLITE_OK) { + TRACE_ERROR("sqlite3_prepare:%s", sqlite3_errmsg(handle)); + result = -1; + } + if (result == 0 && sqlite3_step(stmt) != SQLITE_ROW) { + TRACE_DEBUG("not found table:%s", table); + result = -1; + } + __dp_finalize(stmt); + return result; +} + +static int __rebuild_client_tables(sqlite3 *handle) +{ + int ret = SQLITE_OK; + + if (__check_table(handle, DP_TABLE_LOGGING) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_LOGGING, 0, 0, 0); + if (ret == SQLITE_OK) { + ret = sqlite3_exec(handle, DP_SCHEMA_LOGGING_INDEX, 0, 0, 0); + } + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_DOWNLOAD) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_DOWNLOAD, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_REQUEST) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_REQUEST, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_HEADERS) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_HEADER, 0, 0, 0); + } + if (ret == SQLITE_OK && __check_table(handle, DP_TABLE_NOTIFICATION) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_NOTIFICATION, 0, 0, 0); + } + if (ret != SQLITE_OK) { + TRACE_ERROR("create tables:%d error:%s", ret, sqlite3_errmsg(handle)); + return -1; + } + return 0; +} + +static int __rebuild_client_manager_tables(sqlite3 *handle) +{ + int ret = SQLITE_OK; + if (__check_table(handle, DP_TABLE_CLIENTS) < 0) { + ret = sqlite3_exec(handle, DP_SCHEMA_CLIENTS, 0, 0, 0); + } + if (ret != SQLITE_OK) { + TRACE_ERROR("create tables:%d error:%s", ret, sqlite3_errmsg(handle)); + return -1; + } + return 0; +} + +static int __db_open(sqlite3 **handle, char *database) +{ + if (sqlite3_open_v2(database, handle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { + int errorcode = sqlite3_errcode(*handle); + TRACE_ERROR("error(%d):%s", errorcode, sqlite3_errmsg(*handle)); + *handle = 0; + if (errorcode == SQLITE_CORRUPT) { // remove & re-create + TRACE_SECURE_INFO("unlink [%s]", database); + unlink(database); + errorcode = SQLITE_CANTOPEN; + } + if (errorcode == SQLITE_CANTOPEN) { + // create empty database + if (sqlite3_open(database, handle) != SQLITE_OK ) { + TRACE_SECURE_INFO("failed to connect:%s", database); + unlink(database); + *handle = 0; + return -1; + } + } else { + TRACE_ERROR("can not handle this error:%d", errorcode); + *handle = 0; + return -1; + } + } + __basic_property(*handle); + return 0; +} + +int dp_db_check_connection(void *handle) +{ + if (handle == 0) { + TRACE_ERROR("connection handler is null"); + return -1; + } + int phighwater = 0; + int pcur = 0; + int ret = sqlite3_db_status(handle, SQLITE_DBSTATUS_STMT_USED, &pcur, &phighwater, 0); + if (ret != SQLITE_OK) { + TRACE_INFO("sql(%p) error:%d, used memory:%d, highwater:%d", handle, ret, pcur, phighwater); + return -1; + } + return 0; +} + +int dp_db_open_client_manager(void **handle) +{ + if (*handle == 0) { + char *database = sqlite3_mprintf("%s/%s", DATABASE_DIR, DP_DBFILE_CLIENTS); + if (database == NULL) { + TRACE_ERROR("failed to make clients database file path"); + return -1; + } + if (__db_open((sqlite3 **)handle, database) < 0) { + TRACE_ERROR("failed to open %s", database); + *handle = 0; + } else { + // whenever open new handle, check all tables. it's simple + if (__rebuild_client_manager_tables(*handle) < 0) { + dp_db_close(*handle); + *handle = 0; + } + } + sqlite3_free(database); + } + return *handle ? 0 : -1; +} + +static char *__dp_db_get_client_db_path(char *pkgname) +{ + if (pkgname == NULL) + return NULL; + return sqlite3_mprintf("%s/clients/.%s", DATABASE_DIR, pkgname); +} + +// 0 : remove, -1: error or skip by diff_time +int dp_db_remove_database(char *pkgname, long now_time, long diff_time) +{ + // get file name + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + int result = -1; + // get modified time of database file. + long modified_time = dp_get_file_modified_time(database); + if (modified_time >= now_time) { + TRACE_ERROR("check system timezone %ld vs %ld", modified_time, now_time); + } else if ((now_time - modified_time) > diff_time) { + char *database_journal = sqlite3_mprintf("%s-journal", database); + if (database_journal == NULL) { + TRACE_ERROR("failed to make db journal file path"); + } else { + if (dp_remove_file(database_journal) < 0) { + TRACE_ERROR("failed to remove db journal file path"); + } else { + if (dp_remove_file(database) < 0) { + TRACE_ERROR("failed to remove db file path"); + } else { + result = 0; + } + } + sqlite3_free(database_journal); + } + } + sqlite3_free(database); + return result; +} + +int dp_db_open_client_v2(void **handle, char *pkgname) +{ + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + if (sqlite3_open_v2(database, (sqlite3 **)handle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) { + int errorcode = sqlite3_errcode(*handle); + TRACE_ERROR("error(%d):%s", errorcode, sqlite3_errmsg(*handle)); + *handle = 0; + sqlite3_free(database); + return -1; + } + sqlite3_free(database); + __basic_property(*handle); + return 0; +} + +int dp_db_open_client(void **handle, char *pkgname) +{ + if (*handle == 0) { + char *database = __dp_db_get_client_db_path(pkgname); + if (database == NULL) { + TRACE_ERROR("failed to make db file path"); + return -1; + } + if (__db_open((sqlite3 **)handle, database) < 0) { + TRACE_SECURE_ERROR("failed to open %s", database); + *handle = 0; + } else { + // whenever open new handle, check all tables. it's simple + if (__rebuild_client_tables(*handle) < 0) { + dp_db_close(*handle); + *handle = 0; + } + } + sqlite3_free(database); + } + return *handle ? 0 : -1; +} + +void dp_db_close(void *handle) +{ + if (handle != 0) { + // remove empty page of db + //sqlite3_exec(handle, "VACUUM;", 0, 0, 0); + if (sqlite3_close((sqlite3 *)handle) != SQLITE_OK) + TRACE_ERROR("check sqlite close"); + } +} + +void dp_db_reset(void *stmt) +{ + if (stmt != 0) { + sqlite3_stmt *stmtp = stmt; + sqlite3_clear_bindings(stmtp); + if (sqlite3_reset(stmtp) != SQLITE_OK) { + sqlite3 *handle = sqlite3_db_handle(stmtp); + TRACE_ERROR("reset:%s", sqlite3_errmsg(handle)); + } + } +} + +void dp_db_finalize(void *stmt) +{ + __dp_finalize((sqlite3_stmt *)stmt); +} + +int dp_db_get_errorcode(void *handle) +{ + if (handle == 0) { + TRACE_ERROR("check connection handle"); + return DP_ERROR_DISK_BUSY; + } + int errorcode = sqlite3_errcode((sqlite3 *)handle); + if (errorcode == SQLITE_FULL) { + TRACE_ERROR("SQLITE_FULL-NO_SPACE"); + return DP_ERROR_NO_SPACE; + } else if (errorcode == SQLITE_TOOBIG || + errorcode == SQLITE_LOCKED || errorcode == SQLITE_BUSY) { + TRACE_ERROR("DISK_BUSY %s", sqlite3_errmsg((sqlite3 *)handle)); + return DP_ERROR_DISK_BUSY; + } + return DP_ERROR_NONE; +} + + +#define DP_DB_PARAM_NULL_CHECK do {\ + if (handle == 0) {\ + TRACE_ERROR("check connection handle");\ + return -1;\ + }\ +} while(0) + +#define DP_DB_BUFFER_NULL_CHECK(buffer) do {\ + if (buffer == NULL) {\ + TRACE_ERROR("check available memory");\ + return -1;\ + }\ +} while(0) + +#define DP_DB_BASIC_EXCEPTION_CHECK do {\ + if (errorcode != SQLITE_OK) {\ + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE)\ + *error = DP_ERROR_INVALID_PARAMETER;\ + __dp_finalize(stmt);\ + return -1;\ + }\ +} while(0) + +#define DP_DB_WRITE_STEP_EXCEPTION_CHECK do {\ + errorcode = sqlite3_step(stmt);\ + __dp_finalize(stmt);\ + if (errorcode != SQLITE_DONE) {\ + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE)\ + *error = DP_ERROR_INVALID_PARAMETER;\ + return -1;\ + }\ +} while(0) + +int dp_db_get_ids(void *handle, const char *table, char *idcolumn, int *ids, const char *where, const int limit, char *ordercolumn, char *ordering, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int rows_count = 0; + sqlite3_stmt *stmt = NULL; + + char *order_query = NULL; + if (ordercolumn != NULL) + order_query = sqlite3_mprintf("ORDER BY %s %s", ordercolumn, ( ordering == NULL ? "ASC" : ordering )); + + if (idcolumn == NULL) + idcolumn = DP_DB_COL_ID; + + char *query = sqlite3_mprintf("SELECT %s FROM %s %s %s LIMIT ?", idcolumn, table, ( where == NULL ? "" : where ), ( order_query == NULL ? "" : order_query )); + DP_DB_BUFFER_NULL_CHECK(query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + //TRACE_DEBUG("debug query:%s", query); + sqlite3_free(query); + if (order_query != NULL) + sqlite3_free(order_query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, limit); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { + int columnvalue = sqlite3_column_int(stmt, 0); + //TRACE_DEBUG("id(%d):%d", rows_count, columnvalue); + ids[rows_count++] = columnvalue; + } + } + __dp_finalize(stmt); + return rows_count; +} + +int dp_db_get_crashed_ids(void *handle, const char *table, int *ids, const int limit, int *error) +{ + // make where. + //get ids if state is QUEUED, CONNECTING or DOWNLOADING with auto_download + char *where = sqlite3_mprintf("WHERE %s IS 1 AND (%s IS %d OR %s IS %d OR %s IS %d)", + DP_DB_COL_AUTO_DOWNLOAD, + DP_DB_COL_STATE, DP_STATE_DOWNLOADING, + DP_DB_COL_STATE, DP_STATE_CONNECTING, + DP_DB_COL_STATE, DP_STATE_QUEUED); + if (where != NULL) { + int rows_count = dp_db_get_ids(handle, table, DP_DB_COL_ID, ids, where, limit, NULL, NULL, error); + sqlite3_free(where); + return rows_count; + } + *error = DP_ERROR_OUT_OF_MEMORY; + return -1; +} + + +int dp_db_check_duplicated_int(void *handle, const char *table, const char *column, const int value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int count = 0; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s IS ?", table, column); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, value); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } else { + count = 0; + } + __dp_finalize(stmt); + return count; +} + +int dp_db_check_duplicated_string(void *handle, const int id, const char *table, const char *column, int is_like, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int count = 0; + sqlite3_stmt *stmt = NULL; + + char *id_check = NULL; + if (id >= 0) { + id_check = sqlite3_mprintf("AND %s IS ?", DP_DB_COL_ID); + } + char *query = NULL; + if (is_like > 0) + query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s LIKE ? %s", table, column, (id_check == NULL ? "" : id_check)); + else + query = sqlite3_mprintf("SELECT count(*) FROM %s WHERE %s %s ? %s", table, column, (is_like == 0 ? "IS" : "IS NOT"), (id_check == NULL ? "" : id_check)); + if (id_check != NULL) + sqlite3_free(id_check); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_text(stmt, 1, value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + if (id >= 0) { + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + } + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } else { + count = 0; + } + __dp_finalize(stmt); + return count; +} + +int dp_db_update_client_info(void *handle, const char *pkgname, const char *smack, const int uid, const int gid, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (pkgname == NULL) { + TRACE_ERROR("check pkgname"); + return -1; + } + + int is_update = dp_db_check_duplicated_string(handle, -1, DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE, 0, pkgname, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = NULL; + + if (is_update == 0) + query = sqlite3_mprintf( + "INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s) VALUES (?, ?, %d, %d, 0, DATETIME('NOW'), DATETIME('NOW'))", + DP_TABLE_CLIENTS, DP_DB_COL_SMACK_LABEL, DP_DB_COL_PACKAGE, DP_DB_COL_UID, + DP_DB_COL_GID, DP_DB_COL_REQUEST_COUNT, + DP_DB_COL_CREATE_TIME, DP_DB_COL_ACCESS_TIME, uid, gid); + else + query = sqlite3_mprintf("UPDATE %s SET %s = ?, %s = %d, %s = %d, %s = DATETIME('NOW') WHERE %s IS ?", + DP_TABLE_CLIENTS, DP_DB_COL_SMACK_LABEL, DP_DB_COL_UID, + uid, DP_DB_COL_GID, gid, DP_DB_COL_ACCESS_TIME, DP_DB_COL_PACKAGE); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + if (smack != NULL) { + errorcode = sqlite3_bind_text(stmt, 1, smack, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + } + errorcode = sqlite3_bind_text(stmt, 2, pkgname, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_client_property_string(void *handle, const char *pkgname, const char *column, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (pkgname == NULL || column == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ? LIMIT 1", column, DP_TABLE_CLIENTS, DP_DB_COL_PACKAGE); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_text(stmt, 1, pkgname, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_new_logging(void *handle, const int id, const int state, const int errorvalue, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (?, ?, ?, DATETIME('now'), DATETIME('now'))", + DP_TABLE_LOGGING, DP_DB_COL_ID, DP_DB_COL_STATE, + DP_DB_COL_ERRORCODE, DP_DB_COL_CREATE_TIME, DP_DB_COL_ACCESS_TIME); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, state); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 3, errorvalue); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_update_logging(void *handle, const int id, const int state, const int errorvalue, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("UPDATE %s SET %s = ?, %s = ?, %s = DATETIME('now') WHERE %s = ?", + DP_TABLE_LOGGING, DP_DB_COL_STATE, DP_DB_COL_ERRORCODE, + DP_DB_COL_ACCESS_TIME, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, state); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, errorvalue); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 3, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +// 0:integer, 1:bigint, 2:string, 3:blob +int dp_db_replace_property(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned length, const unsigned valuetype, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = NULL; + + if (is_update == 0) + query = sqlite3_mprintf("INSERT INTO %s (%s, %s) VALUES (?, ?)", table, column, DP_DB_COL_ID); + else + query = sqlite3_mprintf("UPDATE %s SET %s = ? WHERE %s IS ?", table, column, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + if (valuetype == 0) { + int *cast_value = (int *)value; + errorcode = sqlite3_bind_int(stmt, 1, *cast_value); + } else if (valuetype == 1) { + sqlite_int64 *cast_value = (sqlite_int64 *)value; + errorcode = sqlite3_bind_int64(stmt, 1, *cast_value); + } else if (valuetype == 2) { + errorcode = sqlite3_bind_text(stmt, 1, (char *)value, -1, SQLITE_STATIC); + } else if (valuetype == 3) { + errorcode = sqlite3_bind_blob(stmt, 1, value, (int)length, NULL); + } else { + TRACE_ERROR("invalid type:%d", valuetype); + __dp_finalize(stmt); + return -1; + } + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_property_string(void *handle, const int id, const char *table, const char *column, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", column, table, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else if (data_type == SQLITE_BLOB) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_blob(stmt, 0), getbytes * sizeof(unsigned char)); + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + }else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + //TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_get_property_int(void *handle, const int id, const char *table, const char *column, void *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", column, table, DP_DB_COL_ID); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_INTEGER) { + int recv_int = sqlite3_column_int(stmt, 0); + int *pvalue = value; + *pvalue = recv_int; + } else if (data_type == SQLITE_FLOAT) { + unsigned long long recv_int = sqlite3_column_int64(stmt, 0); + unsigned long long *pvalue = value; + *pvalue = recv_int; + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_DONE) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_unset_property_string(void *handle, const int id, const char *table, const char *column, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } else if (is_update == 0) { + *error = DP_ERROR_ID_NOT_FOUND; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("UPDATE %s SET %s = NULL WHERE %s IS ?", table, column, DP_DB_COL_ID); + + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +// "DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s ORDER BY %s %s LIMIT %d)" +int dp_db_delete(void *handle, const int id, const char *table, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int is_update = dp_db_check_duplicated_int(handle, table, DP_DB_COL_ID, id, error); + if (is_update < 0) { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_DISK_BUSY; + return -1; + } else if (is_update == 0) { + *error = DP_ERROR_ID_NOT_FOUND; + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s IS ?", table, DP_DB_COL_ID); + + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_new_header(void *handle, const int id, const char *field, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (field == NULL) { + TRACE_ERROR("check field:%s", field); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s) VALUES (?, ?, ?)", + DP_TABLE_HEADERS, DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD, + DP_DB_COL_HEADER_DATA); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 3, (char *)value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_update_header(void *handle, const int id, const char *field, const char *value, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + + char *query = sqlite3_mprintf("UPDATE %s SET %s = ? WHERE %s IS ? AND %s IS ?", + DP_TABLE_HEADERS, DP_DB_COL_HEADER_DATA, + DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_text(stmt, 1, (char *)value, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 2, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_header_value(void *handle, const int id, const char *field, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (field == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ? AND %s IS ? LIMIT 1", DP_DB_COL_HEADER_DATA, DP_TABLE_HEADERS, DP_DB_COL_ID, DP_DB_COL_HEADER_FIELD); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_text(stmt, 2, (char *)field, -1, SQLITE_STATIC); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +// not supprot blob as column & value for additional condition +int dp_db_cond_delete(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned valuetype, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (id <= 0) { + TRACE_ERROR("check id:%d", id); + return -1; + } + if (table == NULL || column == NULL || value == NULL) { + TRACE_ERROR("check materials for query id:%d", id); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s IS ? AND %s IS ?", table, DP_DB_COL_ID, column); + + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + errorcode = sqlite3_bind_int(stmt, 1, id); + DP_DB_BASIC_EXCEPTION_CHECK; + + if (valuetype == 0) { + int *cast_value = (int *)value; + errorcode = sqlite3_bind_int(stmt, 2, *cast_value); + } else if (valuetype == 1) { + sqlite_int64 *cast_value = (sqlite_int64 *)value; + errorcode = sqlite3_bind_int64(stmt, 2, *cast_value); + } else if (valuetype == 2) { + errorcode = sqlite3_bind_text(stmt, 2, (char *)value, -1, SQLITE_STATIC); + } + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_cond_ids(void *handle, const char *table, const char *getcolumn, const char *column, const int value, int *ids, const int limit, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + int errorcode = SQLITE_OK; + int rows_count = 0; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s IS ?", getcolumn, table, column); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, value); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER) { + int columnvalue = sqlite3_column_int(stmt, 0); + //TRACE_DEBUG("id(%d):%d", rows_count, columnvalue); + ids[rows_count++] = columnvalue; + } + } + __dp_finalize(stmt); + return rows_count; +} + +int dp_db_get_cond_string(void *handle, const char *table, char *wherecolumn, const int wherevalue, const char *getcolumn, unsigned char **value, unsigned *length, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL || getcolumn == NULL || value == NULL || length == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + + if (wherecolumn == NULL) + wherecolumn = DP_DB_COL_ID; + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("SELECT %s FROM %s WHERE %s = ? LIMIT 1", getcolumn, table, wherecolumn); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, wherevalue); + DP_DB_BASIC_EXCEPTION_CHECK; + + *error = DP_ERROR_NONE; + errorcode = sqlite3_step(stmt); + *length = 0; + if (errorcode == SQLITE_ROW) { + int data_type = sqlite3_column_type(stmt, 0); + if (data_type == SQLITE_TEXT) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes + 1, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_text(stmt, 0), getbytes * sizeof(unsigned char)); + getstr[getbytes] = '\0'; + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + } else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else if (data_type == SQLITE_BLOB) { + int getbytes = sqlite3_column_bytes(stmt, 0); + if (getbytes > 0) { + unsigned char *getstr = (unsigned char *)calloc(getbytes, sizeof(unsigned char)); + if (getstr != NULL) { + memcpy(getstr, sqlite3_column_blob(stmt, 0), getbytes * sizeof(unsigned char)); + *value = getstr; + *length = getbytes; + } else { + TRACE_ERROR("check available system memory"); + *error = DP_ERROR_OUT_OF_MEMORY; + } + }else { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } + } else { + TRACE_ERROR("check column type:%d", data_type); + *error = DP_ERROR_NO_DATA; + } + } else if (errorcode == SQLITE_ROW) { + TRACE_DEBUG("no data"); + *error = DP_ERROR_NO_DATA; + } else { + if ((*error = dp_db_get_errorcode(handle)) == DP_ERROR_NONE) + *error = DP_ERROR_ID_NOT_FOUND; + } + __dp_finalize(stmt); + if (*error != DP_ERROR_NO_DATA && *error != DP_ERROR_NONE) + return -1; + return 0; +} + +int dp_db_limit_rows(void *handle, const char *table, int limit, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + if (limit < 0) { + TRACE_ERROR("check limitation:%d", limit); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s ORDER BY %s ASC LIMIT ?)", table, DP_DB_COL_ID, DP_DB_COL_ID, table, DP_DB_COL_CREATE_TIME); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, limit); + DP_DB_BASIC_EXCEPTION_CHECK; + + // apply "ON DELETE CASCADE" + + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_limit_time(void *handle, const char *table, int hours, int *error) +{ + *error = DP_ERROR_INVALID_PARAMETER; + DP_DB_PARAM_NULL_CHECK; + if (table == NULL) { + TRACE_ERROR("check materials for query"); + return -1; + } + if (hours <= 0) { + TRACE_ERROR("check limit time:%d", hours); + return -1; + } + + int errorcode = SQLITE_OK; + sqlite3_stmt *stmt = NULL; + char *query = sqlite3_mprintf("DELETE FROM %s WHERE %s < DATETIME('now','-%d hours')", table, DP_DB_COL_CREATE_TIME, hours); + DP_DB_BUFFER_NULL_CHECK(query); + //TRACE_DEBUG("debug query:%s", query); + errorcode = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL); + sqlite3_free(query); + DP_DB_BASIC_EXCEPTION_CHECK; + *error = DP_ERROR_NONE; + DP_DB_WRITE_STEP_EXCEPTION_CHECK; + return 0; +} + +int dp_db_get_http_headers_list(void *handle, int id, char **headers, int *error) +{ + int errorcode = SQLITE_OK; + int headers_index = 0; + sqlite3_stmt *stmt = NULL; + *error = DP_ERROR_NONE; + DP_DB_PARAM_NULL_CHECK; + + if (id <= 0) { + TRACE_ERROR("[CHECK ID]"); + *error = DP_ERROR_INVALID_PARAMETER; + return -1; + } + + errorcode = + sqlite3_prepare_v2(handle, + "SELECT header_field, header_data FROM header WHERE id = ?", + -1, &stmt, NULL); + + DP_DB_BASIC_EXCEPTION_CHECK; + + errorcode = sqlite3_bind_int(stmt, 1, id); + + DP_DB_BASIC_EXCEPTION_CHECK; + + while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { + int buffer_length = 0; + char *header_field = (char *)(sqlite3_column_text(stmt, 0)); + char *header_data = (char *)(sqlite3_column_text(stmt, 1)); + + // REF : http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 + buffer_length = strlen(header_field) + strlen(header_data) + 1; + char *headers_buffer = calloc(buffer_length + 1, sizeof(char)); + if (headers_buffer == NULL) { + TRACE_ERROR("[CALLOC] headers_buffer"); + continue; + } + int len = snprintf(headers_buffer, buffer_length + 1, + "%s:%s", header_field, header_data); + if (len <= 0) { + if (headers_buffer) + free(headers_buffer); + continue; + } else { + headers_buffer[len] = '\0'; + } + headers[headers_index++] = headers_buffer; + } + + __dp_finalize(stmt); + + return headers_index; +} + diff --git a/provider/download-provider-ipc.c b/provider/download-provider-ipc.c new file mode 100644 index 0000000..e79a6f7 --- /dev/null +++ b/provider/download-provider-ipc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include // shutdown + +#include "download-provider-log.h" +#include "download-provider-ipc.h" + +int dp_ipc_check_stderr(int basecode) +{ + int errorcode = basecode; + if (errno == EPIPE) { + TRACE_STRERROR("[EPIPE:%d] Broken Pipe", errno); + errorcode = DP_ERROR_IO_ERROR; + } else if (errno == EAGAIN) { + TRACE_STRERROR("[EAGAIN:%d]", errno); + errorcode = DP_ERROR_IO_EAGAIN; + } else if (errno == EINTR) { + TRACE_STRERROR("[EINTR:%d]", errno); + errorcode = DP_ERROR_IO_EINTR; + } else if (errno == ENOENT) { + TRACE_STRERROR("[ENOENT:%d]", errno); + errorcode = DP_ERROR_IO_ERROR; + } else { + TRACE_STRERROR("[errno:%d]", errno); + } + return errorcode; +} + +int dp_ipc_write(int sock, void *value, size_t type_size) +{ + if (sock < 0) { + TRACE_ERROR("[ERROR] check sock:%d", sock); + return -1; + } else if (value == NULL) { + TRACE_ERROR("[ERROR] check buffer sock:%d", sock); + return -1; + } else if (write(sock, value, type_size) <= 0) { + TRACE_STRERROR("[IPC.Write] exception sock:%d", sock); + return -1; + } + return 0; +} + +ssize_t dp_ipc_read(int sock, void *value, size_t type_size, + const char *func) +{ + int errorcode = DP_ERROR_NONE; + ssize_t recv_bytes = 0; + + if (sock < 0) { + TRACE_ERROR("[ERROR] %s check sock:%d", func, sock); + return -1; + } + if (value == NULL) { + TRACE_ERROR("[ERROR] %s check buffer sock:%d", func, sock); + return -1; + } + + int tryagain = 3; + do { + errorcode = DP_ERROR_NONE; + recv_bytes = read(sock, value, type_size); + if (recv_bytes < 0) { + TRACE_ERROR("[IPC.Read] %s exception sock:%d", func, sock); + errorcode = dp_ipc_check_stderr(DP_ERROR_IO_ERROR); + } else if (recv_bytes == 0) { + TRACE_ERROR("[ERROR] %s closed peer sock:%d", func, sock); + errorcode = DP_ERROR_IO_ERROR; + } + } while (sock >= 0 && (errorcode == DP_ERROR_IO_EAGAIN || + errorcode == DP_ERROR_IO_EINTR) && (--tryagain > 0)); + return recv_bytes; +} + +dp_ipc_fmt *dp_ipc_get_fmt(int sock) +{ + dp_ipc_fmt *ipc_info = malloc(sizeof(dp_ipc_fmt)); + if (ipc_info == NULL) { + TRACE_ERROR("[ERROR] Fail to malloc"); + return NULL; + } + memset(ipc_info, 0x00, sizeof(dp_ipc_fmt)); + ssize_t recv_size = read(sock, ipc_info, sizeof(dp_ipc_fmt)); + if (recv_size <= 0 || recv_size != sizeof(dp_ipc_fmt)) { + TRACE_STRERROR("socket read ipcinfo read size:%d", recv_size); + free(ipc_info); + return NULL; + } + return ipc_info; +} + +int dp_ipc_query(int sock, int download_id, short section, + unsigned property, int error, size_t size) +{ + dp_ipc_fmt ipc_info; + memset(&ipc_info, 0x00, sizeof(dp_ipc_fmt)); + ipc_info.section = section; + ipc_info.property = property; + ipc_info.id = download_id; + ipc_info.errorcode = error; + ipc_info.size = size; + if (dp_ipc_write(sock, &ipc_info, sizeof(dp_ipc_fmt)) < 0) + return -1; + return 0; +} + +int dp_ipc_socket_free(int sockfd) +{ + if (sockfd < 0) + return -1; + close(sockfd); + return 0; +} diff --git a/provider/download-provider-main.c b/provider/download-provider-main.c new file mode 100755 index 0000000..ded45db --- /dev/null +++ b/provider/download-provider-main.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#include "download-provider-config.h" +#include "download-provider-log.h" +#include "download-provider-client-manager.h" +#include "download-provider-network.h" + +void *dp_client_manager(void *arg); + +int main(int argc, char **argv) +{ + GMainLoop *event_loop; + pthread_t tid; + TRACE_INFO("download-provider's working is started"); + + g_type_init(); + + event_loop = g_main_loop_new(NULL, FALSE); + if (!event_loop) { + TRACE_ERROR("Failed to create g main loop handle"); + return 0; + } + // check network status + if (dp_network_connection_init() < 0) { + TRACE_ERROR("failed to init network-manager"); + return 0; + } + // create a thread for main thread + if (pthread_create(&tid, NULL, dp_client_manager, (void *)event_loop) != 0) { + TRACE_ERROR("failed to create main thread"); + return 0; + } else { + pthread_detach(tid); + TRACE_INFO("download main thread is created[%lu]", tid); + } + + TRACE_INFO("g main loop is started"); + g_main_loop_run(event_loop); + dp_network_connection_destroy(); + g_main_loop_unref(event_loop); + + TRACE_INFO("download-provider's working is done"); + return 0; +} diff --git a/provider/download-provider-network.c b/provider/download-provider-network.c new file mode 100755 index 0000000..5fafe2c --- /dev/null +++ b/provider/download-provider-network.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "download-provider.h" +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-network.h" +#include "download-provider-client-manager.h" + +#include + +#ifdef SUPPORT_WIFI_DIRECT +#include +#endif + +pthread_mutex_t g_dp_network_mutex = PTHREAD_MUTEX_INITIALIZER; +int g_network_status = DP_NETWORK_OFF; +connection_h g_network_connection = 0; +int g_network_is_wifi_direct = 0; + +#ifdef SUPPORT_COMPANION_MODE +// support B3 companion mode +#include "vconf.h" +#include "vconf-keys.h" +#include "SAPInterface.h" +#define VCONFKEY_SAP_CONNECTION_NOTIFICATION VCONFKEY_WMS_WMANAGER_CONNECTED +#define VCONFKEY_SAP_CONNECTION_TYPE "memory/private/sap/conn_type" +#endif + +static int __dp_network_is_companion_mode() +{ +#ifdef SUPPORT_COMPANION_MODE + int wms_connected = 0; + int companion_mode = 0; + vconf_get_int(VCONFKEY_SAP_CONNECTION_NOTIFICATION, &wms_connected); + vconf_get_int(VCONFKEY_SAP_CONNECTION_TYPE, &companion_mode); + TRACE_INFO("wms_connected:%d, companion_mode:%d", wms_connected, companion_mode); + if (wms_connected == 1 && (companion_mode & SAP_BT)) + return 1; + +#endif + return 0; +} + +#ifdef SUPPORT_WIFI_DIRECT + +static int __dp_network_wifi_direct_status() +{ + int is_connected = 0; + wifi_direct_state_e wifi_state = WIFI_DIRECT_STATE_DEACTIVATED; + if (wifi_direct_get_state(&wifi_state) == 0) { + if (wifi_state == WIFI_DIRECT_STATE_CONNECTED) { + TRACE_INFO("WIFI_DIRECT_STATE_CONNECTED"); + is_connected = 1; + } + } + return is_connected; +} + +// support WIFI-Direct +static void __dp_network_wifi_direct_changed_cb + (wifi_direct_error_e error_code, + wifi_direct_connection_state_e connection_state, + const char *mac_address, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + if (connection_state == WIFI_DIRECT_CONNECTION_RSP) { + TRACE_INFO("WIFI_DIRECT_CONNECTION_RSP"); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } else { + TRACE_INFO("WIFI_DIRECT_DISCONNECTION"); + g_network_is_wifi_direct = 0; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} +#endif + +////////////////////////////////////////////////////////////////////////// +/// @brief check the status in more detail by connection type +/// @return dp_network_type +static int __dp_get_network_connection_status(connection_h connection, connection_type_e type) +{ + int network_type = DP_NETWORK_OFF; + if (__dp_network_is_companion_mode() == 1) { + network_type = DP_NETWORK_ALL; + TRACE_INFO("COMPANION MODE"); + } else if (type == CONNECTION_TYPE_WIFI) { + connection_wifi_state_e wifi_state; + wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED; + if (connection_get_wifi_state(connection, &wifi_state) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_wifi_state"); + } else { + if (wifi_state == CONNECTION_WIFI_STATE_CONNECTED) { + TRACE_INFO("WIFI CONNECTED"); + network_type = DP_NETWORK_WIFI; + } + } + } else if (type == CONNECTION_TYPE_CELLULAR) { + connection_cellular_state_e cellular_state; + cellular_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE; + if (connection_get_cellular_state(connection, + &cellular_state) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_cellular_state"); + } else { + if (cellular_state == CONNECTION_CELLULAR_STATE_CONNECTED) { + TRACE_INFO("DATA NETWORK CONNECTED"); + network_type = DP_NETWORK_DATA_NETWORK; + } + } + } else if (type == CONNECTION_TYPE_ETHERNET) { + connection_ethernet_state_e ethernet_state; + ethernet_state = CONNECTION_ETHERNET_STATE_DISCONNECTED; + if (connection_get_ethernet_state(connection, + ðernet_state) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_ethernet_state"); + } else { + if (ethernet_state == CONNECTION_ETHERNET_STATE_CONNECTED) { + TRACE_INFO("ETHERNET CONNECTED"); + network_type = DP_NETWORK_WIFI; + } + } + } else { + TRACE_INFO("DISCONNECTED"); + network_type = DP_NETWORK_OFF; + } + g_network_status = network_type; + return network_type; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief [callback] called whenever changed network status +/// @todo care requests by network status +static void __dp_network_connection_type_changed_cb(connection_type_e type, void *data) +{ + pthread_mutex_lock(&g_dp_network_mutex); + // this callback guarantee that already connected + if (__dp_network_is_companion_mode() == 1) { + TRACE_INFO("COMPANION MODE"); + g_network_status = DP_NETWORK_ALL; + } else if (type == CONNECTION_TYPE_WIFI) { + TRACE_INFO("WIFI CONNECTED"); + g_network_status = DP_NETWORK_WIFI; + } else if (type == CONNECTION_TYPE_CELLULAR) { + TRACE_INFO("DATA NETWORK CONNECTED"); + g_network_status = DP_NETWORK_DATA_NETWORK; + } else if (type == CONNECTION_TYPE_ETHERNET) { + TRACE_INFO("ETHERNET CONNECTED"); + g_network_status = DP_NETWORK_WIFI; + } else { + TRACE_INFO("DISCONNECTED"); + g_network_status = DP_NETWORK_OFF; + } + pthread_mutex_unlock(&g_dp_network_mutex); +} + +////////////////////////////////////////////////////////////////////////// +/// @brief [callback] called when changed network ip +/// @todo auto resume feature +static void __dp_network_connection_ip_changed_cb(const char *ip, const char *ipv6, void *data) +{ + if (dp_network_get_status() != DP_NETWORK_OFF) { + TRACE_DEBUG("[CONNECTION] IP CHANGED"); + // broadcast to all thread for clients + dp_broadcast_signal(); + } +} + +int dp_network_get_status() +{ + int status = DP_NETWORK_OFF; + pthread_mutex_lock(&g_dp_network_mutex); + status = g_network_status; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +int dp_network_is_wifi_direct() +{ + pthread_mutex_lock(&g_dp_network_mutex); + int status = g_network_is_wifi_direct; + pthread_mutex_unlock(&g_dp_network_mutex); + return status; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief create connection handle & regist callback +/// @return 0 : success -1 : failed +int dp_network_connection_init() +{ + int retcode = 0; + +#ifdef SUPPORT_WIFI_DIRECT + if (wifi_direct_initialize() == 0) { + wifi_direct_set_connection_state_changed_cb + (__dp_network_wifi_direct_changed_cb, NULL); + g_network_is_wifi_direct = __dp_network_wifi_direct_status(); + } +#endif + + if ((retcode = connection_create(&g_network_connection)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_create [%d]", retcode); + return -1; + } + if ((retcode = connection_set_type_changed_cb(g_network_connection, + __dp_network_connection_type_changed_cb, NULL)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_set_type_changed_cb [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + + if ((retcode = connection_set_ip_address_changed_cb + (g_network_connection, __dp_network_connection_ip_changed_cb, + NULL)) != CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed __dp_network_connection_ip_changed_cb [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + + connection_type_e type = CONNECTION_TYPE_DISCONNECTED; + if ((retcode = connection_get_type(g_network_connection, &type)) != + CONNECTION_ERROR_NONE) { + TRACE_ERROR("Failed connection_get_type [%d]", retcode); + connection_destroy(g_network_connection); + g_network_connection = 0; + return -1; + } + g_network_status = + __dp_get_network_connection_status(g_network_connection, type); + return 0; +} + +////////////////////////////////////////////////////////////////////////// +/// @brief destroy connection handle +void dp_network_connection_destroy() +{ + pthread_mutex_lock(&g_dp_network_mutex); +#ifdef SUPPORT_WIFI_DIRECT + wifi_direct_unset_connection_state_changed_cb(); + wifi_direct_deinitialize(); +#endif + + if (g_network_connection != 0) { + connection_unset_type_changed_cb(g_network_connection); + connection_unset_ip_address_changed_cb(g_network_connection); + connection_destroy(g_network_connection); + } + g_network_connection = 0; + pthread_mutex_unlock(&g_dp_network_mutex); +} diff --git a/provider/download-provider-notification-manager.c b/provider/download-provider-notification-manager.c new file mode 100644 index 0000000..ea89c0c --- /dev/null +++ b/provider/download-provider-notification-manager.c @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SUPPORT_NOTIFICATION +#include +#include // pthread_kill +#include // ESRCH + +#include "download-provider-log.h" +#include "download-provider-pthread.h" +#include "download-provider-client.h" +#include "download-provider-client-manager.h" +#include "download-provider-notification.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#endif +#include "download-provider-notification-manager.h" + +#ifdef SUPPORT_NOTIFICATION +typedef struct { // manage clients without mutex + int id; + int state; + int noti_priv_id; + double received_size; + double file_size; + dp_noti_type type; + void *slot; // client can not be NULL. it will exist in dummy + void *request; // this can be NULL after destroy + void *next; +} dp_notification_queue_fmt; + + +pthread_mutex_t g_dp_notification_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_notification_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_notification_manager_tid = 0; + +static dp_notification_queue_fmt *g_dp_notification_clear = NULL; +static dp_notification_queue_fmt *g_dp_notification_ongoing = NULL; +static dp_notification_queue_fmt *g_dp_notification = NULL; + +pthread_mutex_t g_dp_notification_queue_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t g_dp_notification_queue_ongoing_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +static int __dp_notification_queue_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const int noti_priv_id, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->noti_priv_id = noti_priv_id; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, int *noti_priv_id, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (noti_priv_id != NULL) + *noti_priv_id = popp->noti_priv_id; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); + return ret; +} + +int __dp_notification_queue_ongoing_pop(dp_notification_queue_fmt **queue, void **slot, void **request, int *id, int *state, double *received_size, double *file_size, dp_noti_type *type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL) { + TRACE_ERROR("check client memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_queue_ongoing_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (queue == NULL || *queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return -1; + } + // get a head of queue + int ret = -1; + do { + dp_notification_queue_fmt *popp = *queue; + *queue = popp->next; + if (popp->slot == NULL) { + TRACE_DEBUG("queue error slot:%p id:%d", popp->slot, popp->id); + } else { + *slot = popp->slot; + if (request != NULL) { + *request = popp->request; + } + *id = popp->id; + *state = popp->state; + if (received_size != NULL) + *received_size = popp->received_size; + if (file_size != NULL) + *file_size = popp->file_size; + *type = popp->type; + ret = 0; + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +static int __dp_notification_queue_ongoing_push(dp_notification_queue_fmt **queue, void *slot, void *request, const int id, const int state, const double received_size, const double file_size, const dp_noti_type type) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (id <= 0) { + TRACE_ERROR("check slot or download id", id); + return -1; + } + + int ret = -1; + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_ongoing_mutex); + // search the tail of queue + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->slot == slot && tailp->request == request) { + if (tailp->id == id && tailp->state == state && tailp->type == type) { + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return 0; + } + } + prevp = tailp; + tailp = tailp->next; + } + dp_notification_queue_fmt *new_queue = (dp_notification_queue_fmt *)malloc(sizeof(dp_notification_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->id = id; + new_queue->state = state; + new_queue->received_size = received_size; + new_queue->file_size = file_size; + new_queue->type = type; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + ret = 0; + } + //TRACE_DEBUG("queue push %d id:%d", i, id); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_ongoing_mutex); + return ret; +} + +void __dp_notification_queue_clear(dp_notification_queue_fmt **queue, const int id) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_notification_queue_mutex); + int i = 0; + dp_notification_queue_fmt *tailp = *queue; + dp_notification_queue_fmt *prevp = NULL; + for (; tailp != NULL; i++) { + if (tailp->id == id) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d id:%d", i, tailp->id); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_notification_queue_mutex); +} + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + TRACE_DEBUG("push clear id:%d noti_priv_id:%d", requestp->id, requestp->noti_priv_id); + if (__dp_notification_queue_push(&g_dp_notification_clear, slot, request, requestp->id, requestp->state, -1, 0, 0, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + dp_notification_manager_wake_up(); + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } +// TRACE_DEBUG("push noti id:%d noti_priv_id:%d type:%d", requestp->id, requestp->noti_priv_id, type); + if (type == DP_NOTIFICATION) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, requestp->id); + if (__dp_notification_queue_push(&g_dp_notification, slot, request, requestp->id, requestp->state, requestp->noti_priv_id, 0, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } else { + __dp_notification_queue_clear(&g_dp_notification, requestp->id); + if (__dp_notification_queue_ongoing_push(&g_dp_notification_ongoing, slot, request, requestp->id, requestp->state, (double)requestp->received_size, (double)requestp->file_size, type) < 0) { + TRACE_ERROR("failed to push to notification id:%d", requestp->id); + return -1; + } + } + dp_notification_manager_wake_up(); + return 0; +} + +static void __dp_notification_manager_check_notification() +{ + int pop_queue = 0; + do { + int errorcode = DP_ERROR_NONE; + int download_id = -1; + int state = -1; + dp_noti_type noti_type = -1; + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + pop_queue = 0; + if (__dp_notification_queue_pop(&g_dp_notification_clear, (void *)&slot, (void *)&request, &download_id, &state, NULL, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + request->noti_priv_id = -1; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)&request->noti_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d type:%d", download_id, noti_priv_id, noti_type); + if (noti_priv_id >= 0) { + if (noti_type > DP_NOTIFICATION) + dp_notification_delete_ongoing(noti_priv_id); + else + dp_notification_delete(noti_priv_id); + } + } + pop_queue++; + continue; + } + int noti_priv_id = -1; + if (__dp_notification_queue_pop(&g_dp_notification, (void *)&slot, (void *)&request, &download_id, &state, ¬i_priv_id, NULL, NULL, ¬i_type) == 0) { + if (slot != NULL) { + __dp_notification_queue_clear(&g_dp_notification_ongoing, download_id); // prevent new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + TRACE_DEBUG("notification id:%d type:%d state:%d", download_id, noti_type, state); + if (request != NULL && request->id == download_id && request->noti_priv_id >= 0) { + dp_notification_delete_ongoing(request->noti_priv_id); + request->noti_priv_id = -1; + } + dp_content_type content_type = DP_CONTENT_UNKNOWN; + if (request != NULL) + content_type = request->content_type; + noti_priv_id = dp_notification_new(slot->client.dbhandle, download_id, state, content_type, slot->pkgname); // lazy API + TRACE_DEBUG("new notification(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to register notification for id:%d", download_id); + } else { + if (request != NULL && request->id == download_id) { + request->noti_priv_id = noti_priv_id; + } + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + pop_queue++; + } + double received_size = 0; + double file_size = 0; + if (__dp_notification_queue_ongoing_pop(&g_dp_notification_ongoing, (void *)&slot, (void *)&request, &download_id, &state, &received_size, &file_size, ¬i_type) == 0) { + if (slot != NULL) { + int noti_priv_id = -1; + int request_id = -1; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL && request->id == download_id) { + request_id = download_id; + if (request->noti_priv_id >= 0) { + noti_priv_id = request->noti_priv_id; + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } else { + TRACE_ERROR("ongoing wrong address id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + continue; + } + + if (request_id < 0) { + TRACE_ERROR("ongoing wrong info id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + slot = NULL; + request = NULL; + continue; + } + if (noti_priv_id < 0 && noti_type > DP_NOTIFICATION_ONGOING) { + TRACE_DEBUG("ongoing precheck id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + noti_type = DP_NOTIFICATION_ONGOING; + } + + TRACE_DEBUG("ongoing id:%d noti_priv_id:%d type:%d state:%d", download_id, noti_priv_id, noti_type, state); + + char *subject = NULL; + if (noti_type == DP_NOTIFICATION || noti_type == DP_NOTIFICATION_ONGOING_UPDATE) { + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } else if (subject == NULL && dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&subject, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + + if (noti_type > DP_NOTIFICATION_ONGOING) { // update + if (noti_priv_id >= 0 && dp_notification_ongoing_update(noti_priv_id, received_size, file_size, subject) < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } + } else { // new ongoing + if (noti_priv_id >= 0) { + TRACE_DEBUG("clear ongoing id:%d noti_priv_id:%d", download_id, noti_priv_id); + dp_notification_delete(noti_priv_id); + dp_notification_delete_ongoing(noti_priv_id); + noti_priv_id = -1; + } + unsigned char *raws_buffer = NULL; + unsigned length = 0; + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (dp_db_get_property_string(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_ONGOING, &raws_buffer, &length, &errorcode) < 0) { + TRACE_DEBUG("failed to get bundle raws id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + noti_priv_id = dp_notification_ongoing_new(slot->pkgname, subject, raws_buffer, length); + TRACE_DEBUG("new ongoing(%d) id:%d type:%d state:%d", noti_priv_id, download_id, noti_type, state); + free(raws_buffer); + if (noti_priv_id < 0) { + TRACE_ERROR("failed to update ongoing for id:%d", download_id); + } else { + if (CLIENT_MUTEX_CHECKLOCK(&slot->mutex) == 0) { + if (request != NULL) + request->noti_priv_id = noti_priv_id; + if (dp_db_replace_property(slot->client.dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_PRIV_ID, (void *)¬i_priv_id, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + } + } + } + free(subject); + } + pop_queue++; + } + } while (pop_queue > 0); +} + +static void *__dp_notification_manager(void *arg) +{ + pthread_cond_init(&g_dp_notification_manager_cond, NULL); + + dp_notification_set_locale(); + + while (g_dp_notification_manager_tid > 0) { + + if (g_dp_notification_manager_tid <= 0) { + TRACE_DEBUG("notification-manager is closed by other thread"); + break; + } + + // check wifi_direct first + __dp_notification_manager_check_notification(); + + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_wait(&g_dp_notification_manager_cond, &g_dp_notification_manager_mutex); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + + TRACE_DEBUG("notification-manager's working is done"); + dp_notification_clear_locale(); + pthread_cond_destroy(&g_dp_notification_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_notification_manager_start() +{ + if (g_dp_notification_manager_tid == 0 || + pthread_kill(g_dp_notification_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create notification-manager"); + if (pthread_create(&g_dp_notification_manager_tid, NULL, + __dp_notification_manager, NULL) != 0) { + TRACE_STRERROR("failed to create notification-manager"); + return -1; + } + } + return 0; +} + +void dp_notification_manager_wake_up() +{ + if (g_dp_notification_manager_tid > 0) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_notification_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + } + } else { + __dp_notification_manager_start(); + } +} + +void dp_notification_manager_kill() +{ + if (g_dp_notification_manager_tid > 0 && + pthread_kill(g_dp_notification_manager_tid, 0) != ESRCH) { + //send signal to notification thread + g_dp_notification_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_notification_manager_mutex); + pthread_cond_signal(&g_dp_notification_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_notification_manager_mutex); + pthread_cancel(g_dp_notification_manager_tid); + int status; + pthread_join(g_dp_notification_manager_tid, (void **)&status); + } +} +#else + +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type) +{ + return 0; +} + +void dp_notification_manager_wake_up() +{ + return; +} + +void dp_notification_manager_kill() +{ + return; +} +#endif diff --git a/provider/download-provider-notification.c b/provider/download-provider-notification.c new file mode 100755 index 0000000..75a6306 --- /dev/null +++ b/provider/download-provider-notification.c @@ -0,0 +1,627 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SUPPORT_NOTIFICATION +#include +#include +#include +#include + +#include "download-provider.h" +#include "download-provider-notification.h" +#include "download-provider-db-defs.h" +#include "download-provider-db.h" +#include "download-provider-log.h" +#include "download-provider-client.h" +#include "download-provider-utils.h" + +#include +#include +#include +#include + +#include +#include +#include +#define __(s) dgettext(PKG_NAME, s) + +#define DP_DOMAIN PKG_NAME +#define DP_LOCALEDIR LOCALE_DIR +#define DP_NOTIFICATION_NO_SUBJECT "No Name" + +#ifdef _TIZEN_2_3_UX +#define DP_NOTIFICATION_DRM_ICON_PATH IMAGE_DIR"/download_manager_icon_drm.png" +#define DP_NOTIFICATION_UNKNOWN_ICON_PATH IMAGE_DIR"/download_manager_icon_unknown.png" +#define DP_NOTIFICATION_EXCEL_ICON_PATH IMAGE_DIR"/download_manager_icon_xls.png" +#define DP_NOTIFICATION_HTML_ICON_PATH IMAGE_DIR"/download_manager_icon_html.png" +#define DP_NOTIFICATION_MUSIC_ICON_PATH IMAGE_DIR"/download_manager_icon_music.png" +#define DP_NOTIFICATION_PDF_ICON_PATH IMAGE_DIR"/download_manager_icon_pdf.png" +#define DP_NOTIFICATION_PPT_ICON_PATH IMAGE_DIR"/download_manager_icon_ppt.png" +#define DP_NOTIFICATION_TEXT_ICON_PATH IMAGE_DIR"/download_manager_icon_text.png" +#define DP_NOTIFICATION_WORD_ICON_PATH IMAGE_DIR"/download_manager_icon_word.png" +#define DP_NOTIFICATION_VIDEO_ICON_PATH IMAGE_DIR"/download_manager_icon_movie.png" +#define DP_NOTIFICATION_IMAGE_ICON_PATH IMAGE_DIR"/download_manager_icon_img.png" +#define DP_NOTIFICATION_FALSH_ICON_PATH IMAGE_DIR"/download_manager_icon_swf.png" +#define DP_NOTIFICATION_TPK_ICON_PATH IMAGE_DIR"/download_manager_icon_tpk.png" +#define DP_NOTIFICATION_VCAL_ICON_PATH IMAGE_DIR"/download_manager_icon_date.png" + +// base path +#define QP_PRELOAD_NOTI_ICON_PATH "/usr/apps/com.samsung.quickpanel/shared/res/noti_icons" +// each application path +#define QP_PRELOAD_COMMON_PATH QP_PRELOAD_NOTI_ICON_PATH"/Common" +#define DP_NOTIFICATION_COMPLETED_ICON_PATH QP_PRELOAD_COMMON_PATH"/noti_download_complete.png" +#define DP_NOTIFICATION_FAILED_ICON_PATH QP_PRELOAD_COMMON_PATH"/noti_download_failed.png" + +#define DP_NOTIFICATION_ONGOING_ICON_PATH "reserved://quickpanel/ani/downloading" +#define DP_NOTIFICATION_DOWNLOADING_ICON_PATH "reserved://indicator/ani/downloading" +#define DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_Processing_download_failed.png" +#define DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_Processing_download_complete.png" +#else +#define DP_NOTIFICATION_DRM_ICON_PATH IMAGE_DIR"/U01_icon_drm.png" +#define DP_NOTIFICATION_UNKNOWN_ICON_PATH IMAGE_DIR"/U01_icon_unkown.png" +#define DP_NOTIFICATION_EXCEL_ICON_PATH IMAGE_DIR"/U01_icon_excel.png" +#define DP_NOTIFICATION_HTML_ICON_PATH IMAGE_DIR"/U01_icon_html.png" +#define DP_NOTIFICATION_MUSIC_ICON_PATH IMAGE_DIR"/U01_list_icon_mp3.png" +#define DP_NOTIFICATION_PDF_ICON_PATH IMAGE_DIR"/U01_icon_pdf.png" +#define DP_NOTIFICATION_PPT_ICON_PATH IMAGE_DIR"/U01_icon_ppt.png" +#define DP_NOTIFICATION_TEXT_ICON_PATH IMAGE_DIR"/U01_icon_text.png" +#define DP_NOTIFICATION_WORD_ICON_PATH IMAGE_DIR"/U01_icon_word.png" +#define DP_NOTIFICATION_VIDEO_ICON_PATH IMAGE_DIR"/U01_list_icon_mp4.png" +#define DP_NOTIFICATION_IMAGE_ICON_PATH IMAGE_DIR"/U01_list_icon_image.png" +#define DP_NOTIFICATION_FALSH_ICON_PATH IMAGE_DIR"/U01_icon_swf.png" +#define DP_NOTIFICATION_TPK_ICON_PATH IMAGE_DIR"/U01_icon_tpk.png" +#define DP_NOTIFICATION_VCAL_ICON_PATH IMAGE_DIR"/U01_icon_vcs.png" + +#define DP_NOTIFICATION_FAILED_ICON_PATH IMAGE_DIR"/noti_download_failed.png" +#define DP_NOTIFICATION_COMPLETED_ICON_PATH IMAGE_DIR"/noti_download_complete.png" + +#define DP_NOTIFICATION_ONGOING_ICON_PATH "reserved://quickpanel/ani/downloading" +#define DP_NOTIFICATION_DOWNLOADING_ICON_PATH "reserved://indicator/ani/downloading" +#define DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_processing_download_fail.png" +#define DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH IMAGE_DIR"/B03_processing_download_complete.png" +#endif + +#define DP_MAX_ICONS_TABLE_COUNT 15 + +char *file_icons_table[DP_MAX_ICONS_TABLE_COUNT]={ + //unknown file type + DP_NOTIFICATION_UNKNOWN_ICON_PATH, + //image + DP_NOTIFICATION_IMAGE_ICON_PATH, + //video + DP_NOTIFICATION_VIDEO_ICON_PATH, + // audio /music + DP_NOTIFICATION_MUSIC_ICON_PATH, + // PDF + DP_NOTIFICATION_PDF_ICON_PATH, + // word + DP_NOTIFICATION_WORD_ICON_PATH, + // ppt + DP_NOTIFICATION_PPT_ICON_PATH, + // excel + DP_NOTIFICATION_EXCEL_ICON_PATH, + // html + DP_NOTIFICATION_HTML_ICON_PATH, + // txt + DP_NOTIFICATION_TEXT_ICON_PATH, + // DRM + DP_NOTIFICATION_DRM_ICON_PATH, + DP_NOTIFICATION_DRM_ICON_PATH, + DP_NOTIFICATION_FALSH_ICON_PATH, + DP_NOTIFICATION_TPK_ICON_PATH, + DP_NOTIFICATION_VCAL_ICON_PATH, +}; + +static const char *__dp_noti_error_str(int err) +{ + switch (err) { + case NOTIFICATION_ERROR_INVALID_PARAMETER: + return "NOTIFICATION_ERROR_INVALID_PARAMETER"; + case NOTIFICATION_ERROR_OUT_OF_MEMORY: + return "NOTIFICATION_ERROR_OUT_OF_MEMORY"; + case NOTIFICATION_ERROR_FROM_DB: + return "NOTIFICATION_ERROR_FROM_DB"; + case NOTIFICATION_ERROR_ALREADY_EXIST_ID: + return "NOTIFICATION_ERROR_ALREADY_EXIST_ID"; + case NOTIFICATION_ERROR_FROM_DBUS: + return "NOTIFICATION_ERROR_FROM_DBUS"; + case NOTIFICATION_ERROR_NOT_EXIST_ID: + return "NOTIFICATION_ERROR_NOT_EXIST_ID"; + default: + break; + } + return "Unknown error"; +} + +char *__dp_noti_get_sender(char *url) +{ + char *temp = NULL; + char *found = NULL; + char *found1 = NULL; + char *sender = NULL; + char *credential_sender = NULL; + + if (url == NULL) + return NULL; + + found = strstr(url, "://"); + if (found != NULL) { + temp = found + 3; + } else { + temp = url; + } + found = strchr(temp, '/'); + if (found != NULL) { + int len = 0; + len = found - temp; + sender = calloc(len + 1, sizeof(char)); + if (sender == NULL) + return NULL; + snprintf(sender, len + 1, "%s", temp); + } else { + sender = dp_strdup(temp); + if(sender == NULL) + return NULL; + } + + // For credential URL + found = strchr(sender, '@'); + found1 = strchr(sender, ':'); + if (found != NULL && found1 != NULL && found1 < found) { + int len = 0; + found = found + 1; + len = strlen(found); + credential_sender = calloc(len + 1, sizeof(char)); + if (credential_sender == NULL) { + free(sender); + return NULL; + } + snprintf(credential_sender, len + 1, "%s", found); + free(sender); + return credential_sender; + } else { + return sender; + } +} + +static char *__dp_noti_status(dp_state_type state) +{ + char *message = NULL; + switch (state) { + case DP_STATE_COMPLETED: + message = "IDS_DM_HEADER_DOWNLOAD_COMPLETE"; + break; + case DP_STATE_CANCELED: + case DP_STATE_FAILED: + message = "IDS_DM_BODY_DOWNLOAD_FAILED_M_STATUS_ABB"; + break; + default: + break; + } + return message; +} + +void __lang_changed_cb(keynode_t *key, void* data) +{ + char *str = NULL; + str = vconf_get_str(VCONFKEY_LANGSET); + if (str != NULL) { + setlocale(LC_ALL, str); + bindtextdomain(PKG_NAME, LOCALE_DIR); + textdomain(PKG_NAME); + } + free(str); +} + +void dp_notification_set_locale() +{ + // move to notification.c + // locale + __lang_changed_cb(NULL, NULL); + if (vconf_notify_key_changed(VCONFKEY_LANGSET, __lang_changed_cb, NULL) != 0) + TRACE_ERROR("Fail to set language changed vconf callback"); +} + +void dp_notification_clear_locale() +{ + // move to notification.c + if (vconf_ignore_key_changed(VCONFKEY_LANGSET, __lang_changed_cb) != 0) + TRACE_ERROR("Fail to unset language changed vconf callback"); +} + +void dp_notification_clear_ongoings() +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_ONGOING); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("[FAIL] clear noti [%s]", __dp_noti_error_str(err)); + } + return; +} + +int dp_notification_ongoing_new(const char *pkgname, const char *subject, unsigned char *raws_buffer, const int raws_length) +{ + int err = NOTIFICATION_ERROR_NONE; + notification_h noti_handle = NULL; + noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING); + if (noti_handle == NULL) { + TRACE_ERROR("failed to create notification handle"); + return -1; + } + + if (subject != NULL) { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, subject, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + } else { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, DP_NOTIFICATION_NO_SUBJECT, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set subject error:%s", __dp_noti_error_str(err)); + } + + err = notification_set_image(noti_handle, + NOTIFICATION_IMAGE_TYPE_ICON, + DP_NOTIFICATION_ONGOING_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon error:%s", __dp_noti_error_str(err)); + } + + if (raws_buffer != NULL && raws_length > 0) { + bundle *b = NULL; + b = bundle_decode_raw((bundle_raw *)raws_buffer, raws_length); + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (b != NULL && pkgname != NULL) { + if (appsvc_set_pkgname(b, pkgname) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set set pkgname"); + } else { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } else { + TRACE_ERROR("failed to create bundle"); + } + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service error:%s", __dp_noti_error_str(err)); + } + if (b != NULL) + bundle_free(b); + } + + err = notification_set_property(noti_handle, + NOTIFICATION_PROP_DISABLE_TICKERNOTI); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set property error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + err = notification_set_image(noti_handle, + NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_DOWNLOADING_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon indicator error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + err = notification_set_display_applist(noti_handle, + NOTIFICATION_DISPLAY_APP_ALL); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set display app all error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + + int priv_id = 0; + err = notification_insert(noti_handle, &priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set priv_id error:%s", __dp_noti_error_str(err)); + notification_free(noti_handle); + return -1; + } + + //TRACE_DEBUG("m_noti_id [%d]", priv_id); + notification_free(noti_handle); + + return priv_id; // store on memory for reuse it +} + + + +int dp_notification_ongoing_update(const int noti_priv_id, const double received_size, const double file_size, const char *subject) +{ + if (noti_priv_id > 0) { + int err = NOTIFICATION_ERROR_NONE; + if (file_size > 0) + err = notification_update_progress(NULL, noti_priv_id, (received_size / file_size)); + else + err = notification_update_size(NULL, noti_priv_id, received_size); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to update error:%s", __dp_noti_error_str(err)); + // return 0 because progress is called frequently + } + if (subject != NULL) { + notification_h noti_handle = NULL; + noti_handle = notification_load(NULL, noti_priv_id); + if (noti_handle != NULL) { + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, subject, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + err = notification_update(noti_handle); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to update by priv_id:%d", noti_priv_id); + } + notification_free(noti_handle); + } else { + TRACE_ERROR("failed to load handle by priv_id:%d", noti_priv_id); + return -1; + } + } + } + return 0; +} + + +int dp_notification_delete_ongoing(const int noti_priv_id) +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_ONGOING, noti_priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to delete notification by priv_id:%d error:%s", noti_priv_id, __dp_noti_error_str(err)); + } + return 0; +} + +int dp_notification_delete(const int noti_priv_id) +{ + int err = NOTIFICATION_ERROR_NONE; + err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NOTI, noti_priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to delete notification by priv_id:%d error:%s", noti_priv_id, __dp_noti_error_str(err)); + } + return 0; +} + + +int dp_notification_new(void *dbhandle, const int download_id, const int state, int content_type, const char *pkgname) +{ + int errorcode = DP_ERROR_NONE; + int err = NOTIFICATION_ERROR_NONE; + + if (state != DP_STATE_COMPLETED && + state != DP_STATE_CANCELED && + state != DP_STATE_FAILED) { + TRACE_ERROR("deny by invalid state:%d id:%d", state, download_id); + return -1; + } + + + notification_h noti_handle = NULL; + noti_handle = notification_create(NOTIFICATION_TYPE_NOTI); + if (noti_handle == NULL) { + TRACE_ERROR("failed to create notification handle"); + return -1; + } + + err = notification_set_layout(noti_handle, NOTIFICATION_LY_NOTI_EVENT_SINGLE); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("Fail to set notification layout [%d]", err); + notification_free(noti_handle); + return -1; + } + + err = notification_set_text_domain(noti_handle, DP_DOMAIN, DP_LOCALEDIR); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("Fail to set text domain [%d]", err); + notification_free(noti_handle); + return -1; + } + + char *string = NULL; + unsigned length = 0; + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_DESCRIPTION, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get description id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (string != NULL) { +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + free(string); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + } else { + string = __dp_noti_status(state); +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, __(string), string, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, __(string), string, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + } + + string = NULL; + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_SUBJECT, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get subject id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + err = NOTIFICATION_ERROR_NONE; + if (string == NULL && dp_db_get_property_string(dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get content_name id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (string == NULL) + string = dp_strdup(DP_NOTIFICATION_NO_SUBJECT); + if (string != NULL) { +#ifdef _TIZEN_2_3_UX + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_TITLE, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#else + err = notification_set_text(noti_handle, + NOTIFICATION_TEXT_TYPE_CONTENT, string, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); +#endif + free(string); + string = NULL; + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set state id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + } + err = notification_set_time(noti_handle, time(NULL)); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set time id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + bundle *b = NULL; + bundle_raw *raws_buffer = NULL; + if (state == DP_STATE_COMPLETED) { + + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_COMPLETE, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get bundle raws id:%d", download_id); + } + if (raws_buffer != NULL) { + b = bundle_decode_raw(raws_buffer, length); + bundle_free_encoded_rawdata(&raws_buffer); + } + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (unsigned char **)&string, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get saved_path id:%d error:%s", download_id, dp_print_errorcode(errorcode)); + } + if (b != NULL && string != NULL) { + if (appsvc_set_operation(b, APPSVC_OPERATION_VIEW) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set service operation id:%d", download_id); + } else { + if (appsvc_set_uri(b, string) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set service uri id:%d", download_id); + } else { + err = notification_set_execute_option(noti_handle, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } + } else { + TRACE_SECURE_ERROR("failed to create bundle id:%d path:%s", download_id, string); + } + free(string); + string = NULL; + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + char *file_type_icon = DP_NOTIFICATION_UNKNOWN_ICON_PATH; + if (content_type > 0 && content_type < DP_MAX_ICONS_TABLE_COUNT) + file_type_icon = file_icons_table[content_type]; + + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, file_type_icon); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_COMPLETED_INDICATOR_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + } else if (state == DP_STATE_CANCELED || state == DP_STATE_FAILED) { + + if (dp_db_get_property_string(dbhandle, download_id, DP_TABLE_NOTIFICATION, DP_DB_COL_NOTI_RAW_FAIL, &raws_buffer, &length, &errorcode) < 0) { + TRACE_ERROR("failed to get bundle raws id:%d", download_id); + } + if (raws_buffer != NULL) { + b = bundle_decode_raw(raws_buffer, length); + bundle_free_encoded_rawdata(&raws_buffer); + } + if (b != NULL) { + err = notification_set_execute_option(noti_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } else { + b = bundle_create(); + if (b != NULL && pkgname != NULL) { + if (appsvc_set_pkgname(b, pkgname) != APPSVC_RET_OK) { + TRACE_ERROR("failed to set set pkgname id:%d", download_id); + } else { + err = notification_set_execute_option(noti_handle, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b); + } + } else { + TRACE_ERROR("failed to create bundle id:%d", download_id); + } + } + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set service id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, + DP_NOTIFICATION_FAILED_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, + DP_NOTIFICATION_FAILED_INDICATOR_ICON_PATH); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set icon id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + } + + if (b != NULL) + bundle_free(b); + + err = notification_set_property(noti_handle, + NOTIFICATION_PROP_DISABLE_TICKERNOTI); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set property id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + err = notification_set_display_applist(noti_handle, + NOTIFICATION_DISPLAY_APP_ALL ^ NOTIFICATION_DISPLAY_APP_INDICATOR); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set display app all id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + int priv_id = 0; + err = notification_insert(noti_handle, &priv_id); + if (err != NOTIFICATION_ERROR_NONE) { + TRACE_ERROR("failed to set priv_id id:%d error:%s", download_id, __dp_noti_error_str(err)); + } + + //TRACE_DEBUG("m_noti_id [%d]", priv_id); + notification_free(noti_handle); + + return priv_id; +} +#else +void dp_notification_clear_ongoings() +{ + return; +} +#endif diff --git a/provider/download-provider-notify.c b/provider/download-provider-notify.c new file mode 100644 index 0000000..3288fde --- /dev/null +++ b/provider/download-provider-notify.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static char *__dp_notify_get_path(pid_t pid) +{ + size_t path_size = sizeof(NOTIFY_DIR) + 21; + char *notify_fifo = (char *)calloc(path_size, sizeof(char)); + if (notify_fifo == NULL) { + TRACE_STRERROR("failed to alocalte fifo path pid:%d", (int)pid); + return NULL; + } + if (snprintf(notify_fifo, path_size,"%s/%d", NOTIFY_DIR, pid) < 0) { + TRACE_STRERROR("failed to make fifo path pid:%d", (int)pid); + free(notify_fifo); + return NULL; + } + return notify_fifo; +} + +int dp_notify_init(pid_t pid) +{ + char *notify_fifo = __dp_notify_get_path(pid); + if (notify_fifo == NULL) + return -1; + int notify_fd = -1; + struct stat fifo_state; + if (stat(notify_fifo, &fifo_state) == 0) // found + unlink(notify_fifo); + if (mkfifo(notify_fifo, 0644/*-rwrr*/) < 0) { + TRACE_STRERROR("failed to make fifo %s", notify_fifo); + } else { + notify_fd = open(notify_fifo, O_RDWR | O_NONBLOCK, 0644); + } + free(notify_fifo); + return notify_fd; +} + +void dp_notify_deinit(pid_t pid) +{ + char *notify_fifo = __dp_notify_get_path(pid); + if (notify_fifo == NULL) + return ; + struct stat fifo_state; + if (stat(notify_fifo, &fifo_state) == 0) // found + unlink(notify_fifo); + free(notify_fifo); +} + +static int __dp_notify_feedback(int sock, int id, int state, int errorcode, unsigned long long received_size) +{ + dp_ipc_event_fmt eventinfo; + memset(&eventinfo, 0x00, sizeof(dp_ipc_event_fmt)); + eventinfo.id = id; + eventinfo.state = state; + eventinfo.errorcode = errorcode; + eventinfo.received_size = received_size; + if (dp_ipc_write(sock, &eventinfo, sizeof(dp_ipc_event_fmt)) < 0) { + // failed to read from socket // ignore this status + return -1; + } + return 0; +} + +int dp_notify_feedback(int sock, void *slot, int id, int state, int errorcode, unsigned long long received_size) +{ + if (__dp_notify_feedback(sock, id, state, errorcode, received_size) < 0) { + TRACE_ERROR("notify failure by IO_ERROR"); + if (slot != NULL) { + dp_client_slots_fmt *base_slot = slot; + if (base_slot->client.notify >= 0) + close(base_slot->client.notify); + base_slot->client.notify = -1; + dp_notify_deinit(base_slot->credential.pid); + TRACE_ERROR("disable notify channel by IO_ERROR"); + } + return -1; + } + return 0; +} diff --git a/provider/download-provider-plugin-download-agent.c b/provider/download-provider-plugin-download-agent.c new file mode 100644 index 0000000..4a9c478 --- /dev/null +++ b/provider/download-provider-plugin-download-agent.c @@ -0,0 +1,994 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include // dlopen +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "xdgmime.h" +#include "content/mime_type.h" + +#define DP_SDCARD_MNT_POINT "/opt/storage/sdcard" +#define DP_MAX_FILE_PATH_LEN 256 +#define DP_MAX_MIME_TABLE_NUM 15 + +typedef struct { + const char *mime; + int content_type; +}mime_table_type; + +const char *ambiguous_mime_type_list[] = { + "text/plain", + "application/octet-stream" +}; + +mime_table_type mime_table[]={ + // PDF + {"application/pdf",DP_CONTENT_PDF}, + // word + {"application/msword",DP_CONTENT_WORD}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.document",DP_CONTENT_WORD}, + // ppt + {"application/vnd.ms-powerpoint",DP_CONTENT_PPT}, + {"application/vnd.openxmlformats-officedocument.presentationml.presentation",DP_CONTENT_PPT}, + // excel + {"application/vnd.ms-excel",DP_CONTENT_EXCEL}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",DP_CONTENT_EXCEL}, + // html + {"text/html",DP_CONTENT_HTML}, + // txt + {"text/txt",DP_CONTENT_TEXT}, + {"text/plain",DP_CONTENT_TEXT}, + // DRM + {"application/vnd.oma.drm.content",DP_CONTENT_SD_DRM}, + {"application/vnd.oma.drm.message",DP_CONTENT_DRM}, + {"application/x-shockwave-flash", DP_CONTENT_FLASH}, + {"application/vnd.tizen.package", DP_CONTENT_TPK}, + {"text/calendar",DP_CONTENT_VCAL}, +}; + +static void *g_da_handle = NULL; +static int (*download_agent_init)(void) = NULL; // int da_init(da_client_cb_t *da_client_callback); +static int (*download_agent_deinit)(void) = NULL; // int da_deinit(); +static int (*download_agent_is_alive)(int) = NULL; // int da_is_valid_download_id(int download_id); +static int (*download_agent_suspend)(int) = NULL; // int da_suspend_download(int download_id); +static int (*download_agent_resume)(int) = NULL; // int da_resume_download(int download_id); +static int (*download_agent_cancel)(int) = NULL; // int da_cancel_download(int download_id); +static int (*download_agent_suspend_without_update)(int) = NULL; // int da_suspend_download_without_update(int download_id); +static int (*download_agent_cancel_without_update)(int) = NULL; // int da_cancel_download_without_update(int download_id); +static int (*download_agent_start)(const char *url, req_data_t *ext_data, da_cb_t *da_cb_data, int *download_id) = NULL; // int da_start_download_with_extension(const char *url, extension_data_t *ext_data, int *download_id); +static dp_content_type __dp_get_content_type(const char *mime, const char *file_path); + +static int __change_error(int err) +{ + int ret = DP_ERROR_NONE; + switch (err) { + case DA_RESULT_OK: + ret = DP_ERROR_NONE; + break; + case DA_ERR_INVALID_ARGUMENT: + ret = DP_ERROR_INVALID_PARAMETER; + break; + case DA_ERR_FAIL_TO_MEMALLOC: + ret = DP_ERROR_OUT_OF_MEMORY; + break; + case DA_ERR_UNREACHABLE_SERVER: + ret = DP_ERROR_NETWORK_UNREACHABLE; + break; + case DA_ERR_HTTP_TIMEOUT: + ret = DP_ERROR_CONNECTION_TIMED_OUT; + break; + case DA_ERR_DISK_FULL: + ret = DP_ERROR_NO_SPACE; + break; + case DA_ERR_INVALID_STATE: + ret = DP_ERROR_INVALID_STATE; + break; + case DA_ERR_NETWORK_FAIL: + ret = DP_ERROR_NETWORK_ERROR; + break; + case DA_ERR_CONNECTION_FAIL: + case DA_ERR_NETWORK_UNAUTHORIZED: + ret = DP_ERROR_CONNECTION_FAILED; + break; + case DA_ERR_INVALID_URL: + ret = DP_ERROR_INVALID_URL; + break; + case DA_ERR_INVALID_INSTALL_PATH: + ret = DP_ERROR_INVALID_DESTINATION; + break; + case DA_ERR_ALREADY_MAX_DOWNLOAD: + ret = DP_ERROR_TOO_MANY_DOWNLOADS; + break; + case DA_ERR_FAIL_TO_CREATE_THREAD: + case DA_ERR_FAIL_TO_ACCESS_FILE: + default: + ret = DP_ERROR_IO_ERROR; + break; + } + return ret; +} + +static int __dp_da_state_feedback(dp_client_slots_fmt *slot, dp_request_fmt *request) +{ + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address"); + return -1; // try cancel + } + + TRACE_INFO("[INFO][%d] state:%s error:%s", request->id, + dp_print_state(request->state), dp_print_errorcode(request->error)); + + int errorcode = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, + request->state, request->error, &errorcode) < 0) { + TRACE_ERROR("logging failure id:%d error:%d", request->id, errorcode); + return -1; // try cancel + } + + request->access_time = (int)time(NULL); + + if (request->state_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, request->id, request->state, request->error, 0) < 0) { + TRACE_ERROR("id:%d disable state callback by IO_ERROR", request->id); + request->state_cb = 0; + } + } + + return 0; +} + +static int __precheck_request(dp_request_fmt *request, int agentid) +{ + if (request == NULL) { + TRACE_ERROR("null-check request req_id:%d", agentid); + return -1; + } + if (request->id < 0 || (request->agent_id != agentid)) { + TRACE_ERROR("id-check request_id:%d agent_id:%d req_id:%d", + request->id, request->agent_id, agentid); + return -1; + } + return 0; +} + +static int __set_file_permission_to_client(dp_client_slots_fmt *slot, dp_request_fmt *request, char *saved_path) +{ + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), (request == NULL ? 0 : request->agent_id)); + return DP_ERROR_INVALID_PARAMETER; + } else if (saved_path == NULL) { + TRACE_ERROR("check null saved path"); + return DP_ERROR_INVALID_PARAMETER; + } + + struct stat lstat_info; + struct stat fstat_info; + int fd; + int errorcode = DP_ERROR_NONE; + char *str = NULL; + str = strrchr(saved_path, '/'); + dp_credential cred = slot->credential; + if (lstat(saved_path, &lstat_info) != -1) { + fd = open (saved_path, O_RDONLY); + if (fd != -1) { + if (fstat(fd, &fstat_info) != -1) { + if (lstat_info.st_mode == fstat_info.st_mode && + lstat_info.st_ino == fstat_info.st_ino && + lstat_info.st_dev == fstat_info.st_dev) { + if ((fchown(fd, cred.uid, cred.gid) != 0) || + (fchmod(fd, S_IRUSR | S_IWUSR | + S_IRGRP | S_IROTH) != 0)) { + TRACE_STRERROR("[ERROR][%d] permission user:%d group:%d", + request->id, cred.uid, cred.gid); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_STRERROR("fstat & lstat info have not matched"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_STRERROR("fstat call failed"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + close(fd); + } else { + TRACE_SECURE_ERROR("open failed for file : %s", saved_path); + errorcode = DP_ERROR_IO_ERROR; + } + } else { + TRACE_STRERROR("lstat call failed"); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + if (errorcode == DP_ERROR_NONE && dp_smack_is_mounted() == 1) { + // get smack_label from sql + char *smack_label = dp_db_get_client_smack_label(slot->pkgname); + if (smack_label == NULL) { + TRACE_SECURE_ERROR("[SMACK][%d] no label", request->id); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else { + size_t len = str - (saved_path); + char *dir_path = (char *)calloc(len + 1, sizeof(char)); + if (dir_path != NULL) { + strncpy(dir_path, saved_path, len); + errorcode = dp_smack_set_label(smack_label, dir_path, saved_path); + free(dir_path); + } else { + TRACE_STRERROR("[ERROR] calloc"); + errorcode = DP_ERROR_OUT_OF_MEMORY; + } + free(smack_label); + } + } + return errorcode; +} + +static void __finished_cb(finished_info_t *info, void *user_req_data, + void *user_client_data) +{ + if (info == NULL) { + TRACE_ERROR("check download info address"); + return ; + } + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), info->download_id); + free(info->etag); + free(info->saved_path); + free(info); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + if (__precheck_request(request, info->download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", info->download_id); + if (dp_cancel_agent_download(info->download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", info->download_id); + free(info->etag); + free(info->saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + int state = DP_STATE_NONE; + int errorcode = DP_ERROR_NONE; + + if (info->http_status > 0) { + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_HTTP_STATUS, (void *)&info->http_status, 0, 0, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set http_status(%d)", request->id, info->http_status); + } + } + + TRACE_SECURE_DEBUG("[FINISH][%d][%s]", request->id, info->saved_path); + if (info->err == DA_RESULT_OK) { + if (info->saved_path != NULL) { + if(strncmp(DP_SDCARD_MNT_POINT, info->saved_path, strlen(DP_SDCARD_MNT_POINT)) != 0) { + errorcode = __set_file_permission_to_client(slot, request, info->saved_path); + } + } else { + TRACE_ERROR("[ERROR][%d] No SavedPath", request->id); + errorcode = DP_ERROR_INVALID_DESTINATION; + } + if (errorcode == DP_ERROR_NONE) + state = DP_STATE_COMPLETED; + else + state = DP_STATE_FAILED; + } else { + if (info->err == DA_RESULT_USER_CANCELED) { + + TRACE_INFO("[CANCELED][%d]", request->id); + + // if state is canceled and error is DP_ERROR_IO_EAGAIN mean ip_changed + if (request->error == DP_ERROR_IO_EAGAIN) { + request->error = DP_ERROR_NONE; + } else { + state = DP_STATE_CANCELED; + errorcode = request->error; + } + + } else { + state = DP_STATE_FAILED; + errorcode = __change_error(info->err); + TRACE_ERROR("[FAILED][%d][%s] agent error:%d", request->id, + dp_print_errorcode(errorcode), info->err); + } + + } + + if (errorcode == DP_ERROR_NONE && info->saved_path != NULL) { + + char *content_name = NULL; + char *str = NULL; + str = strrchr(info->saved_path, '/'); + if (str != NULL) { + str++; + content_name = dp_strdup(str); + } + if (request->file_size == 0) {// missed in download_cb + request->file_size = request->received_size; + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, (void *)&request->file_size, 0, 1, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set content_size(%ld)", request->id, request->file_size); + } + } + // update contentname, savedpath + if (content_name != NULL) { + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (void *)content_name, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set content_name", request->id); + } + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_SAVED_PATH, (void *)info->saved_path, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set saved_path", request->id); + } + free(content_name); + /* update the received file size. + * The last received file size cannot update + * because of reducing update algorithm*/ + if (request->progress_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, request->received_size) < 0) { + TRACE_ERROR("id:%d disable progress callback by IO_ERROR", request->id); + request->progress_cb = 0; + } + } + } + + request->state = state; + request->error = errorcode; + + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download_without_update(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + if (request->noti_type == DP_NOTIFICATION_TYPE_COMPLETE_ONLY || + request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + free(info->etag); + free(info->saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static void __paused_cb(int download_id, void *user_req_data, void *user_client_data) +{ + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), download_id); + return ; + } + dp_queue_manager_wake_up(); +} + +static void __download_info_cb(download_info_t *info, void *user_req_data, void *user_client_data) +{ + if (info == NULL) { + TRACE_ERROR("check download info address"); + return ; + } + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), info->download_id); + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + if (__precheck_request(request, info->download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", info->download_id); + if (dp_cancel_agent_download(info->download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", info->download_id); + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + // update info before sending event + TRACE_SECURE_DEBUG("[DOWNLOAD][%d][%s]", request->id, info->tmp_saved_path); + if (info->tmp_saved_path != NULL) { + int errorcode = DP_ERROR_NONE; + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_MIMETYPE, (void *)info->file_type, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set mimetype", request->id); + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_NAME, (void *)info->content_name, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set contentname", request->id); + } + if (dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (void *)info->tmp_saved_path, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set tmp_saved_path", request->id); + } + if (info->file_size > 0 && dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_CONTENT_SIZE, (void *)&(info->file_size), 0, 1, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set file size", request->id); + } + if (info->etag && dp_db_replace_property(slot->client.dbhandle, request->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (void *)info->etag, 0, 2, &errorcode) < 0) { + TRACE_ERROR("id:%d failed to set etag", request->id); + } + if(strncmp(DP_SDCARD_MNT_POINT, info->tmp_saved_path, strlen(DP_SDCARD_MNT_POINT)) != 0) { + errorcode = __set_file_permission_to_client(slot, request, info->tmp_saved_path); + } + request->error = errorcode; + } else { + request->error = DP_ERROR_IO_ERROR; + } + + if (request->error != DP_ERROR_NONE) { + request->state = DP_STATE_FAILED; + TRACE_ERROR("id:%d try to cancel(%d)", request->id, info->download_id); + if (dp_cancel_agent_download(request->agent_id) < 0) { + TRACE_ERROR("[fail][%d] cancel_agent:%d", request->id, + info->download_id); + } + } else { + request->state = DP_STATE_DOWNLOADING; + request->file_size = info->file_size; // unsigned + TRACE_DEBUG("[STARTED] id:%d agentid:%d", request->id, info->download_id); + } + + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + // notification + if (request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION_ONGOING_UPDATE) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + //get the mime type for dp notification + if (request->noti_type > DP_NOTIFICATION_TYPE_NONE) { + request->content_type = __dp_get_content_type(info->file_type, info->tmp_saved_path); + } + free(info->content_name); + free(info->etag); + free(info->file_type); + free(info->tmp_saved_path); + free(info); + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static void __progress_cb(int download_id, unsigned long long received_size, + void *user_req_data, void *user_client_data) +{ + dp_client_slots_fmt *slot = user_client_data; + dp_request_fmt *request = user_req_data; + if (slot == NULL || request == NULL) { + TRACE_ERROR("check address slot:%p request:%p id:%d agentid:%d", slot, request, (request == NULL ? 0 : request->id), download_id); + return ; + } + CLIENT_MUTEX_LOCK(&slot->mutex); + /* + if (CLIENT_MUTEX_TRYLOCK(&slot->mutex) != 0) { + TRACE_ERROR("slot busy agent_id:%d", download_id); + return ; + } + */ + if (__precheck_request(request, download_id) < 0) { + TRACE_ERROR("error request agent_id:%d", download_id); + if (dp_cancel_agent_download(download_id) < 0) + TRACE_ERROR("failed to call cancel_download(%d)", download_id); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return ; + } + + // For resume case after pause, it change state from connecting to downloading + if (request->state == DP_STATE_CONNECTING) { + request->state = DP_STATE_DOWNLOADING; + if (__dp_da_state_feedback(slot, request) < 0) { + TRACE_ERROR("id:%d check notify channel", request->id); + if (dp_cancel_agent_download(request->agent_id) < 0) + TRACE_ERROR("[fail][%d]cancel_agent", request->id); + } + } + + if (request->state == DP_STATE_DOWNLOADING) { + request->received_size = received_size; + time_t tt = time(NULL); + struct tm *localTime = localtime(&tt); + if(localTime == NULL) { + TRACE_ERROR("[fail]localTime is NULL"); + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return; + } + // send event every 1 second. + if (request->progress_lasttime != localTime->tm_sec) { + request->progress_lasttime = localTime->tm_sec; + + if (request->progress_cb == 1) { + if (slot->client.notify < 0 || + dp_notify_feedback(slot->client.notify, slot, + request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, received_size) < 0) { + // failed to read from socket // ignore this status + TRACE_ERROR("id:%d disable progress callback by IO_ERROR", request->id); + request->progress_cb = 0; + } + } + + if (request->noti_type == DP_NOTIFICATION_TYPE_ALL) { + if (dp_notification_manager_push_notification(slot, request, DP_NOTIFICATION_ONGOING_PROGRESS) < 0) { + TRACE_ERROR("failed to register notification for id:%d", request->id); + } + } + + } + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); +} + +static int __dp_is_ambiguous_mime_type(const char *mime_type) +{ + if (mime_type == NULL) + return -1; + + int index = 0; + int listSize = sizeof(ambiguous_mime_type_list) / sizeof(const char *); + for (index = 0; index < listSize; index++) { + if (0 == strncmp(mime_type, ambiguous_mime_type_list[index], + strlen(ambiguous_mime_type_list[index]))) { + TRACE_DEBUG("It is ambiguous"); + return 0; + } + } + return -1; +} + +static dp_content_type __dp_get_content_type(const char *mime, const char *file_path) +{ + int i = 0; + int type = DP_CONTENT_UNKNOWN; + char *temp_mime = NULL; + if (mime == NULL || strlen(mime) < 1) + return DP_CONTENT_UNKNOWN; + + if ((file_path != NULL) && (strlen(file_path) > 0) && + (__dp_is_ambiguous_mime_type(mime) == 0)) { + const char *ext = strrchr(file_path, '.'); + if (ext == NULL) { + TRACE_ERROR("File Extension is NULL"); + return type; + } + mime_type_get_mime_type(ext + 1, &temp_mime); + } + if (temp_mime == NULL) { + temp_mime = (char *)calloc(1, DP_MAX_FILE_PATH_LEN); + if (temp_mime == NULL) { + TRACE_ERROR("Fail to call calloc"); + return type; + } + strncpy(temp_mime, mime, DP_MAX_FILE_PATH_LEN - 1); + } + TRACE_SECURE_DEBUG("mime type [%s]", temp_mime); + + /* Search a content type from mime table. */ + for (i = 0; i < DP_MAX_MIME_TABLE_NUM; i++) { + if (strncmp(mime_table[i].mime, temp_mime, strlen(temp_mime)) == 0){ + type = mime_table[i].content_type; + break; + } + } + if (type == DP_CONTENT_UNKNOWN) { + const char *unaliased_mime = NULL; + /* unaliased_mimetype means representative mime among similar types */ + unaliased_mime = xdg_mime_unalias_mime_type(temp_mime); + + if (unaliased_mime != NULL) { + TRACE_SECURE_DEBUG("unaliased mime type[%s]",unaliased_mime); + if (strstr(unaliased_mime,"video/") != NULL) + type = DP_CONTENT_VIDEO; + else if (strstr(unaliased_mime,"audio/") != NULL) + type = DP_CONTENT_MUSIC; + else if (strstr(unaliased_mime,"image/") != NULL) + type = DP_CONTENT_IMAGE; + } + } + free(temp_mime); + TRACE_DEBUG("type[%d]", type); + return type; +} + + +int dp_init_agent() +{ + + g_da_handle = dlopen("/usr/lib/libdownloadagent2.so", RTLD_LAZY | RTLD_GLOBAL); + if (!g_da_handle) { + TRACE_ERROR("[dlopen] %s", dlerror()); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + dlerror(); /* Clear any existing error */ + + *(void **) (&download_agent_init) = dlsym(g_da_handle, "da_init"); + if (download_agent_init == NULL ) { + TRACE_ERROR("[dlsym] da_init:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_deinit) = dlsym(g_da_handle, "da_deinit"); + if (download_agent_deinit == NULL ) { + TRACE_ERROR("[dlsym] da_deinit:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_is_alive) = + dlsym(g_da_handle, "da_is_valid_download_id"); + if (download_agent_is_alive == NULL ) { + TRACE_ERROR("[dlsym] da_is_valid_download_id:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_suspend) = + dlsym(g_da_handle, "da_suspend_download"); + if (download_agent_suspend == NULL ) { + TRACE_ERROR("[dlsym] da_suspend_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_resume) = + dlsym(g_da_handle, "da_resume_download"); + if (download_agent_resume == NULL) { + TRACE_ERROR("[dlsym] da_resume_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + +// *(void **) (&download_agent_cancel) = dlsym(g_da_handle, "da_cancel_download_without_update"); + *(void **) (&download_agent_cancel) = + dlsym(g_da_handle, "da_cancel_download"); + if (download_agent_cancel == NULL) { + TRACE_ERROR("[dlsym] da_cancel_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_start) = + dlsym(g_da_handle, "da_start_download"); + if (download_agent_start == NULL) { + TRACE_ERROR("[dlsym] da_start_download:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_cancel_without_update) = dlsym(g_da_handle, "da_cancel_download_without_update"); + if (download_agent_cancel_without_update == NULL) { + TRACE_ERROR("[dlsym] da_cancel_download_without_update:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + *(void **) (&download_agent_suspend_without_update) = dlsym(g_da_handle, "da_suspend_download_without_update"); + if (download_agent_suspend_without_update == NULL) { + TRACE_ERROR("[dlsym] da_suspend_download_without_update:%s", dlerror()); + dlclose(g_da_handle); + g_da_handle = NULL; + return DP_ERROR_OUT_OF_MEMORY; + } + + int da_ret = -1; + da_ret = (*download_agent_init)(); + if (da_ret != DA_RESULT_OK) { + return DP_ERROR_OUT_OF_MEMORY; + } + return DP_ERROR_NONE; +} + +void dp_deinit_agent() +{ + if (g_da_handle != NULL) { + if (download_agent_deinit != NULL) + (*download_agent_deinit)(); + + dlclose(g_da_handle); + g_da_handle = NULL; + } +} + +// 1 : alive +// 0 : not alive +int dp_is_alive_download(int req_id) +{ + int da_ret = 0; + if (req_id < 0) + return 0; + if (download_agent_is_alive != NULL) + da_ret = (*download_agent_is_alive)(req_id); + return da_ret; +} + +// 0 : success +// -1 : failed +int dp_cancel_agent_download(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_cancel != NULL) { + if ((*download_agent_cancel)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +int dp_pause_agent_download(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_suspend != NULL) { + if ((*download_agent_suspend)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + + +// 0 : success +// -1 : failed +int dp_cancel_agent_download_without_update(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_cancel_without_update != NULL) { + if ((*download_agent_cancel_without_update)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +int dp_pause_agent_download_without_update(int req_id) +{ + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return -1; + } + if (dp_is_alive_download(req_id) == 0) { + TRACE_ERROR("[CHECK agent-id:%d] dead request", req_id); + return -1; + } + if (download_agent_suspend_without_update != NULL) { + if ((*download_agent_suspend_without_update)(req_id) == DA_RESULT_OK) + return 0; + } + return -1; +} + +// 0 : success +// -1 : failed +// -2 : pended +int dp_start_agent_download(void *slot, void *request) +{ + int da_ret = -1; + int req_dl_id = -1; + req_data_t *req_data = NULL; + + dp_client_slots_fmt *base_slot = slot; + dp_request_fmt *base_req = request; + + if (slot == NULL || request == NULL) { + TRACE_ERROR("check slot or request address"); + return DP_ERROR_INVALID_PARAMETER; + } + + da_cb_t da_cb = { + __download_info_cb, + __progress_cb, + __finished_cb, + __paused_cb + }; + + req_data = (req_data_t *)calloc(1, sizeof(req_data_t)); + if (req_data == NULL) { + TRACE_ERROR("[ERROR] calloc"); + return DP_ERROR_OUT_OF_MEMORY; + } + + int errorcode = DP_ERROR_NONE; + unsigned length = 0; + char *url = NULL; + char *destination = NULL; + char *tmp_saved_path = NULL; + char *user_tmp_file_path = NULL; + char *filename = NULL; + char *etag = NULL; + int user_network_bonding = 0; + + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_URL, (unsigned char **)&url, &length, &errorcode) < 0 || + url == NULL) { + free(req_data); + if (errorcode == DP_ERROR_NO_DATA) { + TRACE_ERROR("url id:%d NO_DATA", base_req->id); + return DP_ERROR_INVALID_URL; + } else { + TRACE_ERROR("url id:%d DISK_BUSY", base_req->id); + return DP_ERROR_DISK_BUSY; + } + } + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_TEMP_FILE_PATH, (unsigned char **)&user_tmp_file_path, &length, &errorcode) < 0 || + user_tmp_file_path == NULL) { + TRACE_DEBUG("user_tmp_file_path id:%d NO_DATA", base_req->id); + } + + if (user_tmp_file_path != NULL) + req_data->temp_file_path = user_tmp_file_path; + else { + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_FILENAME, (unsigned char **)&filename, &length, &errorcode) < 0 || + filename == NULL) { + TRACE_DEBUG("filename id:%d NO_DATA", base_req->id); + } else + req_data->file_name = filename; + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_DESTINATION, (unsigned char **)&destination, &length, &errorcode) < 0 || + destination == NULL) { + TRACE_DEBUG("destination id:%d NO_DATA", base_req->id); + } else + req_data->install_path = destination; + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_DOWNLOAD, DP_DB_COL_TMP_SAVED_PATH, (unsigned char **)&tmp_saved_path, &length, &errorcode) < 0 || + tmp_saved_path == NULL) { + TRACE_DEBUG("tmp_saved_path id:%d NO_DATA", base_req->id); + } + } + + if (tmp_saved_path != NULL) { + if (dp_db_get_property_string(base_slot->client.dbhandle, base_req->id, DP_TABLE_DOWNLOAD, DP_DB_COL_ETAG, (unsigned char **)&etag, &length, &errorcode) < 0 || + etag == NULL) { + TRACE_DEBUG("etag id:%d NO_DATA", base_req->id); + } + if (etag != NULL) { + TRACE_DEBUG("try to resume id:%d", base_req->id); + req_data->etag = etag; + req_data->temp_file_path = tmp_saved_path; + } else { + /* FIXME later : It is better to handle the unlink function in download agaent module + * or in upload the request data to memory after the download provider process is restarted */ + TRACE_SECURE_INFO("try to restart id:%d remove tmp file:%s", + base_req->id, tmp_saved_path); + if (dp_is_file_exist(tmp_saved_path) == 0) { + if (unlink(tmp_saved_path) != 0) + TRACE_STRERROR("failed to remove file id:%d", base_req->id); + } + } + } + if( dp_db_get_property_int(base_slot->client.dbhandle, base_req->id, DP_TABLE_REQUEST, DP_DB_COL_NETWORK_BONDING, (int *)&user_network_bonding, &errorcode) < 0 || + user_network_bonding < 0) { + TRACE_DEBUG("unable to get network bonding value for id:%d", base_req->id); + } else + req_data->network_bonding = user_network_bonding; + + req_data->pkg_name = base_slot->pkgname; + + // get headers list from header table(DB) + int headers_count = dp_db_check_duplicated_int(base_slot->client.dbhandle, DP_TABLE_HEADERS, DP_DB_COL_ID, base_req->id, &errorcode); + if (headers_count > 0) { + req_data->request_header = calloc(headers_count, sizeof(char *)); + if (req_data->request_header != NULL) { + headers_count = dp_db_get_http_headers_list(base_slot->client.dbhandle, base_req->id, (char **)req_data->request_header, &errorcode); + if (headers_count > 0) + req_data->request_header_count = headers_count; + } + } + + req_data->user_client_data = (void *)slot; + req_data->user_req_data = (void *)request; + + // call start API of agent lib + if (download_agent_start != NULL) + da_ret = (*download_agent_start)(url, req_data, &da_cb, &req_dl_id); + if (req_data->request_header_count > 0) { + int len = 0; + int i = 0; + len = req_data->request_header_count; + for (i = 0; i < len; i++) + free((void *)(req_data->request_header[i])); + free(req_data->request_header); + } + free(url); + free(destination); + free(tmp_saved_path); + free(user_tmp_file_path); + free(filename); + free(etag); + free(req_data); + + if (da_ret == DA_RESULT_OK) { + TRACE_DEBUG("request id :%d SUCCESS agent_id:%d", base_req->id, req_dl_id); + base_req->agent_id = req_dl_id; + } + return __change_error(da_ret); +} + +int dp_resume_agent_download(int req_id) +{ + int da_ret = -1; + if (req_id < 0) { + TRACE_ERROR("[NULL-CHECK] req_id"); + return DP_ERROR_INVALID_PARAMETER; + } + if (download_agent_resume != NULL) + da_ret = (*download_agent_resume)(req_id); + if (da_ret == DA_RESULT_OK) + return DP_ERROR_NONE; + else if (da_ret == DA_ERR_INVALID_STATE) + return DP_ERROR_INVALID_STATE; + return __change_error(da_ret); +} + diff --git a/provider/download-provider-pthread.c b/provider/download-provider-pthread.c new file mode 100644 index 0000000..3ef2816 --- /dev/null +++ b/provider/download-provider-pthread.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "download-provider-log.h" +#include "download-provider-pthread.h" + +static char *__print_pthread_error(int code) +{ + switch(code) + { + case 0: + return "NONE"; + case EINVAL: + return "EINVAL"; + case ENOMEM: + return "ENOMEM"; + case EBUSY: + return "EBUSY"; + case EDEADLK: + return "EDEADLK"; + } + return "UNKNOWN"; +} + +int dp_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + int ret = pthread_mutex_init(mutex, attr); + if (0 == ret || EBUSY == ret) + return 0; + else + TRACE_STRERROR("error:%d.%s", ret, __print_pthread_error(ret)); + return -1; +} + +void dp_mutex_lock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_lock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); +} + +int dp_mutex_check_lock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_lock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + return ret; +} + +int dp_mutex_trylock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_trylock(mutex); + if (ret != 0 && ret != EINVAL) { + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + } + return ret; +} + +int dp_mutex_timedlock(pthread_mutex_t *mutex, int sec, const char *func, int line) +{ + struct timespec deltatime; + deltatime.tv_sec = sec; + deltatime.tv_nsec = 0; + int ret = pthread_mutex_timedlock(mutex, &deltatime); + if (ret != 0) { + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); + } + return ret; +} + +void dp_mutex_unlock(pthread_mutex_t *mutex, const char *func, int line) +{ + int ret = pthread_mutex_unlock(mutex); + if (ret != 0) + TRACE_STRERROR("%s:%d error:%d.%s", func, line, ret, + __print_pthread_error(ret)); +} + +void dp_mutex_destroy(pthread_mutex_t *mutex) +{ + int ret = pthread_mutex_destroy(mutex); + if (ret != 0) { + TRACE_STRERROR("error:%d.%s", ret, __print_pthread_error(ret)); + if(EBUSY == ret) { + if (pthread_mutex_unlock(mutex) == 0) + pthread_mutex_destroy(mutex); + } + } +} diff --git a/provider/download-provider-queue-manager.c b/provider/download-provider-queue-manager.c new file mode 100644 index 0000000..41f4a36 --- /dev/null +++ b/provider/download-provider-queue-manager.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include // pthread_kill +#include // ESRCH + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +pthread_mutex_t g_dp_queue_manager_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t g_dp_queue_manager_cond = PTHREAD_COND_INITIALIZER; +pthread_t g_dp_queue_manager_tid = 0; + +static dp_queue_fmt *g_dp_queue_network_all = NULL; +static dp_queue_fmt *g_dp_queue_network_wifi = NULL; +static dp_queue_fmt *g_dp_queue_network_data_network = NULL; +static dp_queue_fmt *g_dp_queue_network_wifi_direct = NULL; + +static dp_queue_fmt **__dp_queue_manager_get_queue(int network) +{ + switch(network) { + case DP_NETWORK_ALL: + //TRACE_DEBUG("network all"); + return &g_dp_queue_network_all; + case DP_NETWORK_WIFI: + //TRACE_DEBUG("network wifi only"); + return &g_dp_queue_network_wifi; + case DP_NETWORK_DATA_NETWORK: + //TRACE_DEBUG("network data network only"); + return &g_dp_queue_network_data_network; + case DP_NETWORK_WIFI_DIRECT: + //TRACE_DEBUG("network wifi-direct"); + return &g_dp_queue_network_wifi_direct; + default: + break; + } + return NULL; +} +int dp_queue_manager_push_queue(void *slot, void *request) +{ + dp_request_fmt *requestp = request; + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : requestp->id)); + return -1; + } + dp_queue_fmt **queue = __dp_queue_manager_get_queue(requestp->network_type); + if (requestp->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id:%d state:%s", requestp->id, dp_print_state(requestp->state)); + return -1; + } + if (dp_queue_push(queue, slot, request) < 0) { + TRACE_ERROR("failed to push to queue id:%d", requestp->id); + return -1; + } + return 0; +} + +void dp_queue_manager_clear_queue(void *request) +{ + dp_request_fmt *requestp = request; + if (request == NULL) { + TRACE_DEBUG("check address request:%p id:%d", + request, (request == NULL ? 0 : requestp->id)); + return ; + } + dp_queue_fmt **queue = __dp_queue_manager_get_queue(requestp->network_type); + dp_queue_clear(queue, request); +} + +// if return negative, queue-manager try again. +static int __dp_queue_manager_try_download(dp_client_slots_fmt *slot, dp_request_fmt *request) +{ + int errorcode = DP_ERROR_NONE; + int result = 0; + + if (slot == NULL || request == NULL) { + TRACE_DEBUG("check address client:%p request:%p id:%d", slot, + request, (request == NULL ? 0 : request->id)); + // return 0 to ignore this call. + return 0; + } + + if (request->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id %d state:%d", request->id, request->state); + return 0; + } + + // check startcount + + request->startcount++; + request->access_time = (int)time(NULL); + + if (dp_db_replace_property(slot->client.dbhandle, request->id, + DP_TABLE_LOGGING, DP_DB_COL_STARTCOUNT, + (void *)&request->startcount, 0, 0, &errorcode) < 0) { + TRACE_ERROR("failed to set startcount"); + return -1; + } + + errorcode = DP_ERROR_NONE; + + if (dp_is_alive_download(request->agent_id) > 0) + errorcode = dp_resume_agent_download(request->agent_id); + else + // call agent start function + errorcode = dp_start_agent_download(slot, request); + + if (errorcode == DP_ERROR_NONE) { + request->state = DP_STATE_CONNECTING; + } else if (errorcode == DP_ERROR_TOO_MANY_DOWNLOADS || + errorcode == DP_ERROR_DISK_BUSY || + errorcode == DP_ERROR_OUT_OF_MEMORY) { + TRACE_ERROR("push queue id:%d error:%s", request->id, dp_print_errorcode(errorcode)); + // PENDED + request->state = DP_STATE_QUEUED; + result = -1; // try again. + } else if (errorcode == DP_ERROR_INVALID_STATE) { // by resume + // ignore this request + result = -1; + TRACE_ERROR("failed to resume id:%d", request->id); + request->agent_id = -1; // workaround. da_agent will an object for this agent_id later + } else if (errorcode != DP_ERROR_NONE) { + request->state = DP_STATE_FAILED; + } + + request->error = errorcode; + + if (result == 0) { // it's not for retrying + int sqlerror = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, + request->state, request->error, &sqlerror) < 0) { + TRACE_ERROR("logging failure id:%d error:%d", request->id, sqlerror); + } + if (errorcode != DP_ERROR_NONE && request->state_cb == 1) { // announce state + + TRACE_ERROR("notify id:%d error:%s", request->id, dp_print_errorcode(errorcode)); + if (dp_notify_feedback(slot->client.notify, slot, + request->id, request->state, request->error, 0) < 0) { + TRACE_ERROR("disable state callback by IO_ERROR id:%d", request->id); + request->state_cb = 0; + } + } + } + + return result; + +} + +static int __dp_queue_manager_check_queue(dp_queue_fmt **queue) +{ + dp_client_slots_fmt *slot = NULL; + dp_request_fmt *request = NULL; + while (dp_queue_pop(queue, (void *)&slot, (void *)&request) == 0) { // pop a request from queue. + TRACE_DEBUG("queue-manager pop a request"); + if (slot == NULL || request == NULL) { + TRACE_DEBUG("queue error client:%p request:%p id:%d", slot, request, (request == NULL ? 0 : request->id)); + continue; + } + + CLIENT_MUTEX_LOCK(&slot->mutex); + + TRACE_DEBUG("queue info slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : request->id)); + + int errorcode = DP_ERROR_NONE; + int download_state = DP_STATE_NONE; + if (slot != NULL && request != NULL && + dp_db_get_property_int(slot->client.dbhandle, request->id, DP_TABLE_LOGGING, DP_DB_COL_STATE, &download_state, &errorcode) < 0) { + TRACE_ERROR("deny checking id:%d db state:%s memory:%s", request->id, dp_print_state(download_state), dp_print_state(request->state)); + errorcode = DP_ERROR_ID_NOT_FOUND; + } + + if (download_state == DP_STATE_QUEUED && __dp_queue_manager_try_download(slot, request) < 0) { + // if failed to start, push at the tail of queue. try again. + if (dp_queue_push(queue, slot, request) < 0) { + TRACE_ERROR("failed to push to queue id:%d", request->id); + int errorcode = DP_ERROR_NONE; + if (dp_db_update_logging(slot->client.dbhandle, request->id, DP_STATE_FAILED, DP_ERROR_QUEUE_FULL, &errorcode) < 0) { + TRACE_ERROR("failed to update log id:%d", request->id); + } + request->state = DP_STATE_FAILED; + request->error = DP_ERROR_QUEUE_FULL; + } + CLIENT_MUTEX_UNLOCK(&slot->mutex); + return -1; // return negative for taking a break + } + + CLIENT_MUTEX_UNLOCK(&slot->mutex); + + slot = NULL; + request = NULL; + } + return 0; +} + +static void *__dp_queue_manager(void *arg) +{ + pthread_cond_init(&g_dp_queue_manager_cond, NULL); + + if (dp_init_agent() != DP_ERROR_NONE) { + TRACE_ERROR("failed to init agent"); + pthread_cond_destroy(&g_dp_queue_manager_cond); + pthread_exit(NULL); + return 0; + } + + do { + + if (g_dp_queue_manager_tid <= 0) { + TRACE_INFO("queue-manager is closed by other thread"); + break; + } + + // check wifi_direct first + if (dp_network_is_wifi_direct() == 1 && __dp_queue_manager_check_queue(&g_dp_queue_network_wifi_direct) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } else { // enter here if disable wifi-direct or download-agent is available + int network_status = dp_network_get_status(); + if (network_status != DP_NETWORK_OFF) { + TRACE_INFO("queue-manager try to check queue network:%d", network_status); + if (g_dp_queue_network_all != NULL && __dp_queue_manager_check_queue(&g_dp_queue_network_all) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } else { + dp_queue_fmt **queue = __dp_queue_manager_get_queue(network_status); + if (__dp_queue_manager_check_queue(queue) < 0) { + TRACE_ERROR("download-agent is busy, try again after 15 seconds"); + } + } + } + } + + struct timeval now; + struct timespec ts; + gettimeofday(&now, NULL); + ts.tv_sec = now.tv_sec + 5; + ts.tv_nsec = now.tv_usec * 1000; + CLIENT_MUTEX_LOCK(&g_dp_queue_manager_mutex); + pthread_cond_timedwait(&g_dp_queue_manager_cond, &g_dp_queue_manager_mutex, &ts); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + + } while (g_dp_queue_manager_tid > 0); + + TRACE_DEBUG("queue-manager's working is done"); + dp_deinit_agent(); + dp_queue_clear_all(&g_dp_queue_network_all); + pthread_cond_destroy(&g_dp_queue_manager_cond); + pthread_exit(NULL); + return 0; +} + +static int __dp_queue_manager_start() +{ + if (g_dp_queue_manager_tid == 0 || + pthread_kill(g_dp_queue_manager_tid, 0) == ESRCH) { + TRACE_DEBUG("try to create queue-manager"); + if (pthread_create(&g_dp_queue_manager_tid, NULL, + __dp_queue_manager, NULL) != 0) { + TRACE_STRERROR("failed to create queue-manager"); + return -1; + } + } + return 0; +} + +void dp_queue_manager_wake_up() +{ + if (g_dp_queue_manager_tid > 0 && + pthread_kill(g_dp_queue_manager_tid, 0) != ESRCH) { + int locked = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_manager_mutex); + if (locked == 0) { + pthread_cond_signal(&g_dp_queue_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + } + } else { + __dp_queue_manager_start(); + } +} + +void dp_queue_manager_kill() +{ + if (g_dp_queue_manager_tid > 0 && + pthread_kill(g_dp_queue_manager_tid, 0) != ESRCH) { + //send signal to queue thread + g_dp_queue_manager_tid = 0; + CLIENT_MUTEX_LOCK(&g_dp_queue_manager_mutex); + pthread_cond_signal(&g_dp_queue_manager_cond); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_manager_mutex); + pthread_cancel(g_dp_queue_manager_tid); + int status; + pthread_join(g_dp_queue_manager_tid, (void **)&status); + } +} diff --git a/provider/download-provider-queue.c b/provider/download-provider-queue.c new file mode 100644 index 0000000..ad038fd --- /dev/null +++ b/provider/download-provider-queue.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include +#include + +/* queue + * 1. push : at the tail of linked list + * 2. pop : at the head of linked list + * 3. priority push : at the head of linked list + * 4. in pop, check client of slot, search request by download_id + */ + +//dp_queue_fmt *g_dp_queue = NULL; // head of linked list +pthread_mutex_t g_dp_queue_mutex = PTHREAD_MUTEX_INITIALIZER; + +// normal . push at the tail of queue. +int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + dp_client_slots_fmt *baseslot = slot; + dp_request_fmt *new_request = request; + if (slot == NULL || request == NULL || new_request->id <= 0) { + TRACE_ERROR("check client and request memory address"); + return -1; + } else if (new_request->id <= 0) { + TRACE_ERROR("check slot or download id", new_request->id); + return -1; + } else if (new_request->state != DP_STATE_QUEUED) { + TRACE_ERROR("check id:%d state:%s", new_request->id, dp_print_state(new_request->state)); + return -1; + } + + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + // search the tail of queue + int i = 0; + dp_queue_fmt *tailp = *queue; + dp_queue_fmt *prevp = NULL; + TRACE_DEBUG("queue req slot:%p request:%p id:%d", slot, request, (request == NULL ? 0 : new_request->id)); + for (; tailp != NULL; i++) { + dp_request_fmt *qrequestp = tailp->request; + if (tailp->slot == NULL || tailp->request == NULL || + qrequestp->state != DP_STATE_QUEUED) { + TRACE_DEBUG("queue error %d slot:%p request:%p id:%d", i, tailp->slot, tailp->request, (tailp->request == NULL ? 0 : ((dp_request_fmt *)tailp->request)->id)); + } else if (tailp->slot == slot && tailp->request == request && qrequestp->id == new_request->id) { + TRACE_INFO("queue duplicte %d slot:%p request:%p id:%d", i, slot, request, new_request->id); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return 0; + } else { + TRACE_INFO("queue info %d slot:%p request:%p id:%d %s", i, tailp->slot, tailp->request, ((dp_request_fmt *)tailp->request)->id, ((dp_client_slots_fmt *)tailp->slot)->pkgname); + } + prevp = tailp; + tailp = tailp->next; + } + dp_queue_fmt *new_queue = (dp_queue_fmt *)malloc(sizeof(dp_queue_fmt)); + if (new_queue != NULL) { + new_queue->slot = slot; + new_queue->request = request; + new_queue->next = NULL; + if (prevp == NULL) + *queue = new_queue; + else + prevp->next = new_queue; + } else { + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return -1; + } + TRACE_DEBUG("queue push %d info:%s id:%d", i, baseslot->pkgname, new_request->id); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return 0; +} + +int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return -1; + } + if (slot == NULL || request == NULL) { + TRACE_ERROR("check client and request memory address"); + return -1; + } + + int lock = CLIENT_MUTEX_TRYLOCK(&g_dp_queue_mutex); + if (lock != 0) { + TRACE_DEBUG("skip queue is used by other thread"); + return 0; + } + if (*queue == NULL) { + //TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return -1; + } + // get a head of queue + int ret = -1; + dp_queue_fmt *popp; + do { + popp = *queue; + *queue = popp->next; + dp_client_slots_fmt *slotp = popp->slot; + dp_request_fmt *requestp = popp->request; + if (slotp == NULL || requestp == NULL || + requestp->state != DP_STATE_QUEUED) { + TRACE_DEBUG("queue error slot:%p request:%p id:%d", popp->slot, popp->request, (requestp == NULL ? 0 : requestp->id)); + free(popp); + } else { + TRACE_INFO("queue pop slot:%p request:%p id:%d %s", popp->slot, popp->request, requestp->id, slotp->pkgname); + *slot = popp->slot; + *request = popp->request; + ret = 0; + free(popp); + break; + } + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return ret; +} + +void dp_queue_clear(dp_queue_fmt **queue, void *request) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + if (request == NULL) { + TRACE_ERROR("check client and request memory address"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + int i = 0; + dp_queue_fmt *tailp = *queue; + dp_queue_fmt *prevp = NULL; + TRACE_DEBUG("queue clear req request:%p id:%d", request, (request == NULL ? 0 : ((dp_request_fmt *)request)->id)); + for (; tailp != NULL; i++) { + dp_request_fmt *requestp = tailp->request; + TRACE_DEBUG("queue info %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id)); + if (requestp == request) { + // clear. + if (prevp == NULL) + *queue = tailp->next; + else + prevp->next = tailp->next; + TRACE_DEBUG("queue clear this %d request:%p id:%d", i, requestp, (requestp == NULL ? 0 : requestp->id)); + free(tailp); + break; + } + prevp = tailp; + tailp = tailp->next; + } + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); +} + +void dp_queue_clear_all(dp_queue_fmt **queue) +{ + if (queue == NULL) { + TRACE_ERROR("check memory address of queue"); + return ; + } + CLIENT_MUTEX_LOCK(&g_dp_queue_mutex); + if (queue == NULL || *queue == NULL) { + TRACE_DEBUG("queue empty"); + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); + return ; + } + // get a head of queue + do { + dp_queue_fmt *popp = *queue; + *queue = popp->next; + TRACE_DEBUG("queue clear slot:%p request:%p id:%d", popp->slot, popp->request, (popp->request == NULL ? 0 : ((dp_request_fmt *)popp->request)->id)); + free(popp); + } while (*queue != NULL); // if meet the tail of queue + CLIENT_MUTEX_UNLOCK(&g_dp_queue_mutex); +} diff --git a/provider/download-provider-smack.c b/provider/download-provider-smack.c new file mode 100644 index 0000000..3d6b78e --- /dev/null +++ b/provider/download-provider-smack.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define SMACKFS_MAGIC 0x43415d53 +#define SMACKFS_MNT "/smack" + +static int __dp_smack_is_transmute(char *path) +{ + char *dir_label = NULL; + int ret = -1; + if (smack_getlabel(path, &dir_label, SMACK_LABEL_TRANSMUTE) == 0 && + dir_label != NULL) { + if (strncmp(dir_label, "TRUE", strlen(dir_label)) == 0) + ret = 0; + } + free(dir_label); + return ret; +} + +int dp_smack_is_mounted() +{ + struct statfs sfs; + int ret; + do { + ret = statfs(SMACKFS_MNT, &sfs); + } while (ret < 0 && errno == EINTR); + if (ret) { + TRACE_ERROR("[SMACK ERROR]"); + return -1; + } + if (sfs.f_type == SMACKFS_MAGIC) { + return 1; + } + TRACE_ERROR("[SMACK DISABLE]"); + return 0; +} + +int dp_smack_set_label(char *label, char *source, char *target) +{ + if (label == NULL || source == NULL || target == NULL) + return DP_ERROR_PERMISSION_DENIED; + + int is_setted_dir_label = 0; + int errorcode = DP_ERROR_NONE; + + if (__dp_smack_is_transmute(source) < 0) { + TRACE_SECURE_ERROR("[SMACK] no transmute:%s", source); + } else { + char *dir_label = NULL; + if (smack_getlabel(source, &dir_label, SMACK_LABEL_ACCESS) == 0) { + if (smack_have_access(label, dir_label, "t") > 0) { + if (smack_setlabel(target, dir_label, SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", dir_label); + errorcode = DP_ERROR_PERMISSION_DENIED; + } else { + is_setted_dir_label = 1; + } + } else { + TRACE_SECURE_ERROR("[SMACK ERROR] access:%s/%s", label, dir_label); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + } else { + TRACE_SECURE_ERROR("[SMACK ERROR] no label:", source); + errorcode = DP_ERROR_PERMISSION_DENIED; + } + free(dir_label); + } + if (is_setted_dir_label == 0 && + smack_setlabel(target, label, SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", label); + errorcode = DP_ERROR_PERMISSION_DENIED; + // remove file. + if (dp_is_file_exist(target) == 0) + unlink(target); + } + return errorcode; +} + +char *dp_smack_get_label_from_socket(int sock) +{ + char *label = NULL; + if (smack_new_label_from_socket(sock, &label) != 0) { + free(label); + return NULL; + } + return label; +} + +int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir) +{ + if (smack_label == NULL || dir == NULL) { + TRACE_ERROR("check parameter %s/%s", smack_label, dir); + return -1; + } + int ret = -1; + struct stat dstate; + if (stat(dir, &dstate) == 0) { + if ((dstate.st_uid == uid && (dstate.st_mode & (S_IRUSR | S_IWUSR)) == (S_IRUSR | S_IWUSR)) || + (dstate.st_gid == gid && (dstate.st_mode & (S_IRGRP | S_IWGRP)) == (S_IRGRP | S_IWGRP)) || + ((dstate.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH))) { + char *dir_label = NULL; + if (smack_getlabel(dir, &dir_label, SMACK_LABEL_ACCESS) == 0 && + smack_have_access(smack_label, dir_label, "rw") > 0) { + ret = 0; + } else { + TRACE_STRERROR("failed to uid:%d gid:%d smack_label[%s]", uid, gid, smack_label); + if (dir_label) + TRACE_ERROR("failed to get dir_label[%s]", dir_label); + } + free(dir_label); + } else { + TRACE_STRERROR("failed to uid:%d gid:%d smack_label[%s]", uid, gid, smack_label); + } + } else { + TRACE_STRERROR("failed to get state:%s", dir); + } + return ret; +} + +int dp_is_valid_dir(const char *dirpath) +{ + struct stat dir_state; + int stat_ret; + if (dirpath == NULL) { + TRACE_ERROR("check path"); + return -1; + } + stat_ret = stat(dirpath, &dir_state); + if (stat_ret == 0 && S_ISDIR(dir_state.st_mode)) { + return 0; + } + TRACE_STRERROR("failed to valid dir:%s", dirpath); + return -1; +} + +void dp_rebuild_dir(const char *dirpath, mode_t mode) +{ + if (dp_is_valid_dir(dirpath) < 0) { + if (mkdir(dirpath, mode) == 0) { + TRACE_INFO("check directory:%s", dirpath); + if (smack_setlabel(dirpath, "_", SMACK_LABEL_ACCESS) != 0) { + TRACE_SECURE_ERROR("failed to set smack label:%s", dirpath); + } + } else { + TRACE_STRERROR("failed to create directory:%s", dirpath); + } + } +} diff --git a/provider/download-provider-utils.c b/provider/download-provider-utils.c new file mode 100644 index 0000000..a1fb736 --- /dev/null +++ b/provider/download-provider-utils.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "download-provider-log.h" + +char *dp_strdup(char *src) +{ + char *dest = NULL; + size_t src_len = 0; + + if (src == NULL) { + TRACE_ERROR("[CHECK PARAM]"); + return NULL; + } + + src_len = strlen(src); + if (src_len <= 0) { + TRACE_ERROR("[CHECK PARAM] len[%d]", src_len); + return NULL; + } + + dest = (char *)calloc(src_len + 1, sizeof(char)); + if (dest == NULL) { + TRACE_STRERROR("[CHECK] allocation"); + return NULL; + } + memcpy(dest, src, src_len * sizeof(char)); + dest[src_len] = '\0'; + + return dest; +} + +int dp_is_file_exist(const char *file_path) +{ + struct stat file_state; + int stat_ret; + + if (file_path == NULL) { + TRACE_ERROR("[NULL-CHECK] file path is NULL"); + return -1; + } + + stat_ret = stat(file_path, &file_state); + + if (stat_ret == 0) + if (file_state.st_mode & S_IFREG) + return 0; + + return -1; +} + +long dp_get_file_modified_time(const char *file_path) +{ + struct stat file_state; + int stat_ret; + + if (file_path == NULL) { + TRACE_ERROR("[NULL-CHECK] file path is NULL"); + return -1; + } + + stat_ret = stat(file_path, &file_state); + if (stat_ret == 0) + return file_state.st_mtime; + return -1; +} + +int dp_remove_file(const char *file_path) +{ + if ((file_path != NULL && strlen(file_path) > 0) && + dp_is_file_exist(file_path) == 0) { + if (unlink(file_path) != 0) { + TRACE_STRERROR("failed to remove file"); + return -1; + } + return 0; + } + return -1; +} diff --git a/provider/include/download-provider-client-manager.h b/provider/include/download-provider-client-manager.h new file mode 100644 index 0000000..0bb02ec --- /dev/null +++ b/provider/include/download-provider-client-manager.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_CLIENT_MANAGER_H +#define DOWNLOAD_PROVIDER_CLIENT_MANAGER_H + +#include +#include + +typedef struct { + dp_credential credential; + pthread_mutex_t mutex; // lock whenever access client variable + pthread_t thread; + char *pkgname; + dp_client_fmt client; +} dp_client_slots_fmt; + +int dp_client_slot_free(dp_client_slots_fmt *slot); +void dp_broadcast_signal(); +char *dp_db_get_client_smack_label(const char *pkgname); + +#endif diff --git a/provider/include/download-provider-client.h b/provider/include/download-provider-client.h new file mode 100644 index 0000000..6ce8d14 --- /dev/null +++ b/provider/include/download-provider-client.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_CLIENT_H +#define DOWNLOAD_PROVIDER_CLIENT_H + +#include +#include + +typedef struct { + int state; // downloading state, to prevent the crash, placed at the head of structure. + int id; // ID created in create request in requests thread. + int agent_id; + int error; + int network_type; + int access_time; + unsigned state_cb; // set : 1 unset : 0 + unsigned progress_cb; // set : 1 unset : 0 + unsigned startcount; + size_t progress_lasttime; + unsigned long long received_size; // progress + unsigned long long file_size; + dp_content_type content_type; + int noti_type; + int noti_priv_id; + void *next; +} dp_request_fmt; + +typedef struct { + int channel; // ipc , if negative means dummy client + int notify; // event + int access_time; + void *dbhandle; + dp_request_fmt *requests; +} dp_client_fmt; + +void *dp_client_request_thread(void *arg); +char *dp_print_state(int state); +char *dp_print_errorcode(int errorcode); +char *dp_print_section(short section); +char *dp_print_property(unsigned property); +void dp_request_create(dp_client_fmt *client, dp_request_fmt *request); +void dp_request_free(dp_request_fmt *request); +int dp_request_destroy(dp_client_fmt *client, dp_ipc_fmt *ipc_info, dp_request_fmt *requestp); +void dp_client_clear_requests(void *slotp); + +#endif diff --git a/provider/include/download-provider-config.h b/provider/include/download-provider-config.h new file mode 100755 index 0000000..5ab6bce --- /dev/null +++ b/provider/include/download-provider-config.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_CONFIG_H +#define DOWNLOAD_PROVIDER_CONFIG_H + +#include + +// client-manager +#define DP_MAX_CLIENTS 32 // the maximun number of slots +#define DP_CARE_CLIENT_MANAGER_INTERVAL 120 +#define DP_CARE_CLIENT_REQUEST_INTERVAL 120 +#define DP_CARE_CLIENT_CLEAR_INTERVAL 200 + +// database +#define DP_CARE_CLIENT_INFO_PERIOD 48 // hour + +// each client thread +#define DP_MAX_REQUEST MAX_DOWNLOAD_HANDLE +#define DP_LOG_DB_LIMIT_ROWS 1000 +#define DP_LOG_DB_CLEAR_LIMIT_ONE_TIME 100 + +// queue-manager +#define DP_MAX_DOWNLOAD_AT_ONCE 50 + +#endif diff --git a/provider/include/download-provider-db-defs.h b/provider/include/download-provider-db-defs.h new file mode 100644 index 0000000..6fd1a46 --- /dev/null +++ b/provider/include/download-provider-db-defs.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_DB_DEFS_H +#define DOWNLOAD_PROVIDER_DB_DEFS_H + +#define DP_DBFILE_CLIENTS ".download-provider-clients" + +// provider have a groups database file. +#define DP_TABLE_CLIENTS "clients" +// each client has a database file with below tables. file is named as pkgname. +#define DP_TABLE_LOGGING "logging" +#define DP_TABLE_REQUEST "request" +#define DP_TABLE_DOWNLOAD "download" +#define DP_TABLE_HEADERS "header" +#define DP_TABLE_NOTIFICATION "notification" + +// common +#define DP_DB_COL_ROW_ID "ROWID" +#define DP_DB_COL_ID "id" +#define DP_DB_COL_CREATE_TIME "createtime" +#define DP_DB_COL_ACCESS_TIME "accesstime" + +// clients table +#define DP_DB_COL_SMACK_LABEL "smack_label" +#define DP_DB_COL_PACKAGE "package" +#define DP_DB_COL_UID "uid" +#define DP_DB_COL_GID "gid" +#define DP_DB_COL_REQUEST_COUNT "requests" + +// logging table +#define DP_DB_COL_STATE "state" +#define DP_DB_COL_ERRORCODE "errorcode" +#define DP_DB_COL_AUTO_DOWNLOAD "auto_download" +#define DP_DB_COL_STARTCOUNT "startcount" + +// request table +#define DP_DB_COL_URL "url" +#define DP_DB_COL_DESTINATION "destination" +#define DP_DB_COL_FILENAME "filename" +#define DP_DB_COL_STATE_EVENT "state_event" +#define DP_DB_COL_PROGRESS_EVENT "progress_event" +#define DP_DB_COL_NETWORK_TYPE "network_type" +#define DP_DB_COL_NETWORK_BONDING "network_bonding" +#define DP_DB_COL_TEMP_FILE_PATH "temp_file_path" + +// download table +#define DP_DB_COL_SAVED_PATH "saved_path" +#define DP_DB_COL_TMP_SAVED_PATH "tmp_saved_path" +#define DP_DB_COL_MIMETYPE "mimetype" +#define DP_DB_COL_CONTENT_NAME "content_name" +#define DP_DB_COL_ETAG "etag" +#define DP_DB_COL_CONTENT_SIZE "content_size" +#define DP_DB_COL_HTTP_STATUS "http_status" + +// notification table +#define DP_DB_COL_NOTI_TYPE "type" +#define DP_DB_COL_NOTI_SUBJECT "subject" +#define DP_DB_COL_NOTI_DESCRIPTION "description" +#define DP_DB_COL_NOTI_PRIV_ID "priv_id" +#define DP_DB_COL_NOTI_RAW_ONGOING "raw_ongoing" +#define DP_DB_COL_NOTI_RAW_COMPLETE "raw_completed" +#define DP_DB_COL_NOTI_RAW_FAIL "raw_failed" + +// http headers table +#define DP_DB_COL_HEADER_FIELD "header_field" +#define DP_DB_COL_HEADER_DATA "header_data" + + + +// when a client is accepted, add +// when disconnected with no request, clear +// if exist, it's possible to be remain some requests +#define DP_SCHEMA_CLIENTS "CREATE TABLE IF NOT EXISTS clients(\ +id INTEGER UNIQUE PRIMARY KEY,\ +package TEXT UNIQUE NOT NULL,\ +smack_label TEXT DEFAULT NULL,\ +uid INTEGER DEFAULT 0,\ +gid INTEGER DEFAULT 0,\ +requests INTEGER DEFAULT 0,\ +createtime DATE,\ +accesstime DATE\ +)" + +// limitation : 1000 rows, 48 hours standard by createtime +#define DP_SCHEMA_LOGGING "CREATE TABLE IF NOT EXISTS logging(\ +id INTEGER UNIQUE PRIMARY KEY DESC NOT NULL,\ +state INTEGER DEFAULT 0,\ +errorcode INTEGER DEFAULT 0,\ +auto_download BOOLEAN DEFAULT 0,\ +startcount INTEGER DEFAULT 0,\ +createtime DATE,\ +accesstime DATE\ +)" + +#define DP_SCHEMA_REQUEST "CREATE TABLE IF NOT EXISTS request(\ +id INTEGER UNIQUE PRIMARY KEY,\ +state_event BOOLEAN DEFAULT 0,\ +progress_event BOOLEAN DEFAULT 0,\ +network_type TINYINT DEFAULT 3,\ +filename TEXT DEFAULT NULL,\ +destination TEXT DEFAULT NULL,\ +url TEXT DEFAULT NULL,\ +temp_file_path TEXT DEFAULT NULL,\ +network_bonding BOOLEAN DEFAULT 0,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_DOWNLOAD "CREATE TABLE IF NOT EXISTS download(\ +id INTEGER UNIQUE PRIMARY KEY,\ +http_status INTEGER DEFAULT 0,\ +content_size UNSIGNED BIG INT DEFAULT 0,\ +mimetype VARCHAR(64) DEFAULT NULL,\ +content_name TEXT DEFAULT NULL,\ +saved_path TEXT DEFAULT NULL,\ +tmp_saved_path TEXT DEFAULT NULL,\ +etag TEXT DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_NOTIFICATION "CREATE TABLE IF NOT EXISTS notification(\ +id INTEGER UNIQUE PRIMARY KEY,\ +subject TEXT DEFAULT NULL,\ +description TEXT DEFAULT NULL,\ +type INTEGER DEFAULT 0,\ +priv_id INTEGER DEFAULT -1,\ +raw_completed BLOB DEFAULT NULL,\ +raw_failed BLOB DEFAULT NULL,\ +raw_ongoing BLOB DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_HEADER "CREATE TABLE IF NOT EXISTS header(\ +id INTEGER NOT NULL,\ +header_field TEXT DEFAULT NULL,\ +header_data TEXT DEFAULT NULL,\ +FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE\ +)" + +#define DP_SCHEMA_LOGGING_INDEX "CREATE UNIQUE INDEX IF NOT EXISTS requests_index ON logging (id, state, errorcode, createtime, accesstime)" + + + +#endif diff --git a/provider/include/download-provider-db.h b/provider/include/download-provider-db.h new file mode 100755 index 0000000..6f3a938 --- /dev/null +++ b/provider/include/download-provider-db.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_DB_H +#define DOWNLOAD_PROVIDER_DB_H + +int dp_db_check_connection(void *handle); +int dp_db_open_client_manager(void **handle); +int dp_db_open_client(void **handle, char *pkgname); +int dp_db_open_client_v2(void **handle, char *pkgname); +int dp_db_remove_database(char *pkgname, long now_time, long diff_time); +int dp_db_get_ids(void *handle, const char *table, char *idcolumn, int *ids, const char *where, const int limit, char *ordercolumn, char *ordering, int *error); +int dp_db_get_crashed_ids(void *handle, const char *table, int *ids, const int limit, int *error); +void dp_db_close(void *handle); +void dp_db_reset(void *stmt); +void dp_db_finalize(void *stmt); +int dp_db_get_errorcode(void *handle); + +int dp_db_check_duplicated_int(void *handle, const char *table, const char *column, const int value, int *error); +int dp_db_check_duplicated_string(void *handle, const int id, const char *table, const char *column, const int is_like, const char *value, int *error); +int dp_db_update_client_info(void *handle, const char *pkgname, const char *smack, const int uid, const int gid, int *error); +int dp_db_get_client_property_string(void *handle, const char *pkgname, const char *column, unsigned char **value, unsigned *length, int *error); +int dp_db_new_logging(void *handle, const int id, const int state, const int errorvalue, int *error); +int dp_db_update_logging(void *handle, const int id, const int state, const int errorvalue, int *error); +int dp_db_replace_property(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned length, const unsigned valuetype, int *error); +int dp_db_get_property_string(void *handle, const int id, const char *table, const char *column, unsigned char **value, unsigned *length, int *error); +int dp_db_get_property_int(void *handle, const int id, const char *table, const char *column, void *value, int *error); +int dp_db_unset_property_string(void *handle, const int id, const char *table, const char *column, int *error); +int dp_db_delete(void *handle, const int id, const char *table, int *error); + + +int dp_db_new_header(void *handle, const int id, const char *field, const char *value, int *error); +int dp_db_update_header(void *handle, const int id, const char *field, const char *value, int *error); +int dp_db_get_header_value(void *handle, const int id, const char *field, unsigned char **value, unsigned *length, int *error); +int dp_db_cond_delete(void *handle, const int id, const char *table, const char *column, const void *value, const unsigned valuetype, int *error); +int dp_db_get_cond_ids(void *handle, const char *table, const char *getcolumn, const char *column, const int value, int *ids, const int limit, int *error); +int dp_db_get_cond_string(void *handle, const char *table, char *wherecolumn, const int wherevalue, const char *getcolumn, unsigned char **value, unsigned *length, int *error); +int dp_db_limit_rows(void *handle, const char *table, int limit, int *error); +int dp_db_limit_time(void *handle, const char *table, int hours, int *error); +int dp_db_get_http_headers_list(void *handle, int id, char **headers, int *error); + +#endif diff --git a/provider/include/download-provider-ipc.h b/provider/include/download-provider-ipc.h new file mode 100644 index 0000000..afddbe6 --- /dev/null +++ b/provider/include/download-provider-ipc.h @@ -0,0 +1,36 @@ + +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_IPC_H +#define DOWNLOAD_PROVIDER_IPC_H + +#include "download-provider.h" + +int dp_ipc_check_stderr(int basecode); +int dp_ipc_write(int sock, void *value, size_t type_size); +ssize_t dp_ipc_read(int sock, void *value, size_t type_size, + const char *func); + + +dp_ipc_fmt *dp_ipc_get_fmt(int sock); +int dp_ipc_query(int sock, int download_id, short section, + unsigned property, int error, size_t size); + +int dp_ipc_socket_free(int sockfd); + +#endif + diff --git a/provider/include/download-provider-log.h b/provider/include/download-provider-log.h new file mode 100755 index 0000000..5b1b0cd --- /dev/null +++ b/provider/include/download-provider-log.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER2_LOG_H +#define DOWNLOAD_PROVIDER2_LOG_H + +#ifdef SUPPORT_LOG_MESSAGE +#include +#include +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG DOWNLOAD_PROVIDER_LOG_TAG +#if defined(LOGD) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_DEBUG(format, ARG...) LOGD(format, ##ARG) +#else +#define TRACE_DEBUG(...) do { } while(0) +#endif +#define TRACE_ERROR(format, ARG...) LOGE(format, ##ARG) +#define TRACE_STRERROR(format, ARG...) LOGE(format" [%s]", ##ARG, strerror(errno)) +#define TRACE_INFO(format, ARG...) LOGI(format, ##ARG) +#define TRACE_WARN(format, ARG...) LOGW(format, ##ARG) + +#if defined(SECURE_LOGD) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_SECURE_DEBUG(format, ARG...) SECURE_LOGD(format, ##ARG) +#else +#define TRACE_SECURE_DEBUG(...) do { } while(0) +#endif +#if defined(SECURE_LOGI) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_SECURE_INFO(format, ARG...) SECURE_LOGI(format, ##ARG) +#else +#define TRACE_SECURE_INFO(...) do { } while(0) +#endif +#if defined(SECURE_LOGE) && defined(TIZEN_DEBUG_ENABLE) +#define TRACE_SECURE_ERROR(format, ARG...) SECURE_LOGE(format, ##ARG) +#else +#define TRACE_SECURE_ERROR(...) do { } while(0) +#endif + +#else +#define TRACE_DEBUG(...) do { } while(0) +#define TRACE_ERROR(...) do { } while(0) +#define TRACE_STRERROR(...) do { } while(0) +#define TRACE_INFO(...) do { } while(0) +#define TRACE_WARN(...) do { } while(0) +#define TRACE_SECURE_DEBUG(...) do { } while(0) +#define TRACE_SECURE_INFO(...) do { } while(0) +#define TRACE_SECURE_ERROR(...) do { } while(0) +#endif + +#endif diff --git a/provider/include/download-provider-network.h b/provider/include/download-provider-network.h new file mode 100755 index 0000000..73fc12d --- /dev/null +++ b/provider/include/download-provider-network.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_NETWORK_H +#define DOWNLOAD_PROVIDER_NETWORK_H + +#define DP_NETWORK_OFF -1 + +typedef enum { + DP_NETWORK_DATA_NETWORK = 0, + DP_NETWORK_WIFI = 1, + DP_NETWORK_WIFI_DIRECT = 2, + DP_NETWORK_ALL = 3 +} dp_network_defs; + +int dp_network_connection_init(); +void dp_network_connection_destroy(); +int dp_network_get_status(); +int dp_network_is_wifi_direct(); + +#endif diff --git a/provider/include/download-provider-notification-manager.h b/provider/include/download-provider-notification-manager.h new file mode 100644 index 0000000..0ffa740 --- /dev/null +++ b/provider/include/download-provider-notification-manager.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_NOTIFICATION_MANAGER_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_MANAGER_H + +typedef enum { + DP_NOTIFICATION = 0, + DP_NOTIFICATION_ONGOING, + DP_NOTIFICATION_ONGOING_PROGRESS, + DP_NOTIFICATION_ONGOING_UPDATE, +} dp_noti_type; + +void dp_notification_manager_kill(); +void dp_notification_manager_wake_up(); +int dp_notification_manager_clear_notification(void *slot, void *request, const dp_noti_type type); +//int dp_notification_manager_push_notification_ongoing(void *slot, void *request, const dp_noti_type type); +int dp_notification_manager_push_notification(void *slot, void *request, const dp_noti_type type); + +#endif diff --git a/provider/include/download-provider-notification.h b/provider/include/download-provider-notification.h new file mode 100755 index 0000000..eb3f56e --- /dev/null +++ b/provider/include/download-provider-notification.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_NOTIFICATION_H +#define DOWNLOAD_PROVIDER_NOTIFICATION_H + +#ifdef SUPPORT_NOTIFICATION +void dp_notification_set_locale(void); +void dp_notification_clear_locale(void); +void dp_notification_clear_ongoings(void); +int dp_notification_delete_ongoing(const int noti_priv_id); +int dp_notification_delete(const int noti_priv_id); +int dp_notification_ongoing_new(const char *pkgname, const char *subject, unsigned char *raws_buffer, const int raws_length); +int dp_notification_ongoing_update(const int noti_priv_id, const double received_size, const double file_size, const char *subject); +int dp_notification_new(void *dbhandle, const int download_id, const int state, int content_type, const char *pkgname); +#else +void dp_notification_clear_ongoings(void); +#endif + +#endif diff --git a/provider/include/download-provider-notify.h b/provider/include/download-provider-notify.h new file mode 100644 index 0000000..80c21d9 --- /dev/null +++ b/provider/include/download-provider-notify.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_NOTIFY_H +#define DOWNLOAD_PROVIDER_NOTIFY_H + +int dp_notify_init(pid_t pid); +void dp_notify_deinit(pid_t pid); +int dp_notify_feedback(int sock, void *slot, int id, int state, int errorcode, unsigned long long received_size); + +#endif diff --git a/provider/include/download-provider-plugin-download-agent.h b/provider/include/download-provider-plugin-download-agent.h new file mode 100644 index 0000000..e3fb9c7 --- /dev/null +++ b/provider/include/download-provider-plugin-download-agent.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_PLUGIN_DOWNLOAD_AGENT_H +#define DOWNLOAD_PROVIDER_PLUGIN_DOWNLOAD_AGENT_H + +int dp_is_file_exist(const char *file_path); +int dp_init_agent(); +void dp_deinit_agent(); +int dp_start_agent_download(void *slot, void *request); +int dp_resume_agent_download(int req_id); +int dp_pause_agent_download(int req_id); +int dp_cancel_agent_download(int req_id); +int dp_is_alive_download(int req_id); +int dp_cancel_agent_download_without_update(int req_id); +int dp_pause_agent_download_without_update(int req_id); + +#endif diff --git a/provider/include/download-provider-pthread.h b/provider/include/download-provider-pthread.h new file mode 100755 index 0000000..74e6036 --- /dev/null +++ b/provider/include/download-provider-pthread.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_PTHREAD_H +#define DOWNLOAD_PROVIDER_PTHREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// download-provider use default style mutex. +int dp_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +void dp_mutex_lock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_check_lock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_trylock(pthread_mutex_t *mutex, const char *func, int line); +int dp_mutex_timedlock(pthread_mutex_t *mutex, int sec, const char *func, int line); +void dp_mutex_unlock(pthread_mutex_t *mutex, const char *func, int line); +void dp_mutex_destroy(pthread_mutex_t *mutex); + +#define CLIENT_MUTEX_LOCK(mutex) dp_mutex_lock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_CHECKLOCK(mutex) dp_mutex_check_lock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_TRYLOCK(mutex) dp_mutex_trylock(mutex, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_TIMEDLOCK(mutex, sec) dp_mutex_timedlock(mutex, sec, __FUNCTION__, __LINE__) +#define CLIENT_MUTEX_UNLOCK(mutex) dp_mutex_unlock(mutex, __FUNCTION__, __LINE__) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/provider/include/download-provider-queue-manager.h b/provider/include/download-provider-queue-manager.h new file mode 100644 index 0000000..ba7e641 --- /dev/null +++ b/provider/include/download-provider-queue-manager.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_QUEUE_MANAGER_H +#define DOWNLOAD_PROVIDER_QUEUE_MANAGER_H + +void dp_queue_manager_kill(); +void dp_queue_manager_wake_up(); +int dp_queue_manager_push_queue(void *slot, void *request); +void dp_queue_manager_clear_queue(void *request); + +#endif diff --git a/provider/include/download-provider-queue.h b/provider/include/download-provider-queue.h new file mode 100755 index 0000000..a8efcfa --- /dev/null +++ b/provider/include/download-provider-queue.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_QUEUE_H +#define DOWNLOAD_PROVIDER_QUEUE_H + +typedef struct { // manage clients without mutex + void *slot; // client can not be NULL. it will exist in dummy + void *request; + void *next; +} dp_queue_fmt; + +int dp_queue_push(dp_queue_fmt **queue, void *slot, void *request); +int dp_queue_pop(dp_queue_fmt **queue, void **slot, void **request); +void dp_queue_clear(dp_queue_fmt **queue, void *request); +void dp_queue_clear_all(dp_queue_fmt **queue); + +#endif diff --git a/provider/include/download-provider-smack.h b/provider/include/download-provider-smack.h new file mode 100644 index 0000000..aa78d01 --- /dev/null +++ b/provider/include/download-provider-smack.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_SMACK_H +#define DOWNLOAD_PROVIDER_SMACK_H + +#ifdef SUPPORT_SECURITY_PRIVILEGE +#include +#define SECURITY_PRIVILEGE_INTERNET "system::use_internet" +#endif + +int dp_smack_is_mounted(); +int dp_smack_set_label(char *label, char *source, char *target); +char *dp_smack_get_label_from_socket(int sock); +int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir); +void dp_rebuild_dir(const char *dirpath, mode_t mode); +int dp_is_valid_dir(const char *dirpath); + + +#endif diff --git a/provider/include/download-provider-utils.h b/provider/include/download-provider-utils.h new file mode 100644 index 0000000..d965db4 --- /dev/null +++ b/provider/include/download-provider-utils.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_UTILS_H +#define DOWNLOAD_PROVIDER_UTILS_H + +char *dp_strdup(char *src); +int dp_is_file_exist(const char *file_path); +long dp_get_file_modified_time(const char *file_path); +int dp_remove_file(const char *file_path); + +#endif diff --git a/provider/include/download-provider.h b/provider/include/download-provider.h new file mode 100755 index 0000000..92e1fde --- /dev/null +++ b/provider/include/download-provider.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DOWNLOAD_PROVIDER_H +#define DOWNLOAD_PROVIDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DP_STATE_NONE = 0, + DP_STATE_READY = DP_STATE_NONE + 5, // created id, set some info. + DP_STATE_QUEUED = DP_STATE_NONE + 10, // request to start + DP_STATE_CONNECTING = DP_STATE_NONE + 15, // try to connect to url + DP_STATE_DOWNLOADING = DP_STATE_NONE + 20, // started + DP_STATE_PAUSED = DP_STATE_NONE + 30, // paused actually + DP_STATE_COMPLETED = DP_STATE_NONE + 40, + DP_STATE_CANCELED = DP_STATE_NONE + 45, // stopped with error + DP_STATE_FAILED = DP_STATE_NONE + 50 // failed with error +} dp_state_type; + +typedef enum { + DP_ERROR_NONE = 10, + DP_ERROR_INVALID_PARAMETER = DP_ERROR_NONE + 1, + DP_ERROR_OUT_OF_MEMORY = DP_ERROR_NONE + 2, + DP_ERROR_IO_ERROR = DP_ERROR_NONE + 3, + DP_ERROR_NETWORK_UNREACHABLE = DP_ERROR_NONE + 4, + DP_ERROR_CONNECTION_TIMED_OUT = DP_ERROR_NONE + 5, + DP_ERROR_NO_SPACE = DP_ERROR_NONE + 6, + DP_ERROR_FIELD_NOT_FOUND = DP_ERROR_NONE + 7, + DP_ERROR_INVALID_STATE = DP_ERROR_NONE + 8, + DP_ERROR_CONNECTION_FAILED = DP_ERROR_NONE + 9, + DP_ERROR_INVALID_URL = DP_ERROR_NONE + 10, + DP_ERROR_INVALID_DESTINATION = DP_ERROR_NONE + 11, + DP_ERROR_QUEUE_FULL = DP_ERROR_NONE + 12, + DP_ERROR_ALREADY_COMPLETED = DP_ERROR_NONE + 13, + DP_ERROR_FILE_ALREADY_EXISTS = DP_ERROR_NONE + 14, + DP_ERROR_TOO_MANY_DOWNLOADS = DP_ERROR_NONE + 15, + DP_ERROR_NETWORK_ERROR = DP_ERROR_NONE + 16, + DP_ERROR_NO_DATA = DP_ERROR_NONE + 17, + DP_ERROR_UNHANDLED_HTTP_CODE = DP_ERROR_NONE + 18, + DP_ERROR_CANNOT_RESUME = DP_ERROR_NONE + 19, + DP_ERROR_PERMISSION_DENIED = DP_ERROR_NONE + 20, + DP_ERROR_INVALID_NETWORK_TYPE = DP_ERROR_NONE + 21, + DP_ERROR_RESPONSE_TIMEOUT = DP_ERROR_NONE + 50, + DP_ERROR_REQUEST_TIMEOUT = DP_ERROR_NONE + 55, + DP_ERROR_SYSTEM_DOWN = DP_ERROR_NONE + 60, + DP_ERROR_CLIENT_DOWN = DP_ERROR_NONE + 65, + DP_ERROR_DISK_BUSY = DP_ERROR_NONE + 70, + DP_ERROR_ID_NOT_FOUND = DP_ERROR_NONE + 90, + DP_ERROR_IO_EAGAIN = DP_ERROR_NONE + 97, + DP_ERROR_IO_EINTR = DP_ERROR_NONE + 98, + DP_ERROR_IO_TIMEOUT = DP_ERROR_NONE + 99, + DP_ERROR_UNKNOWN = DP_ERROR_NONE + 100 +} dp_error_type; + +typedef enum { + DP_NOTIFICATION_BUNDLE_TYPE_ONGOING = 0, // Ongoing, Failed + DP_NOTIFICATION_BUNDLE_TYPE_COMPLETE, // Completed + DP_NOTIFICATION_BUNDLE_TYPE_FAILED // Failed +} dp_notification_bundle_type; + +typedef enum { + DP_NOTIFICATION_SERVICE_TYPE_ONGOING = 0, // Ongoing, Failed + DP_NOTIFICATION_SERVICE_TYPE_COMPLETE, // Completed + DP_NOTIFICATION_SERVICE_TYPE_FAILED // Failed +} dp_notification_service_type; + + +typedef enum { + DP_NOTIFICATION_TYPE_NONE = 0, // Not register Noti. + DP_NOTIFICATION_TYPE_COMPLETE_ONLY, // Success, Failed + DP_NOTIFICATION_TYPE_ALL // Ongoing, Success, Failed +} dp_notification_type; + + +#ifndef IPC_SOCKET +#define IPC_SOCKET "/opt/data/download-provider/download-provider.sock" +#endif + +#define MAX_DOWNLOAD_HANDLE 32 +#define DP_MAX_STR_LEN 2048 +#define DP_DEFAULT_BUFFER_SIZE 1024 + +// string to check invalid characters in path before using open() and fopen() API's +#define DP_INVALID_PATH_STRING ";\\\":*?<>|()" + + +#include + +typedef struct { + pid_t pid; + uid_t uid; + gid_t gid; +} dp_credential; + +typedef enum { + DP_SEC_NONE = 0, + DP_SEC_INIT, + DP_SEC_DEINIT, + DP_SEC_CONTROL, + DP_SEC_GET, + DP_SEC_SET, + DP_SEC_UNSET +} dp_ipc_section_defs; + +typedef enum { + DP_PROP_NONE = 0, + DP_PROP_CREATE, + DP_PROP_START, + DP_PROP_PAUSE, + DP_PROP_CANCEL, + DP_PROP_DESTROY, + DP_PROP_URL, + DP_PROP_DESTINATION, + DP_PROP_FILENAME, + DP_PROP_STATE_CALLBACK, + DP_PROP_PROGRESS_CALLBACK, + DP_PROP_AUTO_DOWNLOAD, + DP_PROP_NETWORK_TYPE, + DP_PROP_NETWORK_BONDING, + DP_PROP_SAVED_PATH, + DP_PROP_TEMP_SAVED_PATH, + DP_PROP_MIME_TYPE, + DP_PROP_RECEIVED_SIZE, + DP_PROP_TOTAL_FILE_SIZE, + DP_PROP_CONTENT_NAME, + DP_PROP_HTTP_STATUS, + DP_PROP_ETAG, + DP_PROP_STATE, + DP_PROP_ERROR, + DP_PROP_HTTP_HEADERS, + DP_PROP_HTTP_HEADER, + DP_PROP_NOTIFICATION_RAW, + DP_PROP_NOTIFICATION_SUBJECT, + DP_PROP_NOTIFICATION_DESCRIPTION, + DP_PROP_NOTIFICATION_TYPE +} dp_ipc_property_defs; + +typedef enum { + DP_CONTENT_UNKNOWN = 0, + DP_CONTENT_IMAGE, + DP_CONTENT_VIDEO, + DP_CONTENT_MUSIC, + DP_CONTENT_PDF, + DP_CONTENT_WORD, + DP_CONTENT_PPT, // 5 + DP_CONTENT_EXCEL, + DP_CONTENT_HTML, + DP_CONTENT_TEXT, + DP_CONTENT_DRM, + DP_CONTENT_SD_DRM, //10 + DP_CONTENT_FLASH, + DP_CONTENT_TPK, + DP_CONTENT_VCAL, //13 +} dp_content_type; + + +typedef struct { + short section; + unsigned property; + int id; + int errorcode; + size_t size; // followed extra packet size +} dp_ipc_fmt; + +typedef struct { + int id; + int state; + int errorcode; + unsigned long long received_size; +} dp_ipc_event_fmt; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/res/images/Q02_Notification_Download_failed.png b/res/images/redwood/B03_processing_download_complete.png similarity index 59% rename from res/images/Q02_Notification_Download_failed.png rename to res/images/redwood/B03_processing_download_complete.png index 04ec4f07c9dee5e505c92d7ade14dd5c33ce85af..109512eef51535efdaa5e280365f492601f1ba96 100644 GIT binary patch delta 411 zcmV;M0c8G-Bdr)AiBL{Q4GJ0x0000DNk~Le0000g0000g2nGNE0L8<}Td^UY3V#7u zNkl3V*7gUWx)5=MUg=&$yqybA)7cC6J(19U1KcZ$K{) z@*C&_N!1xmfFZC6@ZDJ7q^^(Y3m66XjjV6&{pi%}uIWCpifVL{dw(eDK_6{*U#4f^ z7WgT!JL46B<_Dt^h;!f_xG1o%fh!;`TUb{-i48vn?tyfREw#4zQ2tD>z;JlW_}JPi zJKW{9Ythd#J~IzLXFQ1-&FTzTTK^l5z1A5|8Z>+I{PkH_S3JoJ2m%1bZ%QVI+U7NV zX&P0vJvG+hrwuZtJ~cW7t{Vby$#iBL{Q4GJ0x0000DNk~Le0001K0001K2nGNE0ZxTItg#`U3V#N; zNklulY8RA(rqoU|RzWKWfE!@NTe+Ofbw_u%&dQAcPfpbX00960Vxn8lAS+i8lgvm8 z43ct!00RSqBN`uX(wfh}!0?`dfq&rxR44$-pN}tfBr-5CBr-5CoQDdnXJBAh02RaQ zJY+?Q=o(No{rdH*0V#DafTsEdut53s>sJG*sUEvcY;0@|1X6qhMTwRyO#lD@0RR7D zBDW5pYrR2};6Tb*|Dl)xAEs8=GZI^OQ7fW95L-NuY#B7?z_0)V1A`!%5`PD%_F6n962jf6pV>bLlSYwHxiJ?ZyBucL91RDpcx8tL<4d>LiIIJt0X`# z`KX#2|C4}8w~UCAm66zzmnuyMasU7T0RR7D8g_;72($=VRTvPeN(fac#QNwwG|x29 zI_O{pX+6E_EMyN;Qus))&ZO1rx z<7m_(d;kCd0RR8&nY|H%Fbsu73Tj4Rgp5EoU;w!LwX>GI}#^UXedd(^pbPdua!J5E*r;A-DX!ucvs?X9AiIz zPx!U$K{4i{&8b1-T1_^}ZZCzR{-cZYSgYU5mo#RDT6j=rN`C3$O5~k${#`6#3PLE2 z3vg6q63j^CU%>{Irhn<6bO|UpUG$oA-_C+?U_X9yKQsY=ho^K9F!de^#oKW)USPJW zex{47eZm++A!07Q?IuKQ9N+{@tC^#LZ%=DN#C(gLs+8}$#m=pPq2{mlCOulPZ2E<` ze9Mj2Rfa4S9hg~kYe&ZdMRiWO!sP!K!-&2fdpuVSr$wk z33YP7==r^aK&1wpC&%iq6EwAk5m2a94QY>j0>ao(I6ymR&su~fLHS^WNJys!jiDW= z2B76+81O6?8zl%VpgI+G19I1;N@+;0j!}j5ZZ<8e0)Om3>o`=zgF5@9a@6KjQouw3 zt$)bnqkw45i1)Ko}nDk@qCt6dGz0E>ea*4VxST z5gs1K{5vKouqVu)>)GTOh=CZ0ff%TU@&Nz<|Nrcr(UF2M5QcZ|ATx*pUC9VMb>}a6htclFeq3We$)S48b)( zfCNYoAOR8tNRZ2r{#n?O)aH1v`u%E*1tfEo)>=YK`l`KNQJK1WrTZ+*iAJuagqGB; zn26TYp6V`Z(7I9#0ck`PRBrN6bbM|@_x$NCAb-uHHT5r5l`a*Q3(?(cj~3O0bz71f zbR`52>G5)`rULB-V?dftpERs=+JQ!1eg;Ut^+Ch3U!?1xTpMwC8+e|ivbG-}O%$4+ z2cElkHJIQ4Dbdl`k^1Fyz8hTY@I>H|Xg3*q3rQ)J>IB}sHcF&nT{>Xp2A7R`Muj(h zUw@MBduyd$KvGHtN~w#6vwbj%@Ca6JcpI_bT&%azx8lXJToj?a1zoPOO0(ZBPSqf5J&nuY_cJugQZdr&%(0Va;m}CW`9c((b2+# z$im$P7Qd?t));OrnA%`V$px=qg;dVohA#c*_yVa?PUR$BzN8<8RTY5L8eB+6?OP>% zYDuSBIYF0>lTVN!Kmw#L6`tF)U=K+Mk?C32kjfPiz8s;hU6;Agk}6oa5aR67k-OyX oAV2~n2#_E^0wf5KpjQ1108jgrl1jX4OaK4?07*qoM6N<$f&=#}*Z=?k diff --git a/res/images/redwood/B03_processing_download_fail.png b/res/images/redwood/B03_processing_download_fail.png new file mode 100644 index 0000000000000000000000000000000000000000..be67ffe053479387bc52ea0e5febd31c369c1c78 GIT binary patch literal 1600 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_pdf.png b/res/images/redwood/U01_icon_pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..3f8cda62226864844803a8b625fa80550fc37b6f GIT binary patch literal 4686 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 Q!vFvP07*qoM6N<$g0r632><{9 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_ppt.png b/res/images/redwood/U01_icon_ppt.png new file mode 100644 index 0000000000000000000000000000000000000000..79302eb0081e1ac4ac5f59469864d014be41fc07 GIT binary patch literal 3946 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 Ef-H4iY5)KL literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_swf.png b/res/images/redwood/U01_icon_swf.png new file mode 100644 index 0000000000000000000000000000000000000000..39a49daea4219a997e7b3fef10a902d54ff262f3 GIT binary patch literal 4233 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_text.png b/res/images/redwood/U01_icon_text.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8b3bd80b9212ad9f01f52a0716c173c6a4acab GIT binary patch literal 3832 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_tpk.png b/res/images/redwood/U01_icon_tpk.png new file mode 100644 index 0000000000000000000000000000000000000000..796c788c9f27cf67ac2aa36b9266b369b86ade99 GIT binary patch literal 5319 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 literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_icon_word.png b/res/images/redwood/U01_icon_word.png new file mode 100644 index 0000000000000000000000000000000000000000..a45acd7fd4a721a74cafb447064197b233576dd3 GIT binary patch literal 4669 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 M07*qoM6N<$g30~DZ2$lO literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_list_icon_mp3.png b/res/images/redwood/U01_list_icon_mp3.png new file mode 100644 index 0000000000000000000000000000000000000000..c5176befa6faddc95993e37e32e794de042b5869 GIT binary patch literal 4154 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 Eg2{fr9smFU literal 0 HcmV?d00001 diff --git a/res/images/redwood/U01_list_icon_mp4.png b/res/images/redwood/U01_list_icon_mp4.png new file mode 100644 index 0000000000000000000000000000000000000000..2e3c87b500396199744b7cfc89801e1d53d8ffd1 GIT binary patch literal 3851 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 N002ovPDHLkV1k$;H*Np` literal 0 HcmV?d00001 diff --git a/res/images/redwood/noti_download_complete.png b/res/images/redwood/noti_download_complete.png new file mode 100644 index 0000000000000000000000000000000000000000..6171bd805c9ab892fcfad09fb35331e75aa644a2 GIT binary patch literal 6935 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 literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/B03_Processing_download_complete.png b/res/images/tizen2.3/B03_Processing_download_complete.png new file mode 100644 index 0000000000000000000000000000000000000000..8dfb542dab205a85096444dbcef4dd44ce4c92fc GIT binary patch literal 1268 zcmb7EUufKP98bAf>)hP2S;2}BQU-PNlKZ7eE*E;Xxl3XX%~`JpJ!OcwHDy)L(9QT^~llkbl2l zzMs$M`!~xIg(vs!9@tF~#NPb4QpC@PqpPnM-`9UzG^0hRmcvO@4V#7!3E4swNah`5 z8Wy2p&AoI5ju1rbW4lxi%lgxji5%L9Z0MHbVKhOEjJ7<(tizD3z-imfP&Y2FQlxEV zs3~4g>Rt}k?D2UYPR4<}66WAgV%(DyjtBbSUAjS6an z847!PI|Roo+S9c#*dlj>PO@;?n3mx&fKD=g+a`*yi_-O-5stHE9fU=A$N9VR2c>bJMa`HEVEcovOV42EZP%DpklApc8|IY^)o9q3 zr12cjE1WC?Eve$#q&dJVVmg%tBBv^f(k0jq#9Fk4u|P~}!?G&!vN#NY%85W0L;+;+ zR!)#Pp^MGCL1?%pj6@@>eFvM`5i8|o?BKUm^gLIPq%#m1jp5=z^9wGqeBtuF3;L@9fhH@#TMG zORLw|lc&dCJJz@EE8<^0@x!k_a^$(OTW=m8SUEcILO=O#{L977n+r#>)wp?I-}h_A ztmqd+#WBZEtPi3KL8w zM$ow7#xw>Ti4un!er?&*L39iPaU+^IgOg!4<6u*X0}XNNGJVT9#vcobO+Vg`-}5}b zuea@GzLM0Gj1-+tm+IL}`Qi6o?YS)(zDIt3k<}&&U9D7zAtla8K<5mKH30GOOc?k9 z6Kvf2B`DPCZuyW4R4diqQj!&UJ)_y^RXzsMI$hx=HO8FzypOrR6Z)mr0PHyc}Y0dmN67rG*KcB z^qN!E-ZG?ElmKGUn+jM1jw4p99yeR8Ry-du8gL_KfVZ^(Hjl*axfEEREqo6Qqfgoom7$_jK5*JfAQ9v|C zrbet+94PekS_pj1&xLChd6`_0my!k3hN(;p!}SJCTC~yPOQ5{o)e$_uY%ME(aNYSE z^2>q77{L5M7V9MzRxy;lLTYs(&2T9O(#uE@0ITR`qB2GE#BH<{ z$7!=2x4Z3b1A$uz6K*pa5?GHQD~!MbO;p2j*RjN^Sh83Gj3P<_QH&#`MHmso)L}51%Vg-A6{e-P1?)zO<{EB|qMI%sbV2%0G!tA4xyln?*&Q z&utjo(7bQ&4-GAa)p>iH4nOk8_;~ojKW}Y_5Ifd$e_m|6a_n-~#+<(7%F^Qe7e;^0 zeEeSrccv|Qd_f&ws5^V0@2~jo(QT(=$6tN4hkb6YYqkVO&fR+GnKk9czRRusb!SGI z>`=zr{c2M5#Fe!T<$D%D)RU9p+BNyr``ahFZuXr|-+3-Ay)Tk8=o(5*$^53BeY2{0 z%gMi+vyhi9-+t7V^!sV+nypx?sr00jB7Qp7*?(wSe)>eEKRjDBuuJVca1=W~EUmk6 z@X3+BDHC^BN5^MFmEm=vAdWPvqup8io+x@_{-Nnt1~%@0_q*hc+Ya{paw;uAzuv2u zF1ma(8TT)=?0jved~E##9m9EduifpR!FSvt3{O4i9F6rpb$oy6OZPN<^6}^MXSbwS kg}J%!Z9iRV=^4D;pv!M>q8&Z&g|r`}hxSn)xSrkqA9scRasU7T literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_date.png b/res/images/tizen2.3/download_manager_icon_date.png new file mode 100644 index 0000000000000000000000000000000000000000..f1ff0f843c66bf43fdad74c42be4943677f5d204 GIT binary patch literal 1606 zcmah}drT8|96za}!vSin0<+AsZsLSKu2+uU(L!HWtkBXyBj~b)KCbOW+N*a*Tbxtt z3!HTkn43B>roU}ZV5tQktksg&{vDbpBaol$9!nKi0lA{aMK zhFFpcf=NZEi)vuC65iA2Ap}BJ>kHu^GmJ7Nbh{7Mz<3j*Q30q8hNA!wokmE{^*~eF; z8%13`+3|S%ZBl%Di)+V4;8Me#@2 z`v%S*ZIgCev2Ld>(k?toLur`cz( z-i(buk)4y;+h;%Z+s2Z3ucy2|C%W)Jj?8pVcRC8L+?hESp_}r0ZPK1O!nJQ{(z;-H znR6gEH`O}#wu|Eib97CD{0wvEw9nXyyPHMR52!LbEl-D*#K=u~CD8KM4y|vA^_RA0 zCyKfji5l$Rk2~Am6&4mS4*>Yq!RA1A&Sdy+~Sm7Tw?RErNb&Zqtnp@aI9 z_je?2dA@lsoVx3yD{Iw1-;tkbj+a@>jwuyqTPN&2qu#eJ&zx(^ZR!@Uxx1_)e$1C) zXzHKRhECUCwSYF^r3->P*L^z8)aJZN;+mOL(+Ai-{~qOEp+Nxb0anC|4>ev!qsc$J M1-F^@8tPX43l3#UJpcdz literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_drm.png b/res/images/tizen2.3/download_manager_icon_drm.png new file mode 100644 index 0000000000000000000000000000000000000000..796523232967b9b90ecced109eccb3edb5101d29 GIT binary patch literal 1701 zcmah~eNfYO7_J4B6NJ^Fh;x_=&M%;C`jMuU3T@L$9mQHIpde7%R06cAX_OXq4w;7x zRGgx6qHxD1r-D<o6T= zFge$^VNnc*ml@Y5Q^}e*iIK3d4IUe|!(yY+3`SJ6!)7q%U=)yvt;4NSu)nDp1aOlS zOcH9i8k+*k!ejGEEFnK$Z_LjzicMhjQXtA9p$RM)WdIzOT&rE;kbLE6(dN3hs5nzzJO`&gjpkZ~La8wX-@ITnlOT%*=@N{9XH#)Q^( zz0-zqbeNskKpN?Mn8U`wbnM3!xmbpvA|Ary zDrDnWwbf1;tVV2H7pHZ{u-tcIB?=NVPz0$bh}`iC&}I=7Vb3CLfFc0~7AE0V6Om_M zHXjCq*{MclddJUCDw<1X z%YxihwV{hMYqquGh8R{v-C(-*Zu~9z;Np(?^@%e16L5$3ozwKKll{YA$V6Ec1y6uhd*rGPk6L2J;6?9t=2!)z@!ry2M&@Ot0gh_YNkW zm=Q74@96Hx=P&P{+6Y%$8;6jJxU|X)?yToa-LDywel+tP7t(CVoERp<^^?EkaKPPc z;iDHrK>2bRxaVo$$;1;O(O2HfzmTSwH+@oL*Xt*u^5s741Adk93%t@JW;zS{dds%& z2`Fk=a_i>VEaq>|UIIZ=p&n-kl3k`MLfmFofxE}>YL>G!J7Q*G2KQ>iSGwX&jotlI zN?OS?4_E9$wq?#+-QM?1Tc2oHTIJOi7ngEOU#(qeGuo#42JCuuw(IxQ=G$4H#?9{$ zl-8%Ri}Ekr*m-(Q{SSpkJ*)Ja$JDp3r>CMrcc1@WRa1}<{&mT!n9T=v@YeWlOpvV} z#@ltVm*Os`Qg2yXWhyKs&W5r zg-fek+1v4GB=w}b)Pk&9u^KHF}=1fIP%ev`)#?kN6LLhnx5`oWqmMmHl69u7&#Qid$zN= Q#q;A(E923V@{Dc&08o{FlK=n! literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_html.png b/res/images/tizen2.3/download_manager_icon_html.png new file mode 100644 index 0000000000000000000000000000000000000000..f4a2bfc18e09a6ef8510850146eb8e0b8e093c0b GIT binary patch literal 2359 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 literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_movie.png b/res/images/tizen2.3/download_manager_icon_movie.png new file mode 100644 index 0000000000000000000000000000000000000000..5902a67490cd6d17c6a65bb9020fd8367f0faf2f GIT binary patch literal 1640 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 F{{t8`vjhMD literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_pdf.png b/res/images/tizen2.3/download_manager_icon_pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..96b1a9ae8f3d97d8cb7d6ed3737cb8110946a381 GIT binary patch literal 2005 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 E4@R{ou>b%7 literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_swf.png b/res/images/tizen2.3/download_manager_icon_swf.png new file mode 100644 index 0000000000000000000000000000000000000000..b6335d7147a2279eb83564a2551bd1da4b6ba96b GIT binary patch literal 1878 zcmah~c~BE~6iyMUMv+pj6%S@vwFQ-IHpeE}A)VI8MX+EcDDmsRZ(T1Z2#wgIcYy>u=i9_>vK_NDi-jGbPKs=d9(Ms@6Z375U zgc4jK)e5yH4VgqON;i{H=@HR}^kjpA07HU-AREdN7)e$S*o-N(1+^)`=e#I4cWpx; z@Z5w=R)Q~_iqYx-4Pzz&sX!cP5W+BkAOct-MG$xaAQHkNNXXqtAS^+p2r7~RBNxc2 znTZ565(^#C;#Nv9iDgYF1X-+A@+TE@hBSZ-QWf5HcEFaXq)Tu#x1yZoJak z61~PmLXo6}Ni!R`^GKLI3g&Y6dLfq~=MB2lOmT;zPr(>Nnvta0FiZ(@Ujzh2pkk?7 zB-JQzM1&)_7={%RnIaUE$klQL!PF|@D95X?um)3zV3kHJ)~H|@m&nC3M1f1ym=F`H zF%33~4Wliro;Hx9x)i57f>pm3i)zfIo@LC@43jci0lFlHWh_aI3D86#fd2}LCK#(F zz;!$?qQyuv^$AIYni(VTJijRQ3VpQ*QK-~7rcsE+xP*&aji^FHRT32 zugaPDe{u$K&Ool>_)oEnZgCapn!YT3Zt=2tNSf;yGuIjuZEj+&<2Hq1s%YDVo5f3# zCab2kJ*%o+bAE^P{@F4rhrbN#vS-_(0S_? zEe&4mAI$$cdmMk2yVnD~_ST6_$hG<#vahz&zm#3Pm~!N^No#j$6A~X(e>8lrw0L8{ zmdutI_XXXcc8{=CBJI2{o9lC{vBA-;`@0)b)?7GzurqMZZyDD*yoQ7SIB+sP{_lVb z{&e@4c{LK>?>{*h7ZVq2CvjT70-tF9x?c& zw6s)uc{Lxa+`Pqc>ia&y+}U<~Uv@hm^o6$Mm2CWUg>?7!WP94BY9@0E|Krm&#IZS7 z3;P=eorjb;4vpnbXDraaddW8wfuUjOCov32n6U5?aXV0K5&;m3{My#t50`AyXA zyVviIB{Vgie1FH3_!I%=`4%1RxIurz zt+cqswmP@&vG;qot3hab=BXdUXSfa6!`QC;yJt$@vh`~Q9bS2hvQzSXN@Bu2tOd}} ztzV0Rs^Q@h!jBkx-qbp`D6Z>}v1mu5biG&X)+)yD^3Z~DzaH7z^m8~Ik-9T}U0%jm v|JZ=rowWn!V$H+WD+S*y$k-1(bDzcwuYuDSE`Rj9>rWSkM_?7|)tUbQNU`!P literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_text.png b/res/images/tizen2.3/download_manager_icon_text.png new file mode 100644 index 0000000000000000000000000000000000000000..4961fb52de6b76187f4b9ee56ac5c9225326d94a GIT binary patch literal 1600 zcmah}drT8|96wN=0{-E)fPx&wY&yra*Ius=TCnZ4+KhIjpx~CpKJE$^Z121~>_K?M z7f!)#*(;ktVR6PS)1_+EZ73AmNpNPOOg8t&5El_q2hN351l$#=+aJVT?(X-v@8|RV z{JxLdQ*2$En!Gd_0Dx5UI?N`FP~=IB7v5#xtyTy_24^hiN+>tyb1(#;!zm{LnmvvR z!bUjonk~JA1^^bg$%rxgqSZPI-97n6gVxP|k`D75qRES}fN)_RdO7jGZJhsNmIruy;n;T`o2-d}r zG)GciFv93?Qq`PRBq)7)1P^VoJR|n9bAb{c z8BwVbHOgREg(y@e3{mQpD2nNIk|@V~Sf$LMkRwv5T#g|yY(#WYmChhn=yb3`p*KpT zQLNd^at^PHi25Z3zjIjlxmdMGge zN-@0P57Y;+{n<0qj}^*HE5uKPQRC!ce0}fLp2XMx2<;4C@9%l(o#v#Te%RgyJm5fY zLhX3rMly3`Bz{=n4+t@R^(@nj)Y?%3^y}ja0^1- z3fs3L*4=Gdwr)n4ZP>jdYx-eXY!FOHf3a_@ZE(rKf`;uSJ6c;pH@I(GT9EYj&=ZyS z>Ec6V`!Z|p>d@M(f>HWa-wK;7*}wO#jr-wNP4y>3V}o5Orl!f1&+hE8Kj`p{$+(Fk zr=1`O3DOt$b$7h`@~09>4wM63xG_AM=x*zx_YB=Rc{`=udhz15yWPk-Yvz|t&CQGM zC8giEd2?a&6-`K&^Kkm{;-<6blO==w!Cg5k0|}RA9zA>|*!y8c`tRqS1pM_q%j2^= zmZryxm&1ukNmBm%e3}3FaX4JtvE$Z&=hxVQ{wr@@4)pfIezNtzfde_n3gA*f{jerD zdTLqsy*_)R|4>5pFao3YzJaSinY*o^-rZMR7T26QX^Z>lVB^f>uJcEJXkT(It6?fc zHs$;N+_pA#O?dcNzWuoF{x~(*DLcCHOwy&(Cr>$P|CyMRI_IX&hODz`o4U3v3f{iF zDLowKGh(ODWlYs;Gx(aCfV1is@6y(^#_@4D_<68r=y2i}b;EdK(q9Xjv$PF+hX(F< zl(Nd)+6y%k;feOl&W}G>Ph@)Ved@ZOhYqD>SBJ;9hJVzJ{L~Xt)(wChUkJZ_#sto! zgzl_4stKeu#D_|@@v+^flY3uY{5LmL`IU5(o&vxC5SM*7VO8e|GV)J18?D$kdi(Z& E0NqGokpKVy literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_tpk.png b/res/images/tizen2.3/download_manager_icon_tpk.png new file mode 100644 index 0000000000000000000000000000000000000000..58953be579bfcdbf894d2b0094e9cce7722a131c GIT binary patch literal 2546 zcmai0c{o&iA0N6`OmvZ5F%6+GGiNqqY>gR%uCXD-uI85`~IGD&TspEKHvR$&R$PfV73lo0V_BHgb+bsD2Hc<9J_i0iQus9kbVRPh9RJWVH}ru zA-FN#of#Y-5p2yyI@lv@#bg-)7lc>{F*lMYB8%;iUwFx~^};b4iTEM{Mc5&~8s*RM zL{Rxc5J5oUEQ2usfFKf40G>c30u~4?2Ed{*vWI91;K>9c8Eb|3HjpxHLUst*n@0bp zOSZE^hCz^kj7G=C#-d_zD84Wh4Om-SFK}S7mNE%TQ5+9qi7j~|qeTW9C<+#G1Q3VM zLo6_|g80#p9a3iLR~NVf2ID(1PxLKNvXG(0ECCuoVbEOef?r>xMUXf6Uo(CvEn>zA zK(sd~;ztXEW%&p(S_I2t_wR}p1ZCEcJ%k)tQdp5ResDAwM2~VL?sB|nqcO+mb zG=M-`#JciC5Q`TKF6!mT^nSzQ{uN863PBdc7c%+$$i)iq4C6z5Q5au$trMR`MvaIoA1p7@?;$&l(j}~4uuYbDIi^G z6sEXmbQ9N;32OZQ=6C6vTjM7)5XpZ_3K84ZmgubWO$(7oG)n`simhi|a1J3*rPQRw zPytuWQ963NCr<@@khjrnUJ^-^V8j zPu|-PSq~)~Zu@&eY`{nwYNw^@D!Tna-M)SMQy8z@HP7n9@Z8{$2hCUZzj`K)Mb_Gy zuHlSzJSHtunAG~@K8_Acj;|usT9~eh%63x=Wzm&Q<_l)1Rk?ZVO>3GoGRjbG=}j`ZRWU{-@St1B)sv2enOY;ivkGI=l{!T#xC` zkv|}wY(OS}uU~|Y;0BZml}awE*n2xi>N>2zc^JzPgYLsZ6}m*c_#!1JLrb*fnsmD3 z=kuDqZ@n&Q2&(?{*;D<5)ulmRqI{j~U;lx4r@Odm^!8rKYvb%^dGC%DPVdNTO!awK z>|A(DQ@(gvSb)B>VHSN=f`d)!wA)yUh7~|j#rVS9&kgX;HPHMB@OAf9hnux)dR3yu z5or!|QcWGT&CnnwOK`|saAjs4b8;5A?UXVg5&0jE)nEk4qcrjx&K+N3`s$BamN26uJWNrS~)b2p1+xw3kIh1tm3f$;nX`*&u`kqU2(4M&e zq_gQ2w6b*%jr+8ZsCUt1pP{b2N@hx-NNrPBkcD_EgGXh_P1j?;C-u*gXcNRa< z1q~`HtOziOE2~{~qtEPC%k7@6{iK}*gM<5KD=Zp5*>p;$D=b!C*_3utXliEcU4NdN zCy6TmY%*7})@sXd2S4FZ5o1Pp&?Y9erGE4|<+AT@DG7&#+05Jw8?wrYqF)%3-EwD| zJy5OnGis|9iyMLxB1A^D=FPXt+AE~(4$3*ygw<;4*|yQZ?YRpFbxu2fuFfF&Z-&v0 zlQ%q1TGpXyR^zvKU)-yt%=80kb(M{0JDDkxD9MQ48Lje*JHY7Nd+(y|GTFs%>Iz=$ z6^w=MPdR={4Tsffg*#_jUsfqsw^lcy1*i5H@?w@hPEhI5imZ8Sqt}?sGd=Zb<(Z*N z89$Lcp~;+zLsRZBYW|LM)pANHN2i9F@C_po0%s{VZA}>C6$wdxn zz^ggXw6-3qHtgCLL-EnAy!Wf>n`b+9ByB4z5O*8ZCHIKU`dYgO?hi@#o9Le&uP1v$Q4GYsFhG2en%DXoof?z@xILN&kb#M(qpXKwlimmc3kuo|mR)0E@LTtGK!F!@HFS$O>q4A5Rs7a_*0hng zlKaz&q#oD3FL&l;uGjYMyY+d;23w#)mBMuG+y~!tJWSdiYWpapqAn=bUMutSM<8uX7F}0F*%qZ&B?B}xjBgNy5BhM7;Cwf9un)@D4 z%v|t2L%n=zDKWK{2i2TNd;00|wHLUgYrT(~f|UcNl3wFlg+FADL+g%Tbihu(5t#-JKuT)a-b9f#jn&HP;z*@<6w4 zz})y2^4ST?wC1i|A#&vHs`5vD{IcxYO{P=?^&KJMWktk6X*+vWVpj<@Q_>B2XX literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_unknown.png b/res/images/tizen2.3/download_manager_icon_unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..9a367ec596647b0bc666f8d6b20651d766df6d4b GIT binary patch literal 1631 zcmah}eNfY87!RVr5Qf{t6@?j!+w_n&Nt3jVw6$$ot%K5|U4iYkQQDN|uuV;)EtSm^ zRCMBW4sOl~Y-64u)8WbOPPe-W2aYj4=R|kI^JAiJ-NXau4Xb>(6sg-EoXaJ7pZCr4 z`#s;;VlpmEPMn(v06?-~Ia$cBqR5jF$G?k?XG{4djnfr#X2!|+Z7c<-9ZVSo8r-&W zs*tidDp&PTxd0IBq%FlSY8jRSF_9$44#6;p<02Tva2#F?A`py-A^yg5V3fdc0+E7~myox{ zI-Eoysh_mP?-W88$9V~{*zfm?{1OqvmWyGzTpr;-kQ`nk$5-j$Y=In)FDuGGQa(FN zdpVl%fDuMp8MB&G2zgH*h2Zw)=RYR)_$Cv@r%W8MdBv~@61&}zxF)oHTp{(Z8&hig zER|kLTuAwt)vTSbhchb*=5zOCLlH&Z8=`=v`J&iXl8k+|oAPi5QX%BOh#a(okYE}F z)5>)?qQi9(7?z__xt>I28X1n08Z{KxK^rDV|uMtu0ga2 z8pRqsKF;Q`Q&GD#Z+8+4KM_l4S<1#Stc77#MmxadVmQX@HBkgaule_1SkBvxW=|)jtIE?Ea>~*}_bFMq#mFry_!hOBnb2e{%s=F61Z3gae zpeH^!q$;7)L!tYsbz|@C^S!$xrr!#Rz-(W&W^O37AtvwK#sy2#{|tp=M5M#OhQU=R zeKTCT1~t|;D|}VsykxDd$r!s^G_4bi7o?sYY`*$jlk%NvbIqQ*u3x!hb#XqeADd4=1AYD-*Z#U$k<|L;2`7Nnbe$yAPUmeC>}ebj6ql47a6X?E zTsG~Oi&hf4IC*WhX+?GB%h?TT3%To(bwSpJ-tfr1`GS`UKHAvt zGKCOCI1n5jn9`-j@V+{;*!VEbZHe;TY%4#6;-x1>ZsY_b-G;NB`b>?fikZ zq-^WqSRyR$JoRB~nz2#YT}sioY(>L7>8!>rq3=y`7?$cCY5Jh1rsK+)-5n=;Vnpk1 z4PWjsr&lAwB-eiXu&cg)_6}s|_m1mBt#4)0A2&8;Z0>_@45|VNww3ruFS9^E8Jqx-!Fv7@f!v-3(UDR&01u7hr*THEipmFEd=$0X0J zP3c3GyDj<*<+B;%?5wZv!tm40SVG2?g1p!FK64(M-p_&77fRz*vHb^@=B_W58;|zH kD&CO2cCd~}R{;qSAh6`uHKo=6030q^b^rhX literal 0 HcmV?d00001 diff --git a/res/images/tizen2.3/download_manager_icon_word.png b/res/images/tizen2.3/download_manager_icon_word.png new file mode 100644 index 0000000000000000000000000000000000000000..3218b538852a74ac44bf0c24994da18d0aa0d5e5 GIT binary patch literal 1930 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 SRHJhI(UkHi*+EI_%6|Yma?q*( literal 0 HcmV?d00001 diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt deleted file mode 100644 index 955fa10..0000000 --- a/src/agent/CMakeLists.txt +++ /dev/null @@ -1,89 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(downloadagent C) - -IF("${CMAKE_BUILD_TYPE}" STREQUAL "") - SET(CMAKE_BUILD_TYPE "Debug") -ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") -MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") - -SET(PREFIX ${CMAKE_INSTALL_PREFIX}) -SET(VERSION "0.0.1") -FIND_PROGRAM(UNAME NAMES uname) -EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") - -#DA Engine Include Directory -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include) - -INCLUDE(FindPkgConfig) -pkg_check_modules(subpkgs REQUIRED - libsoup-2.4 - xdgmime - vconf - capi-network-connection - glib-2.0 - dlog -) - -FOREACH(flag ${subpkgs_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -Wall") -SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both") - -IF("${ARCH}" MATCHES "^arm.*") - ADD_DEFINITIONS("-D_TARGET") - SET(CMAKE_C_FLAGS_RELEASE "-mabi=aapcs-linux -msoft-float -O2") -ENDIF("${ARCH}" MATCHES "^arm.*") - -ADD_DEFINITIONS("-D_EFL_PLATFORM") -#allow to install widget, deb pkg and apk for testing -ADD_DEFINITIONS("-DDA_DEBUG_USING_DLOG") -#This should be removed when release a target -ADD_DEFINITIONS("-D_SAMSUNG_MIME_POLICY") - -############################################################################# -#+++++++++++++++++++++++++DA ENGINE+++++++++++++++++++++++++++++++++++++++++++ -############################################################################# - -SET(SRCS_PATH ".") -SET(SRCS_DA_ENGINE - ${SRCS_PATH}/download-agent-debug.c - ${SRCS_PATH}/download-agent-interface.c - ${SRCS_PATH}/download-agent-client-mgr.c - ${SRCS_PATH}/download-agent-dl-mgr.c - ${SRCS_PATH}/download-agent-dl-info-util.c - ${SRCS_PATH}/download-agent-http-queue.c - ${SRCS_PATH}/download-agent-http-misc.c - ${SRCS_PATH}/download-agent-http-mgr.c - ${SRCS_PATH}/download-agent-http-msg-handler.c - ${SRCS_PATH}/download-agent-encoding.c - ${SRCS_PATH}/download-agent-utils.c - ${SRCS_PATH}/download-agent-utils-dl-req-id-history.c - ${SRCS_PATH}/download-agent-basic.c - ${SRCS_PATH}/download-agent-installation.c - ${SRCS_PATH}/download-agent-file.c - ${SRCS_PATH}/download-agent-plugin-libsoup.c - ${SRCS_PATH}/download-agent-plugin-conf.c - ${SRCS_PATH}/download-agent-plugin-install.c - ${SRCS_PATH}/download-agent-mime-util.c -) - -SET(HEADERS - include/download-agent-defs.h - include/download-agent-interface.h -) - -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DA_ENGINE}) -#TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS} "-ldl") -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${subpkgs_LDFLAGS}) -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION 0.0.1) - -############################################################################# -#+++++++++++++++++++++++++INSTALLATION++++++++++++++++++++++++++++++++++++++++ -############################################################################# - -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) - diff --git a/src/agent/download-agent-basic.c b/src/agent/download-agent-basic.c deleted file mode 100644 index d069e7e..0000000 --- a/src/agent/download-agent-basic.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-basic.c - * @brief functions for basic (http) download - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include - -#include "download-agent-basic.h" -#include "download-agent-debug.h" -#include "download-agent-client-mgr.h" -#include "download-agent-utils.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-installation.h" -#include "download-agent-pthread.h" - -static void* __thread_start_download(void* data); -void __thread_clean_up_handler_for_start_download(void *arg); - -static da_result_t __make_source_info_basic_download( - stage_info *stage, - client_input_t *client_input); -static da_result_t __download_content(stage_info *stage); - -da_result_t start_download(const char *url , da_handle_t *dl_req_id) -{ - DA_LOG_FUNC_START(Default); - return start_download_with_extension(url, dl_req_id, NULL); -} - -da_result_t start_download_with_extension( - const char *url, - da_handle_t *dl_req_id, - extension_data_t *extension_data) -{ - da_result_t ret = DA_RESULT_OK; - int download_id = 0; - const char **request_header = DA_NULL; - const char *install_path = DA_NULL; - const char *file_name = DA_NULL; - int request_header_count = 0; - void *user_data = DA_NULL; - client_input_t *client_input = DA_NULL; - client_input_basic_t *client_input_basic = DA_NULL; - download_thread_input *thread_info = DA_NULL; - pthread_attr_t thread_attr; - - DA_LOG_FUNC_START(Default); - - if (extension_data) { - request_header = extension_data->request_header; - if (extension_data->request_header_count) - request_header_count = *(extension_data->request_header_count); - install_path = extension_data->install_path; - file_name = extension_data->file_name; - user_data = extension_data->user_data; - } - - ret = get_available_download_id(&download_id); - if (DA_RESULT_OK != ret) - return ret; - - *dl_req_id = GET_DL_REQ_ID(download_id); - - client_input = (client_input_t *)calloc(1, sizeof(client_input_t)); - if (!client_input) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } else { - client_input->user_data = user_data; - if (install_path) { - int install_path_len = strlen(install_path); - if (install_path[install_path_len-1] == '/') - install_path_len--; - - client_input->install_path = (char *)calloc(1, install_path_len+1); - if (client_input->install_path) - snprintf(client_input->install_path, install_path_len+1, install_path); - } - - if (file_name) { - client_input->file_name = (char *)calloc(1, strlen(file_name)+1); - if (client_input->file_name) - strncpy(client_input->file_name, file_name, strlen(file_name)); - } - - client_input_basic = &(client_input->client_input_basic); - client_input_basic->req_url = (char *)calloc(1, strlen(url)+1); - if(DA_NULL == client_input_basic->req_url) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - strncpy(client_input_basic->req_url ,url,strlen(url)); - - if (request_header_count > 0) { - int i = 0; - client_input_basic->user_request_header = - (char **)calloc(1, sizeof(char *)*request_header_count); - if(DA_NULL == client_input_basic->user_request_header) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - for (i = 0; i < request_header_count; i++) - { - client_input_basic->user_request_header[i] = strdup(request_header[i]); - } - client_input_basic->user_request_header_count = request_header_count; - } - } - - thread_info = (download_thread_input *)calloc(1, sizeof(download_thread_input)); - if (!thread_info) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } else { - thread_info->download_id = download_id; - thread_info->client_input = client_input; - } - if (pthread_attr_init(&thread_attr) != 0) { - ret = DA_ERR_FAIL_TO_CREATE_THREAD; - goto ERR; - } - - if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0) { - ret = DA_ERR_FAIL_TO_CREATE_THREAD; - goto ERR; - } - - if (pthread_create(&GET_DL_THREAD_ID(download_id), &thread_attr, - __thread_start_download, thread_info) < 0) { - DA_LOG_ERR(Thread, "making thread failed.."); - ret = DA_ERR_FAIL_TO_CREATE_THREAD; - } else { - if (GET_DL_THREAD_ID(download_id) < 1) { - DA_LOG_ERR(Thread, "The thread start is failed before calling this"); -// When http resource is leaked, the thread ID is initialized at error handling section of thread_start_download() -// Because the thread ID is initialized, the ptrhead_detach should not be called. This is something like timing issue between threads. -// thread info and basic_dl_input is freed at thread_start_download(). And it should not returns error code in this case. - goto ERR; - } - } - DA_LOG_CRITICAL(Thread, "download thread create download_id[%d] thread id[%lu]", - download_id,GET_DL_THREAD_ID(download_id)); - -ERR: - if (DA_RESULT_OK != ret) { - if (client_input) { - clean_up_client_input_info(client_input); - free(client_input); - client_input = DA_NULL; - } - if (thread_info) { - free(thread_info); - thread_info = DA_NULL; - } - destroy_download_info(download_id); - } - return ret; -} - -da_result_t __make_source_info_basic_download( - stage_info *stage, - client_input_t *client_input) -{ - da_result_t ret = DA_RESULT_OK; - client_input_basic_t *client_input_basic = DA_NULL; - source_info_t *source_info = DA_NULL; - source_info_basic_t *source_info_basic = DA_NULL; - - DA_LOG_FUNC_START(Default); - - if (!stage) { - DA_LOG_ERR(Default, "no stage; DA_ERR_INVALID_ARGUMENT"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - client_input_basic = &(client_input->client_input_basic); - if (DA_NULL == client_input_basic->req_url) { - DA_LOG_ERR(Default, "DA_ERR_INVALID_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - source_info_basic = (source_info_basic_t*)calloc(1, sizeof(source_info_basic_t)); - if (DA_NULL == source_info_basic) { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - - source_info_basic->url = client_input_basic->req_url; - client_input_basic->req_url = DA_NULL; - - if (client_input_basic->user_request_header) { - source_info_basic->user_request_header = - client_input_basic->user_request_header; - source_info_basic->user_request_header_count = - client_input_basic->user_request_header_count; - client_input_basic->user_request_header = DA_NULL; - client_input_basic->user_request_header_count = 0; - } - - source_info = GET_STAGE_SOURCE_INFO(stage); - memset(source_info, 0, sizeof(source_info_t)); - - source_info->source_info_type.source_info_basic = source_info_basic; - - DA_LOG(Default, "BASIC HTTP STARTED: URL=%s", - source_info->source_info_type.source_info_basic->url); -ERR: - return ret; -} - -void __thread_clean_up_handler_for_start_download(void *arg) -{ - DA_LOG_CRITICAL(Default, "cleanup for thread id = %d", pthread_self()); -} - -static void *__thread_start_download(void *data) -{ - da_result_t ret = DA_RESULT_OK; - download_thread_input *thread_info = DA_NULL; - client_input_t *client_input = DA_NULL; - stage_info *stage = DA_NULL; - int download_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(Thread); - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); - - thread_info = (download_thread_input*)data; - if (DA_NULL == thread_info) { - DA_LOG_ERR(Thread, "thread_info is NULL.."); - ret = DA_ERR_INVALID_ARGUMENT; - return DA_NULL; - } else { - download_id = thread_info->download_id; - client_input = thread_info->client_input; - - if(thread_info) { - free(thread_info); - thread_info = DA_NULL; - } - } - - pthread_cleanup_push(__thread_clean_up_handler_for_start_download, (void *)NULL); - - if (DA_FALSE == is_valid_dl_ID(download_id)) { - ret = DA_ERR_INVALID_ARGUMENT; - DA_LOG_ERR(Default, "Invalid Download ID"); - goto ERR; - } - - if (!client_input) { - ret = DA_ERR_INVALID_ARGUMENT; - DA_LOG_ERR(Default, "Invalid client_input"); - goto ERR; - } - - stage = Add_new_download_stage(download_id); - if (!stage) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - DA_LOG_ERR(Default, "STAGE ADDITION FAIL!"); - goto ERR; - } - DA_LOG(Default, "new added Stage : %p", stage); - - GET_DL_USER_DATA(download_id) = client_input->user_data; - GET_DL_USER_INSTALL_PATH(download_id) = client_input->install_path; - client_input->install_path = DA_NULL; - GET_DL_USER_FILE_NAME(download_id) = client_input->file_name; - client_input->file_name = DA_NULL; - - ret = __make_source_info_basic_download(stage, client_input); - /* to save memory */ - if (client_input) { - clean_up_client_input_info(client_input); - free(client_input); - client_input = DA_NULL; - } - - if (ret == DA_RESULT_OK) - ret = __download_content(stage); - -ERR: - if (client_input) { - clean_up_client_input_info(client_input); - free(client_input); - client_input = DA_NULL; - } - - if (DA_RESULT_OK == ret) { - DA_LOG_CRITICAL(Default, "Whole download flow is finished."); - send_user_noti_and_finish_download_flow(download_id); - } else { - DA_LOG_CRITICAL(Default, "DA_STATE_FAILED -Return = %d", ret); - send_client_da_state(download_id, DA_STATE_FAILED, ret); - destroy_download_info(download_id); - } - - pthread_cleanup_pop(0); - DA_LOG_CRITICAL(Thread, "=====thread_start_download - EXIT====="); - pthread_exit((void *)NULL); - return DA_NULL; -} - -da_result_t __download_content(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state = 0; - da_bool_t isDownloadComplete = DA_FALSE; - int download_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(Default); - - download_id = GET_STAGE_DL_ID(stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD, stage); - - do { - stage = GET_DL_CURRENT_STAGE(download_id); - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - download_state = GET_DL_STATE_ON_STAGE(stage); - DA_LOG(Default, "download_state to - [%d] ", download_state); - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - - switch(download_state) { - case DOWNLOAD_STATE_NEW_DOWNLOAD: - ret = requesting_download(stage); - - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - download_state = GET_DL_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - - if (download_state == DOWNLOAD_STATE_CANCELED) { - break; - } else { - if (DA_RESULT_OK == ret) { - ret = handle_after_download(stage); - } - } - break; - case DOWNLOAD_STATE_READY_TO_INSTAL: - send_client_da_state(download_id, DA_STATE_DOWNLOAD_COMPLETE, DA_RESULT_OK); - ret = process_install(stage); - if (DA_RESULT_OK == ret) { - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH,stage); - } - break; - default: - isDownloadComplete = DA_TRUE; - break; - } - }while ((DA_RESULT_OK == ret) && (DA_FALSE == isDownloadComplete)); - - return ret; -} diff --git a/src/agent/download-agent-client-mgr.c b/src/agent/download-agent-client-mgr.c deleted file mode 100644 index 4575fd7..0000000 --- a/src/agent/download-agent-client-mgr.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-client-mgr.c - * @brief client manager module for notifying download ststus information - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include - -#include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-file.h" - -#define IS_CLIENT_Q_HAVING_DATA(QUEUE) (QUEUE->having_data) - -static client_app_mgr_t client_app_mgr; - -static da_result_t __launch_client_thread(void); -static void *__thread_for_client_noti(void *data); -void __thread_clean_up_handler_for_client_thread(void *arg); -static void __pop_client_noti(client_noti_t **out_client_noti); - -void __client_q_goto_sleep_without_lock(void); -void __client_q_wake_up_without_lock(void); -void destroy_client_noti(client_noti_t *client_noti); - -da_result_t init_client_app_mgr() -{ - DA_LOG_FUNC_START(ClientNoti); - - if(client_app_mgr.is_init) - return DA_RESULT_OK; - - client_app_mgr.is_init = DA_TRUE; - client_app_mgr.client_app_info.is_using = DA_FALSE; - client_app_mgr.client_app_info.is_manual_download = DA_FALSE; - client_app_mgr.client_app_info.client_user_agent = DA_NULL; - client_app_mgr.is_thread_init = DA_FALSE; - - return DA_RESULT_OK; -} - -da_bool_t is_client_app_mgr_init(void) -{ - return client_app_mgr.is_init; -} - -da_bool_t is_client_app_mgr_manual_download(void) -{ - return client_app_mgr.is_manual_download; -} - -da_result_t reg_client_app( - da_client_cb_t *da_client_callback, - da_download_managing_method download_method - ) -{ - da_result_t ret = DA_RESULT_OK; - client_queue_t *queue = DA_NULL; - client_noti_t *client_noti = DA_NULL; - - DA_LOG_FUNC_START(ClientNoti); - - if (client_app_mgr.client_app_info.is_using) - return DA_ERR_CLIENT_IS_ALREADY_REGISTERED; - - client_app_mgr.client_app_info.is_using = DA_TRUE; - if (download_method == DA_DOWNLOAD_MANAGING_METHOD_MANUAL) - client_app_mgr.client_app_info.is_manual_download = DA_TRUE; - else - client_app_mgr.client_app_info.is_manual_download = DA_FALSE; - - memset(&(client_app_mgr.client_app_info.client_callback), - 0, sizeof(da_client_cb_t)); - memcpy(&(client_app_mgr.client_app_info.client_callback), - da_client_callback, sizeof(da_client_cb_t)); - - _da_thread_mutex_init(&(client_app_mgr.mutex_client_mgr), DA_NULL); - - /* If some noti is existed at queue, delete all */ - do { - __pop_client_noti(&client_noti); - destroy_client_noti(client_noti); - } while(client_noti != DA_NULL); - - queue = &(client_app_mgr.client_queue); - DA_LOG_VERBOSE(ClientNoti, "client queue = %p", queue); - _da_thread_mutex_init(&(queue->mutex_client_queue), DA_NULL); - _da_thread_cond_init(&(queue->cond_client_queue), DA_NULL); - - ret = __launch_client_thread(); - - return ret; -} - -da_result_t dereg_client_app(void) -{ - client_noti_t *client_noti = DA_NULL; - - DA_LOG_FUNC_START(ClientNoti); - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->download_id = DA_INVALID_ID; - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_TERMINATE; - client_noti->next = DA_NULL; - - _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); - if (client_app_mgr.is_thread_init != DA_TRUE) { - DA_LOG_CRITICAL(ClientNoti, "try to cancel client mgr thread id[%lu]", client_app_mgr.thread_id); - if (pthread_cancel(client_app_mgr.thread_id) < 0) { - DA_LOG_ERR(ClientNoti, "cancel thread is failed!!!"); - } - } else { - void *t_return = NULL; - DA_LOG_VERBOSE(ClientNoti, "pushing Q_CLIENT_NOTI_TYPE_TERMINATE"); - push_client_noti(client_noti); - DA_LOG_CRITICAL(Thread, "===try to join client mgr thread id[%lu]===", client_app_mgr.thread_id); - if (pthread_join(client_app_mgr.thread_id, &t_return) < 0) { - DA_LOG_ERR(Thread, "join client thread is failed!!!"); - } - DA_LOG_CRITICAL(Thread, "===thread join return[%d]===", (char*)t_return); - } - _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); - - /* ToDo: This clean up should be done at the end of client_thread. */ - client_app_mgr.client_app_info.is_using= DA_FALSE; - client_app_mgr.client_app_info.is_manual_download = DA_FALSE; - if(client_app_mgr.client_app_info.client_user_agent) { - free(client_app_mgr.client_app_info.client_user_agent); - client_app_mgr.client_app_info.client_user_agent = DA_NULL; - } - _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); - client_app_mgr.is_thread_init = DA_FALSE; - _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); - _da_thread_mutex_destroy(&(client_app_mgr.mutex_client_mgr)); - return DA_RESULT_OK; -} - -da_result_t send_client_da_state (int download_id, da_state state, int err) -{ - client_noti_t *client_noti = DA_NULL; - user_notify_info_t *send_state_info = DA_NULL; - da_state cur_da_state; - - DA_LOG_FUNC_START(ClientNoti); - - DA_LOG_VERBOSE(ClientNoti, "da_state[%s], download_id[%d]", print_dl_state(state), download_id); - - if (!is_valid_dl_ID(download_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - /* Returning DA_RESULT_OK if download_id is not valid, - * because sending da_state should not effect to download flow. */ - return DA_RESULT_OK; - } - - if (state_watcher_need_redirect_Q(download_id)) { - state_watcher_redirect_state(download_id, state, err); - return DA_RESULT_OK; - } - - cur_da_state = GET_DL_DA_STATE(download_id); - - if ((DA_STATE_SUSPENDED != state) && (cur_da_state == state)) { - DA_LOG(ClientNoti, "inserting da_state is same with current da_state! Not inserting! inserting: %d, cur : %d", state, cur_da_state); - return DA_RESULT_OK; - } - - GET_DL_DA_STATE(download_id) = state; - DA_LOG_VERBOSE(ClientNoti, "change da_state to %d", state); - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->download_id = download_id; - client_noti->user_data = GET_DL_USER_DATA(download_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_SEND_STATE; - client_noti->next = DA_NULL; - - send_state_info = (user_notify_info_t *)&(client_noti->type.da_state_info); - send_state_info->da_dl_req_id = GET_DL_REQ_ID(download_id); - send_state_info->state = state; - send_state_info->err = err; - - DA_LOG(ClientNoti, "pushing da_state=%d, download_id=%d, err=%d, dl_req_id=%d", - state, download_id, err, GET_DL_REQ_ID(download_id)); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t send_client_update_downloading_info ( - int download_id, - int dl_req_id, - unsigned long int total_received_size, - char *saved_path - ) -{ - client_noti_t *client_noti = DA_NULL; - user_downloading_info_t *downloading_info = DA_NULL; - - DA_LOG_FUNC_START(ClientNoti); - - if (!is_valid_dl_ID(download_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - return DA_ERR_INVALID_DL_REQ_ID; - } - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->download_id = download_id; - client_noti->user_data = GET_DL_USER_DATA(download_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO; - client_noti->next = DA_NULL; - - downloading_info = (user_downloading_info_t *)&(client_noti->type.update_downloading_info); - downloading_info->da_dl_req_id = dl_req_id; - downloading_info->total_received_size = total_received_size; - - /* These strings MUST be copied to detach __thread_for_client_noti from download_info */ - if (saved_path) - downloading_info->saved_path = strdup(saved_path); - DA_LOG(ClientNoti, "pushing received_size=%lu, download_id=%d, dl_req_id=%d", - total_received_size, download_id, dl_req_id); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t send_client_update_dl_info ( - int download_id, - int dl_req_id, - char *file_type, - unsigned long int file_size, - char *tmp_saved_path, - char *http_response_header, - char *http_chunked_data - ) -{ - client_noti_t *client_noti = DA_NULL; - user_download_info_t *update_dl_info = DA_NULL; - - DA_LOG_FUNC_START(ClientNoti); - - if (!is_valid_dl_ID(download_id)) { - DA_LOG_ERR(ClientNoti, "Download ID is not valid"); - return DA_ERR_INVALID_DL_REQ_ID; - } - - client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t)); - if (!client_noti) { - DA_LOG_ERR(ClientNoti, "calloc fail"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - client_noti->download_id = download_id; - client_noti->user_data = GET_DL_USER_DATA(download_id); - client_noti->noti_type = Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO; - client_noti->next = DA_NULL; - - update_dl_info = (user_download_info_t *)&(client_noti->type.update_dl_info); - update_dl_info->da_dl_req_id = dl_req_id; - update_dl_info->file_size = file_size; - - /* These strings MUST be copied to detach __thread_for_client_noti from download_info */ - if (file_type) - update_dl_info->file_type = strdup(file_type); - - if (tmp_saved_path) - update_dl_info->tmp_saved_path = strdup(tmp_saved_path); - - if (http_response_header) { - update_dl_info->http_response_header = strdup(http_response_header); - } - if (http_chunked_data) { - update_dl_info->http_chunked_data = calloc (1, file_size); - if (update_dl_info->http_chunked_data) - memcpy(update_dl_info->http_chunked_data, http_chunked_data, - file_size); - } - DA_LOG(ClientNoti, "pushing file_size=%lu, download_id=%d, dl_req_id=%d", - file_size, download_id, dl_req_id); - - push_client_noti(client_noti); - - return DA_RESULT_OK; -} - -da_result_t __launch_client_thread(void) -{ - pthread_t thread_id = DA_NULL; - - DA_LOG_FUNC_START(Thread); - - if (pthread_create(&thread_id,DA_NULL,__thread_for_client_noti,DA_NULL) < 0) { - DA_LOG_ERR(Thread, "making thread failed.."); - return DA_ERR_FAIL_TO_CREATE_THREAD; - } - DA_LOG(Thread, "client mgr thread id[%d]", thread_id); - client_app_mgr.thread_id = thread_id; - return DA_RESULT_OK; -} - -void destroy_client_noti(client_noti_t *client_noti) -{ - if (client_noti) { - if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO) { - user_download_info_t *update_dl_info = DA_NULL; - update_dl_info = (user_download_info_t*)&(client_noti->type.update_dl_info); - if (update_dl_info->file_type) { - free(update_dl_info->file_type); - update_dl_info->file_type = DA_NULL; - } - if (update_dl_info->tmp_saved_path) { - free(update_dl_info->tmp_saved_path); - update_dl_info->tmp_saved_path = DA_NULL; - } - if (update_dl_info->http_response_header) { - free(update_dl_info->http_response_header); - update_dl_info->http_response_header = DA_NULL; - } - if (update_dl_info->http_chunked_data) { - free(update_dl_info->http_chunked_data); - update_dl_info->http_chunked_data = DA_NULL; - } - } else if (client_noti->noti_type == - Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO) { - user_downloading_info_t *downloading_info = DA_NULL; - downloading_info = (user_downloading_info_t*)&(client_noti->type.update_downloading_info); - if (downloading_info->saved_path) { - free(downloading_info->saved_path); - downloading_info->saved_path = DA_NULL; - } - } - free(client_noti); - } -} - - -void push_client_noti(client_noti_t *client_noti) -{ - client_queue_t *queue = DA_NULL; - client_noti_t *head = DA_NULL; - client_noti_t *pre = DA_NULL; - client_noti_t *cur = DA_NULL; - - /* DA_LOG_FUNC_START(ClientNoti); */ - - if(!is_this_client_available()) { - DA_LOG_ERR(ClientNoti, "invalid client"); - return; - } - queue = &(client_app_mgr.client_queue); - _da_thread_mutex_lock (&(queue->mutex_client_queue)); - - head = queue->client_q_head; - if (!head) { - queue->client_q_head = client_noti; - } else { - cur = head; - while (cur->next) { - pre = cur; - cur = pre->next; - } - - if (DA_TRUE == is_this_client_manual_download_type()) { - cur->next = client_noti; - } else if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_SEND_STATE) { - cur->next = client_noti; - } else { - if (cur->noti_type == Q_CLIENT_NOTI_TYPE_SEND_STATE) { - cur->next = client_noti; - } else if (cur->noti_type == Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO) { - /* For UI performance. If the update noti info is existed at queue, - replace it with new update noti info */ - if (cur->download_id == client_noti->download_id) { - /* DA_LOG(ClientNoti, "exchange queue's tail and pushing item"); */ - if (pre == DA_NULL) - queue->client_q_head = client_noti; - else - pre->next = client_noti; - destroy_client_noti(cur); - } else { - cur->next = client_noti; - } - } - } - } - - queue->having_data = DA_TRUE; - - __client_q_wake_up_without_lock(); - - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); -} - -void __pop_client_noti(client_noti_t **out_client_noti) -{ - client_queue_t *queue = DA_NULL; - - /* DA_LOG_FUNC_START(ClientNoti); */ - - queue = &(client_app_mgr.client_queue); - - _da_thread_mutex_lock (&(queue->mutex_client_queue)); - - if (queue->client_q_head) { - *out_client_noti = queue->client_q_head; - queue->client_q_head = queue->client_q_head->next; - } else { - *out_client_noti = DA_NULL; - } - - if (queue->client_q_head == DA_NULL) { - queue->having_data = DA_FALSE; - } - - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); -} - -void __client_q_goto_sleep_without_lock(void) -{ - client_queue_t *queue = DA_NULL; - - /* DA_LOG_FUNC_START(ClientNoti); */ - - queue = &(client_app_mgr.client_queue); - _da_thread_cond_wait(&(queue->cond_client_queue), &(queue->mutex_client_queue)); -} - -void __client_q_wake_up_without_lock(void) -{ - client_queue_t *queue = DA_NULL; - - /* DA_LOG_FUNC_START(ClientNoti); */ - - queue = &(client_app_mgr.client_queue); - _da_thread_cond_signal(&(queue->cond_client_queue)); -} - -void __thread_clean_up_handler_for_client_thread(void *arg) -{ - DA_LOG_CRITICAL(Thread, "cleanup for thread id = %d", pthread_self()); -} - -static void *__thread_for_client_noti(void *data) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t need_wait = DA_TRUE; - client_queue_t *queue = DA_NULL; - client_noti_t *client_noti = DA_NULL; - - DA_LOG_FUNC_START(Thread); - - _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr)); - client_app_mgr.is_thread_init = DA_TRUE; - _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr)); - - queue = &(client_app_mgr.client_queue); - DA_LOG(ClientNoti, "client queue = %p", queue); - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL); - pthread_cleanup_push(__thread_clean_up_handler_for_client_thread, (void *)DA_NULL); - - do { - _da_thread_mutex_lock(&(queue->mutex_client_queue)); - if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) { - DA_LOG(Thread, "Sleep @ thread_for_client_noti!"); - __client_q_goto_sleep_without_lock(); - DA_LOG(Thread, "Woke up @ thread_for_client_noti"); - } - _da_thread_mutex_unlock(&(queue->mutex_client_queue)); - - do { - __pop_client_noti(&client_noti); - if (client_noti == DA_NULL) { - DA_LOG_ERR(ClientNoti, "There is no data on client queue!"); - ret = DA_ERR_INVALID_STATE; - need_wait = DA_FALSE; - } else { - switch (client_noti->noti_type) { - case Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO: - { - user_download_info_t *update_dl_info = DA_NULL;; - update_dl_info = (user_download_info_t*)(&(client_noti->type.update_dl_info)); - if (client_app_mgr.client_app_info.client_callback.update_dl_info_cb) { - client_app_mgr.client_app_info.client_callback.update_dl_info_cb(update_dl_info, client_noti->user_data); - DA_LOG(ClientNoti, "Update download info for download_id=%d, dl_req_id=%d, received size=%lu- DONE", - client_noti->download_id, - update_dl_info->da_dl_req_id, - update_dl_info->file_size - ); - } - } - break; - case Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO: - { - user_downloading_info_t *downloading_info = DA_NULL;; - downloading_info = (user_downloading_info_t*)(&(client_noti->type.update_downloading_info)); - if (client_app_mgr.client_app_info.client_callback.update_progress_info_cb) { - client_app_mgr.client_app_info.client_callback.update_progress_info_cb(downloading_info, client_noti->user_data); - DA_LOG(ClientNoti, "Update downloading info for download_id=%d, dl_req_id=%d, received size=%lu - DONE", - client_noti->download_id, - downloading_info->da_dl_req_id, - downloading_info->total_received_size); - } - } - break; - case Q_CLIENT_NOTI_TYPE_SEND_STATE: - { - user_notify_info_t *da_state_info = DA_NULL; - da_state_info = (user_notify_info_t *)(&(client_noti->type.da_state_info)); - - if (client_app_mgr.client_app_info.client_callback.user_noti_cb) { - DA_LOG(ClientNoti, "User Noti info for download_id=%d, dl_req_id=%d, da_state=%d, err=%d", - client_noti->download_id, - da_state_info->da_dl_req_id, da_state_info->state, - da_state_info->err); - client_app_mgr.client_app_info.client_callback.user_noti_cb(da_state_info, client_noti->user_data); - DA_LOG(ClientNoti, "User Noti info for download_id=%d, dl_req_id=%d, da_state=%d, err=%d - DONE", - client_noti->download_id, - da_state_info->da_dl_req_id, - da_state_info->state, da_state_info->err); - } - } - break; - case Q_CLIENT_NOTI_TYPE_TERMINATE: - DA_LOG_CRITICAL(ClientNoti, "Q_CLIENT_NOTI_TYPE_TERMINATE"); - need_wait = DA_FALSE; - break; - } - destroy_client_noti(client_noti); - } - - if(DA_TRUE == need_wait) { - _da_thread_mutex_lock(&(queue->mutex_client_queue)); - if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) { - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); - break; - } else { - _da_thread_mutex_unlock (&(queue->mutex_client_queue)); - } - } else { - break; - } - } while (1); - } while (DA_TRUE == need_wait); - - _da_thread_mutex_destroy(&(queue->mutex_client_queue)); - _da_thread_cond_destroy(&(queue->cond_client_queue)); - - pthread_cleanup_pop(0); - DA_LOG_CRITICAL(Thread, "=====thread_for_client_noti- EXIT====="); - pthread_exit((void *)NULL); - return DA_NULL; -} - -da_bool_t is_this_client_available(void) -{ - return client_app_mgr.client_app_info.is_using; -} - -da_bool_t is_this_client_manual_download_type(void) -{ - return client_app_mgr.client_app_info.is_manual_download; -} - -da_result_t get_client_download_path(char **out_path) -{ - if (!out_path) { - DA_LOG_ERR(ClientNoti, "DA_ERR_INVALID_ARGUMENT"); - return DA_ERR_INVALID_ARGUMENT; - } - - /* change the directory policy. it doesn't clean the temp direcoty when deinitializing */ - *out_path = strdup(DA_DEFAULT_TMP_FILE_DIR_PATH); - DA_LOG_VERBOSE(ClientNoti, "client download path = [%s]", *out_path); - - return DA_RESULT_OK; -} - -char *get_client_user_agent_string(void) -{ - if (!client_app_mgr.is_init) - return DA_NULL; - - return client_app_mgr.client_app_info.client_user_agent; -} diff --git a/src/agent/download-agent-debug.c b/src/agent/download-agent-debug.c deleted file mode 100644 index dd5e1c5..0000000 --- a/src/agent/download-agent-debug.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-debug.c - * @brief for log system on Download Agent - * @author Keunsoon Lee (keunsoon.lee@samsung.com) - * @author Jungki Kwak (jungki.kwak@samsung.com) - ***/ - -#include -#include - -#include "download-agent-debug.h" -#include "download-agent-utils.h" - -#define STRING_IT(x) #x -#define TURN_ON_LOG(channel) (DALogBitMap |= (0x1<<(channel))) - -int DALogBitMap; - -char *__get_log_env(void); -char **__parsing_log_env(char *in_log_env); -char *__copying_str(char *source, int length); -char *__get_channel_name_from_enum(da_log_channel channel_enum); - -da_result_t init_log_mgr(void) { - da_result_t ret = DA_RESULT_OK; - static da_bool_t did_log_mgr_init = DA_FALSE; - char *log_env = DA_NULL; - char **parsed_log_env = DA_NULL; - char **cur_parsed_log_env = DA_NULL; - int i = 0; - - if (did_log_mgr_init) - return ret; - - did_log_mgr_init = DA_TRUE; - - log_env = __get_log_env(); - if (!log_env) { - /* If no environment values are found, do behave like all logs are turned on except for Soup log */ - DALogBitMap = ~(0x1 << Soup); - return ret; - } - - TURN_ON_LOG(Default); - - parsed_log_env = __parsing_log_env(log_env); - if (parsed_log_env) { - char *channel_keyward = DA_NULL; - for (cur_parsed_log_env = parsed_log_env; *cur_parsed_log_env; cur_parsed_log_env++) { - if (!*cur_parsed_log_env) - break; - for (i = 0; i < DA_LOG_CHANNEL_MAX; i++) { - channel_keyward = __get_channel_name_from_enum(i); - if (channel_keyward && !strcmp(*cur_parsed_log_env, - channel_keyward)) { - TURN_ON_LOG(i); - break; - } - } - free(*cur_parsed_log_env); - } - free(parsed_log_env); - } - - if (log_env) - free(log_env); - - return ret; -} - -char *__get_log_env(void) { - char *log_env = DA_NULL; - - /* environment value has higher priority than configure file */ - log_env = getenv(DA_DEBUG_ENV_KEY); - if (log_env && strlen(log_env)) - return strdup(log_env); - - if (read_data_from_file(DA_DEBUG_CONFIG_FILE_PATH, &log_env)) - return log_env; - - return DA_NULL; -} - -char **__parsing_log_env(char *in_log_env) { - char **out_parsed_result = DA_NULL; - - char **temp_result_array = DA_NULL; - char **cur_temp_result_array = DA_NULL; - int how_many_item = 0; - int how_many_delimeter = 0; - - char delimiter = ','; - - char *org_str = in_log_env; - char *cur_char = org_str; - char *start = org_str; - char *end = org_str; - int target_len = 0; - - if (!org_str) - return DA_NULL; - - /* counting delimiter to know how many items should be memory allocated. - * This causes two round of loop (counting delimiter and real operation). - * But I think it is tolerable, because input parameter is from console. - * And it is also a reason why we should not use fixed length array. - * Users are hard to input very long environment, but it is possible. */ - for (cur_char = org_str; *cur_char; cur_char++) { - if (*cur_char == delimiter) - how_many_delimeter++; - } - how_many_item = how_many_delimeter + 1; - temp_result_array = (char**) calloc(1, how_many_item + 1); - if (!(temp_result_array)) - goto ERR; - - cur_temp_result_array = temp_result_array; - cur_char = org_str; - while (1) { - if (*cur_char == delimiter) { - end = cur_char; - target_len = (int) (end - start); - *cur_temp_result_array++ = __copying_str(start, - target_len); - start = ++cur_char; - continue; - } else if (!(*cur_char)) { - end = cur_char; - target_len = (int) (end - start); - *cur_temp_result_array++ = __copying_str(start, - target_len); - *cur_temp_result_array = DA_NULL; - break; - } else { - cur_char++; - } - } - out_parsed_result = temp_result_array; -ERR: - return out_parsed_result; -} - -char *__copying_str(char *source, int length) { - char *copied_str = DA_NULL; - char *cur_pos = DA_NULL; - char white_space = ' '; - char end_of_line = 10; /* ASCII for LF */ - int i = 0; - - if (!source || !(length > 0)) - return DA_NULL; - - copied_str = (char*) calloc(1, length + 1); - if (copied_str) { - cur_pos = copied_str; - for (i = 0; i < length; i++) { - if ((source[i] != white_space) && (source[i] - != end_of_line)) - *cur_pos++ = source[i]; - } - } - - return copied_str; -} - -char *__get_channel_name_from_enum(da_log_channel channel_enum) { - switch (channel_enum) { - case Soup: - return STRING_IT(Soup); - case HTTPManager: - return STRING_IT(HTTPManager); - case InstallManager: - return STRING_IT(InstallManager); - case FileManager: - return STRING_IT(FileManager); - case DownloadManager: - return STRING_IT(DownloadManager); - case ClientNoti: - return STRING_IT(ClientNoti); - case HTTPMessageHandler: - return STRING_IT(HTTPMessageHandler); - case Encoding: - return STRING_IT(Encoding); - case QueueManager: - return STRING_IT(QueueManager); - case Parsing: - return STRING_IT(Parsing); - case Thread: - return STRING_IT(Thread); - case Default: - return STRING_IT(Default); - default: - return DA_NULL; - } -} diff --git a/src/agent/download-agent-dl-info-util.c b/src/agent/download-agent-dl-info-util.c deleted file mode 100644 index 98e8ff1..0000000 --- a/src/agent/download-agent-dl-info-util.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-dl-info-util.c - * @brief create and destroy functions for download_info - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include - -#include "download-agent-client-mgr.h" -#include "download-agent-dl-info-util.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-file.h" -#include "download-agent-http-mgr.h" -#include "download-agent-plugin-conf.h" - -pthread_mutex_t mutex_download_state[DA_MAX_DOWNLOAD_ID]; -static pthread_mutex_t mutex_download_mgr = PTHREAD_MUTEX_INITIALIZER; -download_mgr_t download_mgr; - -void init_state_watcher(state_watcher_t *state_watcher); -void cleanup_state_watcher(state_watcher_t *state_watcher); - -da_result_t set_default_header_info(void); - -void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic); -void cleanup_req_dl_info_http(req_dl_info *http_download); -void destroy_file_info(file_info *file); - -da_result_t init_download_mgr() { - da_result_t ret = DA_RESULT_OK; - int i = 0; - - DA_LOG_FUNC_START(Default); - - if (is_client_app_mgr_init() == DA_FALSE) { - DA_LOG_ERR(Default, "client app manager is not initiated!"); - return DA_ERR_INVALID_CLIENT; - } - - _da_thread_mutex_lock(&mutex_download_mgr); - - if (download_mgr.is_init == DA_FALSE) { - download_mgr.is_init = DA_TRUE; - - for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { - _da_thread_mutex_init(&mutex_download_state[i], DA_NULL); - init_download_info(i); - } - - init_state_watcher(&(download_mgr.state_watcher)); - init_dl_req_id_history(&(download_mgr.dl_req_id_history)); - - download_mgr.default_hdr_info = (default_http_hdr_info_t *) calloc(1, - sizeof(default_http_hdr_info_t)); - if (download_mgr.default_hdr_info) { - /* Don't check return value, - * because UA and UAprof is not mandatory field at HTTP request header */ - set_default_header_info(); - } else { - DA_LOG_ERR(Default, "DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - } - } - - _da_thread_mutex_unlock(&mutex_download_mgr); - - return ret; -} - -da_result_t deinit_download_mgr(void) { - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock(&mutex_download_mgr); - if (download_mgr.is_init == DA_TRUE) { - int i = 0; - download_info_t *dl_info = DA_NULL; - void *t_return = NULL; - for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { - dl_info = &(download_mgr.download_info[i]); - if (dl_info && dl_info->is_using) { - request_to_abort_http_download(GET_DL_CURRENT_STAGE(i)); - DA_LOG_CRITICAL(Thread, "===download id[%d] thread id[%lu] join===",i, GET_DL_THREAD_ID(i)); -/* Because the download daemon can call the deinit function, the resources of pthread are not freed - FIXME later : It is needed to change the termination flow again. - if (pthread_join(GET_DL_THREAD_ID(i), &t_return) < 0) { - DA_LOG_ERR(Thread, "join client thread is failed!!!"); - } -*/ - DA_LOG_CRITICAL(Thread, "===download id[%d] thread join return[%d]===",i, (char*)t_return); -} -} - download_mgr.is_init = DA_FALSE; - cleanup_state_watcher(&(download_mgr.state_watcher)); - if (NULL != download_mgr.default_hdr_info) { - if (NULL != download_mgr.default_hdr_info->user_agent_string) - free(download_mgr.default_hdr_info->user_agent_string); - - download_mgr.default_hdr_info->user_agent_string = NULL; - - free(download_mgr.default_hdr_info); - download_mgr.default_hdr_info = NULL; - } - deinit_dl_req_id_history(&(download_mgr.dl_req_id_history)); - } - _da_thread_mutex_unlock(&mutex_download_mgr); - return ret; -} - -da_result_t set_default_header_info(void) -{ - da_result_t ret = DA_RESULT_OK; - - ret = get_user_agent_string( - &download_mgr.default_hdr_info->user_agent_string); - - if (DA_RESULT_OK != ret) - goto ERR; - else - DA_LOG(Default, "download_mgr.default_hdr_info->user_agent_string = %s ", - download_mgr.default_hdr_info->user_agent_string); -ERR: - return ret; -} - -void init_download_info(int download_id) -{ - download_info_t *dl_info = DA_NULL; - -// DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock(&mutex_download_state[download_id]); - DA_LOG(Default, "Init download_id [%d] Info", download_id); - dl_info = &(download_mgr.download_info[download_id]); - - dl_info->is_using = DA_FALSE; - dl_info->state = DOWNLOAD_STATE_IDLE; - dl_info->download_stage_data = DA_NULL; - dl_info->dl_req_id = DA_NULL; - dl_info->user_install_path = DA_NULL; - dl_info->user_data = DA_NULL; - - Q_init_queue(&(dl_info->queue)); - - DA_LOG(Default, "Init download_id [%d] Info END", download_id); - _da_thread_mutex_unlock(&mutex_download_state[download_id]); - - return; -} - -void destroy_download_info(int download_id) -{ - download_info_t *dl_info = DA_NULL; - - DA_LOG_FUNC_START(Default); - - DA_LOG(Default, "Destroying download_id [%d] Info", download_id); - - if (download_id == DA_INVALID_ID) { - DA_LOG_ERR(Default, "invalid download_id"); - return; - } - - dl_info = &(download_mgr.download_info[download_id]); - if (DA_FALSE == dl_info->is_using) { -/* DA_LOG_ERR(Default, "invalid download_id"); */ - return; - } - - _da_thread_mutex_lock (&mutex_download_state[download_id]); - dl_info->state = DOWNLOAD_STATE_IDLE; - DA_LOG(Default, "Changed download_state to - [%d] ", dl_info->state); - - dl_info->active_dl_thread_id = 0; - - if (dl_info->download_stage_data != DA_NULL) { - remove_download_stage(download_id, dl_info->download_stage_data); - dl_info->download_stage_data = DA_NULL; - } - dl_info->dl_req_id = DA_NULL; - if (dl_info->user_install_path) { - free(dl_info->user_install_path); - dl_info->user_install_path = DA_NULL; - } - dl_info->user_data = DA_NULL; - dl_info->cur_da_state = DA_STATE_WAITING; - - Q_destroy_queue(&(dl_info->queue)); - - dl_info->is_using = DA_FALSE; - - DA_LOG(Default, "Destroying download_id [%d] Info END", download_id); - _da_thread_mutex_unlock (&mutex_download_state[download_id]); - return; -} - -void *Add_new_download_stage(int download_id) -{ - stage_info *download_stage_data = NULL; - stage_info *new_download_stage_data = NULL; - - DA_LOG_FUNC_START(Default); - - new_download_stage_data = (stage_info*)calloc(1, sizeof(stage_info)); - if (!new_download_stage_data) - goto ERR; - - new_download_stage_data->dl_id = download_id; - download_stage_data = GET_DL_CURRENT_STAGE(download_id); - if (download_stage_data) { - while (download_stage_data->next_stage_info) { - download_stage_data - = download_stage_data->next_stage_info; - }; - download_stage_data->next_stage_info = new_download_stage_data; - } else { - GET_DL_CURRENT_STAGE(download_id) = new_download_stage_data; - } - DA_LOG(Default, "NEW STAGE ADDED FOR DOWNLOAD ID[%d] new_stage[%p]", download_id,new_download_stage_data); - -ERR: - return new_download_stage_data; -} - -void remove_download_stage(int download_id, stage_info *in_stage) -{ - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_START(Default); - - stage = GET_DL_CURRENT_STAGE(download_id); - if (DA_NULL == stage) { - DA_LOG_VERBOSE(Default, "There is no stage field on download_id = %d", download_id); - goto ERR; - } - - if (DA_NULL == in_stage) { - DA_LOG_VERBOSE(Default, "There is no in_stage to remove."); - goto ERR; - } - - if (in_stage == stage) { - DA_LOG_VERBOSE(Default, "Base stage will be removed. in_stage[%p]",in_stage); - DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info); - GET_DL_CURRENT_STAGE(download_id) = stage->next_stage_info; - empty_stage_info(in_stage); - free(in_stage); - in_stage = DA_NULL; - } else { - while (in_stage != stage->next_stage_info) { - stage = stage->next_stage_info; - } - if (in_stage == stage->next_stage_info) { - stage->next_stage_info - = stage->next_stage_info->next_stage_info; - DA_LOG_VERBOSE(Default, "Stage will be removed. in_stage[%p]",in_stage); - DA_LOG_VERBOSE(Default, "next stage[%p]",stage->next_stage_info); - empty_stage_info(in_stage); - free(in_stage); - in_stage = DA_NULL; - } - } - -ERR: - return; -} - -void empty_stage_info(stage_info *in_stage) -{ - source_info_t *source_information = NULL; - req_dl_info *request_download_info = NULL; - file_info *file_information = NULL; - - DA_LOG_FUNC_START(Default); - - DA_LOG(Default, "Stage to Remove:[%p]", in_stage); - source_information = GET_STAGE_SOURCE_INFO(in_stage); - - cleanup_source_info_basic_download( - GET_SOURCE_BASIC(source_information)); - - request_download_info = GET_STAGE_TRANSACTION_INFO(in_stage); - - cleanup_req_dl_info_http(request_download_info); - - file_information = GET_STAGE_CONTENT_STORE_INFO(in_stage); - destroy_file_info(file_information); -} - -void cleanup_source_info_basic_download(source_info_basic_t *source_info_basic) -{ - if (NULL == source_info_basic) - goto ERR; - - DA_LOG_FUNC_START(Default); - - if (NULL != source_info_basic->url) { - free(source_info_basic->url); - source_info_basic->url = DA_NULL; - } - -ERR: - return; - -} - -void cleanup_req_dl_info_http(req_dl_info *http_download) -{ - DA_LOG_FUNC_START(Default); - - if (http_download->http_info.http_msg_request) { - http_msg_request_destroy( - &(http_download->http_info.http_msg_request)); - } - - if (http_download->http_info.http_msg_response) { - http_msg_response_destroy( - &(http_download->http_info.http_msg_response)); - } - - if (DA_NULL != http_download->location_url) { - free(http_download->location_url); - http_download->location_url = DA_NULL; - } - if (DA_NULL != http_download->content_type_from_header) { - free(http_download->content_type_from_header); - http_download->content_type_from_header = DA_NULL; - } - - if (DA_NULL != http_download->etag_from_header) { - free(http_download->etag_from_header); - http_download->etag_from_header = DA_NULL; - } - - http_download->invloved_transaction_id = DA_INVALID_ID; - http_download->content_len_from_header = 0; - http_download->downloaded_data_size = 0; - - _da_thread_mutex_destroy(&(http_download->mutex_http_state)); - - return; -} - -void destroy_file_info(file_info *file_information) -{ -// DA_LOG_FUNC_START(Default); - - if (!file_information) - return; - - if (file_information->file_name_tmp) { - free(file_information->file_name_tmp); - file_information->file_name_tmp = NULL; - } - - if (file_information->file_name_final) { - free(file_information->file_name_final); - file_information->file_name_final = NULL; - } - - if (file_information->content_type) { - free(file_information->content_type); - file_information->content_type = NULL; - } - - if (file_information->pure_file_name) { - free(file_information->pure_file_name); - file_information->pure_file_name = NULL; - } - - if (file_information->extension) { - free(file_information->extension); - file_information->extension = NULL; - } - return; -} - -void clean_up_client_input_info(client_input_t *client_input) -{ - DA_LOG_FUNC_START(Default); - - if (client_input) { - client_input->user_data = NULL; - - if (client_input->install_path) { - free(client_input->install_path); - client_input->install_path = DA_NULL; - } - - if (client_input->file_name) { - free(client_input->file_name); - client_input->file_name = DA_NULL; - } - - client_input_basic_t *client_input_basic = - &(client_input->client_input_basic); - - if (client_input_basic && client_input_basic->req_url) { - free(client_input_basic->req_url); - client_input_basic->req_url = DA_NULL; - } - - if (client_input_basic && client_input_basic->user_request_header) { - int i = 0; - int count = client_input_basic->user_request_header_count; - for (i = 0; i < count; i++) - { - if (client_input_basic->user_request_header[i]) { - free(client_input_basic->user_request_header[i]); - client_input_basic->user_request_header[i] = DA_NULL; - } - } - - free(client_input_basic->user_request_header); - client_input_basic->user_request_header = DA_NULL; - client_input_basic->user_request_header_count = 0; - } - } else { - DA_LOG_ERR(Default, "client_input is NULL."); - } - - return; -} - -da_result_t get_download_id_for_dl_req_id( - da_handle_t dl_req_id, - da_handle_t* download_id) -{ - da_result_t ret = DA_ERR_INVALID_DL_REQ_ID; - int iter = 0; - - if (dl_req_id < 0) { - DA_LOG_ERR(Default, "dl_req_id is less than 0 - %d", dl_req_id); - return DA_ERR_INVALID_DL_REQ_ID; - } - - _da_thread_mutex_lock(&mutex_download_mgr); - for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { - if (download_mgr.download_info[iter].is_using == DA_TRUE) { - if (download_mgr.download_info[iter].dl_req_id == - dl_req_id) { - *download_id = iter; - ret = DA_RESULT_OK; - break; - } - } - } - _da_thread_mutex_unlock(&mutex_download_mgr); - - return ret; -} - - -da_result_t get_available_download_id(da_handle_t *available_id) -{ - da_result_t ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - int i; - - _da_thread_mutex_lock(&mutex_download_mgr); - for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) { - if (download_mgr.download_info[i].is_using == DA_FALSE) { - init_download_info(i); - - download_mgr.download_info[i].is_using = DA_TRUE; - - download_mgr.download_info[i].dl_req_id - = get_available_dl_req_id(&(download_mgr.dl_req_id_history)); - - *available_id = i; - DA_LOG_CRITICAL(Default, "available download id = %d", *available_id); - ret = DA_RESULT_OK; - - break; - } - } - _da_thread_mutex_unlock(&mutex_download_mgr); - - return ret; -} - -da_bool_t is_valid_dl_ID( download_id) -{ - da_bool_t ret = DA_FALSE; - - if (download_id >= 0 && download_id < DA_MAX_DOWNLOAD_ID) { - if (download_mgr.download_info[download_id].is_using == DA_TRUE) - ret = DA_TRUE; - } - - return ret; -} - -void init_state_watcher(state_watcher_t *state_watcher) -{ - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_init(&(state_watcher->mutex), DA_NULL); - - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->type = STATE_WATCHER_TYPE_NONE; - state_watcher->state_watching_bitmap = 0; - state_watcher->is_progressing_to_all = DA_FALSE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); -} - -void cleanup_state_watcher(state_watcher_t *state_watcher) -{ - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->type = STATE_WATCHER_TYPE_NONE; - state_watcher->state_watching_bitmap = 0; - state_watcher->is_progressing_to_all = DA_FALSE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - - _da_thread_mutex_destroy(&(state_watcher->mutex)); -} - -void state_watcher_flag_ON_for_download_id( - state_watcher_t *state_watcher, - int download_id) -{ - unsigned short mask = 0; - - _da_thread_mutex_lock(&(state_watcher->mutex)); - - mask = 1 << download_id; - - state_watcher->state_watching_bitmap |= mask; - - DA_LOG(Default, "state_watcher [%d], download_id [%d]", state_watcher->state_watching_bitmap, download_id); - - _da_thread_mutex_unlock(&(state_watcher->mutex)); -} - -void state_watcher_flag_OFF_for_download_id( - state_watcher_t *state_watcher, - int download_id) -{ - unsigned short mask = 0; - - _da_thread_mutex_lock(&(state_watcher->mutex)); - - mask = ~(1 << download_id); - - state_watcher->state_watching_bitmap &= mask; - - DA_LOG(Default, "state_watcher [%d], download_id [%d]", state_watcher->state_watching_bitmap, download_id); - - _da_thread_mutex_unlock(&(state_watcher->mutex)); -} - -da_bool_t state_watcher_is_flag_on_for_download_id_Q( - state_watcher_t *state_watcher, - int download_id) -{ - da_bool_t b_ret = DA_FALSE; - unsigned short mask = 0; - unsigned short result = 0; - - _da_thread_mutex_lock(&(state_watcher->mutex)); - - mask = 1 << download_id; - - result = state_watcher->state_watching_bitmap & mask; - - /* DA_LOG(Default, "state_watcher after [%d]", state_watcher->state_watching_bitmap); */ - - _da_thread_mutex_unlock(&(state_watcher->mutex)); - - if (result) - b_ret = DA_TRUE; - else - b_ret = DA_FALSE; - - return b_ret; -} - -da_bool_t state_watcher_need_redirect_Q(int download_id) -{ - da_bool_t b_ret = DA_FALSE; - state_watcher_t *state_watcher = DA_NULL; - - state_watcher = &(download_mgr.state_watcher); - - b_ret = state_watcher_is_flag_on_for_download_id_Q(state_watcher, - download_id); - - DA_LOG(Default, "state_watcher - need to redirect? [%d]", b_ret); - - return b_ret; -} - -void state_watcher_redirect_state(int download_id, da_state state, int err) -{ - state_watcher_t *state_watcher = DA_NULL; - - DA_LOG_FUNC_START(Default); - - DA_LOG(Default, "download_id = [%d], receiving state = [%d]", download_id, state); - - state_watcher = &(download_mgr.state_watcher); - - switch (state) { - case DA_STATE_FAILED: - case DA_STATE_FINISHED: - state_watcher_flag_OFF_for_download_id(state_watcher, - download_id); - send_client_da_state(download_id, state, err); - - break; - - case DA_STATE_CANCELED: - state_watcher_flag_OFF_for_download_id(state_watcher, - download_id); - - if (state_watcher->type == STATE_WATCHER_TYPE_CANCEL) { - if (!(state_watcher->state_watching_bitmap) && - (state_watcher->is_progressing_to_all - == DA_FALSE)) { - send_client_da_state(download_id, - DA_STATE_CANCELED_ALL, - DA_RESULT_OK); - } - } else { - send_client_da_state(download_id, state, err); - } - - break; - - case DA_STATE_SUSPENDED: - state_watcher_flag_OFF_for_download_id(state_watcher, - download_id); - - if (state_watcher->type == STATE_WATCHER_TYPE_SUSPEND) { - if (!(state_watcher->state_watching_bitmap) && - (state_watcher->is_progressing_to_all - == DA_FALSE)) { - send_client_da_state(download_id, - DA_STATE_SUSPENDED_ALL, - DA_RESULT_OK); - } - } - - break; - - case DA_STATE_RESUMED: - state_watcher_flag_OFF_for_download_id(state_watcher, - download_id); - - if (state_watcher->type == STATE_WATCHER_TYPE_RESUME) { - if (!(state_watcher->state_watching_bitmap) && - (state_watcher->is_progressing_to_all - == DA_FALSE)) { - send_client_da_state(download_id, - DA_STATE_RESUMED_ALL, - DA_RESULT_OK); - } - } - - break; - - default: - DA_LOG(Default, "blocked..."); - break; - } -} diff --git a/src/agent/download-agent-dl-mgr.c b/src/agent/download-agent-dl-mgr.c deleted file mode 100644 index c00d8a5..0000000 --- a/src/agent/download-agent-dl-mgr.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-dl-mgr.c - * @brief common functions for oma and direct download - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-utils.h" -#include "download-agent-http-mgr.h" -#include "download-agent-installation.h" -#include "download-agent-file.h" -#include "download-agent-plugin-conf.h" - - -static da_result_t __cancel_download_with_download_id(int download_id); -static da_result_t __suspend_download_with_download_id(int download_id); - - -da_result_t requesting_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - req_dl_info *request_session = DA_NULL; - download_state_t download_state = DA_INVALID_ID; - - DA_LOG_FUNC_START(Default); - - if (!stage) { - DA_LOG_ERR(Default, "stage is null.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - ret = make_req_dl_info_http(stage, GET_STAGE_TRANSACTION_INFO(stage)); - if (ret != DA_RESULT_OK) - goto ERR; - - request_session = GET_STAGE_TRANSACTION_INFO(stage); - ret = request_http_download(stage); - if (DA_RESULT_OK == ret) { - DA_LOG(Default, "Http download is complete."); - } else { - DA_LOG_ERR(Default, "Http download is failed. ret = %d", ret); - goto ERR; - } - - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - download_state = GET_DL_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(stage)]); - - /* Ignore install content process if the download is failed or paused or canceled */ - if (download_state == DOWNLOAD_STATE_PAUSED || - download_state == DOWNLOAD_STATE_CANCELED) { - return ret; - } - -ERR: - return ret; -} - -da_result_t handle_after_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - if (DA_TRUE == is_this_client_manual_download_type()) { - if (DA_RESULT_OK == ret) { - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH,stage); - } - return ret; - } - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_READY_TO_INSTAL,stage); - - return ret; -} - -da_result_t process_install(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - if (DA_NULL == stage) - return DA_ERR_INVALID_ARGUMENT; - - /* install process. */ - ret = install_content(stage); - - if (DA_RESULT_OK == ret) { - int download_id = GET_STAGE_DL_ID(stage); - char *content_type = DA_NULL; - - if (GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage))) { - content_type = strdup( - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage))); - } else { - /* Fixme : Is Content-Type on HTTP header mandatory? */ - DA_LOG_ERR(Default, "no content type!"); - ret = DA_ERR_MISMATCH_CONTENT_TYPE; - return ret; - } - - /* update installed path */ - send_client_update_downloading_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) - ); - - if (content_type) { - free(content_type); - content_type = DA_NULL; - } - - return DA_RESULT_OK; - } - return ret; -} - -static da_result_t __cancel_download_with_download_id(int download_id) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state; - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock (&mutex_download_state[download_id]); - download_state = GET_DL_STATE_ON_ID(download_id); - DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(download_id)); - if (download_state == DOWNLOAD_STATE_IDLE) { - /* FIXME later : It is better to check and exit itself at download thread */ - pthread_cancel(GET_DL_THREAD_ID(download_id)); - } else if (download_state >= DOWNLOAD_STATE_READY_TO_INSTAL) { - DA_LOG_CRITICAL(Default, "Already download is completed. Do not send cancel request"); - _da_thread_mutex_unlock (&mutex_download_state[download_id]); - return ret; - } - _da_thread_mutex_unlock (&mutex_download_state[download_id]); - - stage = GET_DL_CURRENT_STAGE(download_id); - if (!stage) - return DA_RESULT_OK; - - ret = request_to_cancel_http_download(stage); - if (ret != DA_RESULT_OK) - goto ERR; - DA_LOG(Default, "Download cancel Successful for download id - %d", download_id); -ERR: - return ret; -} - -da_result_t cancel_download(int dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(Default); - - if ((dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS) || - (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI)) { - DA_LOG(Default, "All download items will be cancelled"); - ret = cancel_download_all(dl_req_id); - return ret; - } - - ret = get_download_id_for_dl_req_id(dl_req_id, &download_id); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(Default, "dl req ID is not Valid"); - goto ERR; - } - - if (DA_FALSE == is_valid_dl_ID(download_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - ret = __cancel_download_with_download_id(download_id); - -ERR: - return ret; - -} - -da_result_t cancel_download_all(int dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - int iter = 0; - da_bool_t b_any_flag_on = DA_FALSE; - - state_watcher_t *state_watcher = DA_NULL; - - DA_LOG_FUNC_START(Default); - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - state_watcher = &(download_mgr.state_watcher); - - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->type = STATE_WATCHER_TYPE_CANCEL; - state_watcher->is_progressing_to_all = DA_TRUE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - } - - for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { - if (download_mgr.download_info[iter].is_using == DA_TRUE) { - download_id = iter; - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - state_watcher_flag_ON_for_download_id(state_watcher, - download_id); - } - b_any_flag_on = DA_TRUE; - - /* ToDo: retry if fail, check download_state, don't set flag for state_watcher if state is invalid */ - ret = __cancel_download_with_download_id(download_id); - /*if (ret == DA_RESULT_OK) { - state_watcher_flag_ON_for_download_id( - state_watcher, download_id); - b_any_flag_on = DA_TRUE; - }*/ - } - - } - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->is_progressing_to_all = DA_FALSE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - } - - if (b_any_flag_on == DA_FALSE) { - DA_LOG_ERR(Default, "There is no item to be able to cancel."); - ret = DA_ERR_INVALID_DL_REQ_ID; - } - - return ret; -} - -static da_result_t __suspend_download_with_download_id(int download_id) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state; - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock (&mutex_download_state[download_id]); - download_state = GET_DL_STATE_ON_ID(download_id); - DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(download_id)); - _da_thread_mutex_unlock (&mutex_download_state[download_id]); - - stage = GET_DL_CURRENT_STAGE(download_id); - if (!stage) - return DA_ERR_CANNOT_SUSPEND; - - ret = request_to_suspend_http_download(stage); - if (ret != DA_RESULT_OK) - goto ERR; - DA_LOG(Default, "Download Suspend Successful for download id-%d", download_id); -ERR: - return ret; -} - -da_result_t suspend_download(int dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - int download_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(Default); - - if ((dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS) || - (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI)) { - DA_LOG(Default, "All download items will be suspended"); - ret = suspend_download_all(dl_req_id); - return ret; - } - - ret = get_download_id_for_dl_req_id(dl_req_id, &download_id); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(Default, "dl req ID is not Valid"); - goto ERR; - } - - if (DA_FALSE == is_valid_dl_ID(download_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - ret = __suspend_download_with_download_id(download_id); - -ERR: - return ret; - -} - -da_result_t suspend_download_all(int dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - int iter = 0; - da_bool_t b_any_flag_on = DA_FALSE; - - state_watcher_t *state_watcher = DA_NULL; - - DA_LOG_FUNC_START(Default); - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - state_watcher = &(download_mgr.state_watcher); - - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->type = STATE_WATCHER_TYPE_SUSPEND; - state_watcher->is_progressing_to_all = DA_TRUE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - } - - for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { - if (download_mgr.download_info[iter].is_using == DA_TRUE) { - download_id = iter; - /* ToDo: retry if fail, check download_state, don't set flag for state_watcher if state is invalid */ - ret = __suspend_download_with_download_id(download_id); - if (ret == DA_RESULT_OK) { - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - state_watcher_flag_ON_for_download_id( - state_watcher, download_id); - } - b_any_flag_on = DA_TRUE; - } - } - - } - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->is_progressing_to_all = DA_FALSE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - } - - if (b_any_flag_on == DA_FALSE) { - DA_LOG_ERR(Default, "There is no item to be able to suspend."); - ret = DA_ERR_CANNOT_SUSPEND; - } - - return ret; -} - -static da_result_t __resume_download_with_download_id(int download_id) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state; - stage_info *stage = DA_NULL; - - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock (&mutex_download_state[download_id]); - download_state = GET_DL_STATE_ON_ID(download_id); - DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(download_id)); - _da_thread_mutex_unlock (&mutex_download_state[download_id]); - - stage = GET_DL_CURRENT_STAGE(download_id); - - ret = request_to_resume_http_download(stage); - if (ret != DA_RESULT_OK) - goto ERR; - DA_LOG(Default, "Download Resume Successful for download id-%d", download_id); -ERR: - return ret; -} - -da_result_t resume_download(int dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - int download_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(Default); - - if ((dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS) || - (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI)) { - DA_LOG(Default, "All download items will be resumed"); - ret = resume_download_all(dl_req_id); - return ret; - } - - ret = get_download_id_for_dl_req_id(dl_req_id, &download_id); - if (ret != DA_RESULT_OK) - goto ERR; - - if (DA_FALSE == is_valid_dl_ID(download_id)) { - DA_LOG_ERR(Default, "Download ID is not Valid"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - ret = __resume_download_with_download_id(download_id); - -ERR: - return ret; -} - -da_result_t resume_download_all(int dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - int iter = 0; - da_bool_t b_any_flag_on = DA_FALSE; - - state_watcher_t *state_watcher = DA_NULL; - - DA_LOG_FUNC_START(Default); - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - state_watcher = &(download_mgr.state_watcher); - - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->type = STATE_WATCHER_TYPE_RESUME; - state_watcher->is_progressing_to_all = DA_TRUE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - } - - for (iter = 0; iter < DA_MAX_DOWNLOAD_ID; iter++) { - if (download_mgr.download_info[iter].is_using == DA_TRUE) { - download_id = iter; - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - state_watcher_flag_ON_for_download_id(state_watcher, - download_id); - } - b_any_flag_on = DA_TRUE; - - /* ToDo: retry if fail, check download_state, don't set flag for state_watcher if state is invalid */ - ret = __resume_download_with_download_id(download_id); - /*if (ret == DA_RESULT_OK) { - state_watcher_flag_ON_for_download_id( - state_watcher, download_id); - b_any_flag_on = DA_TRUE; - }*/ - } - - } - - if (dl_req_id == DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI) { - _da_thread_mutex_lock(&(state_watcher->mutex)); - state_watcher->is_progressing_to_all = DA_FALSE; - _da_thread_mutex_unlock(&(state_watcher->mutex)); - } - - if (b_any_flag_on == DA_FALSE) { - DA_LOG(Default, "There is no item to be able to cancel."); - ret = DA_ERR_INVALID_DL_REQ_ID; - } - - return ret; -} - -da_result_t send_user_noti_and_finish_download_flow(int download_id) -{ - da_result_t ret = DA_RESULT_OK; - download_state_t download_state = DA_NULL; - da_bool_t need_destroy_download_info = DA_FALSE; - - DA_LOG_FUNC_START(Default); - - _da_thread_mutex_lock (&mutex_download_state[download_id]); - download_state = GET_DL_STATE_ON_ID(download_id); - DA_LOG(Default, "state = %d", download_state); - _da_thread_mutex_unlock (&mutex_download_state[download_id]); - - switch (download_state) { - case DOWNLOAD_STATE_FINISH: - send_client_da_state(download_id, DA_STATE_FINISHED, - DA_RESULT_OK); - need_destroy_download_info = DA_TRUE; - break; - case DOWNLOAD_STATE_CANCELED: - send_client_da_state(download_id, DA_STATE_CANCELED, - DA_RESULT_OK); - need_destroy_download_info = DA_TRUE; - break; - default: - DA_LOG(Default, "download state = %d", download_state); - break; - } - - if (need_destroy_download_info == DA_TRUE) { - destroy_download_info(download_id); - } else { - DA_LOG_CRITICAL(Default, "download info is not destroyed"); - } - - return ret; -} - diff --git a/src/agent/download-agent-file.c b/src/agent/download-agent-file.c deleted file mode 100644 index cd5d4ad..0000000 --- a/src/agent/download-agent-file.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-file.c - * @brief functions for file operation - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include -#include -#include - -#include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-file.h" -#include "download-agent-installation.h" -#include "download-agent-mime-util.h" -#include "download-agent-http-mgr.h" - -#define NO_NAME_TEMP_STR "No name" - -static da_result_t __set_file_size(stage_info *stage); -static da_result_t __tmp_file_open(stage_info *stage); - -static char *__derive_extension(stage_info *stage); -static da_result_t __divide_file_name_into_pure_name_N_extesion( - const char *in_file_name, - char **out_pure_file_name, - char **out_extension); -static da_result_t __get_candidate_file_name(stage_info *stage, - char **out_pure_file_name, char **out_extension); - -static da_result_t __file_write_buf_make_buf(file_info *file_storage); -static da_result_t __file_write_buf_destroy_buf(file_info *file_storage); -static da_result_t __file_write_buf_flush_buf(stage_info *stage, - file_info *file_storage); -static da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, - char *body, int body_len); -static da_result_t __file_write_buf_directly_write(stage_info *stage, - file_info *file_storage, char *body, int body_len); - - -da_result_t create_temp_saved_dir(void) -{ - da_result_t ret = DA_RESULT_OK; - char *client_dir_path = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - ret = get_client_download_path(&client_dir_path); - if (DA_RESULT_OK != ret) { - goto ERR; - } else { - if (DA_NULL == client_dir_path) { - DA_LOG_ERR(FileManager, "client_dir_path is DA_NULL"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - } - - if (DA_FALSE == is_dir_exist(client_dir_path)) { - ret = create_dir(client_dir_path); - } - -ERR: - if (client_dir_path) { - free(client_dir_path); - client_dir_path = DA_NULL; - } - return ret; -} - -da_result_t clean_files_from_dir(char* dir_path) -{ - da_result_t ret = DA_RESULT_OK; - struct dirent *d = DA_NULL; - DIR *dir; - char file_path[DA_MAX_FULL_PATH_LEN] = { 0, }; - - DA_LOG_FUNC_START(FileManager); - - if (dir_path == DA_NULL) { - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - if (is_dir_exist(dir_path)) { - dir = opendir(dir_path); - if (DA_NULL == dir) { - DA_LOG_ERR(FileManager, "opendir() for DA_DEFAULT_TMP_FILE_DIR_PATH is failed."); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - } else { - while (DA_NULL != (d = readdir(dir))) { - DA_LOG(FileManager, "%s",d->d_name); - if (0 == strncmp(d->d_name, ".", strlen(".")) - || 0 == strncmp(d->d_name, - "..", - strlen(".."))) { - continue; - } - - memset(file_path, 0x00, DA_MAX_FULL_PATH_LEN); - snprintf(file_path, DA_MAX_FULL_PATH_LEN, - "%s/%s", dir_path, d->d_name); - if (remove(file_path) < 0) { - DA_LOG_ERR(FileManager, "fail to remove file"); - } - } - - closedir(dir); - if (remove(dir_path) < 0) { - DA_LOG_ERR(FileManager, "fail to remove dir"); - } - } - } - -ERR: - return ret; -} - -/* Priority to obtain MIME Type - * 1. HTTP response header's field - * 2. from OMA descriptor file's attribute (mandatory field) - * 3. Otherwise, leave blank for MIME Type - */ -da_result_t get_mime_type(stage_info *stage, char **out_mime_type) -{ - char *mime_type = DA_NULL; - - if (!GET_STAGE_SOURCE_INFO(stage)) - return DA_ERR_INVALID_ARGUMENT; - - /* Priority 1 */ - if (GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage))) { - mime_type = GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage)); - DA_LOG(FileManager, "content type from HTTP response header [%s]", mime_type); - } - - if (!mime_type) { - DA_LOG(FileManager, "no content type derived"); - return DA_RESULT_OK; - } - - /* FIXME really need memory allocation? */ - *out_mime_type = (char *) calloc(1, strlen(mime_type) + 1); - if (*out_mime_type) { - snprintf(*out_mime_type, strlen(mime_type) + 1, mime_type); - DA_LOG_VERBOSE(FileManager, "out_mime_type str[%s] ptr[%p] len[%d]", - *out_mime_type,*out_mime_type,strlen(*out_mime_type)); - } else { - DA_LOG_ERR(FileManager, "fail to allocate memory"); - return DA_ERR_FAIL_TO_MEMALLOC; - } - - DA_LOG(FileManager, "mime type = %s", *out_mime_type); - return DA_RESULT_OK; -} - -da_bool_t is_file_exist(const char *file_path) -{ - struct stat dir_state; - int stat_ret; - - if (file_path == DA_NULL) { - DA_LOG_ERR(FileManager, "file path is DA_NULL"); - return DA_FALSE; - } - - stat_ret = stat(file_path, &dir_state); - - if (stat_ret == 0) { - if (dir_state.st_mode & S_IFREG) { - DA_LOG(FileManager, "Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size); - return DA_TRUE; - } - - return DA_FALSE; - } - return DA_FALSE; - -} - -da_bool_t is_dir_exist(char *file_path) -{ - struct stat dir_state; - int stat_ret; - - if (file_path == DA_NULL) { - DA_LOG_ERR(FileManager, "file path is DA_NULL"); - return DA_FALSE; - } - - stat_ret = stat(file_path, &dir_state); - - if (stat_ret == 0) { - if (dir_state.st_mode & S_IFDIR) { - DA_LOG(FileManager, "Exist! %s is a directory.", file_path); - return DA_TRUE; - } - - return DA_FALSE; - } - return DA_FALSE; -} - -void get_file_size(char *file_path, int *out_file_size) -{ - struct stat dir_state; - int stat_ret; - - *out_file_size = -1; - - if (file_path == DA_NULL) { - DA_LOG_ERR(FileManager, "file path is DA_NULL"); - return; - } - - /* Please do not use ftell() to obtain file size, use stat instead. - * This is a guide from www.securecoding.cert.org - * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file - */ - stat_ret = stat(file_path, &dir_state); - if (stat_ret == 0) { - if (dir_state.st_mode & S_IFREG) { - DA_LOG(FileManager, "size = %lu", dir_state.st_size); - *out_file_size = dir_state.st_size; - } - } - return; -} - -da_result_t __tmp_file_open(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - file_info *file_storage = DA_NULL; - char *actual_file_path = DA_NULL; - char *tmp_file_path = DA_NULL; - void *fd = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) - return DA_ERR_INVALID_ARGUMENT; - - actual_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); - DA_LOG(FileManager, "actual_file_path = %s", actual_file_path); - if (!actual_file_path) - return DA_ERR_INVALID_ARGUMENT; - - tmp_file_path = (char *) calloc(1, (strlen(actual_file_path) + 1)); - if (!tmp_file_path) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - snprintf(tmp_file_path, strlen(actual_file_path) + 1, "%s", actual_file_path); - - GET_CONTENT_STORE_TMP_FILE_NAME(file_storage) = tmp_file_path; - DA_LOG(FileManager, "GET_CONTENT_STORE_TMP_FILE_NAME = %s ",GET_CONTENT_STORE_TMP_FILE_NAME(file_storage)); - - fd = fopen(tmp_file_path, "a"); // for resume - if (fd == DA_NULL) { - DA_LOG_ERR(FileManager, "File open failed"); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = fd; - - DA_LOG(FileManager, "file path for tmp saving = %s", GET_CONTENT_STORE_TMP_FILE_NAME(file_storage)); - -ERR: - if (DA_RESULT_OK != ret) { - if (tmp_file_path) { - free(tmp_file_path); - } - if (file_storage != DA_NULL) { - GET_CONTENT_STORE_TMP_FILE_NAME(file_storage) = DA_NULL; - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; - } - } - return ret; -} - -da_result_t __set_file_size(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - req_dl_info *stage_req_info = DA_NULL; - file_info *file_storage = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - if (!stage) { - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - stage_req_info = GET_STAGE_TRANSACTION_INFO(stage); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) - goto ERR; - - if (GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info) != DA_NULL) { - GET_CONTENT_STORE_FILE_SIZE(file_storage) - = GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info); - } else { - GET_CONTENT_STORE_FILE_SIZE(file_storage) = 0; - } - DA_LOG(FileManager, "file size = %d", GET_CONTENT_STORE_FILE_SIZE(file_storage)); -ERR: - return ret; - -} - -/* Priority to derive extension - * 1. according to MIME-Type - * 2. if MIME-Type is ambiguous or blank, - * 2-1. derived from field's "filename" attribute - * 2-2. derived from url - * 3. if url does not have extension, leave blank for extension - */ -char *__derive_extension(stage_info *stage) -{ - if (!stage) - return DA_NULL; - - source_info_t *source_info = GET_STAGE_SOURCE_INFO(stage); - req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); - file_info *file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - char *extension = DA_NULL; - char *url = DA_NULL; - - /* Priority 1 */ - char *mime_type = DA_NULL; - mime_type = GET_CONTENT_STORE_CONTENT_TYPE(file_info_data); - if (mime_type && !is_ambiguous_MIME_Type(mime_type)) { - char *extension = DA_NULL; - da_result_t ret = get_extension_from_mime_type(mime_type, &extension); - if (ret == DA_RESULT_OK && extension) - return extension; - } - - /* Priority 2-1 */ - http_msg_response_t *http_msg_response = DA_NULL; - http_msg_response = request_info->http_info.http_msg_response; - if (http_msg_response) { - char *file_name = DA_NULL; - da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response, - DA_NULL, &file_name); - if (b_ret && file_name) { - char *extension = DA_NULL; - DA_LOG(FileManager, "Name from Content-Disposition :[%s]", file_name); - __divide_file_name_into_pure_name_N_extesion(file_name, DA_NULL, &extension); - if (file_name) { - free(file_name); - file_name = DA_NULL; - } - if (extension) - return extension; - } - } - /* Priority 2-2 */ - /* If there is location url from response header in case of redirection, - * it try to parse the extention name from the location url */ - if (GET_REQUEST_HTTP_REQ_LOCATION(request_info)) - url = GET_REQUEST_HTTP_REQ_LOCATION(request_info); - else - url = GET_SOURCE_BASIC_URL(source_info); - if (url) { - DA_LOG(FileManager, "url:[%s]", url); - da_bool_t b_ret = da_get_extension_name_from_url(url, &extension); - if (b_ret && extension) - return extension; - } - - return DA_NULL; -} - -/** Priority for deciding file name - * 1. what client wants, which is conveyed by DA_FEATURE_FILE_NAME - * 2. 'filename' option on HTTP response header's Content-Disposition field - * 3. requesting URL - * 4. Otherwise, define it as "No name" - */ -da_result_t __get_candidate_file_name(stage_info *stage, char **out_pure_file_name, char **out_extension) -{ - da_result_t ret = DA_RESULT_OK; - source_info_t *source_info = DA_NULL; - char *pure_file_name = DA_NULL; - char *extension = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - if (!stage || !out_pure_file_name) - return DA_ERR_INVALID_ARGUMENT; - - source_info = GET_STAGE_SOURCE_INFO(stage); - if (!source_info) - return DA_ERR_INVALID_ARGUMENT; - - /* Priority 1 */ - if (!pure_file_name && GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage))) { - __divide_file_name_into_pure_name_N_extesion( - GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage)), - &pure_file_name, &extension); - } - - /* Priority 2 */ - if (!pure_file_name) { - req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); - http_msg_response_t *http_msg_response = DA_NULL; - http_msg_response = request_info->http_info.http_msg_response; - if (http_msg_response) { - char *file_name = DA_NULL; - da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response, - DA_NULL, &file_name); - if (b_ret && file_name) { - DA_LOG(FileManager, "Name from Content-Disposition :[%s]", file_name); - __divide_file_name_into_pure_name_N_extesion(file_name, &pure_file_name, DA_NULL); - if (file_name) { - free(file_name); - file_name = DA_NULL; - } - } - } - } - - /* Priority 3 */ - if (!pure_file_name) { - char *url = DA_NULL; - req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage); - /* If there is location url from response header in case of redirection, - * it try to parse the file name from the location url */ - if (GET_REQUEST_HTTP_REQ_LOCATION(request_info)) - url = GET_REQUEST_HTTP_REQ_LOCATION(request_info); - else - url = GET_SOURCE_BASIC_URL(source_info); - if (url) { - DA_LOG(FileManager, "url: [%s]", url); - da_get_file_name_from_url(url, &pure_file_name); - } - } - - /* Priority 4 */ - if (!pure_file_name) { - pure_file_name = strdup(NO_NAME_TEMP_STR); - if (!pure_file_name) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - } - - *out_pure_file_name = pure_file_name; - pure_file_name = DA_NULL; - DA_LOG(FileManager, "candidate file name [%s]", *out_pure_file_name); - - if (out_extension) { - if (extension) { - *out_extension = extension; - extension = DA_NULL; - } else { - *out_extension = __derive_extension(stage); - DA_LOG(FileManager, "candidate extension [%s]", *out_extension); - } - } - - if (extension) - free(extension); - - return DA_RESULT_OK; - -ERR: - if (extension) - free(extension); - - return ret; -} - - -da_result_t decide_final_file_path(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - char *default_dir = DA_NULL; - char *extension = DA_NULL; - char *tmp_file_path = DA_NULL; - char *file_name_without_extension = DA_NULL; - file_info *file_info_data = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_info_data) - return DA_ERR_INVALID_ARGUMENT; - - ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = get_client_download_path(&default_dir); - if (DA_RESULT_OK != ret || DA_NULL == default_dir) { - goto ERR; - } - - tmp_file_path = get_full_path_avoided_duplication(default_dir, file_name_without_extension, extension); - if (tmp_file_path) { - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) - = tmp_file_path; - tmp_file_path = DA_NULL; - } else { - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - - if (file_name_without_extension && !GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data)) { - GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data) = file_name_without_extension; - file_name_without_extension = DA_NULL; - } - - if (extension && !GET_CONTENT_STORE_EXTENSION(file_info_data)) { - GET_CONTENT_STORE_EXTENSION(file_info_data) = extension; - extension = DA_NULL; - } - -ERR: - DA_LOG(FileManager, "decided file path = %s", GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data)); - if (default_dir) { - free(default_dir); - default_dir = DA_NULL; - } - - if (file_name_without_extension) { - free(file_name_without_extension); - file_name_without_extension = DA_NULL; - } - - if (extension) { - free(extension); - extension = DA_NULL; - } - - return ret; -} - -char *get_full_path_avoided_duplication(char *in_dir, char *in_candidate_file_name, char * in_extension) -{ - char *dir = in_dir; - char *file_name = in_candidate_file_name; - char *extension = in_extension; - char *final_path = DA_NULL; - - int final_path_len = 0; - int extension_len = 0; - - int suffix_count = 0; /* means suffix on file name. up to "_99" */ - const int max_suffix_count = 99; - int suffix_len = (int)log10(max_suffix_count+1) + 1; /* 1 means "_" */ - - if (!in_dir || !in_candidate_file_name) - return DA_NULL; - -// DA_LOG_FUNC_START(FileManager); - DA_LOG(FileManager, "in_candidate_file_name=[%s], in_extension=[%s]", in_candidate_file_name, in_extension); - - if (extension) - extension_len = strlen(extension); - - /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */ - final_path_len = strlen(dir) + 1 + strlen(file_name) + 1 - + suffix_len + extension_len + 1; - - final_path = (char*)calloc(1, final_path_len); - if (!final_path) { - DA_LOG_ERR(FileManager, "DA_ERR_FAIL_TO_MEMALLOC"); - return DA_NULL; - } - - do { - /* e.g) /tmp/abc.jpg - * if there is no extension name, just make a file name without extension */ - if (0 == extension_len) { - if (suffix_count == 0) { - snprintf(final_path, final_path_len, - "%s/%s", dir, file_name); - } else { - snprintf(final_path, final_path_len, - "%s/%s_%d", dir, file_name, suffix_count); - } - } else { - if (suffix_count == 0) { - snprintf(final_path, final_path_len, - "%s/%s.%s", dir, file_name, extension); - } else { - snprintf(final_path, final_path_len, - "%s/%s_%d.%s", - dir, file_name, suffix_count, extension); - } - } - - if (is_file_exist(final_path)) { - suffix_count++; - if (suffix_count > max_suffix_count) { - free(final_path); - final_path = DA_NULL; - break; - } else { - memset(final_path, 0x00, final_path_len); - continue; - } - } - - break; - } while (1); - - DA_LOG(FileManager, "decided path = [%s]", final_path); - return final_path; -} - -da_result_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char **out_pure_file_name, char **out_extension) -{ - char *file_name = DA_NULL; - char *tmp_ptr = DA_NULL; - char temp_file[DA_MAX_FILE_PATH_LEN] = {0,}; - char tmp_ext[DA_MAX_STR_LEN] = {0,}; - int len = 0; - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(FileManager); - - if (!in_file_name) - return DA_ERR_INVALID_ARGUMENT; - - file_name = (char *)in_file_name; - tmp_ptr = strrchr(file_name, '.'); - if (tmp_ptr) - tmp_ptr++; - if (tmp_ptr && out_extension) { - strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1); - *out_extension = strdup((const char*) tmp_ext); - DA_LOG(FileManager, "extension [%s]", *out_extension); - } - - if (!out_pure_file_name) - return ret; - - if (tmp_ptr) - len = tmp_ptr - file_name - 1; - else - len = strlen(file_name); - - if (len >= DA_MAX_FILE_PATH_LEN) { - strncpy((char*) temp_file, file_name, - DA_MAX_FILE_PATH_LEN - 1); - } else { - strncpy((char*) temp_file, file_name, len); - } - - delete_prohibited_char((char*) temp_file, - strlen((char*) temp_file)); - if (strlen(temp_file) < 1) { - *out_pure_file_name = strdup(NO_NAME_TEMP_STR); - } else { - *out_pure_file_name = strdup( - (const char*) temp_file); - } - - DA_LOG(FileManager, "pure file name [%s]", *out_pure_file_name); - return ret; -} - -da_result_t __file_write_buf_make_buf(file_info *file_storage) -{ - da_result_t ret = DA_RESULT_OK; - char *buffer = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - buffer = (char*) calloc(DOWNLOAD_NOTIFY_LIMIT, 1); - if (DA_NULL == buffer) { - DA_LOG_ERR(FileManager, "Calloc failure "); - ret = DA_ERR_FAIL_TO_MEMALLOC; - } else { - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - GET_CONTENT_STORE_FILE_BUFFER(file_storage) = buffer; - } - - return ret; -} - -da_result_t __file_write_buf_destroy_buf(file_info *file_storage) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(FileManager); - - if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) - free(GET_CONTENT_STORE_FILE_BUFFER(file_storage)); - - GET_CONTENT_STORE_FILE_BUFFER(file_storage) = DA_NULL; - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - - return ret; -} - -da_result_t __file_write_buf_flush_buf(stage_info *stage, file_info *file_storage) -{ - da_result_t ret = DA_RESULT_OK; - char *buffer = DA_NULL; - int buffer_size = 0; - int write_success_len = 0; - void *fd = DA_NULL; - - // DA_LOG_FUNC_START(FileManager); - - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); - - if (buffer_size == 0) { - DA_LOG_ERR(FileManager, "no data on buffer.."); - return ret; - } - - fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); - if (DA_NULL == fd) { - DA_LOG_ERR(FileManager, "There is no file handle."); - - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - - write_success_len = fwrite(buffer, sizeof(char), buffer_size, - (FILE *) fd); - fflush((FILE *) fd); - if (write_success_len != buffer_size) { - DA_LOG_ERR(FileManager, "write fails "); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - += write_success_len; - DA_LOG(FileManager, "write %d bytes", write_success_len); - - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE; - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - -ERR: - return ret; -} - -da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, char *body, - int body_len) -{ - da_result_t ret = DA_RESULT_OK; - char *buffer = DA_NULL; - int buffer_size = 0; - - // DA_LOG_FUNC_START(FileManager); - - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); - - memcpy(buffer + buffer_size, body, body_len); - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) += body_len; - - return ret; -} - -da_result_t __file_write_buf_directly_write(stage_info *stage, - file_info *file_storage, char *body, int body_len) -{ - da_result_t ret = DA_RESULT_OK; - int write_success_len = 0; - void *fd = DA_NULL; - - // DA_LOG_FUNC_START(FileManager); - - fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); - if (DA_NULL == fd) { - DA_LOG_ERR(FileManager, "There is no file handle."); - - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - - write_success_len = fwrite(body, sizeof(char), body_len, - (FILE *) fd); - fflush((FILE *) fd); - if (write_success_len != body_len) { - DA_LOG_ERR(FileManager, "write fails "); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - += write_success_len; - DA_LOG(FileManager, "write %d bytes", write_success_len); - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE; - -ERR: - return ret; -} - -da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len) -{ - da_result_t ret = DA_RESULT_OK; - file_info *file_storage = DA_NULL; - int buffer_size = 0; - char *buffer = DA_NULL; - - // DA_LOG_FUNC_START(FileManager); - - if (DA_TRUE == is_this_client_manual_download_type()) { - return ret; - } - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) { - DA_LOG_ERR(FileManager, "file_info is empty."); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_FALSE; - - if (DA_NULL == buffer) { - if (body_len < DOWNLOAD_NOTIFY_LIMIT) { - ret = __file_write_buf_make_buf(file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - - __file_write_buf_copy_to_buf(file_storage, body, body_len); - } else { - ret = __file_write_buf_directly_write(stage, - file_storage, body, body_len); - if (ret != DA_RESULT_OK) - goto ERR; - } - } else { - if (DOWNLOAD_NOTIFY_LIMIT <= body_len) { - ret = __file_write_buf_flush_buf(stage, file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = __file_write_buf_directly_write(stage, - file_storage, body, body_len); - if (ret != DA_RESULT_OK) - goto ERR; - - } else if ((DOWNLOAD_NOTIFY_LIMIT - buffer_size) <= body_len) { - ret = __file_write_buf_flush_buf(stage, file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - - __file_write_buf_copy_to_buf(file_storage, body, body_len); - } else { - __file_write_buf_copy_to_buf(file_storage, body, body_len); - } - } - -ERR: - if (ret != DA_RESULT_OK) { - if (file_storage) { - GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0; - if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) { - free( - GET_CONTENT_STORE_FILE_BUFFER(file_storage)); - GET_CONTENT_STORE_FILE_BUFFER(file_storage) - = DA_NULL; - } - } - } - return ret; -} - -da_result_t file_write_complete(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - file_info*file_storage = DA_NULL; - char *buffer = DA_NULL; - unsigned int buffer_size = 0; - void *fd = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - if (DA_TRUE == is_this_client_manual_download_type()) { - return ret; - } - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) { - DA_LOG_ERR(FileManager, "file_info is DA_NULL."); - ret = DA_ERR_FAIL_TO_ACCESS_FILE; - goto ERR; - } - - buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage); - buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage); - - if (DA_NULL == buffer) { - DA_LOG_ERR(FileManager, "file buffer is DA_NULL"); - } else { - if (buffer_size != 0) { - ret = __file_write_buf_flush_buf(stage, file_storage); - if (ret != DA_RESULT_OK) - goto ERR; - } - __file_write_buf_destroy_buf(file_storage); - } - fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage); - - if (fd) { - // call sync - fsync(fileno(fd)); - fclose(fd); - fd = DA_NULL; - } - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; -ERR: - return ret; -} - -da_result_t start_file_writing(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - file_info *file_info_data = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - if (DA_TRUE == is_this_client_manual_download_type()) { - return ret; - } - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - ret = get_mime_type(stage, - &GET_CONTENT_STORE_CONTENT_TYPE(file_info_data)); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = decide_final_file_path(stage); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = __set_file_size(stage); - if (DA_RESULT_OK != ret) - goto ERR; - - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = 0; - - ret = __tmp_file_open(stage); - -ERR: - return ret; -} - -da_result_t start_file_writing_append(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(FileManager); - if (DA_TRUE == is_this_client_manual_download_type()) { - return ret; - } - - ret = __tmp_file_open(stage); - - return ret; -} - -da_result_t discard_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - file_info *file_storage = DA_NULL; - char *temp_file_path = DA_NULL; - FILE *f_handle = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - - f_handle = GET_CONTENT_STORE_FILE_HANDLE(file_storage); - if (f_handle) { - fclose(f_handle); - GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL; - } - temp_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage); - if (temp_file_path) { - remove_file((const char*) temp_file_path); - free(temp_file_path); - GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = DA_NULL; - } - - return ret; -} - -void clean_paused_file(stage_info *stage) -{ - file_info *file_info_data = DA_NULL; - char *paused_file_path = DA_NULL; - FILE *fd = DA_NULL; - - DA_LOG_FUNC_START(FileManager); - - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - - fd = GET_CONTENT_STORE_FILE_HANDLE(file_info_data); - if (fd) { - fclose(fd); - GET_CONTENT_STORE_FILE_HANDLE(file_info_data) = DA_NULL; - } - - paused_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data); - remove_file((const char*) paused_file_path); - - return; -} - -da_result_t replace_content_file_in_stage(stage_info *stage, - const char *dest_dd_file_path) -{ - da_result_t ret = DA_RESULT_OK; - char *dd_file_path = DA_NULL; - int len; - - DA_LOG_FUNC_START(FileManager); - - if (!dest_dd_file_path - && (DA_FALSE == is_file_exist(dest_dd_file_path))) { - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - dd_file_path - =GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)); - - if (DA_NULL != dd_file_path) { - remove_file((const char*) dd_file_path); - free(dd_file_path); - } - len = strlen(dest_dd_file_path); - dd_file_path = calloc(1, len + 1); - if (!dd_file_path) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - strncpy(dd_file_path, dest_dd_file_path, len); - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)) - = dd_file_path; - -ERR: - return ret; - -} - -da_result_t copy_file(const char *src, const char *dest) -{ - FILE *fs = DA_NULL; - FILE *fd = DA_NULL; - int freadnum = 0; - int fwritenum = 0; - char buff[4096] = { 0, }; - - DA_LOG_FUNC_START(FileManager); - - /* open files to copy */ - fs = fopen(src, "rb"); - if (!fs) { - DA_LOG_ERR(FileManager, "Fail to open src file"); - return DA_ERR_FAIL_TO_ACCESS_FILE; - } - - fd = fopen(dest, "wb"); - if (!fd) { - DA_LOG_ERR(FileManager, "Fail to open dest file"); - - fclose(fs); - return DA_ERR_FAIL_TO_ACCESS_FILE; - } - - /* actual copy */ - while (!feof(fs)) { - memset(buff, 0x00, 4096); - freadnum = fread(buff, sizeof(char), sizeof(buff), fs); - if (freadnum > 0) { - fwritenum = fwrite(buff, sizeof(char), freadnum, fd); - if (fwritenum <= 0) { - DA_LOG(FileManager, "written = %d",fwritenum); - break; - } - } else { - DA_LOG(FileManager, "read = %d",freadnum); - break; - } - } - - fflush(fd); - fsync(fileno(fd)); - fclose(fd); - fclose(fs); - - return DA_RESULT_OK; -} - -da_result_t create_dir(const char *install_dir) -{ - da_result_t ret = DA_RESULT_OK; - /* read/write/search permissions for owner and group, - * and with read/search permissions for others. */ - if (mkdir(install_dir, S_IRWXU | S_IRWXG | S_IRWXO)) { - DA_LOG_ERR(FileManager, "Fail to creaate directory [%s]", install_dir); - ret = DA_ERR_FAIL_TO_ACCESS_STORAGE; - } else { - DA_LOG(FileManager, "[%s] is created!", install_dir); - } - return ret; -} - diff --git a/src/agent/download-agent-http-mgr.c b/src/agent/download-agent-http-mgr.c deleted file mode 100644 index 7f3b36f..0000000 --- a/src/agent/download-agent-http-mgr.c +++ /dev/null @@ -1,1691 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-mgr.c - * @brief Including functions regarding http mgr - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include "download-agent-utils.h" -#include "download-agent-debug.h" -#include "download-agent-client-mgr.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" -#include "download-agent-http-msg-handler.h" -#include "download-agent-file.h" -#include "download-agent-plugin-conf.h" -#include "download-agent-installation.h" -#include "download-agent-plugin-http-interface.h" - -da_result_t make_default_http_request_hdr(const char *url, - char **user_request_header, - int user_request_heaer_count, - http_msg_request_t **out_http_msg_request); -da_result_t create_resume_http_request_hdr(stage_info *stage, - http_msg_request_t **out_resume_request); - -da_result_t start_new_transaction(stage_info *stage); -da_result_t set_http_request_hdr(stage_info *stage); -da_result_t make_transaction_info_and_start_transaction(stage_info *stage); - -da_result_t pause_for_flow_control(stage_info *stage); -da_result_t unpause_for_flow_control(stage_info *stage); - -da_result_t handle_any_input(stage_info *stage); -da_result_t handle_event_control(stage_info *stage, q_event_t *event); -da_result_t handle_event_http(stage_info *stage, q_event_t *event); -da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event); -da_result_t handle_event_http_final(stage_info *stage, q_event_t *event); -da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event); - -da_result_t exchange_url_from_header_for_redirection(stage_info *stage, - http_msg_response_t *http_msg_response); - -da_result_t handle_event_abort(stage_info *stage); -da_result_t handle_event_cancel(stage_info *stage); -da_result_t handle_event_suspend(stage_info *stage); -da_result_t handle_event_resume(stage_info *stage); - -da_result_t handle_http_hdr(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status); -da_result_t handle_http_status_code(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status); -da_result_t handle_http_body(stage_info *stage, char *body, int body_len); - -da_result_t set_hdr_fields_on_download_info(stage_info *stage); - -da_result_t _check_content_type_is_matched(stage_info *stage); -da_result_t _check_enough_memory_for_this_download(stage_info *stage); -da_result_t _check_downloaded_file_size_is_same_with_header_content_size( - stage_info *stage); - -da_result_t _check_this_partial_download_is_available(stage_info *stage, - http_msg_response_t *new_http_msg_response); - -da_result_t _cancel_transaction(stage_info *stage); -da_result_t _disconnect_transaction(stage_info *stage); - -void __parsing_user_request_header(char *user_request_header, - char **out_field, char **out_value); - -http_mgr_t http_mgr; - -da_result_t init_http_mgr(void) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(HTTPManager); - - if (http_mgr.is_http_init == DA_FALSE) { - http_mgr.is_http_init = DA_TRUE; - ret = PI_http_init(); - } - - return ret; -} - - -da_result_t request_to_abort_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - if (!stage) { - DA_LOG_ERR(HTTPManager, "Stage is NULL. download info is already destroyed"); - return DA_ERR_INVALID_ARGUMENT; - } - - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_ABORT, &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event); - } - -ERR: - return ret; -} - -void deinit_http_mgr(void) -{ - DA_LOG_FUNC_START(HTTPManager); - - if (http_mgr.is_http_init == DA_TRUE) { - http_mgr.is_http_init = DA_FALSE; - PI_http_deinit(); - } - - return; -} - -da_result_t request_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - http_state_t http_state = 0; - da_bool_t need_wait = DA_TRUE; - - queue_t *queue = DA_NULL; - req_dl_info *req_info = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - download_id = GET_STAGE_DL_ID(stage); - queue = GET_DL_QUEUE(download_id); - req_info = GET_STAGE_TRANSACTION_INFO(stage); - - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(download_id)); - - CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD, stage); - - do { - ret = handle_any_input(stage); - if (ret != DA_RESULT_OK) { - if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) { - GET_REQUEST_HTTP_RESULT(req_info) = ret; - DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret); - } - _cancel_transaction(stage); - } - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_READY_TO_DOWNLOAD: - ret = start_new_transaction(stage); - if (ret != DA_RESULT_OK) { - if (DA_RESULT_OK == GET_REQUEST_HTTP_RESULT(req_info)) { - GET_REQUEST_HTTP_RESULT(req_info) = ret; - DA_LOG_CRITICAL(HTTPManager, "setting internal error [%d]", ret); - } - DA_LOG(HTTPManager, "exiting with error..."); - need_wait = DA_FALSE; - break; - } - - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_REQUESTED, stage); - - send_client_da_state(download_id, - DA_STATE_DOWNLOAD_STARTED, - DA_RESULT_OK); - break; - - case HTTP_STATE_CANCELED: - case HTTP_STATE_DOWNLOAD_FINISH: - case HTTP_STATE_ABORTED: - DA_LOG(HTTPManager, "exiting..."); - need_wait = DA_FALSE; - break; - - default: - break; - } - - if (need_wait == DA_TRUE) { - _da_thread_mutex_lock(&(queue->mutex_queue)); - if (DA_FALSE == GET_IS_Q_HAVING_DATA(queue)) { - unpause_for_flow_control(stage); - -// DA_LOG(HTTPManager, "Waiting for input"); - Q_goto_sleep(queue); -// DA_LOG(HTTPManager, "Woke up to receive new packet or control event"); - } - _da_thread_mutex_unlock (&(queue->mutex_queue)); - - } - - } while (need_wait == DA_TRUE); - - ret = GET_REQUEST_HTTP_RESULT(req_info); - DA_LOG(HTTPManager, "--------------Exiting request_http_download! ret = %d", ret); - return ret; -} - -da_result_t request_to_cancel_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_CANCEL, &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), q_event); - } - -ERR: - return ret; -} - -da_result_t request_to_suspend_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_PAUSED: - case HTTP_STATE_REQUEST_PAUSE: - DA_LOG_CRITICAL(HTTPManager, "Already paused. http_state = %d", http_state); - ret = DA_ERR_ALREADY_SUSPENDED; - break; - - default: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_SUSPEND, - &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), - q_event); - } - - break; - } - -ERR: - return ret; -} - -da_result_t request_to_resume_http_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "[%d] http_state = %d", GET_STAGE_DL_ID(stage), http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_PAUSED: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME"); - ret = Q_make_control_event(Q_EVENT_TYPE_CONTROL_RESUME, - &q_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager, "fail to make q_control_event"); - goto ERR; - } else { - DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(GET_STAGE_DL_ID(stage))); - Q_push_event(GET_DL_QUEUE(GET_STAGE_DL_ID(stage)), - q_event); - } - - break; - - case HTTP_STATE_REQUEST_PAUSE: - DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. Previous pause is not finished. http_state = %d", GET_STAGE_DL_ID(stage), http_state); - ret = DA_ERR_INVALID_STATE; - - break; - - case HTTP_STATE_RESUMED: - ret = DA_ERR_ALREADY_RESUMED; - - break; - - default: - DA_LOG_ERR(HTTPManager, "[%d] Fail to resume. This is not a paused ID. http_state = %d", GET_STAGE_DL_ID(stage), http_state); - ret = DA_ERR_INVALID_STATE; - - break; - } - -ERR: - return ret; -} - -da_result_t start_new_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - ret = set_http_request_hdr(stage); - if (ret != DA_RESULT_OK) - return ret; - - ret = make_transaction_info_and_start_transaction(stage); - return ret; -} - -da_result_t make_default_http_request_hdr(const char *url, - char **user_request_header, - int user_request_header_count, - http_msg_request_t **out_http_msg_request) -{ - da_result_t ret = DA_RESULT_OK; - - http_msg_request_t *http_msg_request = NULL; - char *user_agent = NULL; - - DA_LOG_FUNC_START(HTTPManager); - - if (!url) { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - ret = http_msg_request_create(&http_msg_request); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = http_msg_request_set_url(http_msg_request, url); - if (ret != DA_RESULT_OK) - goto ERR; - - user_agent = get_user_agent(); - if (user_agent) - http_msg_request_add_field(http_msg_request, HTTP_FIELD_UAGENT, - user_agent); - - http_msg_request_add_field(http_msg_request, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); - http_msg_request_add_field(http_msg_request, HTTP_FIELD_ACCEPT_CHARSET, "utf-8"); - - if (user_request_header && user_request_header_count > 0) { - int i = 0; - for (i = 0; i < user_request_header_count; i++) - { - char *field = NULL; - char *value = NULL; - __parsing_user_request_header(user_request_header[i], - &field, &value); - if (field && value) { - http_msg_request_add_field(http_msg_request, field, value); - if (field) { - free(field); - field = NULL; - } - if (*value) { - free(value); - value= NULL; - } - } else { - DA_LOG_ERR(HTTPManager, "Fail to parse user request header"); - } - } - } else - DA_LOG(HTTPManager, "no user reqeust header inserted"); - - *out_http_msg_request = http_msg_request; - -ERR: - if (ret != DA_RESULT_OK) - http_msg_request_destroy(&http_msg_request); - - return ret; -} - -da_result_t set_http_request_hdr(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - req_dl_info *request_info = DA_NULL; - - char *url = DA_NULL; - char **user_request_header = DA_NULL; - int user_request_header_count = 0; - http_msg_request_t* http_msg_request = NULL; - - DA_LOG_FUNC_START(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - if (DA_NULL == - (url = GET_REQUEST_HTTP_REQ_URL(request_info))) { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - user_request_header = GET_REQUEST_HTTP_USER_REQUEST_HEADER( - request_info); - user_request_header_count = GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT( - request_info); - - ret = make_default_http_request_hdr(url, user_request_header, - user_request_header_count, &http_msg_request); - if (ret == DA_RESULT_OK) - request_info->http_info.http_msg_request = http_msg_request; - -ERR: - return ret; - -} - -da_result_t make_transaction_info_and_start_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - req_dl_info *request_info = DA_NULL; - - input_for_tranx_t *input_for_tranx = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - download_id = GET_STAGE_DL_ID(stage); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - if (GET_REQUEST_HTTP_REQ_URL(request_info) == DA_NULL) { - DA_LOG_ERR(HTTPManager, "url is NULL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - input_for_tranx = (input_for_tranx_t*) calloc(1, - sizeof(input_for_tranx_t)); - if (input_for_tranx == DA_NULL) { - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } else { - input_for_tranx->proxy_addr = get_proxy_address(); - input_for_tranx->queue = GET_DL_QUEUE(download_id); - - input_for_tranx->http_method = PI_HTTP_METHOD_GET; - input_for_tranx->http_msg_request - = request_info->http_info.http_msg_request; - } - - ret = PI_http_start_transaction(input_for_tranx, - &(GET_REQUEST_HTTP_TRANS_ID(request_info))); - if (ret != DA_RESULT_OK) - goto ERR; - -ERR: - if (input_for_tranx) { - free(input_for_tranx); - input_for_tranx = DA_NULL; - } - - return ret; -} - -da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info) -{ - char *url = DA_NULL; - char **user_request_header = DA_NULL; - int user_request_header_count = 0; - source_info_t *source_info = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - if (!stage) { - DA_LOG_ERR(HTTPManager, "stage is NULL"); - return DA_ERR_INVALID_ARGUMENT; - } - - source_info = GET_STAGE_SOURCE_INFO(stage); - - url = source_info->source_info_type.source_info_basic->url; - user_request_header = - source_info->source_info_type.source_info_basic->user_request_header; - user_request_header_count = - source_info->source_info_type.source_info_basic->user_request_header_count; - DA_LOG(HTTPManager, "url [%s]", url); - - if (url) { - GET_REQUEST_HTTP_REQ_URL(out_info) = url; - GET_REQUEST_HTTP_USER_REQUEST_HEADER(out_info) = user_request_header; - GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(out_info) = - user_request_header_count; - } else { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - return DA_ERR_INVALID_URL; - } - - _da_thread_mutex_init(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage)), NULL); - - return DA_RESULT_OK; -} - -da_result_t pause_for_flow_control(stage_info *stage) -{ - return DA_RESULT_OK; -} - -da_result_t unpause_for_flow_control(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - // DA_LOG_FUNC_START(HTTPManager); - - PI_http_unpause_transaction( - GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage))); - return ret; -} -da_result_t handle_event_abort(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t state = 0; - - DA_LOG_FUNC_START(HTTPManager); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - switch (state) { - case HTTP_STATE_READY_TO_DOWNLOAD: - case HTTP_STATE_DOWNLOAD_REQUESTED: - case HTTP_STATE_DOWNLOAD_STARTED: - case HTTP_STATE_DOWNLOADING: - case HTTP_STATE_REQUEST_RESUME: - case HTTP_STATE_REQUEST_PAUSE: - case HTTP_STATE_RESUMED: - case HTTP_STATE_PAUSED: - case HTTP_STATE_REQUEST_CANCEL: - CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - _disconnect_transaction(stage); - break; - case HTTP_STATE_DOWNLOAD_FINISH: - break; - default: - DA_LOG_ERR(HTTPManager, "have to check the flow for this case"); - break; - } - return ret; -} -da_result_t handle_event_cancel(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t state = 0; - - DA_LOG_FUNC_START(HTTPManager); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - switch (state) { - case HTTP_STATE_READY_TO_DOWNLOAD: - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - break; - - case HTTP_STATE_PAUSED: - discard_download(stage); - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - break; - - case HTTP_STATE_DOWNLOAD_REQUESTED: - case HTTP_STATE_DOWNLOAD_STARTED: - case HTTP_STATE_DOWNLOADING: - case HTTP_STATE_REQUEST_RESUME: - case HTTP_STATE_RESUMED: - _cancel_transaction(stage); - CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_CANCEL, stage); - break; - - case HTTP_STATE_DOWNLOAD_FINISH: - break; - - case HTTP_STATE_REQUEST_CANCEL: - DA_LOG(HTTPManager, "HTTP_STATE_REQUEST_CANCEL : cancel is already in progress... "); - break; - - default: - DA_LOG_ERR(HTTPManager, "have to check the flow for this case"); - break; - } - - return ret; -} - -da_result_t handle_event_suspend(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_REQUEST_PAUSE: - DA_LOG(HTTPManager, "already requested to pause! do nothing"); - break; - - case HTTP_STATE_READY_TO_DOWNLOAD: - CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); - send_client_da_state(GET_STAGE_DL_ID(stage), - DA_STATE_SUSPENDED, DA_RESULT_OK); - break; - - default: - _cancel_transaction(stage); - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK; - DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage)); - CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_PAUSE,stage); - break; - } - - return ret; -} - -da_result_t handle_event_resume(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - http_msg_request_t *resume_request = NULL; - - http_state_t http_state = 0; - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - if (http_state != HTTP_STATE_PAUSED) { - DA_LOG_ERR(HTTPManager, "Not HTTP_STATE_PAUSED! http_state = %d", http_state); - ret = DA_ERR_INVALID_STATE; - goto ERR; - } - - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) = DA_RESULT_OK; - DA_LOG_CRITICAL(HTTPManager, "[%d] cleanup internal error", GET_STAGE_DL_ID(stage)); - - CHANGE_HTTP_STATE(HTTP_STATE_REQUEST_RESUME,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); - - ret = create_resume_http_request_hdr(stage, &resume_request); - if (ret != DA_RESULT_OK) - goto ERR; - - if (GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request) - free(GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request); - - GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_request - = resume_request; - - make_transaction_info_and_start_transaction(stage); - -ERR: - return ret; - -} - -da_result_t create_resume_http_request_hdr(stage_info *stage, - http_msg_request_t **out_resume_request) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - req_dl_info *request_info = NULL; - - http_msg_response_t *first_response = NULL; - http_msg_request_t *resume_request = NULL; - - char *value = NULL; - char *url = NULL; - unsigned int downloaded_data_size = 0; - char downloaded_data_size_to_str[32] = { 0, }; - - char *etag_from_response = NULL; - char *date_from_response = NULL; - - DA_LOG_FUNC_START(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - if (!(url = GET_REQUEST_HTTP_REQ_URL(GET_STAGE_TRANSACTION_INFO(stage)))) { - DA_LOG_ERR(HTTPManager, "DA_ERR_NO_URL"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - first_response = request_info->http_info.http_msg_response; - if (first_response) { - b_ret = http_msg_response_get_ETag(first_response, &value); - if (b_ret) { - etag_from_response = value; - value = NULL; - DA_LOG(HTTPManager, "[ETag][%s]", etag_from_response); - } - - b_ret = http_msg_response_get_date(first_response, &value); - if (b_ret) { - date_from_response = value; - value = NULL; - DA_LOG(HTTPManager, "[Date][%s]", date_from_response); - } - - downloaded_data_size - = GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)); - DA_LOG(HTTPManager, "downloaded_data_size = %u", downloaded_data_size); - snprintf(downloaded_data_size_to_str, sizeof(downloaded_data_size_to_str), "bytes=%u-", - downloaded_data_size); - DA_LOG(HTTPManager, "downloaded_data_size_to_str = %s", downloaded_data_size_to_str); - } - - ret = make_default_http_request_hdr(url, NULL, 0, &resume_request); - if (ret != DA_RESULT_OK) - goto ERR; - - if (etag_from_response) { - http_msg_request_add_field(resume_request, HTTP_FIELD_IF_RANGE, - etag_from_response); - } else { - if (date_from_response) { - http_msg_request_add_field(resume_request, - HTTP_FIELD_IF_RANGE, date_from_response); - } - } - - if (strlen(downloaded_data_size_to_str) > 0) - http_msg_request_add_field(resume_request, HTTP_FIELD_RANGE, - downloaded_data_size_to_str); - - *out_resume_request = resume_request; - -ERR: - if (etag_from_response) { - free(etag_from_response); - etag_from_response = NULL; - } - - if (date_from_response) { - free(date_from_response); - date_from_response = NULL; - } - - return ret; -} - -da_result_t handle_any_input(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = GET_STAGE_DL_ID(stage); - - queue_t *queue = DA_NULL; - q_event_t *event = DA_NULL; - - // DA_LOG_FUNC_START(HTTPManager); - - queue = GET_DL_QUEUE(download_id); - - Q_pop_event(queue, &event); - if (event == DA_NULL) { - DA_LOG(HTTPManager, "There is no data on the queue!"); - return DA_RESULT_OK; - } - - switch (event->event_type) { - case Q_EVENT_TYPE_CONTROL: - ret = handle_event_control(stage, event); - break; - - case Q_EVENT_TYPE_DATA_HTTP: - ret = handle_event_http(stage, event); - break; - - default: - break; - } - - Q_destroy_q_event(&event); - - return ret; -} - -da_result_t handle_event_control(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(HTTPManager); - - if (event->event_type == Q_EVENT_TYPE_CONTROL) { - switch (event->type.q_event_control.control_type) { - case Q_EVENT_TYPE_CONTROL_CANCEL: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_CANCEL"); - ret = handle_event_cancel(stage); - break; - - case Q_EVENT_TYPE_CONTROL_SUSPEND: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_SUSPEND"); - ret = handle_event_suspend(stage); - break; - - case Q_EVENT_TYPE_CONTROL_RESUME: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_RESUME"); - ret = handle_event_resume(stage); - break; - case Q_EVENT_TYPE_CONTROL_ABORT: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_ABORT"); - ret = handle_event_abort(stage); - break; - /* Fixme: need to think how we use this type. For now, this type is not used. */ - case Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED"); - break; - } - } - - return ret; -} - -da_result_t handle_event_http(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - q_event_data_http_t *q_event_data_http = DA_NULL; - - // DA_LOG_FUNC_START(HTTPManager); - - if (event->event_type == Q_EVENT_TYPE_DATA_HTTP) { - q_event_data_http = &(event->type.q_event_data_http); - switch (q_event_data_http->data_type) { - case Q_EVENT_TYPE_DATA_PACKET: - ret = handle_event_http_packet(stage, event); - - break; - - case Q_EVENT_TYPE_DATA_FINAL: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_DATA_FINAL"); - ret = handle_event_http_final(stage, event); - - break; - - case Q_EVENT_TYPE_DATA_ABORT: - DA_LOG(HTTPManager, "Q_EVENT_TYPE_DATA_ABORT"); - ret = handle_event_http_abort(stage, event); - - break; - } - } - - return ret; -} - -da_result_t handle_event_http_packet(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t is_handle_hdr_success = DA_TRUE; - q_event_data_http_t *received_data = DA_NULL; - - // DA_LOG_FUNC_START(HTTPManager); - - received_data = &(event->type.q_event_data_http); - - if (received_data->http_response_msg) { - ret = handle_http_hdr(stage, received_data->http_response_msg, - received_data->http_response_msg->status_code); - if (DA_RESULT_OK != ret) { - is_handle_hdr_success = DA_FALSE; - } - - received_data->http_response_msg = NULL; - } - - if (received_data->body_len > 0) { - if (is_handle_hdr_success == DA_TRUE) { - ret = handle_http_body(stage, received_data->body_data, - received_data->body_len); - } - /*For all cases body_data should be deleted*/ - free(received_data->body_data); - received_data->body_data = DA_NULL; - } - - return ret; -} - -da_result_t handle_event_http_final(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - - http_state_t http_state = 0; - int download_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(HTTPManager); - - download_id = GET_STAGE_DL_ID(stage); - _disconnect_transaction(stage); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_REDIRECTED: - CHANGE_HTTP_STATE(HTTP_STATE_READY_TO_DOWNLOAD,stage); - break; - - case HTTP_STATE_DOWNLOAD_REQUESTED: - DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOAD_REQUESTED"); - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); - break; - - case HTTP_STATE_DOWNLOADING: - DA_LOG(HTTPManager, "case HTTP_STATE_DOWNLOADING"); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) { - discard_download(stage); - goto ERR; - } - /* ret = _check_downloaded_file_size_is_same_with_header_content_size(stage); - if(ret != DA_RESULT_OK) - { - discard_download(stage) ; - goto ERR; - } - */ - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); - send_client_update_downloading_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - DA_NULL); - break; - - case HTTP_STATE_REQUEST_PAUSE: - if (GET_CONTENT_STORE_FILE_HANDLE(GET_STAGE_CONTENT_STORE_INFO(stage))) { - ret = file_write_complete(stage); - send_client_update_downloading_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage))); - - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = DA_FALSE; - } - CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); - send_client_da_state(download_id, DA_STATE_SUSPENDED, - DA_RESULT_OK); - DA_LOG(HTTPManager, "Server Notification code is set to NULL"); - break; - - case HTTP_STATE_ABORTED: - case HTTP_STATE_CANCELED: - discard_download(stage); - break; - - case HTTP_STATE_REQUEST_CANCEL: - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED, stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - break; - - default: - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); - break; - } - -ERR: - /* When file complete is failed */ - if (DA_RESULT_OK != ret) { - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_FINISH, stage); - } - return ret; -} - -da_result_t handle_event_http_abort(stage_info *stage, q_event_t *event) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - - DA_LOG_FUNC_START(HTTPManager); - - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage)) - = event->type.q_event_data_http.error_type; - DA_LOG_CRITICAL(HTTPManager, "set internal error code : [%d]", GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))); - _disconnect_transaction(stage); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_REQUEST_PAUSE: - CHANGE_HTTP_STATE(HTTP_STATE_PAUSED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_PAUSED, stage); - send_client_da_state(GET_STAGE_DL_ID(stage), - DA_STATE_SUSPENDED, DA_RESULT_OK); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - break; - - case HTTP_STATE_REQUEST_CANCEL: - CHANGE_HTTP_STATE(HTTP_STATE_CANCELED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_CANCELED, stage); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - break; - - default: - CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage); - ret = file_write_complete(stage); - if (ret != DA_RESULT_OK) - goto ERR; - discard_download(stage); - break; - } -ERR: - return ret; -} - -da_result_t handle_http_hdr(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status) -{ - da_result_t ret = DA_RESULT_OK; - int download_id = DA_INVALID_ID; - http_state_t http_state = 0; - char *response_header_data = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - download_id = GET_STAGE_DL_ID(stage); - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_DOWNLOAD_REQUESTED: - case HTTP_STATE_REQUEST_PAUSE: - case HTTP_STATE_REQUEST_RESUME: - case HTTP_STATE_REDIRECTED: - /* In case of manual download, this is first update. - * So, the client can know the mime type at second update */ - if (DA_TRUE == is_this_client_manual_download_type() && - http_msg_response) { - // SHOULD free response_header_data when it is not used any more - response_header_data = get_http_response_header_raw(http_msg_response); - send_client_update_dl_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - DA_NULL, - response_header_data, - DA_NULL); - if (response_header_data) { - free(response_header_data); - response_header_data = NULL; - } - } - ret = handle_http_status_code(stage, http_msg_response, - http_status); - if (ret != DA_RESULT_OK) - goto ERR; - break; - - case HTTP_STATE_REQUEST_CANCEL: - DA_LOG(HTTPManager, "Cancel is in progress.. http_state = %d", http_state); - break; - - default: - DA_LOG_ERR(HTTPManager, "http_state = %d", http_state); - goto ERR; - } - -ERR: - return ret; -} - -da_result_t handle_http_status_code(stage_info *stage, - http_msg_response_t *http_msg_response, int http_status) -{ - da_result_t ret = DA_RESULT_OK; - - int download_id = DA_INVALID_ID; - req_dl_info *request_info = DA_NULL; - http_state_t http_state = 0; - - DA_LOG_FUNC_START(HTTPManager); - - download_id = GET_STAGE_DL_ID(stage); - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - GET_STAGE_TRANSACTION_INFO(stage)->http_info.http_msg_response - = http_msg_response; - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_status) { - case 200: - case 201: - case 202: - case 203: - if (http_state == HTTP_STATE_REQUEST_RESUME) - clean_paused_file(stage); - ret = set_hdr_fields_on_download_info(stage); - if (ret != DA_RESULT_OK) - goto ERR; - ret = _check_content_type_is_matched(stage); - if (ret != DA_RESULT_OK) - goto ERR; - ret = _check_enough_memory_for_this_download(stage); - if (ret != DA_RESULT_OK) - goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); // ? - break; - - case 206: - DA_LOG(HTTPManager, "HTTP Status is %d - Partial download for resume!",http_status); - if (http_state != HTTP_STATE_REQUEST_RESUME) { - DA_LOG_ERR(HTTPManager, "This download is not resumed, revoke"); - ret = DA_ERR_INVALID_STATE; - goto ERR; - } - ret = _check_this_partial_download_is_available(stage, - http_msg_response); - if (ret != DA_RESULT_OK) - goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_RESUMED,stage); - CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD,stage); - break; - - case 300: - case 301: - case 302: - case 303: - case 305: - case 306: - case 307: - DA_LOG(HTTPManager, "HTTP Status is %d - redirection!",http_status); - ret = exchange_url_from_header_for_redirection(stage, http_msg_response); - if (ret != DA_RESULT_OK) - goto ERR; - CHANGE_HTTP_STATE(HTTP_STATE_REDIRECTED,stage); - http_msg_response_destroy(&http_msg_response); - break; - - case 100: - case 101: - case 102: - case 204: - case 304: - DA_LOG(HTTPManager, "HTTP Status is %d - 204 means server got the request, but no content to reply back, 304 means not modified!",http_status); - ret = DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT; - break; - - case 416: // Requested range not satisfiable - case 503: - case 504: - default: - GET_REQUEST_HTTP_RESULT(request_info) - = DA_ERR_UNREACHABLE_SERVER; - DA_LOG_CRITICAL(HTTPManager, "set internal error code : DA_ERR_UNREACHABLE_SERVER [%d]", DA_ERR_UNREACHABLE_SERVER); - break; - } - -ERR: - return ret; -} - -da_result_t exchange_url_from_header_for_redirection(stage_info *stage, - http_msg_response_t *http_msg_response) -{ - da_result_t ret = DA_RESULT_OK; - char *location = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - if (http_msg_response_get_location(http_msg_response, &location)) { - DA_LOG(HTTPManager, "location = %s\n", location); - GET_REQUEST_HTTP_REQ_LOCATION(GET_STAGE_TRANSACTION_INFO(stage)) = location; - } - - return ret; -} - -da_result_t handle_http_body(stage_info *stage, char *body, int body_len) -{ - da_result_t ret = DA_RESULT_OK; - http_state_t http_state = 0; - int download_id = DA_INVALID_ID; - - // DA_LOG_FUNC_START(HTTPManager); - - download_id = GET_STAGE_DL_ID(stage); - - if (DA_RESULT_OK - != GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))) { - DA_LOG_CRITICAL(HTTPManager, "ignore because internal error code is set with [%d]", - GET_REQUEST_HTTP_RESULT(GET_STAGE_TRANSACTION_INFO(stage))); - return ret; - } - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - // DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - if (http_state == HTTP_STATE_DOWNLOAD_STARTED) { - ret = start_file_writing(stage); - if (DA_RESULT_OK != ret) - goto ERR; - - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING, stage); - send_client_da_state(download_id, DA_STATE_DOWNLOADING, - DA_RESULT_OK); - send_client_update_dl_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_TMP_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - DA_NULL, - DA_NULL); - } else if (http_state == HTTP_STATE_RESUMED) { - ret = start_file_writing_append(stage); - if (DA_RESULT_OK != ret) - goto ERR; - - CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING,stage); - send_client_da_state(download_id, DA_STATE_RESUMED, - DA_RESULT_OK); - send_client_da_state(download_id, DA_STATE_DOWNLOADING, - DA_RESULT_OK); - } - - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - http_state = GET_HTTP_STATE_ON_STAGE(stage); - // DA_LOG(HTTPManager, "http_state = %d", http_state); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - - switch (http_state) { - case HTTP_STATE_REDIRECTED: - DA_LOG(HTTPManager, "Just ignore http body, because this body is not for redirection one."); - break; - - case HTTP_STATE_DOWNLOADING: - /* Should this function before updating download info - * Because it extract mime type at once only if first download updating at client */ - ret = file_write_ongoing(stage, body, body_len); - if (ret != DA_RESULT_OK) - goto ERR; - if (DA_TRUE == is_this_client_manual_download_type()) { - send_client_update_dl_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), - body_len, - GET_CONTENT_STORE_TMP_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - DA_NULL, - body); - } else if ((DA_TRUE == - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)))) { - send_client_update_downloading_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - DA_NULL); - - IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)) - = DA_FALSE; - } - break; - - case HTTP_STATE_REQUEST_PAUSE: - if (DA_TRUE == is_this_client_manual_download_type()) { - send_client_update_dl_info( - download_id, - GET_DL_REQ_ID(download_id), - GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)), - GET_CONTENT_STORE_TMP_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)), - body, - DA_NULL); - } else { - ret = file_write_ongoing(stage, body, body_len); - if (ret != DA_RESULT_OK) - goto ERR; - } - break; - - default: - DA_LOG(HTTPManager, "Do nothing! http_state is in case %d", http_state); - - goto ERR; - } - -ERR: - return ret; -} - -/* Function should be renamed , as it is actually not setting the header fields in download info */ -da_result_t set_hdr_fields_on_download_info(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - req_dl_info *request_info = DA_NULL; - http_msg_response_t *http_msg_response = NULL; - - char *value = NULL; - int int_value = 0; - - DA_LOG_FUNC_START(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - http_msg_response - = request_info->http_info.http_msg_response; - if (!http_msg_response) { - DA_LOG_ERR(HTTPManager, "There is no header data!!"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - b_ret = http_msg_response_get_content_type(http_msg_response, &value); - if (b_ret) { - GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value; - value = NULL; - DA_LOG(HTTPManager, "[Content-Type][%s] - stored", GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info)); - } - - b_ret = http_msg_response_get_content_length(http_msg_response, - &int_value); - if (b_ret) { - GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = int_value; - int_value = 0; - DA_LOG(HTTPManager, "[Content-Length][%d] - stored", GET_REQUEST_HTTP_HDR_CONT_LEN(request_info)); - } - - b_ret = http_msg_response_get_ETag(http_msg_response, &value); - if (b_ret) { - GET_REQUEST_HTTP_HDR_ETAG(request_info) = value; - value = NULL; - DA_LOG(HTTPManager, "[ETag][%s] - stored ", GET_REQUEST_HTTP_HDR_ETAG(request_info)); - } - -ERR: - return ret; -} - -da_result_t _check_content_type_is_matched(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - req_dl_info *request_info = DA_NULL; - source_info_t *source_info = DA_NULL; - char *content_type_from_server = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - source_info = GET_STAGE_SOURCE_INFO(stage); - - content_type_from_server = GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info); - if (content_type_from_server == DA_NULL) { - DA_LOG(HTTPManager, "http header has no Content-Type field, no need to compare"); - return DA_RESULT_OK; - } - - return ret; -} - -da_result_t _check_enough_memory_for_this_download(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - req_dl_info *request_info = DA_NULL; - - long long cont_len = 0; - da_storage_size_t memory; - - DA_LOG_FUNC_START(HTTPManager); - - memset(&memory, 0x00, sizeof(da_storage_size_t)); - request_info = GET_STAGE_TRANSACTION_INFO(stage); - - cont_len = (long long) GET_REQUEST_HTTP_HDR_CONT_LEN(request_info); - if (cont_len) { - ret = get_available_memory(DA_STORAGE_PHONE, &memory); - if (DA_RESULT_OK == ret) { - DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %lld",memory.b_available,memory.b_size, cont_len); - if (memory.b_available < ((cont_len - + SAVE_FILE_BUFFERING_SIZE_50KB) - / memory.b_size)) /* 50KB buffering */ - { - ret = DA_ERR_DISK_FULL; - goto ERR; - } - } - } - -ERR: - return ret; -} - -da_result_t _check_this_partial_download_is_available(stage_info *stage, - http_msg_response_t *new_http_msg_response) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - char *origin_ETag = NULL; - char *new_ETag = NULL; - - int remained_content_len = 0; - da_storage_size_t memory; - - char *value = NULL; - int int_value = 0; - - DA_LOG_FUNC_START(HTTPManager); - - origin_ETag - = GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)); - - b_ret = http_msg_response_get_content_length(new_http_msg_response, - &int_value); - if (b_ret) { - remained_content_len = int_value; - int_value = 0; - DA_LOG(HTTPManager, "[remained_content_len][%d]", remained_content_len); - } - - b_ret = http_msg_response_get_ETag(new_http_msg_response, &value); - if (b_ret) { - new_ETag = value; - value = NULL; - DA_LOG(HTTPManager, "[new ETag][%s]", new_ETag); - } else { - goto ERR; - } - - if (0 != strcmp(origin_ETag, new_ETag)) { - DA_LOG_ERR(HTTPManager, "ETag is not identical! revoke!"); - /* FIXME Later : Need to detail error exception handling */ - ret = DA_ERR_NETWORK_FAIL; - /*ret = DA_ERR_MISMATCH_HTTP_HEADER; */ - goto ERR; - } - - if (remained_content_len) { - ret = get_available_memory(DA_STORAGE_PHONE, &memory); - if (DA_RESULT_OK == ret) { - DA_LOG(HTTPManager, "Memory avail: %lu, Memory block :%lu Content: %lld",memory.b_available,memory.b_size, remained_content_len ); - if (memory.b_available < ((remained_content_len - + SAVE_FILE_BUFFERING_SIZE_50KB) - / memory.b_size)) /* 50KB buffering */ - { - ret = DA_ERR_DISK_FULL; - goto ERR; - } - } - } - -ERR: - if (new_ETag) { - free(new_ETag); - new_ETag = DA_NULL; - } - - return ret; -} - -da_result_t _check_downloaded_file_size_is_same_with_header_content_size( - stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - req_dl_info *request_info = DA_NULL; - file_info *file_info_data = DA_NULL; - - char *real_file_path = DA_NULL; - int content_size_from_real_file = DA_INVALID_ID; - unsigned int content_size_from_http_header = DA_INVALID_ID; - - DA_LOG_FUNC_START(HTTPManager); - - request_info = GET_STAGE_TRANSACTION_INFO(stage); - file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage); - - content_size_from_http_header - = GET_CONTENT_STORE_FILE_SIZE(file_info_data); - - if (content_size_from_http_header > 0) { - real_file_path - = GET_CONTENT_STORE_TMP_FILE_NAME(file_info_data); - get_file_size(real_file_path, - &content_size_from_real_file); - - if ((unsigned int) content_size_from_real_file - != content_size_from_http_header) { - DA_LOG_ERR(HTTPManager, "size from header = %d, real size = %d, DA_ERR_MISMATCH_CONTENT_SIZE", content_size_from_http_header, content_size_from_real_file); - ret = DA_ERR_MISMATCH_CONTENT_SIZE; - } - } - - return ret; -} - -da_result_t _disconnect_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - int transaction_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(HTTPManager); - - transaction_id - = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)); - - DA_LOG(HTTPManager, "transaction_id = %d download_id = %d", transaction_id, GET_STAGE_DL_ID(stage)); - - if (transaction_id != DA_INVALID_ID) { - ret = PI_http_disconnect_transaction(transaction_id); - GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)) - = DA_INVALID_ID; - } - - return ret; -} - -da_result_t _cancel_transaction(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - int transaction_id = DA_INVALID_ID; - - DA_LOG_FUNC_START(HTTPManager); - - transaction_id - = GET_REQUEST_HTTP_TRANS_ID(GET_STAGE_TRANSACTION_INFO(stage)); - - DA_LOG(HTTPManager, "transaction_id = %d", transaction_id); - - if (transaction_id != DA_INVALID_ID) { - http_state_t state = 0; - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - state = GET_HTTP_STATE_ON_STAGE(stage); - if (state <= HTTP_STATE_DOWNLOAD_REQUESTED) - ret = PI_http_cancel_transaction(transaction_id, DA_TRUE); - else - ret = PI_http_cancel_transaction(transaction_id, DA_FALSE); - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(stage))); - } - - return ret; -} - -void __parsing_user_request_header(char *user_request_header, - char **out_field, char **out_value) -{ - int len = 0; - char *pos = NULL; - char *temp_pos = NULL; - char *field = NULL; - char *value = NULL; - - DA_LOG_FUNC_START(HTTPManager); - - if (!user_request_header) { - DA_LOG_ERR(HTTPManager, "user_request_header is NULL"); - goto ERR; - } - - pos = strchr(user_request_header, ':'); - if (!pos) { - DA_LOG_ERR(HTTPManager, "Fail to parse"); - goto ERR; - } - temp_pos = (char *)user_request_header; - while (*temp_pos) - { - if (temp_pos == pos || *temp_pos == ' ') { - len = temp_pos - user_request_header; - break; - } - temp_pos++; - } - if (len < 1) { - DA_LOG_ERR(HTTPManager, "Wrong field name"); - goto ERR; - } - field = (char *)calloc(1, len + 1); - if (!field) { - DA_LOG_ERR(HTTPManager, "Fail to calloc"); - goto ERR; - } - strncpy(field, user_request_header, len); - pos++; - while (*pos) - { - if (*pos != ' ') - break; - pos++; - } - len = strlen(pos) + 1; - value = (char *)calloc(1, len + 1); - if (!value) { - DA_LOG_ERR(HTTPManager, "Fail to calloc"); - goto ERR; - } - strncpy(value, pos, len); - *out_field = field; - *out_value = value; - DA_LOG(HTTPManager, "field[%s], value[%s]", field, value); - - return; -ERR: - if (field) { - free(field); - field = NULL; - } - return; -} - diff --git a/src/agent/download-agent-http-misc.c b/src/agent/download-agent-http-misc.c deleted file mode 100644 index b43be29..0000000 --- a/src/agent/download-agent-http-misc.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-misc.c - * @brief Including miscellaneous functions for http - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include "download-agent-http-misc.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-plugin-conf.h" -#include "download-agent-client-mgr.h" - -#define DEFAULT_HTTP_ACCEPT_HEADERS \ - "Accept-Language: en\r\n" \ - "Accept-Charset: utf-8\r\n" \ - - -char* get_user_agent() -{ - char *uagent_str = DA_NULL; - - DA_LOG_FUNC_START(Default); - - uagent_str = get_client_user_agent_string(); - if (uagent_str) { - return uagent_str; - } else { - return GET_USER_AGENT; - } -} - -da_bool_t is_supporting_protocol(const char* protocol) -{ - if((protocol == NULL) || (1 > strlen(protocol))) - { - return DA_FALSE; - } - - if(!strcasecmp(protocol, "http")) - { - return DA_TRUE; - } - else if(!strcasecmp(protocol, "https")) - { - return DA_TRUE; - } - else - { - return DA_FALSE; - } - -} diff --git a/src/agent/download-agent-http-queue.c b/src/agent/download-agent-http-queue.c deleted file mode 100644 index 375075c..0000000 --- a/src/agent/download-agent-http-queue.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-queue.c - * @brief Including functions regarding http queue - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#include "download-agent-http-queue.h" -#include "download-agent-http-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-pthread.h" - -void init_q_event_data_http(q_event_t *q_event); -void init_q_event_control(q_event_t *q_event); - -void Q_init_queue(queue_t *queue) -{ - queue->having_data = DA_FALSE; - queue->control_head = DA_NULL; - queue->data_head = DA_NULL; - queue->queue_size = 0; - - _da_thread_mutex_init(&(queue->mutex_queue), DA_NULL); - _da_thread_cond_init(&(queue->cond_queue), DA_NULL); -} - -void Q_destroy_queue(queue_t *queue) -{ - q_event_t *event = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - do { - Q_pop_event(queue, &event); - Q_destroy_q_event(&event); - } while(event); - - queue->having_data = DA_FALSE; - queue->control_head = DA_NULL; - queue->data_head = DA_NULL; - queue->queue_size = 0; - - _da_thread_mutex_destroy(&(queue->mutex_queue)); - _da_thread_cond_destroy(&(queue->cond_queue)); -} - -void Q_init_q_event(q_event_t *q_event) -{ - switch(q_event->event_type) { - case Q_EVENT_TYPE_DATA_HTTP: - init_q_event_data_http(q_event); - break; - case Q_EVENT_TYPE_CONTROL: - init_q_event_control(q_event); - break; - } - - q_event->size = 0; - q_event->next = DA_NULL; -} - -void Q_destroy_q_event(q_event_t **in_q_event) -{ - q_event_t *q_event = DA_NULL; - q_event = *in_q_event; - - if(q_event == DA_NULL) - return; - -// DA_LOG(HTTPManager, "destroying size = %d", q_event->size); - - switch(q_event->event_type) { - case Q_EVENT_TYPE_DATA_HTTP: - init_q_event_data_http(q_event); - q_event->size = 0; - q_event->next = DA_NULL; - free(q_event); - break; - case Q_EVENT_TYPE_CONTROL: - init_q_event_control(q_event); - q_event->size = 0; - q_event->next = DA_NULL; - free(q_event); - break; - } -} - -da_result_t Q_make_control_event(q_event_type_control control_type, q_event_t **out_event) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - q_event = (q_event_t *)calloc(1, sizeof(q_event_t)); - if(q_event == DA_NULL) { - DA_LOG_ERR(HTTPManager, "calloc fail for q_event"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - - *out_event = DA_NULL; - } else { - q_event->event_type = Q_EVENT_TYPE_CONTROL; - q_event->type.q_event_control.control_type = control_type; - q_event->next = DA_NULL; - - *out_event = q_event; - } - - return ret; -} - -da_result_t Q_make_http_data_event(q_event_type_data data_type, q_event_t **out_event) -{ - da_result_t ret = DA_RESULT_OK; - q_event_t *q_event = DA_NULL; - -// DA_LOG_FUNC_START(HTTPManager); - - q_event = (q_event_t *)calloc(1, sizeof(q_event_t)); - if(q_event == DA_NULL) { - DA_LOG_ERR(HTTPManager, "calloc fail for q_event"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - *out_event = DA_NULL; - } else { - q_event->event_type = Q_EVENT_TYPE_DATA_HTTP; - q_event->type.q_event_data_http.data_type = data_type; - q_event->next = DA_NULL; - - *out_event = q_event; - -// DA_LOG(HTTPManager, "made event = %x", *out_event); - } - - return ret; - -} - -da_result_t Q_set_status_code_on_http_data_event(q_event_t *q_event, int status_code) -{ - da_result_t ret = DA_RESULT_OK; - -// DA_LOG_FUNC_START(HTTPManager); - - if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { - DA_LOG_ERR(HTTPManager, "status_code can be set only for Q_EVENT_TYPE_DATA_HTTP."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - q_event->type.q_event_data_http.status_code = status_code; - -// DA_LOG(HTTPManager, "status_code = %d, q_event = %x", q_event->type.q_event_data_http.status_code, q_event); - -ERR: - return ret; - -} - -da_result_t Q_set_http_body_on_http_data_event(q_event_t *q_event, int body_len, char *body_data) -{ - da_result_t ret = DA_RESULT_OK; - -// DA_LOG_FUNC_START(HTTPManager); - - if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { - DA_LOG_ERR(HTTPManager, "http body can be set only for Q_EVENT_TYPE_DATA_HTTP."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - q_event->type.q_event_data_http.body_len = body_len; - q_event->type.q_event_data_http.body_data = body_data; - q_event->size = body_len; - -// DA_LOG(HTTPManager, "body_len = %d, body_data = %x, q_event = %x", q_event->type.q_event_data_http.body_len, q_event->type.q_event_data_http.body_data, q_event); - -ERR: - return ret; - -} - -da_result_t Q_set_error_type_on_http_data_event(q_event_t *q_event, int error_type) -{ - da_result_t ret = DA_RESULT_OK; - -// DA_LOG_FUNC_START(HTTPManager); - - if(q_event->event_type != Q_EVENT_TYPE_DATA_HTTP) { - DA_LOG_ERR(HTTPManager, "error_type can be set only for Q_EVENT_TYPE_DATA_HTTP."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - q_event->type.q_event_data_http.error_type = error_type; - - DA_LOG(HTTPManager, "error_type = %d, q_event = %p", q_event->type.q_event_data_http.error_type, q_event); - -ERR: - return ret; - -} - -da_bool_t Q_push_event(const queue_t *in_queue, const q_event_t *in_event) -{ - da_bool_t b_ret = DA_FALSE; - queue_t *queue = (queue_t *)in_queue; - - _da_thread_mutex_lock (&(queue->mutex_queue)); - b_ret = Q_push_event_without_lock(in_queue, in_event); - _da_thread_mutex_unlock (&(queue->mutex_queue)); - - return b_ret; -} - -da_bool_t Q_push_event_without_lock(const queue_t *in_queue, const q_event_t *in_event) -{ - da_bool_t b_ret = DA_FALSE; - queue_t *queue = (queue_t *)in_queue; - q_event_t *event = (q_event_t *)in_event; - q_event_type event_type; - q_event_t *head = DA_NULL; - q_event_t *cur = DA_NULL; - -// DA_LOG_FUNC_START(HTTPManager); -// DA_LOG(HTTPManager, "queue = %x", in_queue); - - event_type = event->event_type; - -// _da_thread_mutex_lock (&(queue->mutex_queue)); - - if(event_type == Q_EVENT_TYPE_CONTROL) { - head = queue->control_head; - if(head == DA_NULL) { - queue->control_head = event; - } else { - cur = head; - - while(cur->next != DA_NULL) { - cur = cur->next; - } - cur->next= event; - } - b_ret = DA_TRUE; - } else { - if((event->size == 0) || (queue->queue_size < MAX_QUEUE_SIZE)) { - head = queue->data_head; - if(head == DA_NULL) { - queue->data_head = event; - } else { - cur = head; - while(cur->next != DA_NULL) { - cur = cur->next; - } - cur->next= event ; - } - - queue->queue_size += event->size; -// DA_LOG(HTTPManager, "queue size is %d", queue->queue_size); - - b_ret = DA_TRUE; - } else { - DA_LOG_CRITICAL(HTTPManager, "rejected event's size is %d queue_size %d", event->size, queue->queue_size); - b_ret = DA_FALSE; - } - } - - queue->having_data = DA_TRUE; - Q_wake_up(queue); -// _da_thread_mutex_unlock (&(queue->mutex_queue)); - return b_ret; -} - -void Q_pop_event(const queue_t *in_queue, q_event_t **out_event) -{ - queue_t *queue = (queue_t*)in_queue; - -// DA_LOG_FUNC_START(HTTPManager); -// DA_LOG(HTTPManager, "queue = %x", in_queue); - - /** Pop Priority - * 1. If there are control event, control event should pop first - * 2. If there is no control event, data event should pop - * 3. If there is no control and data event on queue, pop NULL - */ - - _da_thread_mutex_lock (&(queue->mutex_queue)); - - if(queue->control_head != DA_NULL) {/* Priority 1 */ - *out_event = queue->control_head; - queue->control_head = queue->control_head->next; - } else { - if(queue->data_head != DA_NULL) {/* Priority 2 */ - *out_event = queue->data_head; - queue->data_head = queue->data_head->next; - queue->queue_size -= (*out_event)->size; -// DA_LOG(HTTPManager, "queue size is %d", queue->queue_size); - } else {/* Priority 3 */ - *out_event = DA_NULL; - } - } - - if((queue->control_head == DA_NULL) && (queue->data_head == DA_NULL)) { - queue->having_data = DA_FALSE; - } else { - queue->having_data = DA_TRUE; - } - - _da_thread_mutex_unlock (&(queue->mutex_queue)); - -} - -void Q_goto_sleep(const queue_t *in_queue) -{ -// DA_LOG_FUNC_START(HTTPManager); - DA_LOG(HTTPManager, "sleep for %p", in_queue); - -//** SHOULD NOT use mutex **// - -// _da_thread_mutex_lock (&(in_queue->mutex_queue)); - _da_thread_cond_wait((pthread_cond_t*)(&(in_queue->cond_queue)),(pthread_mutex_t*) (&(in_queue->mutex_queue))); -// _da_thread_mutex_unlock (&(in_queue->mutex_queue)); -} - -void Q_wake_up(const queue_t *in_queue) -{ -// DA_LOG_FUNC_START(HTTPManager); - DA_LOG(HTTPManager, "wake up for %p", in_queue); - -//** SHOULD NOT use mutex **// - -// _da_thread_mutex_lock (&(in_queue->mutex_queue)); - _da_thread_cond_signal((pthread_cond_t*)(&(in_queue->cond_queue))); -// _da_thread_mutex_unlock (&(in_queue->mutex_queue)); -} - -void init_q_event_data_http(q_event_t *q_event) -{ - q_event_data_http_t *q_event_data_http; - -// DA_LOG_FUNC_START(HTTPManager); - - if(q_event->event_type == Q_EVENT_TYPE_DATA_HTTP) { - q_event_data_http = &(q_event->type.q_event_data_http); - - if(q_event_data_http) { - q_event_data_http->status_code = DA_NULL; - if(q_event_data_http->http_response_msg) { - http_msg_response_destroy(&(q_event_data_http->http_response_msg)); - } - - if(q_event_data_http->body_len > 0 ) { - if (q_event_data_http->body_data) { - free(q_event_data_http->body_data); - q_event_data_http->body_data = DA_NULL; - } - } - q_event_data_http->error_type = DA_NULL; - } - } -} - -void init_q_event_control(q_event_t *q_event) -{ - q_event_control_t *q_event_control; - -// DA_LOG_FUNC_START(HTTPManager); - - if(q_event->event_type == Q_EVENT_TYPE_CONTROL) { - q_event_control = &(q_event->type.q_event_control); - if(q_event_control) { - q_event_control->control_type = DA_NULL; - } - } - -} diff --git a/src/agent/download-agent-installation.c b/src/agent/download-agent-installation.c deleted file mode 100644 index f0ffcfa..0000000 --- a/src/agent/download-agent-installation.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-installation.c - * @brief Functions for Content Installation - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include -#include - -#include "download-agent-client-mgr.h" -#include "download-agent-dl-info-util.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" -#include "download-agent-installation.h" -#include "download-agent-file.h" -#include "download-agent-plugin-install.h" - -da_result_t _extract_file_path_which_will_be_installed(char *in_file_name, char *in_extension, char *in_install_path_client_wants, char **out_will_install_path); - -da_result_t install_content(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - - file_info *file_storage = DA_NULL; - char *temp_saved_file_path = DA_NULL; - char *install_file_path = DA_NULL; - unsigned int start_time = 0; - - DA_LOG_FUNC_START(InstallManager); - - if (!stage) - return DA_ERR_INVALID_ARGUMENT; - - file_storage = GET_STAGE_CONTENT_STORE_INFO(stage); - if (!file_storage) { - DA_LOG_ERR(InstallManager,"file_storage structure is NULL"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - temp_saved_file_path = - GET_CONTENT_STORE_TMP_FILE_NAME(file_storage); - DA_LOG(InstallManager,"Source path[%s]",temp_saved_file_path); - - ret = check_enough_storage(stage); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = _extract_file_path_which_will_be_installed( - GET_CONTENT_STORE_PURE_FILE_NAME(file_storage), - GET_CONTENT_STORE_EXTENSION(file_storage), - GET_DL_USER_INSTALL_PATH(GET_STAGE_DL_ID(stage)), - &install_file_path); - if (ret != DA_RESULT_OK) - goto ERR; - - DA_LOG(InstallManager,"Installing path [%s]", install_file_path); - DA_LOG(InstallManager,"Move start time : [%ld]",start_time=time(NULL)); - ret = move_file(temp_saved_file_path, install_file_path); - if (ret != DA_RESULT_OK) - goto ERR; - - if (GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage)) - free(GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage)); - GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = install_file_path; - install_file_path = DA_NULL; - - -ERR: - if (ret != DA_RESULT_OK) { - remove_file(GET_CONTENT_STORE_TMP_FILE_NAME(file_storage)); - remove_file(install_file_path); - } else { - } - return ret; -} - -da_result_t _extract_file_path_which_will_be_installed(char *in_file_name, char *in_extension, char *in_install_path_client_wants, char **out_will_install_path) -{ - da_result_t ret = DA_RESULT_OK; - char *install_dir = NULL; - char *default_install_dir = NULL; - char *final_path = NULL; - char *pure_file_name = in_file_name; - char *extension = in_extension; - - if (!in_file_name || !out_will_install_path) - return DA_ERR_INVALID_ARGUMENT; - - *out_will_install_path = DA_NULL; - - if (in_install_path_client_wants) { - install_dir = in_install_path_client_wants; - } else { - default_install_dir = PI_get_default_install_dir(); - if (default_install_dir) - install_dir = default_install_dir; - else - return DA_ERR_FAIL_TO_INSTALL_FILE; - } - - if (DA_FALSE == is_dir_exist(install_dir)) { - ret = create_dir(install_dir); - if (ret != DA_RESULT_OK) - return DA_ERR_FAIL_TO_INSTALL_FILE; - } - - final_path = get_full_path_avoided_duplication(install_dir, pure_file_name, extension); - if (!final_path) - ret = DA_ERR_FAIL_TO_INSTALL_FILE; - - *out_will_install_path = final_path; - - DA_LOG(InstallManager,"Final install path[%s]", *out_will_install_path); - - return ret; -} diff --git a/src/agent/download-agent-interface.c b/src/agent/download-agent-interface.c deleted file mode 100644 index 292233c..0000000 --- a/src/agent/download-agent-interface.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-interface.c - * @brief Interface for Download Agent. - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include "download-agent-interface.h" -#include "download-agent-debug.h" -#include "download-agent-utils.h" -#include "download-agent-http-mgr.h" -#include "download-agent-http-misc.h" -#include "download-agent-client-mgr.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-basic.h" -#include "download-agent-file.h" -#include "download-agent-installation.h" - -int da_init( - da_client_cb_t *da_client_callback, - da_download_managing_method download_method) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - if (!da_client_callback) { - ret = DA_ERR_INVALID_ARGUMENT; - return ret; - } - - ret = init_log_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = init_client_app_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = reg_client_app(da_client_callback, download_method); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = init_http_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = init_download_mgr(); - if (ret != DA_RESULT_OK) - goto ERR; - - ret = create_temp_saved_dir(); - if (ret != DA_RESULT_OK) - goto ERR; - -ERR: - if (DA_RESULT_OK != ret) - da_deinit(); - - DA_LOG_CRITICAL(Default, "Return ret = %d", ret); - - return ret; -} - -/* TODO:: deinit should clean up all the clients... */ -int da_deinit() -{ - da_result_t ret = DA_RESULT_OK; - char *client_dir_path = DA_NULL; - - DA_LOG_FUNC_START(Default); - if (DA_FALSE == is_this_client_available()) { - ret = DA_ERR_INVALID_CLIENT; - return ret; - } - - deinit_http_mgr(); - deinit_download_mgr(); - - ret = get_client_download_path(&client_dir_path); - if (ret == DA_RESULT_OK) { - ret = clean_files_from_dir(client_dir_path); - - if (client_dir_path) { - free(client_dir_path); - client_dir_path = DA_NULL; - } - } - - dereg_client_app(); - DA_LOG(Default, "====== da_deinit EXIT ====="); - - return ret; -} - -int da_start_download( - const char *url, - da_handle_t *da_dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - DA_LOG(Default, "url = %s", url); - - *da_dl_req_id = DA_INVALID_ID; - - if (DA_FALSE == is_this_client_available()) { - ret = DA_ERR_INVALID_CLIENT; - goto ERR; - } - - if (DA_FALSE == is_valid_url(url, &ret)) - goto ERR; - - ret = start_download(url, da_dl_req_id); - if (ret != DA_RESULT_OK) - goto ERR; - -ERR: - DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *da_dl_req_id, ret); - return ret; -} - -int da_start_download_with_extension( - const char *url, - da_handle_t *da_dl_req_id, - ... -) -{ - da_result_t ret = DA_RESULT_OK; - va_list argptr; - char *property_name = NULL; - int req_header_count = 0; - int i = 0; - - extension_data_t extension_data; - - DA_LOG_FUNC_START(Default); - - DA_LOG(Default, "url = %s", url); - - *da_dl_req_id = DA_INVALID_ID; - extension_data.request_header= NULL; - extension_data.request_header_count = NULL; - extension_data.install_path = NULL; - extension_data.file_name = NULL; - extension_data.user_data = NULL; - - if (DA_FALSE == is_this_client_available()) { - ret = DA_ERR_INVALID_CLIENT; - goto ERR; - } - - if (DA_FALSE == is_valid_url(url, &ret)) - goto ERR; - - va_start(argptr, da_dl_req_id); - property_name = va_arg(argptr, char*); - - // FIXME How about changing type for property_name enum? - if (!property_name) { - DA_LOG_ERR(Default, "No property input!"); - ret = DA_ERR_INVALID_ARGUMENT; - } else { - while (property_name && (ret == DA_RESULT_OK)) { - DA_LOG_VERBOSE(Default, "property_name = [%s]", property_name); - - if (!strncmp(property_name, DA_FEATURE_USER_DATA, strlen(DA_FEATURE_USER_DATA))) { - extension_data.user_data = va_arg(argptr, void*); - if (extension_data.user_data) { - property_name = va_arg(argptr, char*); - } else { - DA_LOG_ERR(Default, "No property value for DA_FEATURE_USER_DATA!"); - ret = DA_ERR_INVALID_ARGUMENT; - } - } else if (!strncmp(property_name, DA_FEATURE_INSTALL_PATH, strlen(DA_FEATURE_INSTALL_PATH))) { - extension_data.install_path = va_arg(argptr, const char*); - if (extension_data.install_path) { - property_name = va_arg(argptr, char*); - } else { - DA_LOG_ERR(Default, "No property value for DA_FEATURE_INSTALL_PATH!"); - ret = DA_ERR_INVALID_ARGUMENT; - } - } else if (!strncmp(property_name, DA_FEATURE_FILE_NAME, strlen(DA_FEATURE_FILE_NAME))) { - extension_data.file_name = va_arg(argptr, const char*); - if (extension_data.file_name) { - property_name = va_arg(argptr, char*); - } else { - DA_LOG_ERR(Default, "No property value for DA_FEATURE_FILE_NAME!"); - ret = DA_ERR_INVALID_ARGUMENT; - } - } else if (!strncmp(property_name, DA_FEATURE_REQUEST_HEADER, strlen(DA_FEATURE_REQUEST_HEADER))) { - extension_data.request_header = va_arg(argptr, const char **); - extension_data.request_header_count = va_arg(argptr, const int *); - if (extension_data.request_header && - extension_data.request_header_count) { - property_name = va_arg(argptr, char *); - } else { - DA_LOG_ERR(Default, "No property value for DA_FEATURE_REQUEST_HEADER!"); - ret = DA_ERR_INVALID_ARGUMENT; - } - } else { - DA_LOG_ERR(Default, "Unknown property name; [%s]", property_name); - ret = DA_ERR_INVALID_ARGUMENT; - } - } - } - - va_end(argptr); - - if (ret != DA_RESULT_OK) - goto ERR; - - if (extension_data.request_header_count) { - DA_LOG_VERBOSE(Default, "input request_header_count = [%d]", - *(extension_data.request_header_count)); - for (i = 0; i < *(extension_data.request_header_count); i++) - { - if (extension_data.request_header[i]) { - req_header_count++; - DA_LOG_VERBOSE(Default, "request_header = [%s]", - extension_data.request_header[i]); - } - } - DA_LOG(Default, "actual request_header_count = [%d]", req_header_count); - if (*(extension_data.request_header_count) != req_header_count) { - DA_LOG_ERR(Default, "Request header count is not matched with number of request header array"); - extension_data.request_header = NULL; - extension_data.request_header_count = NULL; - } - } - - if (extension_data.install_path) - DA_LOG_VERBOSE(Default, "install path = [%s]", extension_data.install_path); - - if (extension_data.file_name) - DA_LOG_VERBOSE(Default, "file_name = [%s]", extension_data.file_name); - - ret = start_download_with_extension(url, da_dl_req_id, &extension_data); - -ERR: - DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *da_dl_req_id, ret); - return ret; -} - -int da_cancel_download(da_handle_t da_dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - DA_LOG_VERBOSE(Default, "Cancel for dl_req_id = %d", da_dl_req_id); - - if (DA_FALSE == is_this_client_available()) { - ret = DA_ERR_INVALID_CLIENT; - goto ERR; - } - - ret = cancel_download(da_dl_req_id); - -ERR: - DA_LOG_CRITICAL(Default, "Return: Cancel id = %d, ret = %d", da_dl_req_id, ret); - return ret; -} - -int da_suspend_download(da_handle_t da_dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - DA_LOG_VERBOSE(Default, "Suspend for dl_req_id = %d", da_dl_req_id); - - if (DA_FALSE == is_this_client_available()) { - ret = DA_ERR_INVALID_CLIENT; - goto ERR; - } - ret = suspend_download(da_dl_req_id); - -ERR: - DA_LOG_CRITICAL(Default, "Return: Suspend id = %d, ret = %d", da_dl_req_id, ret); - return ret; -} - -int da_resume_download(da_handle_t da_dl_req_id) -{ - da_result_t ret = DA_RESULT_OK; - - DA_LOG_FUNC_START(Default); - - DA_LOG_VERBOSE(Default, "Resume for dl_req_id = %d", da_dl_req_id); - - if (DA_FALSE == is_this_client_available()) { - ret = DA_ERR_INVALID_CLIENT; - goto ERR; - } - ret = resume_download(da_dl_req_id); - -ERR: - DA_LOG_CRITICAL(Default, "Return: Resume id = %d, ret = %d", da_dl_req_id, ret); - return ret; -} - diff --git a/src/agent/download-agent-plugin-conf.c b/src/agent/download-agent-plugin-conf.c deleted file mode 100644 index 6a510b6..0000000 --- a/src/agent/download-agent-plugin-conf.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-conf.c - * @brief Platform dependent functions for get configuration data from target - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include -#include -#include - -#ifdef _EFL_PLATFORM -#include -#include -#include -#endif /* _EFL_PLATFORM */ - -#include "download-agent-plugin-conf.h" -#include "download-agent-debug.h" -#include "download-agent-file.h" - -#define DEFAULT_UA_STR "Mozilla/5.0 (Linux; U; Tizen 1.0; en-us) AppleWebKit/534.46 (KHTML, like Gecko) Mobile Tizen Browser/1.0" - -da_result_t __get_conf_string(const char *key, char **out_string); - -da_result_t __get_conf_string(const char *key, char **out_string) -{ -#ifdef _EFL_PLATFORM - if (!key || !out_string) { - DA_LOG_ERR(Default,"Invalid Argument"); - return DA_ERR_INVALID_ARGUMENT; - } - - *out_string = vconf_get_str(key); - return DA_RESULT_OK; -#else - if (out_string) - *out_string = NULL; - - return DA_RESULT_OK; -#endif -} - -da_result_t get_storage_type(da_storage_type_t *type) -{ - da_result_t ret = DA_RESULT_OK; -#ifdef _EFL_PLATFORM - int value = -1; -#endif - - if (!type) { - DA_LOG_ERR(Default,"DA_ERR_CONF_FAIL"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - -#ifdef _EFL_PLATFORM - if (0 != vconf_get_int(VCONFKEY_SETAPPL_DEFAULT_MEM_WAP_INT, &value)) { - DA_LOG_ERR(Default,"DA_ERR_CONF_FAIL"); - ret = DA_ERR_FAIL_TO_GET_CONF_VALUE; - goto ERR; - } - - switch (value) { - case SETTING_DEF_MEMORY_PHONE: - DA_LOG(Default,"Storage set - DA_STORAGE_PHONE"); - *type = DA_STORAGE_PHONE; - break; - case SETTING_DEF_MEMORY_MMC: - *type = DA_STORAGE_MMC; - DA_LOG(Default,"Storage set - DA_STORAGE_MMC"); - break; - case SETTING_DEF_MEMORY_MAX: - *type = DA_STORAGE_SYSTEM; - DA_LOG(Default,"Storage set - DA_STORAGE_SYSTEM"); - break; - default: - DA_LOG_ERR(Default,"DA_ERR_CONF_FAIL"); - ret = DA_ERR_FAIL_TO_GET_CONF_VALUE; - break; - } -#endif - -ERR: - return ret; - -} - -da_result_t get_user_agent_string(char **uagent_str) -{ - da_result_t ret = DA_RESULT_OK; -#ifdef _EFL_PLATFORM - char *key = DA_NULL; -#endif - - DA_LOG_FUNC_START(Default); - - if (!uagent_str) { - DA_LOG_ERR(Default,"Invalid Argument"); - return DA_ERR_INVALID_ARGUMENT; - } - -#ifdef _EFL_PLATFORM - key = VCONFKEY_ADMIN_UAGENT; - ret = __get_conf_string(key, uagent_str); - if(ret == DA_RESULT_OK) { - if(*uagent_str) { - DA_LOG(Default,"getting uagent_str = \n%s", *uagent_str); - return ret; - } - } - DA_LOG_ERR(Default,"No UA information from vconf !!"); - *uagent_str = strdup(DEFAULT_UA_STR); - DA_LOG(Default,"Set default UA"); -#else - *uagent_str = strdup(DEFAULT_UA_STR); -#endif - return ret; -} - -char *get_proxy_address(void) -{ -#ifdef _EFL_PLATFORM - char *proxy = NULL; - char *proxyRet = NULL; - connection_h handle = NULL; - connection_address_family_e family = CONNECTION_ADDRESS_FAMILY_IPV4; - - DA_LOG_FUNC_START(Default); - if (connection_create(&handle) < 0) { - DA_LOG_ERR(Default,"Fail to create connection handle"); - return NULL; - } - - if (connection_get_proxy(handle, family, &proxyRet) < 0) { - DA_LOG_ERR(Default,"Fail to get proxy address"); - connection_destroy(handle); - return NULL; - } - - if (proxyRet) { - DA_LOG(Default,"===== Proxy address[%s] =====", proxyRet); - proxy = strdup(proxyRet); - free(proxyRet); - proxyRet = NULL; - connection_destroy(handle); - return proxy; - } - - if (connection_destroy(handle) < 0) { - DA_LOG_ERR(Default,"Fail to desctory connection handle"); - return NULL; - } - return NULL; -#else - return NULL; -#endif -} diff --git a/src/agent/download-agent-plugin-install.c b/src/agent/download-agent-plugin-install.c deleted file mode 100644 index 81f703a..0000000 --- a/src/agent/download-agent-plugin-install.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-install.c - * @brief Platform dependency functions for installation a content to target - * @author Jungki,Kwak(jungki.kwak@samsung.com) - ***/ - -#include "download-agent-plugin-install.h" -#include "download-agent-debug.h" -#include "download-agent-plugin-conf.h" - -#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/media/Downloads" -#define DA_DEFAULT_INSTALL_PATH_FOR_MMC "/opt/storage/sdcard/Downloads" - -char *PI_get_default_install_dir(void) -{ - da_storage_type_t type; - - if (DA_RESULT_OK != get_storage_type(&type)) - return NULL; - - /* ToDo: need to refactoring later */ - if (type == DA_STORAGE_MMC) - return DA_DEFAULT_INSTALL_PATH_FOR_MMC; - else - return DA_DEFAULT_INSTALL_PATH_FOR_PHONE; -} diff --git a/src/agent/download-agent-plugin-libsoup.c b/src/agent/download-agent-plugin-libsoup.c deleted file mode 100644 index 676c4c6..0000000 --- a/src/agent/download-agent-plugin-libsoup.c +++ /dev/null @@ -1,968 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-libsoup.c - * @brief Platform dependent functions for interface of libsoup http module - * @author Keunsoon Lee (keunsoon.lee@samsung.com) - * @author Jungki Kwak (jungki.kwak@samsung.com) - ***/ - -#include -#include - -#include "download-agent-debug.h" -#include "download-agent-plugin-libsoup.h" -#include "download-agent-http-misc.h" -#include "download-agent-utils.h" -#include "download-agent-pthread.h" - -pthread_mutex_t mutex_for_session_table = PTHREAD_MUTEX_INITIALIZER; - -pi_session_table_t pi_session_table[MAX_SESSION_COUNT] = { { 0, }, }; -da_bool_t using_content_sniffing; - -da_bool_t _pi_http_is_this_session_table_entry_using( - const int in_session_table_entry); - -da_result_t PI_http_init(void) -{ - DA_LOG_FUNC_START(HTTPManager); - - using_content_sniffing = DA_TRUE; - - return DA_RESULT_OK; -} - -void PI_http_deinit(void) -{ - DA_LOG_FUNC_START(HTTPManager); - - return; -} - -da_result_t _set_proxy_on_soup_session(SoupSession *session, char *proxy_addr) -{ - da_result_t ret = DA_RESULT_OK; - - - if (proxy_addr && strlen(proxy_addr) > 0) { - DA_LOG_CRITICAL(HTTPManager,"received proxy = %s \n", proxy_addr); - if (!strstr(proxy_addr, "0.0.0.0")) { - if (strstr((const char *)proxy_addr, "http") == DA_NULL) { - /* DA_LOG(Default,"There is no \"http://\" on received uri, so, add it."); */ - - char *tmp_str = DA_NULL; - int needed_len = 0; - - needed_len = strlen(proxy_addr) + strlen( - SCHEME_HTTP) + 1; - tmp_str = (char *) calloc(1, needed_len); - if (!tmp_str) { - DA_LOG_ERR(HTTPManager,"DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - snprintf(tmp_str, needed_len, "%s%s", - SCHEME_HTTP, proxy_addr); - - g_object_set(session, SOUP_SESSION_PROXY_URI, - soup_uri_new(tmp_str), NULL); - - free(tmp_str); - } else { - DA_LOG(HTTPManager,"There is \"http\" on uri, so, push this address to soup directly."); - g_object_set(session, SOUP_SESSION_PROXY_URI, - soup_uri_new(proxy_addr), NULL); - } - } - } else { - DA_LOG(HTTPManager,"There is no proxy value"); - } -ERR: - return ret; -} - -void _fill_soup_msg_header(SoupMessage *msg, - const input_for_tranx_t *input_for_tranx) -{ - SoupMessageHeaders *headers = msg->request_headers; - - http_msg_request_t *input_http_msg_request; - http_msg_iter_t http_msg_iter; - http_msg_iter_t http_msg_iter_pre; - - char *field; - char *value; - - input_http_msg_request = input_for_tranx->http_msg_request; - - http_msg_request_get_iter(input_http_msg_request, &http_msg_iter); - http_msg_iter_pre = http_msg_iter; - while (http_msg_get_field_with_iter(&http_msg_iter, &field, &value)) { - if ((field != DA_NULL) && (value != DA_NULL)) { - DA_LOG(HTTPManager,"[%s] %s", field, value); - soup_message_headers_append(headers, field, value); - } - http_msg_iter_pre = http_msg_iter; - } - - if (input_http_msg_request->http_body) { - char body_len_str[16] = { 0, }; - int body_len = strlen(input_http_msg_request->http_body); - - snprintf(body_len_str, sizeof(body_len_str), "%d", body_len); - - soup_message_headers_append(headers, "Content-Length", - body_len_str); - soup_message_headers_append(headers, "Content-Type", - "text/plain"); - soup_message_body_append(msg->request_body, SOUP_MEMORY_COPY, - input_http_msg_request->http_body, body_len); - } -} - -da_result_t PI_http_start_transaction(const input_for_tranx_t *input_for_tranx, - int *out_tranx_id) -{ - da_result_t ret = DA_RESULT_OK; - - int session_table_entry = -1; - pi_http_method_t pi_http_method = PI_HTTP_METHOD_GET; - - queue_t *queue = DA_NULL; - - char *url = DA_NULL; - - SoupSession *session = DA_NULL; - SoupMessage *msg = DA_NULL; - - DA_LOG_FUNC_START(HTTPManager); - - if (DA_FALSE == _pi_http_is_valid_input_for_tranx(input_for_tranx)) { - DA_LOG_ERR(HTTPManager,"input_for_tranx is invalid"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } else { - queue = input_for_tranx->queue; - pi_http_method = input_for_tranx->http_method; - url = input_for_tranx->http_msg_request->url; - } - - session_table_entry = _pi_http_get_avaiable_session_table_entry(); - if (session_table_entry == -1) { - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - DA_LOG(HTTPManager,"session_table_entry = %d", session_table_entry); - - if (DA_FALSE == _pi_http_register_queue_to_session_table( - session_table_entry, queue)) { - _pi_http_destroy_session_table_entry(session_table_entry); - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - - /* modified by keunsoon.lee 2010-09-20 use sync_new() instead of async_new() for make different soup thread from UI main thread*/ - session = soup_session_sync_new(); - /* session=soup_session_async_new(); */ - if (!session) { - DA_LOG_ERR(HTTPManager,"Fail to create session"); - return DA_ERR_INVALID_URL; - } - DA_LOG(HTTPManager,"session[%p]", session); -/* - SoupLogger* logger = soup_logger_new(SOUP_LOGGER_LOG_BODY, -1); - soup_logger_attach(logger, session); - g_object_unref(logger); -*/ - if (DA_FALSE == _pi_http_register_session_to_session_table( - session_table_entry, session)) { - _pi_http_init_session_table_entry(session_table_entry); - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - - g_object_set(session, SOUP_SESSION_MAX_CONNS, MAX_SESSION_COUNT, NULL); - /* Set timeout unlimited time to resume a download which has ETag when the network is re-connected - * => This is changed to 180 seconds due to limitation of max downloading items. - */ - g_object_set(session, SOUP_SESSION_TIMEOUT, MAX_TIMEOUT, NULL); - - _set_proxy_on_soup_session(session, input_for_tranx->proxy_addr); - - switch (pi_http_method) { - case PI_HTTP_METHOD_GET: - msg = soup_message_new(METHOD_GET, url); - break; - case PI_HTTP_METHOD_POST: - msg = soup_message_new(METHOD_POST, url); - break; - case PI_HTTP_METHOD_HEAD: - msg = soup_message_new(METHOD_HEAD, url); - break; - default: - DA_LOG_ERR(HTTPManager,"Cannot enter here"); - break; - } - DA_LOG(HTTPManager,"msg[%p]", msg); - /* if it is failed to create a msg, the url can be invalid, becasue of the input argument of soup_message_new API */ - if (msg == NULL) { - DA_LOG_ERR(HTTPManager,"Fail to create message"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - _fill_soup_msg_header(msg, input_for_tranx); - - g_signal_connect(msg, "restarted", G_CALLBACK(_pi_http_restarted_cb), - NULL); /* for redirection case */ - g_signal_connect(msg, "got-headers", - G_CALLBACK(_pi_http_gotheaders_cb), NULL); - g_signal_connect(msg, "got-chunk", G_CALLBACK(_pi_http_gotchunk_cb), - NULL); - - if (using_content_sniffing) { - soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_SNIFFER); - g_signal_connect(msg, "content-sniffed", - G_CALLBACK(_pi_http_contentsniffed_cb), NULL); - } else { - soup_message_disable_feature(msg, SOUP_TYPE_CONTENT_SNIFFER); - } - - soup_session_queue_message(session, msg, _pi_http_finished_cb, NULL); -// g_signal_connect(msg, "finished", G_CALLBACK(_pi_http_finished_cb), NULL); - - if (DA_FALSE == _pi_http_register_msg_to_session_table( - session_table_entry, msg)) { - _pi_http_destroy_session_table_entry(session_table_entry); - ret = DA_ERR_ALREADY_MAX_DOWNLOAD; - goto ERR; - } - - *out_tranx_id = session_table_entry; - DA_LOG(HTTPManager,"*out_tranx_id = %d", *out_tranx_id); - -ERR: - return ret; -} - -da_result_t PI_http_disconnect_transaction(int in_tranx_id) -{ - da_result_t ret = DA_RESULT_OK; - int session_table_entry = -1; - - DA_LOG_FUNC_START(HTTPManager); - - DA_LOG(HTTPManager,"in_tranx_id = %d", in_tranx_id); - - session_table_entry = in_tranx_id; - - _pi_http_destroy_session_table_entry(session_table_entry); - - return ret; -} - -da_result_t PI_http_cancel_transaction(int in_tranx_id, da_bool_t abort_option) -{ - da_result_t ret = DA_RESULT_OK; - SoupSession *session; - SoupMessage *msg; - int session_table_entry = -1; - - DA_LOG_FUNC_START(HTTPManager); - - DA_LOG(HTTPManager,"in_tranx_id = %d", in_tranx_id); - - session_table_entry = in_tranx_id; - if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) { - DA_LOG_CRITICAL(HTTPManager,"not using session"); - return ret; - } - session = GET_SESSION_FROM_TABLE_ENTRY(session_table_entry); - msg = GET_MSG_FROM_TABLE_ENTRY(session_table_entry); - - if (DA_NULL == session) { - DA_LOG_ERR(HTTPManager,"invalid session = %p", session); - goto ERR; - } - - if (DA_NULL == msg) { - DA_LOG_ERR(HTTPManager,"invalid message = %p", msg); - goto ERR; - } - DA_LOG(HTTPManager,"Call soup cancel API : abort option[%d]",abort_option); - if (abort_option) - soup_session_abort(session); - else - soup_session_cancel_message(session, msg, SOUP_STATUS_CANCELLED); - DA_LOG(HTTPManager,"Call soup cancel API-Done"); -ERR: - return ret; -} - -void PI_http_pause_transaction(int transaction_id) -{ - int session_table_entry = -1; - pthread_mutex_t *mutex; - pthread_cond_t *cond; - - DA_LOG_FUNC_START(HTTPManager); - - DA_LOG(HTTPManager,"in_tranx_id = %d", transaction_id); - - session_table_entry = transaction_id; - - if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) - return; - - mutex = &(pi_session_table[session_table_entry].mutex); - cond = &(pi_session_table[session_table_entry].cond); - - _da_thread_mutex_lock (mutex); - - if (pi_session_table[session_table_entry].is_paused == DA_FALSE) { - DA_LOG_CRITICAL(HTTPManager,"paused!"); - pi_session_table[session_table_entry].is_paused = DA_TRUE; - _da_thread_cond_wait(cond, mutex); - } else { - DA_LOG_CRITICAL(HTTPManager,"NOT paused!"); - } - - _da_thread_mutex_unlock (mutex); - -} - -void PI_http_unpause_transaction(int transaction_id) -{ - int session_table_entry = -1; - pthread_mutex_t* mutex; - pthread_cond_t* cond; - - /* DA_LOG_FUNC_START(Default); */ - - session_table_entry = transaction_id; - - if (!_pi_http_is_this_session_table_entry_using(session_table_entry)) - return; - - mutex = &(pi_session_table[session_table_entry].mutex); - cond = &(pi_session_table[session_table_entry].cond); - - _da_thread_mutex_lock (mutex); - - if (pi_session_table[session_table_entry].is_paused == DA_TRUE) { - DA_LOG_CRITICAL(HTTPManager,"wake up!"); - pi_session_table[session_table_entry].is_paused = DA_FALSE; - _da_thread_cond_signal(cond); - } - - _da_thread_mutex_unlock (mutex); - -} - -da_bool_t _pi_http_is_valid_input_for_tranx( - const input_for_tranx_t *input_for_tranx) -{ - if (!(input_for_tranx->http_msg_request)) { - DA_LOG_ERR(HTTPManager,"http_msg_request is NULL"); - return DA_FALSE; - } - - if (!((input_for_tranx->http_method == PI_HTTP_METHOD_GET) || - (input_for_tranx->http_method == PI_HTTP_METHOD_POST) || - (input_for_tranx->http_method == PI_HTTP_METHOD_HEAD))) { - DA_LOG_ERR(HTTPManager,"http_method is neither GET or POST or HEAD"); - return DA_FALSE; - } - - return DA_TRUE; -} - -da_bool_t _pi_http_is_this_session_table_entry_using( - const int in_session_table_entry) -{ - da_bool_t is_using = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(in_session_table_entry)) - return DA_FALSE; - - _da_thread_mutex_lock (&mutex_for_session_table); - - is_using = pi_session_table[in_session_table_entry].is_using; - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return is_using; -} - -void _pi_http_init_session_table_entry(const int in_session_table_entry) -{ - int entry = in_session_table_entry; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) - return; - -// _da_thread_mutex_lock (&mutex_for_session_table); - - pi_session_table[entry].is_using = DA_TRUE; - pi_session_table[entry].msg = NULL; - pi_session_table[entry].session = NULL; - pi_session_table[entry].queue = NULL; - - _da_thread_mutex_init(&(pi_session_table[entry].mutex), DA_NULL); - _da_thread_cond_init(&(pi_session_table[entry].cond), NULL); - pi_session_table[entry].is_paused = DA_FALSE; - -// _da_thread_mutex_unlock (&mutex_for_session_table); - - return; -} - -void _pi_http_destroy_session_table_entry(const int in_session_table_entry) -{ - int entry = in_session_table_entry; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) - return; - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_paused == DA_TRUE) - PI_http_unpause_transaction(entry); - - /* Warning! Do not g_object_unref(msg) here! - * soup_session_queue_message() steals msg's reference count, - * so, we don't need to do anything for memory management. - * - * But, if using soup_session_send_message(), MUST call g_object_unref(msg). */ - /* if (pi_session_table[entry].msg) - g_object_unref(pi_session_table[entry].msg); */ - - pi_session_table[entry].msg = NULL; - - /* FIXME Cannot g_object_unref(session) here, - * because msg inside this session is not destoryed yet. - * The msg's reference count is stealed by soup_session_queue_message(), - * and it will be destroyed when _pi_http_finished_cb() is returned. - * For now, this _pi_http_destroy_session_table_entry() is called inside - * _pi_http_finished_cb(), so, g_object_unref(session) is not working. - * Should find out call this function after _pi_http_finished_cb(). */ - if (pi_session_table[entry].session) - g_object_unref(pi_session_table[entry].session); - else - DA_LOG_ERR(HTTPManager,"session is NULL. Cannot unref this."); - DA_LOG(HTTPManager,"unref session [%p]",pi_session_table[entry].session); - - pi_session_table[entry].session = NULL; - - pi_session_table[entry].queue = NULL; - pi_session_table[entry].is_paused = DA_FALSE; - pi_session_table[entry].is_using = DA_FALSE; - - _da_thread_mutex_destroy(&(pi_session_table[entry].mutex)); - _da_thread_cond_destroy(&(pi_session_table[entry].cond)); - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return; -} - -int _pi_http_get_avaiable_session_table_entry(void) -{ - int i; - int avaiable_entry = -1; - - _da_thread_mutex_lock (&mutex_for_session_table); - - for (i = 0; i < MAX_SESSION_COUNT; i++) { - if (pi_session_table[i].is_using == DA_FALSE) { - /* pi_session_table[i].is_using = DA_TRUE; */ - DA_LOG(HTTPManager,"available entry = %d", i); - - avaiable_entry = i; - - break; - } - } - _pi_http_init_session_table_entry(avaiable_entry); - _da_thread_mutex_unlock (&mutex_for_session_table); - - return avaiable_entry; -} - -da_bool_t _pi_http_register_queue_to_session_table( - const int in_session_table_entry, const queue_t *in_queue) -{ - int entry = in_session_table_entry; - queue_t *queue = (queue_t *) in_queue; - da_bool_t ret = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return DA_FALSE; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_using == DA_FALSE) { - DA_LOG_ERR(HTTPManager,"this entry [%d] is not using", entry); - ret = DA_FALSE; - } else { - pi_session_table[entry].queue = queue; - DA_LOG(HTTPManager,"queue = %p", pi_session_table[entry].queue); - ret = DA_TRUE; - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return ret; -} - -da_bool_t _pi_http_register_session_to_session_table( - const int in_session_table_entry, SoupSession *session) -{ - int entry = in_session_table_entry; - da_bool_t ret = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return DA_FALSE; - } - - if (DA_NULL == session) { - DA_LOG_ERR(HTTPManager,"invalid session = %p",session); - return DA_FALSE; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_using == DA_FALSE) { - ret = DA_FALSE; - } else { - pi_session_table[entry].session = session; - ret = DA_TRUE; - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return ret; -} - -da_bool_t _pi_http_register_msg_to_session_table( - const int in_session_table_entry, SoupMessage *msg) -{ - int entry = in_session_table_entry; - da_bool_t ret = DA_FALSE; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return DA_FALSE; - } - - if (DA_NULL == msg) { - DA_LOG_ERR(HTTPManager,"invalid msg = %p",msg); - return DA_FALSE; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - if (pi_session_table[entry].is_using == DA_FALSE) { - ret = DA_FALSE; - } else { - pi_session_table[entry].msg = msg; - ret = DA_TRUE; - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - return ret; -} - -queue_t *_pi_http_get_queue_from_session_table_entry( - const int in_session_table_entry) -{ - int entry = in_session_table_entry; - queue_t *out_queue = NULL; - - if (DA_FALSE == IS_VALID_SESSION_TABLE_ENTRY(entry)) { - DA_LOG_ERR(HTTPManager,"invalid entry = %d", entry); - return out_queue; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - out_queue = pi_session_table[entry].queue; - _da_thread_mutex_unlock (&mutex_for_session_table); - - return out_queue; -} - -void _pi_http_store_read_header_to_queue(SoupMessage *msg, const char *sniffedType) -{ - da_result_t ret = DA_RESULT_OK; - - queue_t *da_queue = NULL; - q_event_t *da_event = NULL; - q_event_type_data da_event_type_data; - - int session_table_entry = -1; - SoupMessageHeadersIter headers_iter; - - const char *header_name; - const char *header_value; - - http_msg_response_t *http_msg_response = NULL; - - /* DA_LOG_FUNC_START(Default); */ - - if (msg->response_headers) { - ret = http_msg_response_create(&http_msg_response); - if (ret != DA_RESULT_OK) - return; - - http_msg_response_set_status_code(http_msg_response, - msg->status_code); - - DA_LOG(HTTPManager,"\n----raw header---------------------------------------------"); - DA_LOG_CRITICAL(HTTPManager,"status code = %d", msg->status_code); - soup_message_headers_iter_init(&headers_iter, - msg->response_headers); - while (soup_message_headers_iter_next(&headers_iter, - &header_name, &header_value)) { - if ((header_name != DA_NULL) && (header_value - != DA_NULL)) { - http_msg_response_add_field(http_msg_response, - header_name, header_value); - } - } - DA_LOG(HTTPManager,"\n-------------------------------------------------------------\n"); - - } - - if (using_content_sniffing && sniffedType) - http_msg_response_set_content_type(http_msg_response, sniffedType); - - session_table_entry - = _pi_http_get_session_table_entry_from_message(msg); - if (session_table_entry == -1) { - DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - da_event_type_data = Q_EVENT_TYPE_DATA_PACKET; - - da_queue = _pi_http_get_queue_from_session_table_entry( - session_table_entry); - - ret = Q_make_http_data_event(da_event_type_data, &da_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager,"fail to make da_event"); - goto ERR; - } else { - Q_set_status_code_on_http_data_event(da_event, msg->status_code); - da_event->type.q_event_data_http.http_response_msg - = http_msg_response; - - Q_push_event(da_queue, da_event); - } - return; - -ERR: - if (DA_RESULT_OK != ret) - http_msg_response_destroy(&http_msg_response); - - return; -} - -void _pi_http_store_read_data_to_queue(SoupMessage *msg, const char* body_data, - int received_body_len) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - char *body_buffer = NULL; - queue_t *da_queue = NULL; - q_event_t *da_event = NULL; - q_event_type_data da_event_type_data; - int session_table_entry = -1; - int http_status = -1; - - /* DA_LOG_FUNC_START(Default); */ - - http_status = msg->status_code; - - session_table_entry - = _pi_http_get_session_table_entry_from_message(msg); - if (session_table_entry == -1) { - DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - if (received_body_len == 0) { - DA_LOG(HTTPManager,"Q_EVENT_TYPE_DATA_FINAL"); - da_event_type_data = Q_EVENT_TYPE_DATA_FINAL; - } else { - da_event_type_data = Q_EVENT_TYPE_DATA_PACKET; - if (received_body_len > 0) { - body_buffer = (char*) calloc(1, received_body_len); - DA_LOG(HTTPManager,"body_buffer[%p]msg[%p]",body_buffer,msg); - if (body_buffer == DA_NULL) { - DA_LOG_ERR(HTTPManager,"DA_ERR_FAIL_TO_MEMALLOC"); - goto ERR; - } - memcpy(body_buffer, body_data, received_body_len); - } - } - - da_queue = _pi_http_get_queue_from_session_table_entry( - session_table_entry); - - ret = Q_make_http_data_event(da_event_type_data, &da_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager,"fail to make da_event"); - goto ERR; - } else { - Q_set_status_code_on_http_data_event(da_event, http_status); - Q_set_http_body_on_http_data_event(da_event, received_body_len, - body_buffer); - - _da_thread_mutex_lock (&(da_queue->mutex_queue)); - b_ret = Q_push_event_without_lock(da_queue, da_event); - if (b_ret == DA_FALSE) { - DA_LOG_CRITICAL(HTTPManager,"----------------------------------------fail to push!"); - - pthread_mutex_t *session_mutex = NULL; - pthread_cond_t *session_cond = NULL; - - session_mutex - = &(pi_session_table[session_table_entry].mutex); - session_cond - = &(pi_session_table[session_table_entry].cond); - - /* MUST keep this order for these mutexes */ - _da_thread_mutex_lock (session_mutex); - _da_thread_mutex_unlock (&(da_queue->mutex_queue)); - - if (pi_session_table[session_table_entry].is_paused - == DA_FALSE) { - DA_LOG_CRITICAL(HTTPManager,"paused!"); - pi_session_table[session_table_entry].is_paused - = DA_TRUE; - _da_thread_cond_wait(session_cond, session_mutex); - } else { - DA_LOG_CRITICAL(HTTPManager,"NOT paused!"); - } - - _da_thread_mutex_unlock (session_mutex); - - DA_LOG_CRITICAL(HTTPManager,"wake up! push again"); - Q_push_event(da_queue, da_event); - } else { - _da_thread_mutex_unlock (&(da_queue->mutex_queue)); - } - - } - - return; - -ERR: - if (DA_RESULT_OK != ret) { - if (DA_NULL != body_buffer) { - free(body_buffer); - } - } - - return; -} - -int _translate_error_code(int soup_error) -{ - switch (soup_error) { - case SOUP_STATUS_CANT_RESOLVE: - case SOUP_STATUS_CANT_RESOLVE_PROXY: - case SOUP_STATUS_CANT_CONNECT: - case SOUP_STATUS_CANT_CONNECT_PROXY: - case SOUP_STATUS_IO_ERROR: - case SOUP_STATUS_MALFORMED: - case SOUP_STATUS_TRY_AGAIN: - case SOUP_STATUS_TOO_MANY_REDIRECTS: - return DA_ERR_NETWORK_FAIL; - - case SOUP_STATUS_SSL_FAILED: - return DA_ERR_SSL_FAIL; - - default: - return DA_RESULT_OK; - } -} - -void _pi_http_store_neterr_to_queue(SoupMessage *msg) -{ - da_result_t ret = DA_RESULT_OK; - int error_type = -1; - queue_t *da_queue = NULL; - q_event_t *da_event = NULL; - int session_table_entry = -1; - - DA_LOG_FUNC_START(HTTPManager); - - error_type = _translate_error_code(msg->status_code); - - session_table_entry - = _pi_http_get_session_table_entry_from_message(msg); - if (session_table_entry == -1) { - DA_LOG_ERR(HTTPManager,"Fail to find matched session table entry.."); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - - da_queue = _pi_http_get_queue_from_session_table_entry( - session_table_entry); - - DA_LOG_CRITICAL(HTTPManager,"Q_EVENT_TYPE_DATA_ABORT"); - ret = Q_make_http_data_event(Q_EVENT_TYPE_DATA_ABORT, &da_event); - if (ret != DA_RESULT_OK) { - DA_LOG_ERR(HTTPManager,"fail to make da_event"); - goto ERR; - } else { - Q_set_error_type_on_http_data_event(da_event, error_type); - - Q_push_event(da_queue, da_event); - } - -ERR: - return; -} - -int _pi_http_get_session_table_entry_from_message(SoupMessage *msg) -{ - - int out_entry = -1; - int i; - - if (DA_NULL == msg) { - DA_LOG_ERR(HTTPManager,"invalid message = %p", msg); - return out_entry; - } - - _da_thread_mutex_lock (&mutex_for_session_table); - - for (i = 0; i < MAX_SESSION_COUNT; i++) { - if (pi_session_table[i].is_using == DA_TRUE) { - if (pi_session_table[i].msg == msg) { - out_entry = i; - break; - } - } - } - - _da_thread_mutex_unlock (&mutex_for_session_table); - - if (i == MAX_SESSION_COUNT) { - DA_LOG_ERR(HTTPManager,"fail to find message = %p", msg); - } - - return out_entry; - -} - -void _pi_http_finished_cb(SoupSession *session, SoupMessage *msg, gpointer data) -{ - char *url = NULL; - - DA_LOG_FUNC_START(HTTPManager); - - url = soup_uri_to_string(soup_message_get_uri(msg), DA_FALSE); - - DA_LOG(HTTPManager,"status_code[%d], reason[%s], url[%s]",msg->status_code,msg->reason_phrase,url); - - if (url) { - free(url); - url = NULL; - } - - if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { - if (msg->status_code == SOUP_STATUS_CANCELLED) { - _pi_http_store_read_data_to_queue(msg, DA_NULL, 0); - } else { - _pi_http_store_neterr_to_queue(msg); - } - } else { - _pi_http_store_read_data_to_queue(msg, DA_NULL, 0); - } - -} - -/* this callback is called in case of redirection */ -void _pi_http_restarted_cb(SoupMessage *msg, gpointer data) -{ - DA_LOG_FUNC_START(HTTPManager); - /* Location URL is needed when extracting the file name from url. - * So, the response header should be handled by http mgr.*/ - _pi_http_store_read_header_to_queue(msg, NULL); -} - -void _pi_http_gotheaders_cb(SoupMessage *msg, gpointer data) -{ - DA_LOG_FUNC_START(HTTPManager); - - if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) { - DA_LOG(HTTPManager,"Redirection !!"); - if (SOUP_STATUS_NOT_MODIFIED != msg->status_code) - return; - } - - soup_message_body_set_accumulate(msg->response_body, FALSE); - - if (!using_content_sniffing) - _pi_http_store_read_header_to_queue(msg, NULL); - else - DA_LOG(HTTPManager,"ignore because content sniffing is turned on"); -} - -void _pi_http_contentsniffed_cb(SoupMessage *msg, const char *sniffedType, - GHashTable *params, gpointer data) -{ - DA_LOG_FUNC_START(HTTPManager); - - if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) { - DA_LOG(HTTPManager,"Redirection !!"); - if (SOUP_STATUS_NOT_MODIFIED != msg->status_code) - return; - } - - if (using_content_sniffing) - _pi_http_store_read_header_to_queue(msg, sniffedType); -} - -void _pi_http_gotchunk_cb(SoupMessage *msg, SoupBuffer *chunk, gpointer data) -{ - DA_LOG_FUNC_START(HTTPManager); - - if (SOUP_STATUS_IS_REDIRECTION(msg->status_code)) - return; - - if (chunk->data && chunk->length > 0) { - _pi_http_store_read_data_to_queue(msg, chunk->data, - chunk->length); - } -} - diff --git a/src/agent/download-agent-utils-dl-req-id-history.c b/src/agent/download-agent-utils-dl-req-id-history.c deleted file mode 100644 index 35ab700..0000000 --- a/src/agent/download-agent-utils-dl-req-id-history.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-utils-dl-req-id-history.c - * @brief Including operations for dl-req-id-history - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#include "download-agent-type.h" -#include "download-agent-utils.h" -#include "download-agent-utils-dl-req-id-history.h" - -da_result_t init_dl_req_id_history(dl_req_id_history_t *dl_req_id_history) -{ - da_result_t ret = DA_RESULT_OK; - - /* Initial dl_req_id_history will be starting number for dl_req_id. - * dl_req_id will be sequentially increased from the dl_req_id_history, - * then dl_req_id_history will be updated. */ - _da_thread_mutex_init(&(dl_req_id_history->mutex), DA_NULL); - _da_thread_mutex_lock(&(dl_req_id_history->mutex)); - get_random_number(&(dl_req_id_history->starting_num)); - dl_req_id_history->cur_dl_req_id = DA_INVALID_ID; - _da_thread_mutex_unlock(&(dl_req_id_history->mutex)); - - DA_LOG_CRITICAL(Default,"starting num = %d", dl_req_id_history->starting_num); - return ret; -} - -da_result_t deinit_dl_req_id_history(dl_req_id_history_t *dl_req_id_history) -{ - da_result_t ret = DA_RESULT_OK; - - _da_thread_mutex_lock(&(dl_req_id_history->mutex)); - dl_req_id_history->starting_num = DA_INVALID_ID; - dl_req_id_history->cur_dl_req_id = DA_INVALID_ID; - _da_thread_mutex_unlock(&(dl_req_id_history->mutex)); - - _da_thread_mutex_destroy(&(dl_req_id_history->mutex)); - - return ret; -} - -int get_available_dl_req_id(dl_req_id_history_t *dl_req_id_history) -{ - int dl_req_id = 0; - - _da_thread_mutex_lock(&(dl_req_id_history->mutex)); - - if (dl_req_id_history->cur_dl_req_id == DA_INVALID_ID) - dl_req_id_history->cur_dl_req_id = dl_req_id_history->starting_num; - else if (dl_req_id_history->cur_dl_req_id > 254) - dl_req_id_history->cur_dl_req_id = 1; - else - dl_req_id_history->cur_dl_req_id++; - - dl_req_id = dl_req_id_history->cur_dl_req_id; - - _da_thread_mutex_unlock(&(dl_req_id_history->mutex)); - - DA_LOG_CRITICAL(Default,"dl_req_id = %d", dl_req_id); - return dl_req_id; -} diff --git a/src/agent/download-agent-utils.c b/src/agent/download-agent-utils.c deleted file mode 100644 index 662ca00..0000000 --- a/src/agent/download-agent-utils.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-utils.c - * @brief Including some utilitis - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "download-agent-client-mgr.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-file.h" -#include "download-agent-http-misc.h" -#include "download-agent-mime-util.h" -#include "download-agent-utils.h" -#include "download-agent-plugin-conf.h" -#include "download-agent-plugin-install.h" -#include "download-agent-dl-info-util.h" - -#define DA_HTTP_HEADER_CONTENT_TYPE "Content-Type" -#define DA_HTTP_HEADER_CONTENT_LENGTH "Content-Length" -#define DA_FILE_NUMBER_LIMIT (1024*1024) -// Addition or deletion of entries in this list should be in sync with the -// enumaration download_content_t defined in download-agent-dl-mgr.h - -void get_random_number(int *out_num) -{ - int temp = DA_INVALID_ID; - unsigned int seed = (unsigned)time(0); - - temp = (int)(rand_r(&seed) % 100 + 1.0); - *out_num = temp; -} - -da_result_t get_extension_from_mime_type(char *mime_type, char **extension) -{ - da_result_t ret = DA_RESULT_OK; - char *ext = DA_NULL; - - DA_LOG_FUNC_START(Default); - if (DA_NULL == mime_type || DA_NULL == extension) { - DA_LOG_ERR(Default,"received mime_type is null"); - ret = DA_ERR_INVALID_ARGUMENT; - goto ERR; - } - DA_LOG(Default,"input mime type = %s", mime_type); - if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) { - DA_LOG_ERR(Default,"can't find proper extension!"); - goto ERR; - } - *extension = ext; - DA_LOG(Default,"found extension = %s", *extension); - -ERR: - return ret; -} - -int read_data_from_file(char *file, char **out_buffer) -{ - FILE *fd; - int file_size = -1; - char *buffer = NULL; - int buffer_len = 0; - int read_len = 0; - - *out_buffer = NULL; - - if (!file) - return 0; - - /* open file with "rb", because fread() handles the file as binary mode */ - fd = fopen(file, "rb"); - if (!fd) { - DA_LOG_ERR(FileManager,"File open err! received file path = [%s]", file); - return 0; - } - - get_file_size(file, &file_size); - if (file_size <= 0) { - DA_LOG_ERR(FileManager,"file size is [%d]", file_size); - fclose(fd); - return 0; - } - - /* A guide from www.securecoding.cert.org - * : FIO17-C. Do not rely on an ending null character when using fread() - * - * buffer is initialized with null through calloc(), so, it is always null-terminated even if fread() failed. - * allocate memory one more byte to ensure null-terminated even if the file is not null-terminated. - */ - buffer_len = sizeof(char) * file_size; - buffer = (char *)calloc(1, buffer_len + 1); - if (buffer) { - read_len = fread(buffer, sizeof(char), file_size, fd); - if (read_len == file_size) { - *out_buffer = buffer; - } else { - DA_LOG_ERR(FileManager,"File Read Not Complete read length = %d", read_len); - free(buffer); - buffer = NULL; - buffer_len = 0; - } - } else { - buffer_len = 0; - } - - fclose(fd); - - return buffer_len; -} - -da_result_t check_enough_storage(stage_info *stage) -{ - da_result_t ret = DA_RESULT_OK; - unsigned long cont_size = 0; - da_storage_size_t avail_memory = {0, }; - da_storage_type_t type = DA_STORAGE_PHONE; - - DA_LOG_FUNC_START(Default); - - /* check enough storage here because of multiple download */ - ret = get_storage_type(&type); - if (DA_RESULT_OK != ret) - return ret; - - cont_size - = GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage)); - - DA_LOG(Default,"cont_size [%d]", cont_size); - if (cont_size) { - ret = get_available_memory(DA_STORAGE_PHONE, &avail_memory); - if (DA_RESULT_OK == ret && (avail_memory.b_available - < ((cont_size + SAVE_FILE_BUFFERING_SIZE_5MB) - / avail_memory.b_size))) /* 5MB buffering */ - { - DA_LOG_ERR(Default,"There is no space for content in Phone memory"); - return DA_ERR_DISK_FULL; - } else if (DA_RESULT_OK != ret) { - return ret; - } - /* If default memeory type is mmc, - * it need to check phone memroy for temproary folder - * and mmc memory for actual install folder */ - if (type == DA_STORAGE_MMC) { - DA_LOG(Default,"Storage type == DA_STORAGE_MMC\n"); - ret = get_available_memory(type, &avail_memory); - if (DA_RESULT_OK == ret && (avail_memory.b_available - < ((cont_size + SAVE_FILE_BUFFERING_SIZE_50KB) - / avail_memory.b_size))) /* 50KB buffering */ - { - DA_LOG_ERR(Default,"There is no space for content in MMC memory"); - return DA_ERR_DISK_FULL; - } else if (DA_RESULT_OK != ret) { - return ret; - } - } - } - - return ret; -} - -da_result_t get_available_memory( - da_storage_type_t storage_type, - da_storage_size_t *avail_memory) -{ - int fs_ret = 0; - struct statfs filesys_info = {0, }; - - DA_LOG_FUNC_START(Default); - - if (!avail_memory) - return DA_ERR_INVALID_ARGUMENT; - - if (storage_type == DA_STORAGE_PHONE) { - fs_ret = statfs(DA_DEFAULT_TMP_FILE_DIR_PATH, &filesys_info); - } else if (storage_type == DA_STORAGE_MMC) { - char *default_install_dir = NULL; - default_install_dir = PI_get_default_install_dir(); - if (default_install_dir) { - fs_ret = statfs(default_install_dir, &filesys_info); - } else { - return DA_ERR_FAIL_TO_ACCESS_STORAGE; - } - } else { - DA_LOG_ERR(Default,"Invalid storage type"); - return DA_ERR_INVALID_ARGUMENT; - } - - if (fs_ret != 0) { - DA_LOG_ERR(Default,"Phone file path :statfs error - [%d]", errno); - return DA_ERR_FAIL_TO_ACCESS_FILE; - } - - avail_memory->b_available = filesys_info.f_bavail; - avail_memory->b_size = filesys_info.f_bsize; - - DA_LOG(Default, "Memory type : %d", storage_type); - DA_LOG(Default, "Available Memory(f_bavail) : %lu", filesys_info.f_bavail); - DA_LOG(Default, "Available Memory(f_bsize) : %d", filesys_info.f_bsize); - DA_LOG(Default, "Available Memory(kbytes) : %lu", (filesys_info.f_bavail/1024)*filesys_info.f_bsize); - - return DA_RESULT_OK; -} - -da_bool_t is_valid_url(const char* url, da_result_t *err_code) -{ - da_result_t ret = DA_RESULT_OK; - da_bool_t b_ret = DA_FALSE; - - int wanted_str_len = 0; - char *wanted_str = NULL; - char *wanted_str_start = NULL; - char *wanted_str_end = NULL; - - if ((DA_NULL == url) || (1 > strlen(url))) { - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - wanted_str_start = (char*)url; - wanted_str_end = strstr(url, "://"); - if (!wanted_str_end) { - DA_LOG_ERR(Default,"No protocol on this url"); - ret = DA_ERR_INVALID_URL; - goto ERR; - } - - wanted_str_len = wanted_str_end - wanted_str_start; - wanted_str = (char*)calloc(1, wanted_str_len + 1); - if (!wanted_str) { - DA_LOG_ERR(Default,"DA_ERR_FAIL_TO_MEMALLOC"); - ret = DA_ERR_FAIL_TO_MEMALLOC; - goto ERR; - } - strncpy(wanted_str, wanted_str_start, wanted_str_len); - - b_ret = is_supporting_protocol(wanted_str); - if (!b_ret) { - ret = DA_ERR_UNSUPPORTED_PROTOCAL; - goto ERR; - } - -ERR: - if (wanted_str) { - free(wanted_str); - wanted_str = NULL; - } - - if (err_code) - *err_code = ret; - - return b_ret; -} - -da_result_t move_file(const char *from_path, const char *to_path) -{ - da_result_t ret = DA_RESULT_OK; - - if (!from_path || !to_path) - return DA_ERR_INVALID_ARGUMENT; - - if (rename(from_path, to_path) != 0) { - DA_LOG_CRITICAL(FileManager,"rename failed : syserr[%d]",errno); - if (errno == EXDEV) { - DA_LOG_CRITICAL(FileManager,"File system is diffrent. Try to copy a file"); - ret = copy_file(from_path, to_path); - if (ret == DA_RESULT_OK) { - remove_file(from_path); - } else { - if (is_file_exist(to_path)) - remove_file(to_path); - ret = DA_ERR_FAIL_TO_INSTALL_FILE; - } - } else { - ret = DA_ERR_FAIL_TO_INSTALL_FILE; - } - } - return ret; -} - -void remove_file(const char *file_path) -{ - DA_LOG_FUNC_START(FileManager); - - if (file_path) { - DA_LOG(FileManager,"remove file [%s]", file_path); - if (unlink(file_path) < 0) { - DA_LOG_ERR(FileManager,"file removing failed."); - } - } -} - -char *print_dl_state(da_state state) -{ - switch (state) { - case DA_STATE_WAITING: - return "DA_STATE_WAITING"; - case DA_STATE_DOWNLOAD_STARTED: - return "DA_STATE_DOWNLOAD_STARTED"; - case DA_STATE_DOWNLOADING: - return "DA_STATE_DOWNLOADING"; - case DA_STATE_DOWNLOAD_COMPLETE: - return "DA_STATE_DOWNLOAD_COMPLETE"; - case DA_STATE_FINISHED: - return "DA_STATE_FINISHED"; - case DA_STATE_CANCELED: - return "DA_STATE_CANCELED"; - case DA_STATE_CANCELED_ALL: - return "DA_STATE_CANCELED_ALL"; - case DA_STATE_SUSPENDED: - return "DA_STATE_SUSPENDED"; - case DA_STATE_SUSPENDED_ALL: - return "DA_STATE_SUSPENDED_ALL"; - case DA_STATE_RESUMED: - return "DA_STATE_RESUMED"; - case DA_STATE_FAILED: - return "DA_STATE_FAILED"; - default: - return "STATE ERROR"; - - } -} - diff --git a/src/agent/include/download-agent-basic.h b/src/agent/include/download-agent-basic.h deleted file mode 100644 index 7c27dec..0000000 --- a/src/agent/include/download-agent-basic.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-basic.h - * @brief - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_Basic_H -#define _Download_Agent_Basic_H - -#include - -#include "download-agent-type.h" -#include "download-agent-interface.h" -#include "download-agent-dl-mgr.h" - -typedef struct _extension_data_t { - const char **request_header; - const int *request_header_count; - const char *install_path; - const char *file_name; - void *user_data; -} extension_data_t; - -da_result_t start_download(const char* url, da_handle_t *dl_req_id); -da_result_t start_download_with_extension(const char *url , da_handle_t *dl_req_id, extension_data_t *extension_data); - -#endif diff --git a/src/agent/include/download-agent-client-mgr.h b/src/agent/include/download-agent-client-mgr.h deleted file mode 100644 index 2ac50ee..0000000 --- a/src/agent/include/download-agent-client-mgr.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-client-mgr.h - * @brief - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_Client_Mgr_H -#define _Download_Agent_Client_Mgr_H - -#include - -#include "download-agent-type.h" -#include "download-agent-interface.h" - -#include "download-agent-pthread.h" - -typedef enum { - Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO, - Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO, - Q_CLIENT_NOTI_TYPE_SEND_STATE, - Q_CLIENT_NOTI_TYPE_TERMINATE, -} client_noti_type; - -typedef struct _client_noti_t client_noti_t; -struct _client_noti_t { - int download_id; - void *user_data; - client_noti_type noti_type; - union _client_type { - user_download_info_t update_dl_info ; - user_downloading_info_t update_downloading_info ; - user_notify_info_t da_state_info ; - } type; - - client_noti_t *next; -}; - -typedef struct _client_queue_t { - da_bool_t having_data; - client_noti_t *client_q_head; - pthread_mutex_t mutex_client_queue; - pthread_cond_t cond_client_queue; -} client_queue_t; - -typedef struct _client_app_info_t { - da_bool_t is_using; - da_bool_t is_manual_download; - da_client_cb_t client_callback; - char *client_user_agent; -} client_app_info_t; - -typedef struct _client_app_mgr_t { - da_bool_t is_init; - da_bool_t is_manual_download; - client_queue_t client_queue; - client_app_info_t client_app_info; - pthread_t thread_id; - da_bool_t is_thread_init; - pthread_mutex_t mutex_client_mgr; -} client_app_mgr_t; - -da_result_t init_client_app_mgr(void); -da_bool_t is_client_app_mgr_init(void); - -da_result_t reg_client_app(da_client_cb_t *da_client_callback, - da_download_managing_method download_method); -da_result_t dereg_client_app(void); - -da_result_t send_client_da_state (int download_id, da_state state, int err); -da_result_t send_client_update_dl_info (int download_id, int dl_req_id, - char *file_type, unsigned long int file_size, char *tmp_saved_path, - char *http_response_header, char *http_raw_data); -da_result_t send_client_update_downloading_info (int download_id, int dl_req_id, - unsigned long int total_received_size, char *saved_path); - -da_result_t get_client_download_path(char **out_path); -char *get_client_user_agent_string(void); - -da_bool_t is_this_client_available(void); -da_bool_t is_this_client_manual_download_type(void); - -void push_client_noti(client_noti_t *client_noti); - -#endif diff --git a/src/agent/include/download-agent-debug.h b/src/agent/include/download-agent-debug.h deleted file mode 100644 index 5f89fa4..0000000 --- a/src/agent/include/download-agent-debug.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-debug.h - * @brief Including some debug utilitis - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_Debug_H -#define _Download_Agent_Debug_H - -#include "download-agent-type.h" - -#define DA_DEBUG_ENV_KEY "DOWNLOAD_AGENT_DEBUG" -#define DA_DEBUG_CONFIG_FILE_PATH "/tmp/.download_agent.conf" - -#define IS_LOG_ON(channel) (DALogBitMap & (0x1<<(channel))) - -typedef enum { - Soup, - HTTPManager, - InstallManager, - FileManager, - DownloadManager, - ClientNoti, - HTTPMessageHandler, - Encoding, - QueueManager, - Parsing, - Thread, - Default, - DA_LOG_CHANNEL_MAX -} da_log_channel; - -extern int DALogBitMap; - -da_result_t init_log_mgr(void); - -#ifdef NODEBUG - #define DA_LOG(channel, format, ...) ((void)0) - #define DA_LOG_CRITICAL(channel, format, ...) ((void)0) - #define DA_LOG_VERBOSE(channel, format, ...) ((void)0) - #define DA_LOG_ERR(channel, format, ...) ((void)0) - #define DA_LOG_FUNC_START(channel, ...) ((void)0) - -#else /* NODEBUG */ -#include -#include -#include - -#ifdef DA_DEBUG_USING_DLOG - #include - #ifdef LOG_TAG - #undef LOG_TAG - #endif /* LOG_TAG */ - #define LOG_TAG "DownloadAgent" - - #define DA_LOG(channel, format, ...) LOGD_IF(IS_LOG_ON(channel), "[%s] "format"\n", __FUNCTION__, ##__VA_ARGS__); - #define DA_LOG_CRITICAL(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), "[%s] "format"\n", __FUNCTION__, ##__VA_ARGS__); - #define DA_LOG_VERBOSE(channel, format, ...) LOGV_IF(IS_LOG_ON(channel), "[%s] "format"\n", __FUNCTION__, ##__VA_ARGS__); - #define DA_LOG_ERR(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), "[%s] ERR! "format"\n", __FUNCTION__, ##__VA_ARGS__); - #define DA_LOG_FUNC_START(channel, ...) LOGV_IF(IS_LOG_ON(channel), "[%s] starting... \n", __FUNCTION__); -#else /* DA_DEBUG_USING_DLOG */ - #include - #include - - #define DA_LOG(channel, format, ...) do {\ - IS_LOG_ON(channel) \ - ? fprintf(stderr, "[DA][%u][%s(): %d] "format"\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__) \ - : ((void)0);\ - }while(0) - #define DA_LOG_ERR(channel, format, ...) do {\ - IS_LOG_ON(channel) \ - ? fprintf(stderr, "[DA][%u][ERR][%s(): %d]\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__, ##__VA_ARGS__) \ - : ((void)0); \ - }while(0) - #define DA_LOG_FUNC_START(channel, ...) do {\ - IS_LOG_ON(channel) \ - ? fprintf(stderr, "[DA][%u][%s(): %d] starting\n",(unsigned int)syscall(__NR_gettid), __FUNCTION__,__LINE__) \ - : ((void)0); \ - }while(0) - #define DA_LOG_CRITICAL DA_LOG - #define DA_LOG_VERBOSE DA_LOG -#endif /* DA_DEBUG_USING_DLOG */ -#endif /* NDEBUG */ -#endif /* _Download_Agent_Debug_H */ diff --git a/src/agent/include/download-agent-defs.h b/src/agent/include/download-agent-defs.h deleted file mode 100644 index 7c605e8..0000000 --- a/src/agent/include/download-agent-defs.h +++ /dev/null @@ -1,317 +0,0 @@ -/** - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-defs.h - * @brief including types and defines for Download Agent - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - */ - -#ifndef _Download_Agent_Defs_H -#define _Download_Agent_Defs_H - -/** - * @{ - */ -#ifndef DEPRECATED -#define DEPRECATED __attribute__((deprecated)) -#endif - -/** - * @ingroup Reference - */ -typedef int da_handle_t; - -/** - * @ingroup Reference - * Max count to download files simultaneously. \n - * Main reason for this restriction is because of Network bandwidth. - */ -#define DA_MAX_DOWNLOAD_REQ_AT_ONCE 5 - -/** - * @ingroup Reference - */ -#define DA_RESULT_OK 0 - -#define DA_TRUE 1 -#define DA_FALSE 0 -#define DA_NULL 0 -#define DA_INVALID_ID -1 - -/** - * @ingroup Reference - * special \c dl_req_id to indicate all \c dl_req_id on current status \n\n - * If client wants to do something (cancel/suspend/resume) for all \c dl_req_id, simply use this. \n - * This sends a command to all downloading threads on current status without any changes on state notification. \n - * That is, it is same with calling each dl_req_id separately. - * @see DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI - */ -#define DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS -1 -/** - * @ingroup Reference - * This is also indicates all \c dl_req_id, but it will not send state notification for each \c dl_req_id. \n - * Instead, DA_STATE_XXX_ALL will be sent. - * @see DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS - */ -#define DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI -2 -/** - * @} - */ - -/** - * @ingroup Reference - * @addtogroup ExtensionFeatures Extension features - * @{ - * @brief Download Agent's extension features using by da_start_download_with_extension() - * - * When calling \a da_start_download_with_extension function, use these defines for property name. \n - * -*/ -/** - * @fn DA_FEATURE_REQUEST_HEADER - * @brief receiving reqeust header for requesting URL on \a da_start_download_with_extension. - * @remarks - * property value type for this is 'char**'. - * value is valid if it has the string array which consist the name of http header field and the value of http header. - * ex) Cookie: SID=1234 - * @see da_start_download_with_extension - */ -#define DA_FEATURE_REQUEST_HEADER "request_header" - -/** - * @def DA_FEATURE_USER_DATA - * @brief receiving user data for requesting URL on \a da_start_download_with_extension. - * @remarks - * property value type for this is 'void*'. - * @details - * Every client callback will convey this value. - * @see da_start_download_with_extension - */ -#define DA_FEATURE_USER_DATA "user_data" - -/** - * @def DA_FEATURE_INSTALL_PATH - * @brief Downloaded file will be installed on designated path. - * @remarks - * property value type for this is 'char*'. - * @warning - * If the path is invalid, DA_ERR_INVALID_INSTALL_PATH will be returned. \n - * No file name accepts, but only path does. - * @see da_start_download_with_extension - */ -#define DA_FEATURE_INSTALL_PATH "install_path" - -/** - * @def DA_FEATURE_FILE_NAME - * @brief Downloaded file will be stored with the designated name. - * @remarks - * property value type for this is 'char*'. - * @warning - * No path accepts, but only file name dose. \n\n - * If the designated file name does not include extension, DA will extract an extension automatically and use it. \n - * If the designated file name includes extension, DA will use the extension without any check. \n\n - * It is not guaranteed to play or execute the stored file if client designates wrong extension.
- * If you are not confident of extension, DO NOT designate extension, but send just pure file name.

- * Client MUST check \a saved_path of \a user_download_info_t.
- * Because really decided file name can be different from the designated one.
- * For example, actual file name can have numbering postfix if another file has same name is exist on storing directory. \n - * (e.g. abc.mp3 to abc_1.mp3) \n\n - * This feature is ignored in case of OMA/Midlet download. \n - * @see da_start_download_with_extension - * @see user_download_info_t - */ -#define DA_FEATURE_FILE_NAME "file_name" -/** -*@} -*/ - -/** - * @ingroup Reference - * DA_DOWNLOAD_MANAGING_METHOD_MANUAL means that DA pass chunked packetes and response header data to the client in direct. - * This is only availalbe in case of A link download (HTTP) - * Please refer to sample code (da-test/md-sample.c) - */ -typedef enum { - DA_DOWNLOAD_MANAGING_METHOD_AUTO = 0, // DA handle all download progress including install a content. Support A link(HTTP) / OMA / MIDP download. - DA_DOWNLOAD_MANAGING_METHOD_MANUAL, // DA pass only chuncked packets, response header data, state and error code to the client. Support only A link (HTTP) download - DA_DOWNLOAD_MANAGING_METHOD_MAX -} da_download_managing_method; - -/** - * @warning depricated - */ -typedef enum { - DA_INSTALL_FAIL_REASON_OK = 0, // install is succeed - DA_INSTALL_FAIL_REASON_INSUFFICIENT_MEMORY, // There is no sufficient memory on target - DA_INSTALL_FAIL_REASON_USER_CANCELED, // user canceled installation - DA_INSTALL_FAIL_REASON_MAX -} da_install_fail_reason; - - -/** - * @ingroup Reference - * Download Agent notifies these states to client with \a da_notify_cb, when it is changed. \n - * Most of these value are informative, except for DA_STATE_WAITING_USER_CONFIRM. \n - * @remark Guarantee that one of following state is the final one. - * @li DA_STATE_FINISHED - * @li DA_STATE_CANCELED - * @li DA_STATE_FAILED - * @see user_notify_info_t - * @see da_notify_cb - * @par - @li For default download - \n DA_STATE_DOWNLOAD_STARTED, - DA_STATE_DOWNLOADING, - DA_STATE_DOWNLOAD_COMPLETE, - - @li For cancel, suspend, resume - \n DA_STATE_CANCELED, - DA_STATE_SUSPENDED, - DA_STATE_RESUMED, - - @li Last notification for all case - \n DA_STATE_FINISHED, - DA_STATE_FAILED, - */ -typedef enum { - DA_STATE_WAITING = 0, - /// Requested download to Web server for designated URL - DA_STATE_DOWNLOAD_STARTED, // 1 - /// Started to receiving HTTP body data - DA_STATE_DOWNLOADING, // 2 - /// Completed to download from Web server. Not yet registered to system. - DA_STATE_DOWNLOAD_COMPLETE, // 3 - /// Suspended download - DA_STATE_SUSPENDED, // 4 - /// Suspended all download. Emitted only if receiving DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI. - DA_STATE_SUSPENDED_ALL, // 5 - /// Resumed download which was suspended - DA_STATE_RESUMED, // 6 - /// Resumed all download. Emitted only if receiving DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI. - DA_STATE_RESUMED_ALL, // 7 - /// Finished all process to download. - DA_STATE_FINISHED, // 8 - /// Canceled download - DA_STATE_CANCELED, // 9 - /// Canceled all download. Emitted only if receiving DA_DOWNLOAD_REQ_ID_FOR_ALL_ITEMS_WITH_UNIFIED_NOTI. - DA_STATE_CANCELED_ALL, // 10 - /// Failed to download - DA_STATE_FAILED // 11 -} da_state; - - -/** - * @ingroup Reference - * @addtogroup ErrorCodes Error codes - * @{ - */ - -/** - * @{ - */ -// InputError Input error (-100 ~ -199) -// Client passed wrong parameter -#define DA_ERR_INVALID_ARGUMENT -100 -#define DA_ERR_INVALID_DL_REQ_ID -101 -#define DA_ERR_INVALID_CLIENT -102 -#define DA_ERR_INVALID_DD -103 -#define DA_ERR_INVALID_URL -104 -#define DA_ERR_INVALID_HANDLE -105 -#define DA_ERR_INVALID_INSTALL_PATH -106 -#define DA_ERR_INVALID_MIME_TYPE -107 - -// Client passed correct parameter, but Download Agent rejects the request because of internal policy. -#define DA_ERR_MISMATCH_CLIENT_DD -150 -#define DA_ERR_ALREADY_CANCELED -160 -#define DA_ERR_ALREADY_SUSPENDED -161 -#define DA_ERR_ALREADY_RESUMED -162 -#define DA_ERR_CANNOT_SUSPEND -170 -#define DA_ERR_CANNOT_RESUME -171 -#define DA_ERR_WAITING_USER_CONFIRM -180 -#define DA_ERR_WAITING_INSTALL_RESULT -181 -#define DA_ERR_INVALID_STATE -190 -#define DA_ERR_ALREADY_MAX_DOWNLOAD -191 -#define DA_ERR_UNSUPPORTED_PROTOCAL -192 -#define DA_ERR_CLIENT_IS_ALREADY_REGISTERED -193 -/** - * @} - */ - -/** - * @{ - */ -// System error (-200 ~ -299) -#define DA_ERR_FAIL_TO_MEMALLOC -200 -#define DA_ERR_FAIL_TO_CREATE_THREAD -210 -#define DA_ERR_FAIL_TO_OBTAIN_MUTEX -220 -#define DA_ERR_FAIL_TO_ACCESS_FILE -230 -#define DA_ERR_DISK_FULL -240 -/** - * @} - */ - -/** - * @{ - */ -// Platform error (-300 ~ -399) -#define DA_ERR_FAIL_TO_GET_CONF_VALUE -300 -#define DA_ERR_FAIL_TO_ACCESS_STORAGE -310 -#define DA_ERR_DLOPEN_FAIL -330 -/** - * @} - */ - -/** - * @{ - */ -// Network error (-400 ~ -499) -#define DA_ERR_NETWORK_FAIL -400 -#define DA_ERR_UNREACHABLE_SERVER -410 -#define DA_ERR_HTTP_TIMEOUT -420 -#define DA_ERR_SSL_FAIL -430 -/** - * @} - */ - -/** - * @{ - */ -// HTTP error - not conforming with HTTP spec (-500 ~ -599) -#define DA_ERR_MISMATCH_CONTENT_TYPE -500 -#define DA_ERR_MISMATCH_CONTENT_SIZE -501 -#define DA_ERR_SERVER_RESPOND_BUT_SEND_NO_CONTENT -502 -/** - * @} - */ - -/** - * @{ - */ -// install error (-800 ~ -899) -#define DA_ERR_FAIL_TO_INSTALL_FILE -800 -/** -*@} -*/ - -/** -*@} -*/ -#endif - diff --git a/src/agent/include/download-agent-dl-info-util.h b/src/agent/include/download-agent-dl-info-util.h deleted file mode 100644 index f17715d..0000000 --- a/src/agent/include/download-agent-dl-info-util.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-dl-info-util.h - * @brief - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_Dl_Info_Util_H -#define _Download_Agent_Dl_Info_Util_H - -#include "download-agent-type.h" -#include "download-agent-http-queue.h" -#include "download-agent-utils-dl-req-id-history.h" - -#define DA_MAX_DOWNLOAD_ID DA_MAX_DOWNLOAD_REQ_AT_ONCE -#define DA_MAX_TYPE_COUNT 10 - -#define DOWNLOAD_NOTIFY_LIMIT (1024*32) //bytes -extern pthread_mutex_t mutex_download_state[]; - -typedef enum { - DOWNLOAD_STATE_IDLE = 0, - DOWNLOAD_STATE_NEW_DOWNLOAD = 20, /* stage */ - - DOWNLOAD_STATE_READY_TO_INSTAL = 55, /* stage */ - - DOWNLOAD_STATE_FINISH = 60, /* stage */ - - DOWNLOAD_STATE_PAUSED = 70, /* http */ - DOWNLOAD_STATE_CANCELED, /* http */ - -} download_state_t; - -typedef enum { - HTTP_STATE_READY_TO_DOWNLOAD = 0, - HTTP_STATE_REDIRECTED = 1, - HTTP_STATE_DOWNLOAD_REQUESTED = 2, - HTTP_STATE_DOWNLOAD_STARTED = 3, - HTTP_STATE_DOWNLOADING = 4, - HTTP_STATE_DOWNLOAD_FINISH = 5, - HTTP_STATE_REQUEST_CANCEL = 6, - HTTP_STATE_REQUEST_PAUSE = 7, - HTTP_STATE_REQUEST_RESUME = 8, - HTTP_STATE_CANCELED = 9, - HTTP_STATE_PAUSED = 10, - HTTP_STATE_RESUMED = 11, - HTTP_STATE_ABORTED = 12, - -} http_state_t; - -typedef struct _client_input_basic_t { - char *req_url; - char **user_request_header; - int user_request_header_count; -} client_input_basic_t; - - -typedef struct _client_input_t { - void *user_data; - char *install_path; - char *file_name; - client_input_basic_t client_input_basic; -} client_input_t; - -typedef struct _download_thread_input { - int download_id; - client_input_t *client_input; -} download_thread_input; - -typedef struct _source_info_basic_t { - int dl_id; - char *url; - char **user_request_header; - int user_request_header_count; -} source_info_basic_t; - -typedef struct _source_info_t { - union _source_info_type { - source_info_basic_t *source_info_basic; - } source_info_type; -} source_info_t; - -#define GET_SOURCE_TYPE(SOURCE) ((SOURCE)->source_type) -#define GET_SOURCE_BASIC(SOURCE) ((SOURCE)->source_info_type.source_info_basic) -#define GET_SOURCE_BASIC_URL(SOURCE) (GET_SOURCE_BASIC(SOURCE)->url) - -typedef struct _req_dl_info { - http_info_t http_info; - - /* This is just pointer assignment from stage source info. */ - char *destination_url; - /* The location url is assigned here in case of redirection. - * At this time, the pointer should be freed. */ - char *location_url; - char **user_request_header; - int user_request_header_count; - - http_state_t http_state; - pthread_mutex_t mutex_http_state; - - da_result_t result; - /*************** will be depreciated ***********************/ - /* ToDo : previous http_info should be saved in case of pause */ - char *content_type_from_header; /* calloced in set hdr fiels on download info */ - int content_len_from_header; - char *etag_from_header; - - unsigned long int downloaded_data_size; - - int invloved_transaction_id; -} req_dl_info; - -#define GET_REQUEST_HTTP_RESULT(REQUEST) (REQUEST->result) -#define GET_REQUEST_HTTP_TRANS_ID(REQUEST) (REQUEST->invloved_transaction_id) -#define GET_REQUEST_HTTP_REQ_URL(REQUEST) (REQUEST->destination_url) -#define GET_REQUEST_HTTP_REQ_LOCATION(REQUEST) (REQUEST->location_url) -#define GET_REQUEST_HTTP_USER_REQUEST_HEADER(REQUEST) (REQUEST->user_request_header) -#define GET_REQUEST_HTTP_USER_REQUEST_HEADER_COUNT(REQUEST) (REQUEST->user_request_header_count) -#define GET_REQUEST_HTTP_HDR_ETAG(REQUEST) (REQUEST->etag_from_header) -#define GET_REQUEST_HTTP_HDR_CONT_TYPE(REQUEST) (REQUEST->content_type_from_header) -#define GET_REQUEST_HTTP_HDR_CONT_LEN(REQUEST) (REQUEST->content_len_from_header) -#define GET_REQUEST_HTTP_CONTENT_OFFSET(REQUEST)(REQUEST->downloaded_data_size) -#define GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE) (GET_STAGE_TRANSACTION_INFO(STAGE)->mutex_http_state) -#define GET_HTTP_STATE_ON_STAGE(STAGE) (GET_STAGE_TRANSACTION_INFO(STAGE)->http_state) -#define CHANGE_HTTP_STATE(STATE,STAGE) {\ - _da_thread_mutex_lock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE)));\ - GET_HTTP_STATE_ON_STAGE(STAGE) = STATE;\ - DA_LOG_CRITICAL(Default, "Changed http_state to - [%d] ", GET_HTTP_STATE_ON_STAGE(STAGE));\ - _da_thread_mutex_unlock(&(GET_REQUEST_HTTP_MUTEX_HTTP_STATE(STAGE)));\ -} - -typedef struct _file_info { - void *file_handle; - char *pure_file_name; - char *extension; - char *file_name_tmp; /* malloced in make file info. */ - char *file_name_final; /* malloced in set_file_path_for_final_saving */ - char *content_type; /* malloced in make file info. */ - char *add_to_buffer; - unsigned int file_size; /* http header's Content-Length has higher priority than DD's */ - unsigned int total_bytes_written_to_file; /* current written file size */ - unsigned int bytes_written_to_file; - unsigned int current_buffer_len; -} file_info; - -#define GET_CONTENT_STORE_PURE_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->pure_file_name -#define GET_CONTENT_STORE_EXTENSION(FILE_CNTXT) (FILE_CNTXT)->extension -#define GET_CONTENT_STORE_TMP_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->file_name_tmp -#define GET_CONTENT_STORE_ACTUAL_FILE_NAME(FILE_CNTXT) (FILE_CNTXT)->file_name_final -#define GET_CONTENT_STORE_FILE_HANDLE(FILE_CNTXT) (FILE_CNTXT)->file_handle -#define GET_CONTENT_STORE_FILE_SIZE(FILE_CNTXT) (FILE_CNTXT)->file_size -#define GET_CONTENT_STORE_CURRENT_FILE_SIZE(FILE_CNTXT) (FILE_CNTXT)->total_bytes_written_to_file -#define IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(FILE_CNTXT) (FILE_CNTXT)->bytes_written_to_file -#define GET_CONTENT_STORE_FILE_BUFFER(FILE_CNTXT) (FILE_CNTXT)->add_to_buffer -#define GET_CONTENT_STORE_FILE_BUFF_LEN(FILE_CNTXT) ((FILE_CNTXT)->current_buffer_len) -#define GET_CONTENT_STORE_CONTENT_TYPE(FILE_CNTXT) (FILE_CNTXT)->content_type - -typedef struct _stage_info { - int dl_id; - source_info_t dl_request; - req_dl_info dl_tansaction_context; - file_info dl_content_storage; - struct _stage_info *next_stage_info; -} stage_info; - -#define GET_STAGE_DL_ID(STAGE) ((STAGE)->dl_id) -#define GET_STAGE_SOURCE_INFO(STAGE) (&((STAGE)->dl_request)) -#define GET_STAGE_TRANSACTION_INFO(STAGE) (&((STAGE)->dl_tansaction_context)) -#define GET_STAGE_CONTENT_STORE_INFO(STAGE) (&((STAGE)->dl_content_storage)) -#define GET_STAGE_INSTALLATION_INFO(STAGE) (&((STAGE)->post_dl_context)) - -typedef struct _download_info_t { - da_bool_t is_using; - int download_id; - int dl_req_id; - pthread_t active_dl_thread_id; - download_state_t state; - stage_info *download_stage_data; - da_state cur_da_state; - queue_t queue; - // FIXME have client_input itself, not to have each of them - char *user_install_path; - char *user_file_name; - void *user_data; -} download_info_t; - -#define GET_DL_THREAD_ID(ID) (download_mgr.download_info[ID].active_dl_thread_id) -#define GET_DL_STATE_ON_ID(ID) (download_mgr.download_info[ID].state) -#define GET_DL_STATE_ON_STAGE(STAGE) (GET_DL_STATE_ON_ID(GET_STAGE_DL_ID(STAGE))) -#define GET_DL_CURRENT_STAGE(ID) (download_mgr.download_info[ID].download_stage_data) -#define GET_DL_REQ_ID(ID) (download_mgr.download_info[ID].dl_req_id) -#define GET_DL_DA_STATE(ID) (download_mgr.download_info[ID].cur_da_state) -#define GET_DL_QUEUE(ID) &(download_mgr.download_info[ID].queue) -#define GET_DL_USER_INSTALL_PATH(ID) (download_mgr.download_info[ID].user_install_path) -#define GET_DL_USER_FILE_NAME(ID) (download_mgr.download_info[ID].user_file_name) -#define GET_DL_USER_DATA(ID) (download_mgr.download_info[ID].user_data) -#define IS_THIS_DL_ID_USING(ID) (download_mgr.download_info[ID].is_using) - -#define CHANGE_DOWNLOAD_STATE(STATE,STAGE) {\ - _da_thread_mutex_lock (&mutex_download_state[GET_STAGE_DL_ID(STAGE)]);\ - GET_DL_STATE_ON_STAGE(STAGE) = STATE;\ - DA_LOG_CRITICAL(Default, "Changed download_state to - [%d] ", GET_DL_STATE_ON_STAGE(STAGE));\ - _da_thread_mutex_unlock (&mutex_download_state[GET_STAGE_DL_ID(STAGE)]);\ - } - -typedef enum { - STATE_WATCHER_TYPE_NONE = 0, - STATE_WATCHER_TYPE_CANCEL, - STATE_WATCHER_TYPE_SUSPEND, - STATE_WATCHER_TYPE_RESUME -} state_watcher_type_t; - -typedef struct _state_watcher_t { - state_watcher_type_t type; - unsigned short state_watching_bitmap; - da_bool_t is_progressing_to_all; - pthread_mutex_t mutex; -} state_watcher_t; - -typedef struct _default_http_hdr_info_t { - char *user_agent_string; -} default_http_hdr_info_t; - -#define GET_USER_AGENT (download_mgr.default_hdr_info->user_agent_string) - -typedef struct _download_mgr_t { - da_bool_t is_init; - download_info_t download_info[DA_MAX_DOWNLOAD_ID]; - default_http_hdr_info_t *default_hdr_info; - state_watcher_t state_watcher; - - /* FIXME: This is temporary solution to prevent crash on following case; - * 1) OMA download(that is, DA's libsoup is using) is on progressing on Browser - * 2) User push END hard key - * 3) da_deinit() is called. - on UI thread - * 4) cancel_download(all) is called. - * 5) plugin-libsoup.c calls soup_session_cancel_message(). - * 6) da_deinit() is finished and process is over. - * 7) soup's callback for soup_session_cancel_message() is trying to be called - on UI thread - * 8) Browser crashed because the callback address is no longer exist. - * - * Here is a temporary solution; - * If cancel is from da_deinit(), plugin-libsoup.c will not call soup_session_cancel_message(). - * So, append following variable to recognize this. - **/ - //da_bool_t is_progressing_deinit; - - dl_req_id_history_t dl_req_id_history; -} download_mgr_t; - -extern download_mgr_t download_mgr; - -da_result_t init_download_mgr(); -da_result_t deinit_download_mgr(void); - -void init_download_info(int download_id); -void destroy_download_info(int download_id); - -void *Add_new_download_stage(int download_id); -void remove_download_stage(int download_id, stage_info *in_stage); - -void empty_stage_info(stage_info *in_stage); - -void clean_up_client_input_info(client_input_t *client_input); - -da_result_t get_available_download_id(da_handle_t *available_id); -da_result_t get_download_id_for_dl_req_id(da_handle_t dl_req_id , da_handle_t* download_id); -da_bool_t is_valid_dl_ID(int download_id); - -void state_watcher_flag_ON_for_download_id(state_watcher_t *state_watcher, - int download_id); -void state_watcher_flag_OFF_for_download_id(state_watcher_t *state_watcher, - int download_id); -da_bool_t state_watcher_need_redirect_Q(int download_id); -void state_watcher_redirect_state(int download_id, da_state state, int err); - -#endif /* _Download_Agent_Dl_Info_Util_H */ diff --git a/src/agent/include/download-agent-dl-mgr.h b/src/agent/include/download-agent-dl-mgr.h deleted file mode 100644 index 2a2bc0d..0000000 --- a/src/agent/include/download-agent-dl-mgr.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-dl-mgr.h - * @brief - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_Dl_Mgr_H -#define _Download_Agent_Dl_Mgr_H - -#include "download-agent-type.h" -#include "download-agent-dl-info-util.h" - -da_result_t cancel_download (int dl_req_id); -da_result_t cancel_download_all (int dl_req_id); - -da_result_t suspend_download (int dl_req_id); -da_result_t suspend_download_all (int dl_req_id); - -da_result_t resume_download (int dl_req_id); -da_result_t resume_download_all (int dl_req_id); - -da_result_t requesting_download(stage_info *stage); -da_result_t handle_after_download(stage_info *stage); -da_result_t process_install(stage_info *stage); -da_result_t send_user_noti_and_finish_download_flow(int download_id); - -#endif diff --git a/src/agent/include/download-agent-file.h b/src/agent/include/download-agent-file.h deleted file mode 100644 index c15c046..0000000 --- a/src/agent/include/download-agent-file.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-file.h - * @brief - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_File_H -#define _Download_Agent_File_H - -#include -#include -#include - -#include "download-agent-type.h" -#include "download-agent-dl-mgr.h" - -#ifdef _TARGET -#define DA_DEFAULT_TMP_FILE_DIR_PATH "/opt/media/.tmp_download" -#else -// FIXME Later : temporary code -#define DA_DEFAULT_TMP_FILE_DIR_PATH "/tmp/.tmp_download" -#endif - -da_bool_t is_file_exist(const char *file_path); -da_bool_t is_dir_exist(char *dir_path); - -void get_file_size(char *file_path, int *out_file_size); - -da_result_t clean_files_from_dir(char* dir_path); -da_result_t create_temp_saved_dir(void); - -da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len); -da_result_t file_write_complete(stage_info *stage); -da_result_t start_file_writing(stage_info *stage); -da_result_t start_file_writing_append(stage_info *stage); - -da_result_t get_mime_type(stage_info *stage, char **out_mime_type); -da_result_t discard_download(stage_info *stage) ; -void clean_paused_file(stage_info *stage); -da_result_t replace_content_file_in_stage(stage_info *stage, const char *dest_dd_file_path); -da_result_t decide_final_file_path(stage_info *stage); -char *get_full_path_avoided_duplication(char *in_dir, char *in_candidate_file_name, char * in_extension); - -da_result_t copy_file(const char *src, const char *dest); -da_result_t create_dir(const char *install_dir); - -#endif diff --git a/src/agent/include/download-agent-http-mgr.h b/src/agent/include/download-agent-http-mgr.h deleted file mode 100644 index de661f2..0000000 --- a/src/agent/include/download-agent-http-mgr.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-mgr.h - * @brief Including functions regarding http mgr - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Http_Mgr_H -#define _Download_Agent_Http_Mgr_H - -#include - -#include "download-agent-type.h" -#include "download-agent-dl-mgr.h" -#include "download-agent-http-queue.h" - -#define DA_MAX_SESSION_INFO DA_MAX_DOWNLOAD_ID -#define DA_MAX_TRANSACTION_INFO 10 -#define DA_MAX_TRANSACTION_MUTEX DA_MAX_SESSION_INFO*DA_MAX_TRANSACTION_INFO - -typedef struct _http_mgr_t -{ - da_bool_t is_init; - da_bool_t is_http_init; -}http_mgr_t; - -extern http_mgr_t http_mgr; - -da_result_t init_http_mgr(void); -void deinit_http_mgr(void); -da_result_t make_req_dl_info_http(stage_info *stage, req_dl_info *out_info); -da_result_t request_http_download(stage_info *stage); -da_result_t request_to_cancel_http_download(stage_info *stage); -da_result_t request_to_abort_http_download(stage_info *stage); -da_result_t request_to_suspend_http_download(stage_info *stage); -da_result_t request_to_resume_http_download(stage_info *stage); - -#endif diff --git a/src/agent/include/download-agent-http-misc.h b/src/agent/include/download-agent-http-misc.h deleted file mode 100644 index b60cb23..0000000 --- a/src/agent/include/download-agent-http-misc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-misc.h - * @brief Including miscellaneous functions for http - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Http_Misc_H -#define _Download_Agent_Http_Misc_H - -#include - -#include "download-agent-type.h" - -#define SCHEME_HTTP "http://" -#define SCHEME_HTTPS "https://" -#define SCHEME_CID "cid:" - -#define METHOD_GET "GET" -#define METHOD_POST "POST" -#define METHOD_HEAD "HEAD" - -#define HTTP_TAG_UAGENT "User-Agent: " -#define HTTP_TAG_HOST "Host: " -#define HTTP_TAG_UAPROF "X-Wap-Profile: " -#define HTTP_TAG_CONTENT_LENGTH "Content-Length: " -#define HTTP_TAG_CONTENT_TYPE "Content-Type: " -#define HTTP_TAG_IF_MATCH "If-Match: " -#define HTTP_TAG_RANGE "Range: " -#define HTTP_TAG_IF_RANGE "If-Range: " - -#define END_OF_FIELD "\r\n" - -char* get_user_agent(); - -da_bool_t is_supporting_protocol(const char* protocol); - -#endif diff --git a/src/agent/include/download-agent-http-msg-handler.h b/src/agent/include/download-agent-http-msg-handler.h deleted file mode 100644 index bcb9444..0000000 --- a/src/agent/include/download-agent-http-msg-handler.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-msg-handler.h - * @brief Utilities to manipulate HTTP messages - * @author Keunsoon Lee (keunsoon.lee@samsung.com) - */ - -#ifndef _Download_Agent_Http_Msg_Handler_H -#define _Download_Agent_Http_Msg_Handler_H - -#include "download-agent-type.h" - -#define HTTP_FIELD_UAGENT "User-Agent" -#define HTTP_FIELD_HOST "Host" -#define HTTP_FIELD_UAPROF "X-Wap-Profile" -#define HTTP_FIELD_CONTENT_LENGTH "Content-Length" -#define HTTP_FIELD_CONTENT_TYPE "Content-Type" -#define HTTP_FIELD_IF_MATCH "If-Match" -#define HTTP_FIELD_RANGE "Range" -#define HTTP_FIELD_IF_RANGE "If-Range" -#define HTTP_FIELD_ACCEPT_LANGUAGE "Accept-Language" -#define HTTP_FIELD_ACCEPT_CHARSET "Accept-Charset" - -typedef struct _http_header_options_t http_header_options_t; -struct _http_header_options_t{ - char* field; - char* value; - - http_header_options_t* next; -}; - -typedef struct _http_header_t http_header_t; -struct _http_header_t{ - char* field; - char* value; - http_header_options_t* options; - - char* raw_value; // raw string including options - - http_header_t* next; -}; - -typedef struct{ - char* http_method; - char* url; - http_header_t* head; - char* http_body; -}http_msg_request_t; - - -typedef struct{ - int status_code; - http_header_t* head; -}http_msg_response_t; - -typedef http_header_t* http_msg_iter_t; - - -typedef struct{ - http_msg_request_t* http_msg_request; - http_msg_response_t* http_msg_response; -}http_info_t; - - -da_result_t http_msg_request_create(http_msg_request_t** http_msg_request); -void http_msg_request_destroy(http_msg_request_t** http_msg_request); - -da_result_t http_msg_request_set_method(http_msg_request_t* http_msg_request, const char* method); -da_result_t http_msg_request_get_method(http_msg_request_t* http_msg_request, const char** method); - -da_result_t http_msg_request_set_url(http_msg_request_t* http_msg_request, const char* url); -da_result_t http_msg_request_get_url(http_msg_request_t* http_msg_request, const char** url); - -da_result_t http_msg_request_set_body(http_msg_request_t* http_msg_request, const char* body); -da_result_t http_msg_request_get_body(http_msg_request_t* http_msg_request, const char** body); - -da_result_t http_msg_request_add_field(http_msg_request_t* http_msg_request, const char* field, const char* value); - - -da_result_t http_msg_response_create(http_msg_response_t** http_msg_response); -void http_msg_response_destroy(http_msg_response_t** http_msg_response); - -da_result_t http_msg_response_set_status_code(http_msg_response_t* http_msg_response, int status_code); -da_result_t http_msg_response_get_status_code(http_msg_response_t* http_msg_response, int* status_code); - -da_result_t http_msg_response_add_field(http_msg_response_t* http_msg_response, const char* field, const char* value); - -/* Caution! Caller must free memory for every "char** out_xxx" for followings */ -da_bool_t http_msg_response_get_content_type(http_msg_response_t* http_msg_response, char** out_type); -void http_msg_response_set_content_type(http_msg_response_t* http_msg_response, const char* in_type); - -da_bool_t http_msg_response_get_content_length(http_msg_response_t* http_msg_response, int* out_length); -da_bool_t http_msg_response_get_content_disposition(http_msg_response_t* http_msg_response, char** out_disposition, char** out_file_name); -da_bool_t http_msg_response_get_ETag(http_msg_response_t* http_msg_response, char** out_value); -da_bool_t http_msg_response_get_date(http_msg_response_t* http_msg_response, char** out_value); -da_bool_t http_msg_response_get_location(http_msg_response_t* http_msg_response, char** out_value); -// should be refactored later -da_result_t http_msg_response_get_boundary(http_msg_response_t* http_msg_response, char** out_val); - - -da_result_t http_msg_request_get_iter(http_msg_request_t* http_msg_request, http_msg_iter_t* http_msg_iter); -da_result_t http_msg_response_get_iter(http_msg_response_t* http_msg_response, http_msg_iter_t* http_msg_iter); - -// should remove later -da_bool_t http_msg_get_field_with_iter(http_msg_iter_t* http_msg_iter, char** field, char** value); -da_bool_t http_msg_get_header_with_iter(http_msg_iter_t* http_msg_iter, char** out_field, http_header_t** out_header); - -char *get_http_response_header_raw(http_msg_response_t *http_msg_response); - -da_bool_t extract_attribute_from_header(char* szHeadStr, const char* szFindStr, char** ppRtnValue); -#endif // _Download_Agent_Http_Msg_Handler_H diff --git a/src/agent/include/download-agent-http-queue.h b/src/agent/include/download-agent-http-queue.h deleted file mode 100644 index 1a7f4e1..0000000 --- a/src/agent/include/download-agent-http-queue.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-http-queue.h - * @brief Including functions regarding http queue - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Http_Queue_H -#define _Download_Agent_Http_Queue_H - - -#include "download-agent-type.h" -#include "download-agent-http-msg-handler.h" - -#include -#include - -#define MAX_QUEUE_SIZE 1024*64 - -typedef enum -{ - Q_EVENT_TYPE_DATA_HTTP, - Q_EVENT_TYPE_CONTROL, -}q_event_type; - -typedef enum -{ - Q_EVENT_TYPE_CONTROL_CANCEL, - Q_EVENT_TYPE_CONTROL_SUSPEND, - Q_EVENT_TYPE_CONTROL_RESUME, - Q_EVENT_TYPE_CONTROL_NET_DISCONNECTED, - Q_EVENT_TYPE_CONTROL_ABORT, -// [090205][jungki]not used yet. -// Q_EVENT_TYPE_CONTROL_USER_CONFIRM_RESULT, -// Q_EVENT_TYPE_CONTROL_INSTALL_RESULT, -}q_event_type_control; - -typedef enum -{ - Q_EVENT_TYPE_DATA_PACKET, - Q_EVENT_TYPE_DATA_FINAL, - Q_EVENT_TYPE_DATA_ABORT, -}q_event_type_data; - -typedef struct _q_event_data_http_t -{ - q_event_type_data data_type; - - int status_code; - - http_msg_response_t* http_response_msg; - - int body_len; - char *body_data; - - da_result_t error_type; -}q_event_data_http_t; - -typedef struct _q_event_control_t -{ - q_event_type_control control_type; -}q_event_control_t; - -typedef struct _q_event_t q_event_t; -struct _q_event_t -{ - int size; - q_event_type event_type; - union _type - { - q_event_data_http_t q_event_data_http; - q_event_control_t q_event_control; - } type; - - q_event_t *next; -}; - -typedef struct _queue_t -{ - da_bool_t having_data; - - q_event_t *control_head; - q_event_t *data_head; - - pthread_mutex_t mutex_queue; - pthread_cond_t cond_queue; - - int queue_size; -}queue_t; - -void Q_init_queue(queue_t *queue); -void Q_destroy_queue(queue_t *queue); - -void Q_init_q_event(q_event_t *q_event); -void Q_destroy_q_event(q_event_t **q_event); - -da_result_t Q_make_control_event(q_event_type_control control_type, q_event_t **out_event); - -da_result_t Q_make_http_data_event(q_event_type_data data_type, q_event_t **out_event); -da_result_t Q_set_status_code_on_http_data_event(q_event_t *q_event, int status_code); -da_result_t Q_set_http_body_on_http_data_event(q_event_t *q_event, int body_len, char *body_data); -da_result_t Q_set_error_type_on_http_data_event(q_event_t *q_event, int error_type); - - -da_bool_t Q_push_event(const queue_t *in_queue, const q_event_t *in_event); -da_bool_t Q_push_event_without_lock(const queue_t *in_queue, const q_event_t *in_event); -void Q_pop_event(const queue_t *in_queue, q_event_t **out_event); - -#define GET_IS_Q_HAVING_DATA(QUEUE) (QUEUE->having_data) - -void Q_goto_sleep(const queue_t *in_queue); -void Q_wake_up(const queue_t *in_queue); - - -#endif diff --git a/src/agent/include/download-agent-installation.h b/src/agent/include/download-agent-installation.h deleted file mode 100644 index 5cf8dbf..0000000 --- a/src/agent/include/download-agent-installation.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-installation.h - * @brief Functions Declaration for Content Installation - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - - -#ifndef _Download_Agent_Installation_H -#define _Download_Agent_Installation_H - -#include "download-agent-utils.h" -#include "download-agent-debug.h" -#include "download-agent-dl-mgr.h" - -da_result_t install_content(stage_info *stage); - -#endif diff --git a/src/agent/include/download-agent-interface.h b/src/agent/include/download-agent-interface.h deleted file mode 100644 index 8ceee58..0000000 --- a/src/agent/include/download-agent-interface.h +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-interface.h - * @brief Interface for Download Agent. - * @author Keunsoon Lee (keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - * - */ - -#ifndef _Download_Agent_Interface_H -#define _Download_Agent_Interface_H - -#ifdef __cplusplus - extern "C" - { -#endif - -#include "download-agent-defs.h" -#include - -/** - * @ingroup Internet_FW - * @addtogroup DownloadAgent Download Agent - * @{ - * @brief Download Agent is a UI-less shared library to download files from Internet. - * @par Details - * Download Agent is a module to download stuffs through HTTP. \n - * Download Agent can download several files simultaneously using multi-thread. \n\n - * If any application wants to download something from Internet, then use this like following. \n - * 1) Be a client for Download Agent. \n - * 2) Pass a URL which you want to download to Download Agent. \n - * 3) Get notifications and result from Download Agent. \n - */ - -/** - * @ingroup DownloadAgent - * @addtogroup QuickGuide Quick Guide - * @{ - * @par Step 1. To implement required callbacks to receive notifications - * \c da_notify_cb and \c da_update_download_info_cb are required almost all cases. \n - * @remark Do not free anything on the callbacks. DA will take care of them. - * @remark If you want to use \a user_param, set it with \a DA_FEATURE_USER_DATA - * @remark You can free user_param when receiving one of following \a da_state. - * @li DA_STATE_FINISHED - * @li DA_STATE_FAILED - * @li DA_STATE_CANCELED - * @par - * @code - * // main.c - * #include - * - * void notify_cb(user_notify_info_t *notify_info, void* user_param) - * { - * if (!notify_info) - * return; - * printf("id [%d], state [%d]", notify_info->da_dl_req_id, notify_info->state); - * if (notify_info->state == DA_STATE_FAILED) - * printf("error code [%d]", notify_info->err); - * } - * - * void update_download_info_cb(user_download_info_t *download_info, void* user_param) - * { - * if (!download_info) - * return; - * printf("id [%d], file size [%d/%d]", download_info->da_dl_req_id, - * download_info->file_size); - * } - * - * void update_downloading_info_cb(user_downloading_info_t *downloading_info, void* user_param) - * { - * if (!downloading_info) - * return; - * printf("id [%d], received size [%d]", downloading_info->da_dl_req_id, - * downloading_info->total_received_size); - * } - * @endcode - * @endcode - * - * @par Step 2. To register the callbacks - * set NULL for callbacks you do not want to know. - * @code - * // continued after Step 1 - * - * void download_initialize() - * { - * int da_ret; - * da_client_cb_t da_cb = { notify_cb, NULL, update_download_info_cb, update_downloading_info_cb, NULL }; - * - * da_ret = da_init (&da_cb, 0); - * if(da_ret == DA_RESULT_OK) - * printf("successed\n"); - * else - * printf("failed with error code %d\n", da_ret); - * } - * @endcode - * - * @par Step 3. To request a download - * You can meet the da_req_id on Step 1 callbacks again. \n - * Downloaded file is automatically registered to system. (e.g. File DB) \n - * If there is another file has same name on registering directory, new one's name would have numbering postfix. \n - * (e.g. abc.mp3 to abc_1.mp3) - * @see da_start_download_with_extension - * @code - * // continued after Step 2 - * void start_download() - * { - * int da_ret; - * da_handle_t da_req_id; - * char *url = "http://www.test.com/sample.mp3"; - * da_ret = da_start_download(url, &da_req_id); - * if(da_ret == DA_RESULT_OK) - * printf("successed\n"); - * else - * printf("failed with error code %d\n", da_ret); - * } - * @endcode - * - * @par Step 4. To do whatever client wants with information obtained from callbacks - * - * @par Step 5. To de-initialize when client does not use Download Agent anymore - * @code - * // continued after Step 3 - * void download_deinit() - * { - * int da_ret; - * da_ret = da_deinit(); - * if(da_ret == DA_RESULT_OK) - * printf("successed\n"); - * else - * printf("failed with error code %d\n", da_ret); - * } - * @endcode - * @} - */ - - /** - * @ingroup DownloadAgent - * @addtogroup Reference - * @{ - */ - -/** - * @ingroup Reference - * @addtogroup NotificationCallbacks Notification callbacks for client - * @brief Download Agent notifies many information with these callbacks to client. - * @{ - */ -/** - * @struct user_notify_info_t - * @brief Download Agent will send its state through this structure. - * @see da_notify_cb - * @par - * This is used only by callback /a user_notify_info_t. \n - */ -typedef struct { - /// download request id for this notification - da_handle_t da_dl_req_id; - /// Download Agent's current state corresponding to the da_dl_req_id - da_state state; - /// convey error code if necessary, or it is zero. - int err; -} user_notify_info_t; - -/** - * @struct user_downloading_info_t - * @brief Download Agent will send current downloading file's information through this structure. - * @see da_update_downloading_info_cb - * @par - * This is used only by callback /a da_update_downloading_info_cb. \n - */ -typedef struct { - /// download request id for this updated download information - da_handle_t da_dl_req_id; - /// received size of chunked data. - unsigned long int total_received_size; - /// This has only file name for now. - char *saved_path; -} user_downloading_info_t; - -/** - * @struct user_download_info_t - * @brief Download Agent will send current download's information through this structure. - * @see da_update_download_info_cb - * @par - * This is used only by callback /a da_update_download_info_cb. \n - */ -typedef struct { - /// download request id for this updated download information - da_handle_t da_dl_req_id; - /// file's mime type from http header. - char *file_type; - /// file size from http header. - unsigned long int file_size; - /// This is same with 'saved_path' for now. - char *tmp_saved_path; - /// This is raw data of response header - char *http_response_header; - /// This is raw data of chunked data - char *http_chunked_data; -} user_download_info_t; - -/** - * @typedef da_notify_cb - * @brief Download Agent will call this function to notify its state. - * - * This is user callback function registered on \a da_init. \n - * - * @remarks For the most of time, this state is just informative, so, user doesn't need to do any action back to Download Agent. - * @remarks But, Download Agent will wait for user's specific action after notifying some states. - * - * @warning Download will be holding until getting user confirmation result through the function. - * - * @param[in] state state from Download Agent - * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA - * - * @see da_init - * @see da_client_cb_t - */ -typedef void (*da_notify_cb) (user_notify_info_t *notify_info, void* user_param); - -/** - * @brief Download Agent will call this function to update received size of download-requested file. - * - * This is user callback function registered on \a da_init. \n - * This is informative, so, user doesn't need to do any action back to Download Agent.\n - * - * @param[in] downloading_info updated downloading information - * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA - * - * @see da_init - * @see da_client_cb_t - */ -typedef void (*da_update_downloading_info_cb) (user_downloading_info_t *downloading_info, void* user_param); - -/** - * @brief Download Agent will call this function to update mime type, temp file name, total file sizeand installed path. - * - * This is user callback function registered on \a da_init. \n - * This is informative, so, user doesn't need to do any action back to Download Agent.\n - * - * @param[in] download_info updated download information - * @param[in] user_param user parameter which is set with \a DA_FEATURE_USER_DATA - * - * @see da_init - * @see da_client_cb_t - */ -typedef void (*da_update_download_info_cb) (user_download_info_t *download_info, void* user_param); - - /** - * @struct da_client_cb_t - * @brief This structure convey User's callback functions for \a da_init - * @see da_init - */ -typedef struct { - /// callback to convey \a da_state and error code - da_notify_cb user_noti_cb; - /// callback to convey download information - da_update_download_info_cb update_dl_info_cb; - /// callback to convey downloading information while downloading including received file size - da_update_downloading_info_cb update_progress_info_cb; -} da_client_cb_t; -/** - * @} - */ - -/** - * @fn int da_init (da_client_cb_t *da_client_callback,da_download_managing_method download_method) - * @ingroup Reference - * @brief This function initiates Download Agent and registers user callback functions. - * @warning This should be called at once when client application is initialized before using other Download Agent APIs - * @warning This function is paired with da_deinit function. - * - * @pre None. - * @post None. - * - * @param[in] da_client_callback User callback function structure. The type is struct data pointer. - * @param[in] download_method Application can choose to manage download manually or automatically.The Enum data da_download_managing_method is defined at download-agent-defs.h. - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. - * @remarks User MUST call this function first rather than any other DA APIs. \n - * Please do not call UI code at callback function in direct. \n - * It is better that it returns as soon as copying the data of callback functon. \n - * @see da_deinit - * @par Example - * @code - * #include - * - * void da_notify_cb(user_notify_info_t *notify_info, void *user_param); - * void da_update_download_info_cb(user_download_info_t *download_info,void* user_param); - * void da_update_downloading_info_cb(user_downloading_info_t *downloading_info,void* user_param); - * - * - * int download_initialize() - * { - * int da_ret; - * da_client_cb_t da_cb = {0}; - * - * da_cb.user_noti_cb = ¬ify_cb; - * da_cb.update_dl_info_cb = &update_download_info_cb; - * da_cb.update_progress_info_cb = &update_downloading_info_cb; - * - * da_ret = da_init (&da_cb, 0); - * if (da_ret == DA_RESULT_OK) { - * // printf("successed\n"); - * return true; - * } else { - * // printf("failed with error code %d\n", da_ret); - * return fail; - * } - * } - * @endcode - */ -int da_init ( - da_client_cb_t *da_client_callback, - da_download_managing_method download_method -); - - - /** - * @fn int da_deinit () - * @ingroup Reference - * @brief This function deinitiates Download Agent. - * - * This function destroys all infomation for client manager. - * When Download Agent is not used any more, please call this function. - * Usually when client application is destructed, this is needed. - * - * @remarks This is paired with da_init. \n - * The client Id should be the one from /a da_init(). \n - * Otherwise, it cannot excute to deinitialize. \n - * - * @pre da_init() must be called in advance. - * @post None. - * - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. - * @see da_init - * @par Example - * @code - * #include - * - * - * int download_deinitialize() - * { - * int da_ret; - * da_ret = da_deinit(); - * if(da_ret == DA_RESULT_OK) { - * // printf("successed\n"); - * return true; - * } else { - * // printf("failed with error code %d\n", da_ret); - * return fail; - * } - * } - @endcode - */ -int da_deinit (); - - - /** - * @fn int da_start_download(const char *url, da_handle_t *da_dl_req_id) - * @ingroup Reference - * @brief This function starts to download a content on passed URL. - * - * Useful information and result are conveyed through following callbacks. - * @li da_notify_cb - * @li da_update_download_info_cb - * - * @pre da_init() must be called in advance. - * @post None. - * @remarks - * Downloaded file is automatically registered to system. (e.g. File DB) \n - * If there is another file has same name on registering directory, new one's name would have numbering postfix. \n - * (e.g. abc.mp3 to abc_1.mp3) - * - * @param[in] url url to start download - * @param[out] da_dl_req_id assigned download request id for this URL - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. - * - * @see None. - * - * @par Example - * @code - * #include - * - * int da_ret; - * int da_dl_req_id; - * char* url = "http://www.test.com/sample.mp3"; - * - * da_ret = da_start_download(url,&da_dl_req_id); - * if (da_ret == DA_RESULT_OK) - * printf("download requesting is successed\n"); - * else - * printf("download requesting is failed with error code %d\n", da_ret); - * @endcode - */ -int da_start_download( - const char *url, - da_handle_t *da_dl_req_id -); - -/** -* @fn int da_start_download_with_extension(const char *url, da_handle_t *da_dl_req_id, ...) -* @ingroup Reference -* @brief This function starts to download a content on passed URL with passed extension. -* -* Useful information and result are conveyed through following callbacks. -* @li da_notify_cb -* @li da_update_download_info_cb -* -* @pre da_init() must be called in advance. -* @post None. -* @remarks This API operation is exactly same with da_start_download(), except for input properties. \n -* Input properties' count is unlimited, but they MUST be a pair(name and value) and terminated by NULL. \n -* Refer to following for property name and value type. \n -* -* @li DA_FEATURE_REQUEST_HEADER : char** int * \n -* @li DA_FEATURE_USER_DATA : void* \n -* @li DA_FEATURE_INSTALL_PATH : char* \n -* @li DA_FEATURE_FILE_NAME : char* \n -* -* @see ExtensionFeatures -* -* @param[in] url url to start download -* @param[out] da_dl_req_id assigned download request id for this URL -* @param[in] first_property_name first property name to supply -* @param[in] first_property_value first property value to supply. This value's type can be int, char* or void*, which is up to first_property_name. -* @param[in] ... -* @return DA_RESULT_OK for success, or DA_ERR_XXX for fail. DA_ERR_XXX is defined at download-agent-def.h. -* -* -* @par Example -* @code - #include - - int da_ret; - int da_dl_req_id; - const char *url = "https://www.test.com/sample.mp3"; - const char *install_path = "/myFiles/music"; - const char *my_data = strdup("data"); // should free after getting DA_STATE_FINISHED or DA_STATE_FAILED or DA_STATE_CANCELED - - da_ret = da_start_download_with_extension(url, &da_dl_req_id, DA_FEATURE_INSTALL_PATH, install_path - , DA_FEATURE_USER_DATA, (void*)my_data, NULL); - if (da_ret == DA_RESULT_OK) - printf("download requesting is successed\n"); - else - printf("download requesting is failed with error code %d\n", da_ret); - @endcode -*/ -int da_start_download_with_extension( - const char *url, - da_handle_t *da_dl_req_id, - ... -); - - -/** - * @fn int da_cancel_download(da_handle_t da_dl_req_id) - * @ingroup Reference - * @brief This function cancels a download for passed da_dl_req_id. - * - * Client can use this function if user wants to cancel already requested download. - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then previous requested download can be keep downloading. - * @remarks After calling this function, all information for the da_dl_req_id will be deleted. So, client cannot request anything for the da_dl_req_id. - * - * @pre There should be exist ongoing or suspended download for da_dl_req_id. - * @post None. - * - * @param[in] da_dl_req_id download request id - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail - * - * @see None. - * - * @par Example - * @code - #include - - int da_ret; - int da_dl_req_id; - - da_ret = da_cancel_download(da_dl_req_id); - if(da_ret == DA_RESULT_OK) { - // printf("download with [%d] is successfully canceled.\n", da_dl_req_id); - } - else { - // in this case, downloading with da_dl_req_id is keep ongoing. - printf("failed to cancel with error code %d\n", da_ret); - } - @endcode - */ -int da_cancel_download( - da_handle_t da_dl_req_id -); - - -/** - * @fn int da_suspend_download(da_handle_t da_dl_req_id) - * @ingroup Reference - * @brief This function suspends downloading for passed da_dl_req_id. - * - * Client can use this function if user wants to suspend already requested download. - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then previous requested download can be keep downloading. - * @remarks After calling this function, all information for the da_dl_req_id will be remained. So, client can request resume for the da_dl_req_id. - * @remarks Client should cancel or resume for this da_dl_req_id, or all information for the da_dl_req_id will be leaved forever. - * - * @pre There should be exist ongoing download for da_dl_req_id. - * @post None. - * - * @param[in] da_dl_req_id download request id - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail - * - * @see da_resume_download() - * @see da_cancel_download() - * - * @par Example - * @code - #include - - int da_ret; - int da_dl_req_id; - - da_ret = da_suspend_download(da_dl_req_id); - if(da_ret == DA_RESULT_OK) { - // printf("download with [%d] is successfully suspended.\n", da_dl_req_id); - } - else { - // in this case, downloading with da_dl_req_id is keep ongoing. - printf("failed to suspend with error code %d\n", da_ret); - } - @endcode - */ -int da_suspend_download( - da_handle_t da_dl_req_id -); - - - -/** - * @fn int da_resume_download(da_handle_t da_dl_req_id) - * @ingroup Reference - * @brief This function resumes downloading for passed da_dl_req_id. - * - * Client can use this function if user wants to resume suspended download. - * - * @remarks Should check return value. \n - * If return value is not DA_RESULT_OK, then requested download can be not to resume. - * - * @pre There should be exist suspended download for da_dl_req_id. - * @post None. - * - * @param[in] da_dl_req_id download request id - * @return DA_RESULT_OK for success, or DA_ERR_XXX for fail - * - * @see da_suspend_download() - * - * @par Example - * @code - #include - - int da_ret; - int da_dl_req_id; - - da_ret = da_resume_download(da_dl_req_id); - if(da_ret == DA_RESULT_OK) { - // printf("download with [%d] is successfully resumed.\n", da_dl_req_id); - } - else { - // in this case, downloading with da_dl_req_id is keep suspended. - printf("failed to resume with error code %d\n", da_ret); - } - @endcode - */ -int da_resume_download( - da_handle_t da_dl_req_id -); - - -/** -* @} -*/ - -/** -*@} -*/ - -#ifdef __cplusplus - } -#endif - -#endif //_Download_Agent_Interface_H - - diff --git a/src/agent/include/download-agent-mime-util.h b/src/agent/include/download-agent-mime-util.h deleted file mode 100644 index 4eb5382..0000000 --- a/src/agent/include/download-agent-mime-util.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-mime-util.h - * @brief - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - * @author Jungki Kwak(jungki.kwak@samsung.com) - ***/ - -#ifndef _Download_Agent_Mime_Table_H -#define _Download_Agent_Mime_Table_H - -#include "download-agent-type.h" - -#define NO_EXTENSION_NAME_STR "dat" - -typedef struct { - char *standard; - char *normal; -} Ext_translation_table; - -da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type); -da_bool_t da_get_extension_name_from_url(char* url, char** ext); -da_result_t da_mime_get_ext_name(char* mime, char **ext); -da_bool_t da_get_file_name_from_url(char* url, char** name) ; -void delete_prohibited_char(char* szTarget, int str_len); -#endif diff --git a/src/agent/include/download-agent-plugin-conf.h b/src/agent/include/download-agent-plugin-conf.h deleted file mode 100644 index 8baad4c..0000000 --- a/src/agent/include/download-agent-plugin-conf.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-conf.h - * @brief Including some functions to get configuration data from platform - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - -#ifndef _Download_Agent_Plugin_Conf_H -#define _Download_Agent_Plugin_Conf_H - -#include "download-agent-type.h" -#include "download-agent-interface.h" -#include "download-agent-utils.h" - -da_result_t get_user_agent_string(char **uagent_str); -da_result_t get_storage_type(da_storage_type_t *type); -char *get_proxy_address(void); - -#endif diff --git a/src/agent/include/download-agent-plugin-http-interface.h b/src/agent/include/download-agent-plugin-http-interface.h deleted file mode 100644 index 0cd733b..0000000 --- a/src/agent/include/download-agent-plugin-http-interface.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-http-interface.h - * @brief Including functions regarding http plugin interface - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Plugin_Http_Interface_H -#define _Download_Agent_Plugin_Http_Interface_H - -#include "download-agent-type.h" -#include "download-agent-http-msg-handler.h" - -typedef enum { - PI_HTTP_METHOD_GET = 1, - PI_HTTP_METHOD_POST = 2, - PI_HTTP_METHOD_HEAD = 3 -} pi_http_method_t; - - -typedef struct _input_for_tranx_t { - pi_http_method_t http_method; - - char *proxy_addr; - queue_t *queue; - - http_msg_request_t* http_msg_request; -} input_for_tranx_t; - - - -da_result_t PI_http_init(void); -void PI_http_deinit(void); - -da_result_t PI_http_start_transaction(const input_for_tranx_t *input_for_tranx, int *out_tranx_id); -da_result_t PI_http_cancel_transaction(int in_tranx_id, da_bool_t abort_option); -da_result_t PI_http_disconnect_transaction(int in_tranx_id); -void PI_http_pause_transaction(int transaction_id); -void PI_http_unpause_transaction(int transaction_id); - -#endif - diff --git a/src/agent/include/download-agent-plugin-install.h b/src/agent/include/download-agent-plugin-install.h deleted file mode 100644 index cdf48fe..0000000 --- a/src/agent/include/download-agent-plugin-install.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-install.h - * @brief Including functions for installing a content - * @author Jungki,Kwak(jungki.kwak@samsung.com) - ***/ - - -#ifndef _Download_Agent_Plugin_Install_H -#define _Download_Agent_Plugin_Install_H - -#include "download-agent-type.h" - -char *PI_get_default_install_dir(void); - -#endif diff --git a/src/agent/include/download-agent-plugin-libsoup.h b/src/agent/include/download-agent-plugin-libsoup.h deleted file mode 100644 index a8a7284..0000000 --- a/src/agent/include/download-agent-plugin-libsoup.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-plugin-libsoup.h - * @brief Including functions regarding libsoup plugin - * @author Jungki Kwak (jungki.kwak@samsung.com) - ***/ - - -#ifndef _Download_Agent_Plugin_Libsoup_H -#define _Download_Agent_Plugin_Libsoup_H - -#include -#include - -#include "download-agent-http-queue.h" -#include "download-agent-pthread.h" -#include "download-agent-plugin-http-interface.h" - -typedef struct _pi_session_table_t { - da_bool_t is_using; - SoupSession *session; - SoupMessage *msg; - queue_t *queue; - pthread_mutex_t mutex; - pthread_cond_t cond; - da_bool_t is_paused; -} pi_session_table_t; - -extern pi_session_table_t pi_session_table[]; - -#define MAX_SESSION_COUNT DA_MAX_DOWNLOAD_REQ_AT_ONCE -#define MAX_TIMEOUT 180 // second - -#define IS_VALID_SESSION_TABLE_ENTRY(ENTRY) ((((ENTRY) < 0) || ((ENTRY) > MAX_SESSION_COUNT-1)) ? 0 : 1) - - -#define GET_SESSION_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].session) -#define GET_MSG_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].msg) -#define GET_QUEUE_FROM_TABLE_ENTRY(ENTRY) (pi_session_table[ENTRY].queue) - - -da_bool_t _pi_http_is_valid_input_for_tranx(const input_for_tranx_t *input_for_tranx); - -void _pi_http_init_session_table_entry(const int in_session_table_entry); -void _pi_http_destroy_session_table_entry(const int in_session_table_entry); -int _pi_http_get_avaiable_session_table_entry(void); - -da_bool_t _pi_http_register_queue_to_session_table(const int session_table_entry, const queue_t *in_queue); -da_bool_t _pi_http_register_session_to_session_table(const int in_session_table_entry, SoupSession *session); -da_bool_t _pi_http_register_msg_to_session_table(const int in_session_table_entry, SoupMessage *msg); - -queue_t * _pi_http_get_queue_from_session_table_entry(const int in_session_table_entry); -int _pi_http_get_session_table_entry_from_message(SoupMessage *msg); - -void _pi_http_store_read_data_to_queue(SoupMessage *msg,const char* body_data, int received_body_len); -void _pi_http_store_read_header_to_queue(SoupMessage *msg, const char *sniffedType); -void _pi_http_store_neterr_to_queue(SoupMessage *msg); - - -void _pi_http_finished_cb(SoupSession *session, SoupMessage* msg, gpointer data); -void _pi_http_restarted_cb(SoupMessage* msg, gpointer data); -void _pi_http_gotheaders_cb(SoupMessage* msg, gpointer data); -void _pi_http_contentsniffed_cb(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data); -void _pi_http_gotchunk_cb(SoupMessage* msg, SoupBuffer* chunk, gpointer data); - - -#endif diff --git a/src/agent/include/download-agent-pthread.h b/src/agent/include/download-agent-pthread.h deleted file mode 100644 index cc43b06..0000000 --- a/src/agent/include/download-agent-pthread.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-pthread.h - * @brief Wrapping pthread functions - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Pthread_H -#define _Download_Agent_Pthread_H - -#include -#include -#include - -#include "download-agent-type.h" -#include "download-agent-debug.h" - -#define _da_thread_mutex_init(mutex_add, attr) { \ - int ret = 0; \ - do{ \ - ret = pthread_mutex_init(mutex_add, attr); \ - if (0 == ret){ \ - break; \ - } \ - else if(EINVAL == ret){ \ - DA_LOG_ERR(Default, "pthread_mutex_init FAIL with EINVAL."); \ - break; \ - } \ - else if(ENOMEM == ret){ \ - DA_LOG_ERR(Default, "pthread_mutex_init FAIL with ENOMEM."); \ - break; \ - } \ - else{ \ - DA_LOG_ERR(Default, "pthread_mutex_init FAIL with %d.", ret); \ - break; \ - } \ - }while(1); \ - } - -#define _da_thread_cond_init(cond_add, attr) do{ \ - if (0 != pthread_cond_init(cond_add, attr)){\ - DA_LOG_ERR(Default, "pthread_cond_init FAIL");} \ - }while(0) - - - -#define _da_thread_mutex_lock(mutex_add) {\ - int ret = 0;\ - do{\ - ret = pthread_mutex_lock(mutex_add);\ - if (0 == ret){\ - break;\ - }\ - else if(EINVAL == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with EINVAL.");\ - break;\ - }\ - else if(EDEADLK == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with EDEADLK.");\ - break;\ - }\ - else{\ - DA_LOG_ERR(Default, "pthread_mutex_lock FAIL with %d.", ret);\ - break;\ - }\ - }while(1);\ - } - - -#define _da_thread_mutex_unlock(mutex_add) {\ - int ret = 0;\ - do{\ - ret = pthread_mutex_unlock(mutex_add);\ - if (0 == ret){\ - break;\ - }\ - else if(EINVAL == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with EINVAL.");\ - break;\ - }\ - else if(EPERM == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with EPERM.");\ - break;\ - }\ - else{\ - DA_LOG_ERR(Default, "pthread_mutex_unlock FAIL with %d.", ret);\ - break;\ - }\ - }while(1);\ - } - - -#define _da_thread_cond_signal(cond_add) do{ \ - if (0 != pthread_cond_signal(cond_add)){\ - DA_LOG_ERR(Default, "pthread_cond_signal FAIL");} \ - }while(0) - - - -#define _da_thread_cond_wait(cond_add, mutex_add) do{ \ - if (0 != pthread_cond_wait(cond_add, mutex_add)){\ - DA_LOG_ERR(Default, "pthread_cond_wait FAIL");} \ - }while(0) - -#define _da_thread_cond_timed_wait(cond_add, mutex_add, time) do{ \ - if (0 != pthread_cond_timedwait(cond_add, mutex_add, time)){\ - DA_LOG_ERR(Default, "pthread_cond_wait FAIL");} \ - }while(0) - - -#define _da_thread_cond_destroy(cond_add) do{ \ - if (0 != pthread_cond_destroy(cond_add)){\ - DA_LOG_ERR(Default, "pthread_cond_destroy FAIL");} \ - }while(0) - -#define _da_thread_mutex_destroy(mutex_add) {\ - int ret = 0;\ - do{\ - ret = pthread_mutex_destroy(mutex_add);\ - if (0 == ret){\ - break;\ - }\ - else if(EINVAL == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with EINVAL.");\ - break;\ - }\ - else if(EBUSY == ret){\ - DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with EBUSY.");\ - break;\ - }\ - else{\ - DA_LOG_ERR(Default, "pthread_mutex_destroy FAIL with %d.", ret);\ - break;\ - }\ - }while(1);\ - } - -#endif diff --git a/src/agent/include/download-agent-type.h b/src/agent/include/download-agent-type.h deleted file mode 100644 index 0bdb753..0000000 --- a/src/agent/include/download-agent-type.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-type.h - * @brief including types and defines for Download Agent. This is internally used - * @author Jungki Kwak (jungki.kwak@samsung.com) - */ - -#ifndef _Download_Agent_Types_H -#define _Download_Agent_Types_H - -#include "download-agent-defs.h" - -typedef int da_result_t; -typedef int da_bool_t; - -#define IS_NOT_VALID_ID(x) (x <= DA_INVALID_ID) - -#define DA_MAX_URI_LEN 1024 -#define DA_MAX_FULL_PATH_LEN 356 // need configuration -#define DA_MAX_FILE_PATH_LEN 256 // need configuration -#define DA_MAX_STR_LEN 256 -#define DA_MAX_MIME_STR_LEN 256 -#define DA_MAX_PROXY_ADDR_LEN 64 // e.g. 100.200.300.400:10000 - - -#endif - diff --git a/src/agent/include/download-agent-utils-dl-req-id-history.h b/src/agent/include/download-agent-utils-dl-req-id-history.h deleted file mode 100644 index d255b42..0000000 --- a/src/agent/include/download-agent-utils-dl-req-id-history.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-utils-dl-req-id-history.h - * @brief Including operations for dl-req-id-history - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Utils_Hash_Table_H -#define _Download_Agent_Utils_Hash_Table_H - -#include "download-agent-pthread.h" - -typedef struct _dl_req_id_history_t dl_req_id_history_t; -struct _dl_req_id_history_t { - int starting_num; - int cur_dl_req_id; - pthread_mutex_t mutex; -}; - -da_result_t init_dl_req_id_history(dl_req_id_history_t *dl_req_id_history); -da_result_t deinit_dl_req_id_history(dl_req_id_history_t *dl_req_id_history); - -int get_available_dl_req_id(dl_req_id_history_t *dl_req_id_history); - - -#endif /* _Download_Agent_Utils_Hash_Table_H */ diff --git a/src/agent/include/download-agent-utils.h b/src/agent/include/download-agent-utils.h deleted file mode 100644 index fddd56c..0000000 --- a/src/agent/include/download-agent-utils.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Download Agent - * - * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungki Kwak , Keunsoon Lee - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file download-agent-utils.h - * @brief Including some utilitis - * @author Keunsoon Lee(keunsoon.lee@samsung.com) - ***/ - - -#ifndef _Download_Agent_Utils_H -#define _Download_Agent_Utils_H - -#include -#include "download-agent-defs.h" -#include "download-agent-interface.h" -#include "download-agent-dl-mgr.h" - -/* Todo : move these to mime-util.c */ -#define MIME_ODF "application/vnd.oasis.opendocument.formula" -#define MIME_OMA_DD "application/vnd.oma.dd+xml" -#define MIME_MIDP_JAR "application/vnd.sun.j2me.java-archive" -#define MIME_MULTIPART_MESSAGE "multipart/related" -#define MIME_TEXT_PLAIN "text/plain" - -#define SAVE_FILE_BUFFERING_SIZE_50KB (50*1024) -#define SAVE_FILE_BUFFERING_SIZE_5MB (5*1024*1024) - -#define DA_SLEEP(x) \ - do \ - { \ - struct timespec interval,remainder; \ - interval.tv_sec = (unsigned int)((x)/1000); \ - interval.tv_nsec = (((x)-(interval.tv_sec*1000))*1000000); \ - nanosleep(&interval,&remainder); \ - } while(0) - -typedef enum { - DA_STORAGE_PHONE, /*To Store in Phone memory*/ - DA_STORAGE_MMC, /*To Store in MMC */ - DA_STORAGE_SYSTEM /*To Store in both Phone and MMC*/ -} da_storage_type_t; - -typedef struct _da_storage_size_t { - unsigned long b_available; - unsigned long b_size; -} da_storage_size_t; - -void get_random_number(int *out_num); -da_result_t get_available_dd_id(da_handle_t *available_id); - -da_result_t get_extension_from_mime_type(char *mime_type, char **extension); - -da_result_t get_available_memory(da_storage_type_t storage_type, da_storage_size_t *avail_memory); -da_result_t check_enough_storage(stage_info *stage); - -da_bool_t is_valid_url(const char* url, da_result_t *err_code); - -int read_data_from_file(char *file, char**out_buffer); - -da_result_t move_file(const char *from_path, const char *to_path); -void remove_file(const char *file_path); - -char* print_dl_state(da_state state); - -char* _stristr(const char* long_str, const char* find_str); - -#endif diff --git a/src/download-provider-db.c b/src/download-provider-db.c deleted file mode 100644 index f72ca59..0000000 --- a/src/download-provider-db.c +++ /dev/null @@ -1,1096 +0,0 @@ -#include - -#include -#include - -#include "download-provider-config.h" -#include "download-provider-db.h" -#include "download-provider-log.h" - -__thread sqlite3 *g_download_provider_db = 0; - -void __download_provider_db_close() -{ - if (g_download_provider_db) { - db_util_close(g_download_provider_db); - } - g_download_provider_db = 0; -} - -int __download_provider_db_open() -{ - if (db_util_open(DOWNLOAD_PROVIDER_DOWNLOADING_DB_NAME, - &g_download_provider_db, - DB_UTIL_REGISTER_HOOK_METHOD) != SQLITE_OK) { - TRACE_DEBUG_MSG("failed db_util_open [%s][%s]", - DOWNLOAD_PROVIDER_DOWNLOADING_DB_NAME, - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; - } - return g_download_provider_db ? 0 : -1; -} - -void _download_provider_sql_close(sqlite3_stmt *stmt) -{ - if (sqlite3_finalize(stmt) != SQLITE_OK) - TRACE_DEBUG_MSG("failed sqlite3_finalize [%s]", - sqlite3_errmsg(g_download_provider_db)); - - __download_provider_db_close(); -} - -int _download_provider_sql_open() -{ - __download_provider_db_close(); - return __download_provider_db_open(); -} - -int download_provider_db_requestinfo_remove(int uniqueid) -{ - int errorcode; - sqlite3_stmt *stmt = NULL; - - if (uniqueid <= 0) { - TRACE_DEBUG_MSG("[NULL-CHECK]"); - return -1; - } - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "delete from downloading where uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, uniqueid) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - _download_provider_sql_close(stmt); - return 0; - } - TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; -} - -int download_provider_db_requestinfo_new(download_clientinfo *clientinfo) -{ - int errorcode; - sqlite3_stmt *stmt = NULL; - - if (!clientinfo || !clientinfo->requestinfo - || clientinfo->requestinfo->requestid <= 0) { - TRACE_DEBUG_MSG("[NULL-CHECK]"); - return -1; - } - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "INSERT INTO downloading (uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath) VALUES (?, ?, ?, ?, ?, DATETIME('now'), ?, ?, ?, ?)", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, clientinfo->requestinfo->requestid) != - SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (clientinfo->requestinfo->client_packagename.length > 1) { - if (sqlite3_bind_text - (stmt, 2, clientinfo->requestinfo->client_packagename.str, - -1, NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - // notification - if (sqlite3_bind_int(stmt, 3, clientinfo->requestinfo->notification) != - SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (clientinfo->downloadinfo && sizeof(clientinfo->downloadinfo->content_name) > 1) { - if (sqlite3_bind_text - (stmt, 5, clientinfo->downloadinfo->content_name, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - if (sqlite3_bind_int(stmt, 6, clientinfo->state) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (clientinfo->requestinfo->url.length > 1) { - if (sqlite3_bind_text - (stmt, 7, clientinfo->requestinfo->url.str, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - if (clientinfo->downloadinfo && sizeof(clientinfo->downloadinfo->mime_type) > 1) { - if (sqlite3_bind_text - (stmt, 8, clientinfo->downloadinfo->mime_type, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - if (clientinfo->tmp_saved_path) { - if (sqlite3_bind_text - (stmt, 9, clientinfo->tmp_saved_path, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - _download_provider_sql_close(stmt); - return 0; - } - TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; -} - -int download_provider_db_requestinfo_update_column(download_clientinfo *clientinfo, - download_db_column_type type) -{ - int errorcode; - sqlite3_stmt *stmt = NULL; - - if (!clientinfo || !clientinfo->requestinfo - || clientinfo->requestinfo->requestid <= 0) { - TRACE_DEBUG_MSG("[NULL-CHECK]"); - return -1; - } - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - switch (type) { - case DOWNLOAD_DB_PACKAGENAME: - if (clientinfo->requestinfo->client_packagename.length <= 1 - || !clientinfo->requestinfo->client_packagename.str) { - TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "UPDATE downloading SET packagename = ? WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_text - (stmt, 1, clientinfo->requestinfo->client_packagename.str, - -1, NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - break; - case DOWNLOAD_DB_NOTIFICATION: - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "UPDATE downloading SET notification = ? WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int - (stmt, 1, - clientinfo->requestinfo->notification) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - break; - case DOWNLOAD_DB_STATE: - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "UPDATE downloading SET state = ? WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, clientinfo->state) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - break; - case DOWNLOAD_DB_MIMETYPE: - if (!clientinfo->downloadinfo) { - TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "UPDATE downloading SET mimetype = ? WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_text - (stmt, 1, clientinfo->downloadinfo->mime_type, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - break; - case DOWNLOAD_DB_FILENAME: - if (!clientinfo->downloadinfo - || sizeof(clientinfo->downloadinfo->content_name) < 1) { - TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "UPDATE downloading SET filename = ? WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_text - (stmt, 1, clientinfo->downloadinfo->content_name, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - break; - case DOWNLOAD_DB_SAVEDPATH: - if (!clientinfo->tmp_saved_path) { - TRACE_DEBUG_MSG("[NULL-CHECK] type [%d]", type); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "UPDATE downloading SET savedpath = ? WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_text - (stmt, 1, clientinfo->tmp_saved_path, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - break; - default: - TRACE_DEBUG_MSG("Wrong type [%d]", type); - return -1; - } - - if (sqlite3_bind_int(stmt, 2, clientinfo->requestinfo->requestid) != - SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - _download_provider_sql_close(stmt); - return 0; - } - TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; -} - -download_dbinfo_list *download_provider_db_get_list(int state) -{ - int errorcode; - int listcount; - int i = 0; - int buffer_length = 0; - sqlite3_stmt *stmt = NULL; - char *buffer; - download_dbinfo_list *m_list = NULL; - - listcount = download_provider_db_list_count(state); - if (listcount <= 0) - return NULL; - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return NULL; - } - - if (state != DOWNLOAD_STATE_NONE) { - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "SELECT uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath FROM downloading WHERE state = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - if (sqlite3_bind_int(stmt, 1, state) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - } else { - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "SELECT uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath FROM downloading", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - } - m_list = (download_dbinfo_list *) calloc(1, sizeof(download_dbinfo_list)); - m_list->item = - (download_dbinfo *) calloc(listcount, sizeof(download_dbinfo)); - m_list->count = listcount; - - while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW - && (i < listcount)) { - m_list->item[i].requestid = sqlite3_column_int(stmt, 0); - buffer = (char *)(sqlite3_column_text(stmt, 1)); - m_list->item[i].packagename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].packagename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].packagename, buffer, - buffer_length * sizeof(char)); - m_list->item[i].packagename[buffer_length] = '\0'; - } - m_list->item[i].notification = sqlite3_column_int(stmt, 2); - buffer = (char *)(sqlite3_column_text(stmt, 3)); - m_list->item[i].installpath = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].installpath - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].installpath, buffer, - buffer_length * sizeof(char)); - m_list->item[i].installpath[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 4)); - m_list->item[i].filename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].filename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].filename, buffer, - buffer_length * sizeof(char)); - m_list->item[i].filename[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 5)); - m_list->item[i].createdate = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].createdate - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].createdate, buffer, - buffer_length * sizeof(char)); - m_list->item[i].createdate[buffer_length] = '\0'; - } - m_list->item[i].state = sqlite3_column_int(stmt, 6); - buffer = (char *)(sqlite3_column_text(stmt, 7)); - m_list->item[i].url = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].url - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].url, buffer, - buffer_length * sizeof(char)); - m_list->item[i].url[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 8)); - m_list->item[i].mimetype = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].mimetype - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].mimetype, buffer, - buffer_length * sizeof(char)); - m_list->item[i].mimetype[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 9)); - m_list->item[i].saved_path = NULL; - if (buffer) { - buffer_length = strlen(buffer); - m_list->item[i].saved_path - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(m_list->item[i].saved_path, buffer, - buffer_length * sizeof(char)); - m_list->item[i].saved_path[buffer_length] = '\0'; - } - i++; - } - m_list->count = i; - - if (i <= 0) { - TRACE_DEBUG_MSG("sqlite3_step is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - download_provider_db_list_free(m_list); - return NULL; - } - _download_provider_sql_close(stmt); - return m_list; -} - -int download_provider_db_list_count(int state) -{ - int errorcode; - int count = 0; - sqlite3_stmt *stmt = NULL; - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - if (state != DOWNLOAD_STATE_NONE) { - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "SELECT count(*) FROM downloading WHERE state = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, state) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } else { - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "SELECT count(*) FROM downloading", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_ROW) { - count = sqlite3_column_int(stmt, 0); - _download_provider_sql_close(stmt); - return count; - } - TRACE_DEBUG_MSG("sqlite3_step is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return 0; -} - -void download_provider_db_info_free(download_dbinfo *info) -{ - if (!info) - return; - - info->requestid = 0; - if (info->packagename) - free(info->packagename); - info->packagename = NULL; - if (info->installpath) - free(info->installpath); - info->installpath = NULL; - if (info->filename) - free(info->filename); - info->filename = NULL; - if (info->createdate) - free(info->createdate); - info->createdate = NULL; - if (info->url) - free(info->url); - info->url = NULL; - if (info->mimetype) - free(info->mimetype); - info->mimetype = NULL; - if (info->etag) - free(info->etag); - info->etag = NULL; - if (info->saved_path) - free(info->saved_path); - info->saved_path = NULL; -} - -void download_provider_db_list_free(download_dbinfo_list *list) -{ - int i = 0; - if (!list) - return; - - if (list->count > 0 && list->item) { - for (i = 0; i < list->count; i++) - download_provider_db_info_free(&list->item[i]); - list->count = 0; - free(list->item); - list->item = NULL; - } - free(list); - list = NULL; -} - -download_dbinfo *download_provider_db_get_info(int requestid) -{ - if (requestid <= 0) - return NULL; - - int errorcode; - int buffer_length = 0; - sqlite3_stmt *stmt = NULL; - char *buffer = NULL; - download_dbinfo *dbinfo = NULL; - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return NULL; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "SELECT uniqueid, packagename, notification, installpath, filename, creationdate, state, url, mimetype, savedpath FROM downloading WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - if (sqlite3_bind_int(stmt, 1, requestid) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - - if ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { - dbinfo = (download_dbinfo *) calloc(1, sizeof(download_dbinfo)); - dbinfo->requestid = sqlite3_column_int(stmt, 0); - buffer = (char *)(sqlite3_column_text(stmt, 1)); - dbinfo->packagename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->packagename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->packagename, buffer, - buffer_length * sizeof(char)); - dbinfo->packagename[buffer_length] = '\0'; - } - dbinfo->notification = sqlite3_column_int(stmt, 2); - buffer = (char *)(sqlite3_column_text(stmt, 3)); - dbinfo->installpath = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->installpath - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->installpath, buffer, - buffer_length * sizeof(char)); - dbinfo->installpath[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 4)); - dbinfo->filename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->filename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->filename, buffer, - buffer_length * sizeof(char)); - dbinfo->filename[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 5)); - dbinfo->createdate = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->createdate - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->createdate, buffer, - buffer_length * sizeof(char)); - dbinfo->createdate[buffer_length] = '\0'; - } - dbinfo->state = sqlite3_column_int(stmt, 6); - buffer = (char *)(sqlite3_column_text(stmt, 7)); - dbinfo->url = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->url - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->url, buffer, - buffer_length * sizeof(char)); - dbinfo->url[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 8)); - dbinfo->mimetype = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->mimetype - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->mimetype, buffer, - buffer_length * sizeof(char)); - dbinfo->mimetype[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 9)); - dbinfo->saved_path = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->saved_path - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->saved_path, buffer, - buffer_length * sizeof(char)); - dbinfo->saved_path[buffer_length] = '\0'; - } - } else { - TRACE_DEBUG_MSG("sqlite3_step is failed. [%s] errorcode[%d]", - sqlite3_errmsg(g_download_provider_db), errorcode); - __download_provider_db_close(); - download_provider_db_info_free(dbinfo); - free(dbinfo); - return NULL; - } - _download_provider_sql_close(stmt); - return dbinfo; -} - -download_request_info *download_provider_db_get_requestinfo(download_dbinfo *dbinfo) -{ - if (!dbinfo || dbinfo->requestid <= 0) - return NULL; - - download_request_info *requestinfo = - (download_request_info *) calloc(1, sizeof(download_request_info)); - requestinfo->requestid = dbinfo->requestid; - if (dbinfo->packagename) { - requestinfo->client_packagename.length = - strlen(dbinfo->packagename); - if (requestinfo->client_packagename.length > 1) { - requestinfo->client_packagename.str - = - (char *) - calloc((requestinfo->client_packagename.length + 1), - sizeof(char)); - memcpy(requestinfo->client_packagename.str, - dbinfo->packagename, - requestinfo->client_packagename.length * - sizeof(char)); - requestinfo->client_packagename.str[requestinfo-> - client_packagename. - length] = '\0'; - } - } - if (dbinfo->url) { - requestinfo->url.length = strlen(dbinfo->url); - if (requestinfo->url.length > 1) { - requestinfo->url.str - = - (char *)calloc((requestinfo->url.length + 1), - sizeof(char)); - memcpy(requestinfo->url.str, dbinfo->url, - requestinfo->url.length * sizeof(char)); - requestinfo->url.str[requestinfo->url.length] = '\0'; - } - } - if (dbinfo->installpath) { - requestinfo->install_path.length = strlen(dbinfo->installpath); - if (requestinfo->install_path.length > 1) { - requestinfo->install_path.str - = - (char *) - calloc((requestinfo->install_path.length + 1), - sizeof(char)); - memcpy(requestinfo->install_path.str, - dbinfo->installpath, - requestinfo->install_path.length * sizeof(char)); - requestinfo->install_path.str[requestinfo->install_path. - length] = '\0'; - } - } - if (dbinfo->filename) { - requestinfo->filename.length = strlen(dbinfo->filename); - if (requestinfo->filename.length > 1) { - requestinfo->filename.str - = - (char *)calloc((requestinfo->filename.length + 1), - sizeof(char)); - memcpy(requestinfo->filename.str, dbinfo->filename, - requestinfo->filename.length * sizeof(char)); - requestinfo->filename.str[requestinfo->filename. - length] = '\0'; - } - } - // disable callback. - memset(&requestinfo->callbackinfo, 0x00, sizeof(callback_info)); - requestinfo->notification = dbinfo->notification; - return requestinfo; -} - -int download_provider_db_history_new(download_clientinfo *clientinfo) -{ - int errorcode; - sqlite3_stmt *stmt = NULL; - - if (!clientinfo || !clientinfo->requestinfo - || clientinfo->requestinfo->requestid <= 0) { - TRACE_DEBUG_MSG("[NULL-CHECK]"); - return -1; - } - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "INSERT INTO history (uniqueid, packagename, filename, creationdate, state, mimetype, savedpath) VALUES (?, ?, ?, DATETIME('now'), ?, ?, ?)", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, clientinfo->requestinfo->requestid) != - SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (clientinfo->requestinfo->client_packagename.length > 1) { - if (sqlite3_bind_text - (stmt, 2, clientinfo->requestinfo->client_packagename.str, - -1, NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - if (clientinfo->downloadinfo && sizeof(clientinfo->downloadinfo->content_name) > 1) { - if (sqlite3_bind_text - (stmt, 3, clientinfo->downloadinfo->content_name, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - if (sqlite3_bind_int(stmt, 4, clientinfo->state) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (clientinfo->downloadinfo && sizeof(clientinfo->downloadinfo->mime_type) > 1) { - if (sqlite3_bind_text - (stmt, 5, clientinfo->downloadinfo->mime_type, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - if (clientinfo->tmp_saved_path) { - if (sqlite3_bind_text - (stmt, 6, clientinfo->tmp_saved_path, -1, - NULL) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_text is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - _download_provider_sql_close(stmt); - download_provider_db_history_limit_rows(); - return 0; - } - TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; -} - -int download_provider_db_history_remove(int uniqueid) -{ - int errorcode; - sqlite3_stmt *stmt = NULL; - - if (uniqueid <= 0) { - TRACE_DEBUG_MSG("[NULL-CHECK]"); - return -1; - } - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "delete from history where uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, uniqueid) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - _download_provider_sql_close(stmt); - return 0; - } - TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; -} - -int download_provider_db_history_limit_rows() -{ - int errorcode; - sqlite3_stmt *stmt = NULL; - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return -1; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "DELETE FROM history where uniqueid NOT IN (SELECT uniqueid FROM history ORDER BY id DESC LIMIT ?)", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - if (sqlite3_bind_int(stmt, 1, DOWNLOAD_PROVIDER_HISTORY_DB_LIMIT_ROWS) - != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return -1; - } - errorcode = sqlite3_step(stmt); - if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) { - _download_provider_sql_close(stmt); - return 0; - } - TRACE_DEBUG_MSG("sqlite3_step is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - __download_provider_db_close(); - return -1; -} - -download_dbinfo *download_provider_db_history_get_info(int requestid) -{ - if (requestid <= 0) - return NULL; - - int errorcode; - int buffer_length = 0; - sqlite3_stmt *stmt = NULL; - char *buffer = NULL; - download_dbinfo *dbinfo = NULL; - - if (_download_provider_sql_open() < 0) { - TRACE_DEBUG_MSG("db_util_open is failed [%s]", - sqlite3_errmsg(g_download_provider_db)); - return NULL; - } - - errorcode = - sqlite3_prepare_v2(g_download_provider_db, - "SELECT packagename, filename, creationdate, state, mimetype, savedpath FROM history WHERE uniqueid = ?", - -1, &stmt, NULL); - if (errorcode != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_prepare_v2 is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - if (sqlite3_bind_int(stmt, 1, requestid) != SQLITE_OK) { - TRACE_DEBUG_MSG("sqlite3_bind_int is failed. [%s]", - sqlite3_errmsg(g_download_provider_db)); - _download_provider_sql_close(stmt); - return NULL; - } - - if ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) { - dbinfo = (download_dbinfo *) calloc(1, sizeof(download_dbinfo)); - dbinfo->requestid = requestid; - TRACE_DEBUG_INFO_MSG("found id from db [%d]", requestid); - buffer = (char *)(sqlite3_column_text(stmt, 0)); - dbinfo->packagename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->packagename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->packagename, buffer, - buffer_length * sizeof(char)); - dbinfo->packagename[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 1)); - dbinfo->filename = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->filename - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->filename, buffer, - buffer_length * sizeof(char)); - dbinfo->filename[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 2)); - dbinfo->createdate = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->createdate - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->createdate, buffer, - buffer_length * sizeof(char)); - dbinfo->createdate[buffer_length] = '\0'; - } - dbinfo->state = sqlite3_column_int(stmt, 3); - buffer = (char *)(sqlite3_column_text(stmt, 4)); - dbinfo->mimetype = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->mimetype - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->mimetype, buffer, - buffer_length * sizeof(char)); - dbinfo->mimetype[buffer_length] = '\0'; - } - buffer = (char *)(sqlite3_column_text(stmt, 5)); - dbinfo->saved_path = NULL; - if (buffer) { - buffer_length = strlen(buffer); - dbinfo->saved_path - = (char *)calloc(buffer_length + 1, sizeof(char)); - memcpy(dbinfo->saved_path, buffer, - buffer_length * sizeof(char)); - dbinfo->saved_path[buffer_length] = '\0'; - } - } else { - TRACE_DEBUG_MSG("sqlite3_step is failed. [%s] errorcode[%d]", - sqlite3_errmsg(g_download_provider_db), errorcode); - __download_provider_db_close(); - download_provider_db_info_free(dbinfo); - free(dbinfo); - return NULL; - } - _download_provider_sql_close(stmt); - return dbinfo; -} diff --git a/src/download-provider-ipc.c b/src/download-provider-ipc.c deleted file mode 100644 index 835c387..0000000 --- a/src/download-provider-ipc.c +++ /dev/null @@ -1,324 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "download-provider-ipc.h" -#include "download-provider-log.h" -#include "bundle.h" - -int ipc_receive_header(int fd) -{ - if (fd <= 0) - return -1; - - download_controls msgheader = 0; - if (read(fd, &msgheader, sizeof(download_controls)) < 0) { - TRACE_DEBUG_MSG("failed to read message header (%s)", - strerror(errno)); - return -1; - } - return msgheader; -} - -int ipc_send_stateinfo(download_clientinfo *clientinfo) -{ - if (!clientinfo || clientinfo->clientfd <= 0) - return -1; - - download_state_info stateinfo; - download_controls type = DOWNLOAD_CONTROL_GET_STATE_INFO; - memset(&stateinfo, 0x00, sizeof(download_state_info)); - stateinfo.state = clientinfo->state; - stateinfo.err = clientinfo->err; - - // send control - if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - if (send(clientinfo->clientfd, &stateinfo, sizeof(download_state_info), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - return type; -} - -int ipc_send_request_stateinfo(download_clientinfo *clientinfo) -{ - if (!clientinfo || clientinfo->clientfd <= 0) - return -1; - - download_request_state_info requeststateinfo; - download_controls type = DOWNLOAD_CONTROL_GET_REQUEST_STATE_INFO; - memset(&requeststateinfo, 0x00, sizeof(download_request_state_info)); - requeststateinfo.stateinfo.state = clientinfo->state; - requeststateinfo.stateinfo.err = clientinfo->err; - if (clientinfo->requestinfo) - requeststateinfo.requestid = clientinfo->requestinfo->requestid; - - // send control - if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - if (send - (clientinfo->clientfd, &requeststateinfo, sizeof(download_request_state_info), - 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - return type; -} - -int ipc_send_downloadinfo(download_clientinfo *clientinfo) -{ - if (!clientinfo || clientinfo->clientfd <= 0 - || !clientinfo->downloadinfo) - return -1; - - download_controls type = DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO; - // send control - if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - if (send - (clientinfo->clientfd, clientinfo->downloadinfo, - sizeof(download_content_info), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - return type; -} - -int ipc_send_downloadinginfo(download_clientinfo *clientinfo) -{ - if (!clientinfo || clientinfo->clientfd <= 0 - || !clientinfo->downloadinginfo) - return -1; - - download_controls type = DOWNLOAD_CONTROL_GET_DOWNLOADING_INFO; - // send control - if (send(clientinfo->clientfd, &type, sizeof(download_controls), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - if (send - (clientinfo->clientfd, clientinfo->downloadinginfo, - sizeof(downloading_state_info), 0) < 0) { - TRACE_DEBUG_MSG("failed to send message header (%s)", - strerror(errno)); - return -1; - } - return type; -} - -extern int service_import_from_bundle(service_h service, bundle *data); -int ipc_receive_request_msg(download_clientinfo *clientinfo) -{ - if (!clientinfo || clientinfo->clientfd <= 0) - return -1; - - if (!clientinfo->requestinfo) - clientinfo->requestinfo = - (download_request_info *) calloc(1, sizeof(download_request_info)); - - if (!clientinfo->requestinfo) - return -1; - - // read reqeust structure - if (read - (clientinfo->clientfd, clientinfo->requestinfo, - sizeof(download_request_info)) < 0) { - TRACE_DEBUG_MSG("failed to read message header"); - return -1; - } - if (clientinfo->requestinfo->client_packagename.length > 1 - && clientinfo->requestinfo->client_packagename.length < DP_MAX_STR_LEN) { - clientinfo->requestinfo->client_packagename.str = - (char *) - calloc((clientinfo->requestinfo->client_packagename.length + - 1), sizeof(char)); - if (read - (clientinfo->clientfd, - clientinfo->requestinfo->client_packagename.str, - clientinfo->requestinfo->client_packagename.length * - sizeof(char)) < 0) { - TRACE_DEBUG_MSG - ("failed to read message header client_app_id(%s)", - strerror(errno)); - return -1; - } - clientinfo->requestinfo->client_packagename.str[clientinfo-> - requestinfo-> - client_packagename. - length] = '\0'; - TRACE_DEBUG_INFO_MSG("request client_packagename [%s]", - clientinfo->requestinfo->client_packagename. - str); - } - if (clientinfo->requestinfo->url.length > 1 - && clientinfo->requestinfo->url.length < DP_MAX_URL_LEN) { - clientinfo->requestinfo->url.str = - (char *)calloc((clientinfo->requestinfo->url.length + 1), - sizeof(char)); - if (read - (clientinfo->clientfd, clientinfo->requestinfo->url.str, - clientinfo->requestinfo->url.length * sizeof(char)) < 0) { - TRACE_DEBUG_MSG("failed to read message header url(%s)", - strerror(errno)); - return -1; - } - clientinfo->requestinfo->url.str[clientinfo->requestinfo->url. - length] = '\0'; - TRACE_DEBUG_INFO_MSG("request url [%s]", - clientinfo->requestinfo->url.str); - } - if (clientinfo->requestinfo->install_path.length > 1 - && clientinfo->requestinfo->install_path.length < DP_MAX_PATH_LEN) { - clientinfo->requestinfo->install_path.str = - (char *) - calloc((clientinfo->requestinfo->install_path.length + 1), - sizeof(char)); - if (read - (clientinfo->clientfd, - clientinfo->requestinfo->install_path.str, - clientinfo->requestinfo->install_path.length * - sizeof(char)) < 0) { - TRACE_DEBUG_MSG - ("failed to read message header install_path(%s)", - strerror(errno)); - return -1; - } - clientinfo->requestinfo->install_path.str[clientinfo-> - requestinfo-> - install_path.length] = - '\0'; - TRACE_DEBUG_INFO_MSG("request install_path [%s]", - clientinfo->requestinfo->install_path.str); - } - if (clientinfo->requestinfo->filename.length > 1 - && clientinfo->requestinfo->filename.length < DP_MAX_STR_LEN) { - clientinfo->requestinfo->filename.str = - (char *) - calloc((clientinfo->requestinfo->filename.length + 1), - sizeof(char)); - if (read - (clientinfo->clientfd, - clientinfo->requestinfo->filename.str, - clientinfo->requestinfo->filename.length * sizeof(char)) < - 0) { - TRACE_DEBUG_MSG - ("failed to read message header filename(%s)", - strerror(errno)); - return -1; - } - clientinfo->requestinfo->filename.str[clientinfo->requestinfo-> - filename.length] = '\0'; - TRACE_DEBUG_INFO_MSG("request filename [%s]", - clientinfo->requestinfo->filename.str); - } - if (clientinfo->requestinfo->service_data.length > 1) { - bundle_raw *raw_data = NULL; - int len = 0; - bundle *b = NULL; - service_h service_handle; - clientinfo->requestinfo->service_data.str = - (char *) - calloc((clientinfo->requestinfo->service_data.length + 1), - sizeof(char)); - if (read - (clientinfo->clientfd, - clientinfo->requestinfo->service_data.str, - clientinfo->requestinfo->service_data.length * sizeof(char)) < - 0) { - TRACE_DEBUG_MSG - ("failed to read message header filename(%s)", - strerror(errno)); - return -1; - } - clientinfo->requestinfo->service_data.str[clientinfo->requestinfo-> - service_data.length] = '\0'; - raw_data = (bundle_raw *)clientinfo->requestinfo->service_data.str; - len = clientinfo->requestinfo->service_data.length; - if ((b = bundle_decode(raw_data, len)) == NULL) { - TRACE_DEBUG_MSG("Failed to decode bundle raw data"); - return -1; - } - if (service_create(&service_handle) < 0) { - TRACE_DEBUG_MSG("Failed to create service handle"); - bundle_free(b); - return -1; - } - if (service_import_from_bundle(service_handle, b) < 0) { - TRACE_DEBUG_MSG("Failed to import service handle"); - bundle_free(b); - service_destroy(service_handle); - return -1; - } - - clientinfo->service_handle = service_handle; - char *pkg = NULL; - service_get_package(service_handle, &pkg); - if (pkg) { - TRACE_DEBUG_MSG("operation### [%s]",pkg); - free(pkg); - } - - bundle_free(b); - } - if (clientinfo->requestinfo->headers.rows) { - clientinfo->requestinfo->headers.str = - (download_flexible_string *) calloc(clientinfo->requestinfo->headers. - rows, sizeof(download_flexible_string)); - int i = 0; - for (i = 0; i < clientinfo->requestinfo->headers.rows; i++) { - if (read - (clientinfo->clientfd, - &clientinfo->requestinfo->headers.str[i], - sizeof(download_flexible_string)) < 0) { - TRACE_DEBUG_MSG - ("failed to read message header headers(%s)", - strerror(errno)); - return -1; - } - if (clientinfo->requestinfo->headers.str[i].length > 1) { - TRACE_DEBUG_INFO_MSG("headers[%d] length[%d]", i, - clientinfo->requestinfo-> - headers.str[i].length); - clientinfo->requestinfo->headers.str[i].str = - (char *) - calloc((clientinfo->requestinfo->headers. - str[i].length + 1), sizeof(char)); - if (read - (clientinfo->clientfd, - clientinfo->requestinfo->headers.str[i]. - str, - clientinfo->requestinfo->headers.str[i]. - length * sizeof(char)) < 0) { - TRACE_DEBUG_MSG - ("failed to read message header headers(%s)", - strerror(errno)); - return -1; - } - clientinfo->requestinfo->headers.str[i]. - str[clientinfo->requestinfo->headers.str[i]. - length] = '\0'; - TRACE_DEBUG_INFO_MSG("headers[%d][%s]", i, - clientinfo->requestinfo-> - headers.str[i].str); - } - } - } - return 0; -} diff --git a/src/download-provider-main.c b/src/download-provider-main.c deleted file mode 100644 index 4751fba..0000000 --- a/src/download-provider-main.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "download-provider-config.h" -#include "download-provider-log.h" - -GMainLoop *gMainLoop = 0; // need for libsoup, decided the life-time by mainloop. - -int lock_download_provider_pid(char *path); -void *run_manage_download_server(void *args); - -void TerminateDaemon(int signo) -{ - TRACE_DEBUG_INFO_MSG("Received SIGTERM"); - if (g_main_loop_is_running(gMainLoop)) - g_main_loop_quit(gMainLoop); -} - -static gboolean CreateThreadFunc(void *data) -{ - pthread_t thread_pid; - pthread_attr_t thread_attr; - if (pthread_attr_init(&thread_attr) != 0) { - TRACE_DEBUG_MSG("failed to init pthread attr"); - TerminateDaemon(SIGTERM); - return FALSE; - } - if (pthread_attr_setdetachstate(&thread_attr, - PTHREAD_CREATE_DETACHED) != 0) { - TRACE_DEBUG_MSG("failed to set detach option"); - TerminateDaemon(SIGTERM); - return 0; - } - // create thread for receiving the client request. - if (pthread_create - (&thread_pid, &thread_attr, run_manage_download_server, - data) != 0) { - TRACE_DEBUG_MSG - ("failed to create pthread for run_manage_download_server"); - TerminateDaemon(SIGTERM); - } - return FALSE; -} - -int main() -{ - if (chdir("/") < 0) { - TRACE_DEBUG_MSG("failed to call setsid or chdir"); - exit(EXIT_FAILURE); - } -#if 0 - // close all console I/O - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); -#endif - - if (signal(SIGTERM, TerminateDaemon) == SIG_ERR) { - TRACE_DEBUG_MSG("failed to register signal callback"); - exit(EXIT_FAILURE); - } - // write IPC_FD_PATH. and lock - if (lock_download_provider_pid(DOWNLOAD_PROVIDER_LOCK_PID) < 0) { - TRACE_DEBUG_MSG - ("It need to check download-provider is already alive"); - TRACE_DEBUG_MSG("Or fail to create pid file in (%s)", - DOWNLOAD_PROVIDER_LOCK_PID); - exit(EXIT_FAILURE); - } - // if exit socket file, delete it - if (access(DOWNLOAD_PROVIDER_IPC, F_OK) == 0) { - unlink(DOWNLOAD_PROVIDER_IPC); - } - // libsoup need mainloop. - - gMainLoop = g_main_loop_new(NULL, 0); - - g_type_init(); - - g_idle_add(CreateThreadFunc, gMainLoop); - - g_main_loop_run(gMainLoop); - - TRACE_DEBUG_INFO_MSG("Download-Provider will be terminated."); - - // if exit socket file, delete it - if (access(DOWNLOAD_PROVIDER_IPC, F_OK) == 0) { - unlink(DOWNLOAD_PROVIDER_IPC); - } - // delete pid file - if (access(DOWNLOAD_PROVIDER_LOCK_PID, F_OK) == 0) { - unlink(DOWNLOAD_PROVIDER_LOCK_PID); - } - exit(EXIT_SUCCESS); -} diff --git a/src/download-provider-notification.c b/src/download-provider-notification.c deleted file mode 100644 index 0bbc4de..0000000 --- a/src/download-provider-notification.c +++ /dev/null @@ -1,396 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "download-provider-notification.h" -#include "download-provider-utils.h" -#include "download-provider-log.h" - -#include - -#define S_(s) dgettext("sys_string", s) - -#define DP_NOTIFICATION_ICON_PATH IMAGE_DIR"/Q02_Notification_Download_failed.png" - -void print_app_error_message(int ret) -{ - switch (ret) { - case APP_ERROR_NONE: - TRACE_DEBUG_MSG("APP_ERROR_NONE"); - break; - case APP_ERROR_INVALID_PARAMETER: - TRACE_DEBUG_MSG("APP_ERROR_INVALID_PARAMETER"); - break; - case APP_ERROR_OUT_OF_MEMORY: - TRACE_DEBUG_MSG("APP_ERROR_OUT_OF_MEMORY"); - break; - case APP_ERROR_INVALID_CONTEXT: - TRACE_DEBUG_MSG("APP_ERROR_INVALID_CONTEXT"); - break; - case APP_ERROR_NO_SUCH_FILE: - TRACE_DEBUG_MSG("APP_ERROR_NO_SUCH_FILE"); - break; - case APP_ERROR_ALREADY_RUNNING: - TRACE_DEBUG_MSG("APP_ERROR_ALREADY_RUNNING"); - break; - default: - TRACE_DEBUG_MSG("Unknown error"); - break; - } -} - -void print_notification_error_message(int ret) -{ - switch (ret) { - case UI_NOTIFICATION_ERROR_NONE: - TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_NONE"); - break; - case UI_NOTIFICATION_ERROR_INVALID_PARAMETER: - TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_INVALID_PARAMETER"); - break; - case UI_NOTIFICATION_ERROR_OUT_OF_MEMORY: - TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_OUT_OF_MEMORY"); - break; - case UI_NOTIFICATION_ERROR_DB_FAILED: - TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_DB_FAILED"); - break; - case UI_NOTIFICATION_ERROR_NO_SUCH_FILE: - TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_NO_SUCH_FILE"); - break; - case UI_NOTIFICATION_ERROR_INVALID_STATE: - TRACE_DEBUG_MSG("UI_NOTIFICATION_ERROR_INVALID_STATE"); - break; - default: - TRACE_DEBUG_MSG("Unknown error"); - break; - } -} - -char *__get_string_status(int state) -{ - char *message = NULL; - switch (state) { - case DOWNLOAD_STATE_FINISHED: - //message = S_("IDS_COM_POP_SUCCESS"); - message = "Completed"; - break; - case DOWNLOAD_STATE_STOPPED: - //message = S_("IDS_COM_POP_CANCELLED"); - message = "Canclled"; - break; - case DOWNLOAD_STATE_FAILED: - //message = S_("IDS_COM_POP_FAILED"); - message = "Failed"; - break; - default: - break; - } - return message; -} - -bool download_provider_appfw_notification_cb(ui_notification_h notification, - void *user_data) -{ - if (!user_data) - return false; - download_clientinfo *clientinfo = (download_clientinfo *) user_data; - if (!clientinfo->downloadinfo) - return false; - - bool checkInfo = false; - char *title = NULL; - char *content = NULL; - ui_notification_get_title(notification, &title); - ui_notification_get_content(notification, &content); - - TRACE_DEBUG_MSG("title [%s]", title); - TRACE_DEBUG_MSG("content [%s]", content); - - // relatively unique - if (title) { - int title_length = strlen(title); - int content_name_length = - strlen(clientinfo->downloadinfo->content_name); - if (title_length == content_name_length) - if (strncmp - (title, clientinfo->downloadinfo->content_name, - title_length) == 0) - checkInfo = true; - } - // Only when matched title. - if (checkInfo && content) { - checkInfo = false; - char *failed_content = - __get_string_status(DOWNLOAD_STATE_FAILED); - if (failed_content) { - int content_length = strlen(content); - int content_name_length = strlen(failed_content); - if (content_length == content_name_length) - if (strncmp - (content, failed_content, - content_length) == 0) - checkInfo = true; - free(failed_content); - } - if (!checkInfo) { - char *stopped_content = - __get_string_status(DOWNLOAD_STATE_STOPPED); - if (stopped_content) { - int content_length = strlen(content); - int content_name_length = - strlen(stopped_content); - if (content_length == content_name_length) - if (strncmp - (content, stopped_content, - content_length) == 0) - checkInfo = true; - free(stopped_content); - } - } - } - - if (title) - free(title); - if (content) - free(content); - - if (checkInfo) { // compare info with noti info. - TRACE_DEBUG_MSG("ui_notification_cancel"); - ui_notification_cancel(notification); - return false; // do not search noti item anymore. - } - return true; -} - -int destroy_appfw_service(download_clientinfo *clientinfo) -{ - if (!clientinfo) - return -1; - - if (clientinfo->service_handle) { - service_destroy(clientinfo->service_handle); - } - clientinfo->service_handle = NULL; - return 0; -} - -int create_appfw_service(download_clientinfo *clientinfo, bool ongoing) -{ - if (!clientinfo) - return -1; - - if (ongoing) { - if (!clientinfo->service_handle) { - if (service_create(&clientinfo->service_handle) < 0) { - TRACE_DEBUG_MSG("failed service_create (%s)", strerror(errno)); - return false; - } - if (clientinfo->requestinfo - && clientinfo->requestinfo->client_packagename.str) { - if (service_set_package(clientinfo->service_handle, - clientinfo->requestinfo-> - client_packagename.str) < 0) - TRACE_DEBUG_MSG("failed service_set_package (%s)", - strerror(errno)); - } - } - } else { - if (clientinfo->service_handle) { - destroy_appfw_service(clientinfo); - } - if (service_create(&clientinfo->service_handle) < 0) { - TRACE_DEBUG_MSG("failed service_create (%s)", strerror(errno)); - return false; - } - } - return 0; -} - -int destroy_appfw_notification(download_clientinfo *clientinfo) -{ - if (!clientinfo) - return -1; - - destroy_appfw_service(clientinfo); - if (clientinfo->ui_notification_handle) { - bool ongoing = 0; - ui_notification_is_ongoing(clientinfo->ui_notification_handle, - &ongoing); - if (ongoing) { - if (ui_notification_cancel - (clientinfo->ui_notification_handle) < 0) - TRACE_DEBUG_MSG("Fail ui_notification_cancel"); - } - ui_notification_destroy(clientinfo->ui_notification_handle); - } - clientinfo->ui_notification_handle = NULL; - return 0; -} - -int create_appfw_notification(download_clientinfo *clientinfo, bool ongoing) -{ - if (!clientinfo) - return -1; - - int ret = 0; - - if (ui_notification_create(ongoing, &clientinfo->ui_notification_handle) - < 0) { - TRACE_DEBUG_MSG("Fail to create notification handle"); - return -1; - } - - if (clientinfo->downloadinfo) { - TRACE_DEBUG_MSG("###content_name[%s]", clientinfo->downloadinfo->content_name); - char *title = clientinfo->downloadinfo->content_name; - if (!title) - //title = S_("IDS_COM_BODY_NO_NAME"); - title = "No name"; - if (ui_notification_set_title( - clientinfo->ui_notification_handle, title) < 0) { - TRACE_DEBUG_MSG - ("failed ui_notification_set_title (%s)", - strerror(errno)); - destroy_appfw_notification(clientinfo); - return -1; - } - } - - if (ui_notification_set_icon - (clientinfo->ui_notification_handle, - DP_NOTIFICATION_ICON_PATH) < 0) { - TRACE_DEBUG_MSG("Fail ui_notification_set_icon (%s)", - strerror(errno)); - destroy_appfw_notification(clientinfo); - return -1; - } - - - create_appfw_service(clientinfo, ongoing); - if (!ongoing) { - // view the special viewer by contents - if (clientinfo->downloadinginfo - && sizeof(clientinfo->downloadinginfo->saved_path) > 0 - && clientinfo->state == DOWNLOAD_STATE_FINISHED) { - if (service_set_operation - (clientinfo->service_handle, - SERVICE_OPERATION_VIEW) < 0) { - TRACE_DEBUG_MSG - ("Fail service_set_operation"); - destroy_appfw_service(clientinfo); - } - if (service_set_uri(clientinfo->service_handle, - clientinfo->downloadinginfo->saved_path) - < 0) { - TRACE_DEBUG_MSG("Fail service_set_uri"); - destroy_appfw_service(clientinfo); - } - } else { - if (service_set_package(clientinfo->service_handle, - clientinfo->requestinfo-> - client_packagename.str) < 0) - TRACE_DEBUG_MSG("failed service_set_package (%s)", - strerror(errno)); - } - } - if (ui_notification_set_service - (clientinfo->ui_notification_handle, - clientinfo->service_handle) < 0) { - TRACE_DEBUG_MSG("Fail ui_notification_set_service"); - destroy_appfw_service(clientinfo); - } - - if ((ret = - ui_notification_post(clientinfo->ui_notification_handle)) != - UI_NOTIFICATION_ERROR_NONE) { - TRACE_DEBUG_MSG("Fail to post [%d]", ret); - print_notification_error_message(ret); - destroy_appfw_notification(clientinfo); - return -1; - } - - return 0; -} - -int set_downloadinginfo_appfw_notification(download_clientinfo *clientinfo) -{ - if (!clientinfo || !clientinfo->downloadinginfo) - return -1; - - if (!clientinfo->ui_notification_handle) { - create_appfw_notification(clientinfo, true); - } - - if (!clientinfo->ui_notification_handle) - return -1; - - if (clientinfo->downloadinfo && clientinfo->downloadinfo->file_size > 0) { - double progress = - (double)clientinfo->downloadinginfo->received_size / - (double)clientinfo->downloadinfo->file_size; - if (ui_notification_update_progress - (clientinfo->ui_notification_handle, - UI_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE, progress) < 0) { - TRACE_DEBUG_MSG("Fail to update progress"); - destroy_appfw_notification(clientinfo); - return -1; - } - } else { - if (ui_notification_update_progress - (clientinfo->ui_notification_handle, - UI_NOTIFICATION_PROGRESS_TYPE_SIZE, - (double)(clientinfo->downloadinginfo->received_size)) < - 0) { - TRACE_DEBUG_MSG("Fail to update size"); - destroy_appfw_notification(clientinfo); - return -1; - } - } - - return 0; -} - -int set_downloadedinfo_appfw_notification(download_clientinfo *clientinfo) -{ - if (!clientinfo) - return -1; - - destroy_appfw_notification(clientinfo); - - if (!clientinfo->ui_notification_handle) - create_appfw_notification(clientinfo, false); - - // fill downloaded info to post to notification bar. - char *message = __get_string_status(clientinfo->state); - TRACE_DEBUG_MSG("message : [%s]", message); - if (message) { - if (ui_notification_set_content - (clientinfo->ui_notification_handle, message) < 0) - TRACE_DEBUG_MSG("Fail to set content"); - } - - time_t tt = time(NULL); - struct tm *localTime = localtime(&tt); - - if (ui_notification_set_time - (clientinfo->ui_notification_handle, localTime) < 0) - TRACE_DEBUG_MSG("Fail to set time"); - - if (ui_notification_update(clientinfo->ui_notification_handle) < 0) - TRACE_DEBUG_MSG("Fail to ui_notification_update"); - - destroy_appfw_notification(clientinfo); - return 0; -} - -void clear_downloadinginfo_appfw_notification() -{ - ui_notification_cancel_all_by_type(true); - return; -} diff --git a/src/download-provider-pid.c b/src/download-provider-pid.c deleted file mode 100644 index b580ae9..0000000 --- a/src/download-provider-pid.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -int lock_download_provider_pid(char *path) -{ - int lockfd = 0; - if ((lockfd = open(path, O_WRONLY | O_CREAT, (0666 & (~000)))) < 0) { - return -1; - } else if (lockf(lockfd, F_TLOCK, 0) < 0) { - close(lockfd); - return -1; - } - return 0; -} diff --git a/src/download-provider-receiver.c b/src/download-provider-receiver.c deleted file mode 100644 index a2146b5..0000000 --- a/src/download-provider-receiver.c +++ /dev/null @@ -1,1239 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "download-provider-config.h" -#include "download-provider-log.h" -#include "download-provider-pthread.h" -#include "download-provider-notification.h" -#include "download-provider-ipc.h" -#include "download-provider-db.h" -#include "download-provider-utils.h" - -#include "download-agent-defs.h" -#include "download-agent-interface.h" - -int _init_agent(void); -void _deinit_agent(void); -static void __downloading_info_cb(user_downloading_info_t *download_info, - void *user_data); -static void __download_info_cb(user_download_info_t *download_info, - void *user_data); -static void __notify_cb(user_notify_info_t *notify_info, void *user_data); -static int __change_error(int err); -static int __change_state(da_state state); - -void TerminateDaemon(int signo); - -pthread_attr_t g_download_provider_thread_attr; -fd_set g_download_provider_socket_readset; -fd_set g_download_provider_socket_exceptset; - -int _change_pended_download(download_clientinfo *clientinfo) -{ - if (!clientinfo) - return -1; - clientinfo->state = DOWNLOAD_STATE_PENDED; - clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; - download_provider_db_requestinfo_update_column(clientinfo, DOWNLOAD_DB_STATE); - ipc_send_request_stateinfo(clientinfo); - return 0; -} - -void *_start_download(void *args) -{ - int da_ret = -1; - int req_dl_id = -1; - - download_clientinfo_slot *clientinfoslot = - (download_clientinfo_slot *) args; - if (!clientinfoslot) { - TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo_slot"); - return 0; - } - download_clientinfo *clientinfo = - (download_clientinfo *) clientinfoslot->clientinfo; - if (!clientinfo) { - TRACE_DEBUG_MSG("[NULL-CHECK] download_clientinfo"); - return 0; - } - - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - clientinfo->state = DOWNLOAD_STATE_READY; - clientinfo->err = DOWNLOAD_ERROR_NONE; - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - - // call start_download() of download-agent - if (clientinfo->requestinfo->headers.rows > 0) { - int len = 0; - int i = 0; - char **req_header = NULL; - len = clientinfo->requestinfo->headers.rows; - req_header = calloc(len, sizeof(char *)); - if (!req_header) { - TRACE_DEBUG_MSG("fail to calloc"); - return 0; - } - for (i = 0; i < len; i++) - req_header[i] = - strdup(clientinfo->requestinfo->headers.str[i].str); - if (clientinfo->requestinfo->install_path.length > 1) { - if (clientinfo->requestinfo->filename.length > 1) - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_REQUEST_HEADER, - req_header, &len, - DA_FEATURE_INSTALL_PATH, - clientinfo->requestinfo->install_path.str, - DA_FEATURE_FILE_NAME, - clientinfo->requestinfo->filename.str, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - else - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_REQUEST_HEADER, - req_header, &len, - DA_FEATURE_INSTALL_PATH, - clientinfo->requestinfo->install_path.str, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - } else { - if (clientinfo->requestinfo->filename.length > 1) - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_REQUEST_HEADER, - req_header, &len, - DA_FEATURE_FILE_NAME, - clientinfo->requestinfo->filename.str, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - else - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_REQUEST_HEADER, - req_header, &len, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - } - for (i = 0; i < len; i++) { - if (req_header[i]) - free(req_header[i]); - } - } else { - if (clientinfo->requestinfo->install_path.length > 1) { - if (clientinfo->requestinfo->filename.length > 1) - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_INSTALL_PATH, - clientinfo->requestinfo->install_path.str, - DA_FEATURE_FILE_NAME, - clientinfo->requestinfo->filename.str, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - else - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_INSTALL_PATH, - clientinfo->requestinfo->install_path.str, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - } else { - if (clientinfo->requestinfo->filename.length > 1) - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_FILE_NAME, - clientinfo->requestinfo->filename.str, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - else - da_ret = - da_start_download_with_extension(clientinfo->requestinfo-> - url.str, &req_dl_id, - DA_FEATURE_USER_DATA, - (void *)clientinfoslot, - NULL); - } - } - - // if start_download() return error cause of maximun download limitation, - // set state to DOWNLOAD_STATE_PENDED. - if (da_ret == DA_ERR_ALREADY_MAX_DOWNLOAD) { - TRACE_DEBUG_INFO_MSG("change to pended request [%d]", da_ret); - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - _change_pended_download(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - return 0; - } else if (da_ret != DA_RESULT_OK) { - TRACE_DEBUG_INFO_MSG("Fail to request start [%d]", da_ret); - /* FIXME : need to seperate in detail according to error return values */ - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - clientinfo->state = DOWNLOAD_STATE_FAILED; - clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - download_provider_db_requestinfo_remove(clientinfo-> - requestinfo->requestid); - ipc_send_request_stateinfo(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - return 0; - } - - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - - TRACE_DEBUG_INFO_MSG("started download [%d]", da_ret); - - clientinfo->req_id = req_dl_id; - clientinfo->state = DOWNLOAD_STATE_DOWNLOADING; - clientinfo->err = DOWNLOAD_ERROR_NONE; - - download_provider_db_requestinfo_update_column(clientinfo, - DOWNLOAD_DB_STATE); - - // sync return // client should be alive till this line at least. - ipc_send_request_stateinfo(clientinfo); - - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - return 0; -} - -int _create_download_thread(download_clientinfo_slot *clientinfo_slot) -{ - if (!clientinfo_slot) - return -1; - - // create thread for receiving the reqeust info from client. - // and if possible, it will create the thread for listening the event. - clientinfo_slot->clientinfo->state = DOWNLOAD_STATE_READY; - clientinfo_slot->clientinfo->err = DOWNLOAD_ERROR_NONE; - if (pthread_create - (&clientinfo_slot->clientinfo->thread_pid, - &g_download_provider_thread_attr, _start_download, - clientinfo_slot) != 0) { - TRACE_DEBUG_INFO_MSG("failed to call pthread_create for client"); - TRACE_DEBUG_INFO_MSG("Change to pended job"); - _change_pended_download(clientinfo_slot->clientinfo); - return -1; - } - return 0; -} - -int _handle_new_connection(download_clientinfo_slot *clientinfo_list, download_clientinfo *request_clientinfo) -{ - int searchslot = 0; - unsigned active_count = 0; - - // NULL - checking - if (!clientinfo_list || !request_clientinfo ) { - TRACE_DEBUG_MSG("NULL-CHECK"); - return -1; - } - - CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL); - -#ifdef SO_PEERCRED - socklen_t cr_len = - sizeof(request_clientinfo->credentials); - if (getsockopt - (request_clientinfo->clientfd, SOL_SOCKET, - SO_PEERCRED, &request_clientinfo->credentials, - &cr_len) == 0) { - TRACE_DEBUG_INFO_MSG - ("Client Info : pid=%d, uid=%d, gid=%d\n", - request_clientinfo->credentials.pid, - request_clientinfo->credentials.uid, - request_clientinfo->credentials.gid); - } -#endif - - download_controls type = - ipc_receive_header(request_clientinfo->clientfd); - TRACE_DEBUG_INFO_MSG("[ACCEPT] HEADER : [%d] ", type); - // first of all, receive requestinfo . - if (type <= 0 || ipc_receive_request_msg(request_clientinfo) < 0) { - TRACE_DEBUG_MSG("Ignore this connection, Invalid command"); - clear_clientinfo(request_clientinfo); - return -1; - } - - if (type == DOWNLOAD_CONTROL_STOP - || type == DOWNLOAD_CONTROL_GET_STATE_INFO - || type == DOWNLOAD_CONTROL_RESUME - || type == DOWNLOAD_CONTROL_PAUSE) { - // get requestid from socket. - if (request_clientinfo->requestinfo - && request_clientinfo->requestinfo->requestid > 0) { - // search requestid in slots. - int searchindex = get_same_request_slot_index - (clientinfo_list, - request_clientinfo->requestinfo->requestid); - if (type == DOWNLOAD_CONTROL_STOP) { - TRACE_DEBUG_INFO_MSG("Request : DOWNLOAD_CONTROL_STOP"); - if (searchindex >= 0) { - if (da_cancel_download - (clientinfo_list[searchindex].clientinfo->req_id) - == DA_RESULT_OK) { - request_clientinfo->state = DOWNLOAD_STATE_STOPPED; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - if (clientinfo_list[searchindex].clientinfo->requestinfo - && clientinfo_list[searchindex].clientinfo->requestinfo->notification) - set_downloadedinfo_appfw_notification(clientinfo_list[searchindex].clientinfo); - download_provider_db_requestinfo_remove(request_clientinfo->requestinfo->requestid); - download_provider_db_history_new(clientinfo_list[searchindex].clientinfo); - } else { - request_clientinfo->state = DOWNLOAD_STATE_FAILED; - request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - } - } else { // no found - request_clientinfo->state = DOWNLOAD_STATE_NONE; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } - ipc_send_stateinfo(request_clientinfo); - } else if (type == DOWNLOAD_CONTROL_GET_STATE_INFO) { - // search slots/downloading db/history db - if (searchindex > 0) { // exist in slots (memory) - request_clientinfo->state = - clientinfo_list[searchindex].clientinfo->state; - request_clientinfo->err = - clientinfo_list[searchindex].clientinfo->err; - } else { //search downloading db or history db - download_dbinfo* dbinfo = - download_provider_db_get_info( - request_clientinfo->requestinfo->requestid); - if (dbinfo) { // found in downloading db..it means crashed job - request_clientinfo->state = DOWNLOAD_STATE_PENDED; - request_clientinfo->err = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; - } else { // no exist in downloading db - dbinfo = download_provider_db_history_get_info( - request_clientinfo->requestinfo->requestid); - if (!dbinfo) { // no info anywhere - request_clientinfo->state = DOWNLOAD_STATE_NONE; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } else { //history info - request_clientinfo->state = dbinfo->state; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } - } - download_provider_db_info_free(dbinfo); - free(dbinfo); - } - ipc_send_stateinfo(request_clientinfo); - // estabilish the spec of return value. - } else if (type == DOWNLOAD_CONTROL_PAUSE) { - if (searchindex >= 0) { - if (da_suspend_download - (clientinfo_list[searchindex].clientinfo->req_id) - == DA_RESULT_OK) { - request_clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } else { - request_clientinfo->state = DOWNLOAD_STATE_FAILED; - request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - } - } else { // no found - request_clientinfo->state = DOWNLOAD_STATE_NONE; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } - ipc_send_stateinfo(request_clientinfo); - } else if (type == DOWNLOAD_CONTROL_RESUME) { - if (searchindex >= 0) { - if (da_resume_download - (clientinfo_list[searchindex].clientinfo->req_id) - == DA_RESULT_OK) { - request_clientinfo->state = DOWNLOAD_STATE_DOWNLOADING; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } else { - request_clientinfo->state = DOWNLOAD_STATE_FAILED; - request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - } - } else { // no found - request_clientinfo->state = DOWNLOAD_STATE_NONE; - request_clientinfo->err = DOWNLOAD_ERROR_NONE; - } - ipc_send_stateinfo(request_clientinfo); - } - ipc_receive_header(request_clientinfo->clientfd); - } - clear_clientinfo(request_clientinfo); - return 0; - } - - if (type != DOWNLOAD_CONTROL_START) { - TRACE_DEBUG_MSG - ("Now, DOWNLOAD_CONTROL_START is only supported"); - clear_clientinfo(request_clientinfo); - return -1; - } - - // check whether requestinfo has requestid or not. - if (request_clientinfo->requestinfo - && request_clientinfo->requestinfo->requestid > 0) { - // search same request id. - int searchindex = get_same_request_slot_index(clientinfo_list, - request_clientinfo->requestinfo->requestid); - if (searchindex < 0) { - TRACE_DEBUG_INFO_MSG("Not Found Same Request ID"); - /* Try to search history db */ - download_dbinfo *dbinfo = download_provider_db_history_get_info( - request_clientinfo->requestinfo->requestid); - if (dbinfo == NULL) { - /* Try to serach downloading db. The crashed job can not be uploaded to memory */ - dbinfo = download_provider_db_get_info( - request_clientinfo->requestinfo->requestid); - if (dbinfo == NULL) { - /* Invalid id */ - request_clientinfo->state = DOWNLOAD_STATE_FAILED; - request_clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - ipc_send_request_stateinfo(request_clientinfo); - clear_clientinfo(request_clientinfo); - return 0; - } - } - download_provider_db_info_free(dbinfo); - free(dbinfo); - } else { // found request id. // how to deal etag ? - // connect to slot. - TRACE_DEBUG_INFO_MSG("Found Same Request ID slot[%d]", searchindex); - CLIENT_MUTEX_LOCK(&(request_clientinfo->client_mutex)); - // close previous socket. - if (clientinfo_list[searchindex].clientinfo->clientfd > 0) - close(clientinfo_list[searchindex].clientinfo->clientfd); - // change to new socket. - clientinfo_list[searchindex].clientinfo->clientfd = - request_clientinfo->clientfd; - // update some info. - clientinfo_list[searchindex].clientinfo->requestinfo->callbackinfo = - request_clientinfo->requestinfo->callbackinfo; - clientinfo_list[searchindex].clientinfo->requestinfo->notification = - request_clientinfo->requestinfo->notification; - request_clientinfo->clientfd = 0; // prevent to not be disconnected. - CLIENT_MUTEX_UNLOCK(&(request_clientinfo->client_mutex)); - clear_clientinfo(request_clientinfo); - - if (clientinfo_list[searchindex].clientinfo->state - == DOWNLOAD_STATE_READY - || clientinfo_list[searchindex].clientinfo->state - >= DOWNLOAD_STATE_FINISHED) { - active_count = get_downloading_count(clientinfo_list); - if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) { - // deal as pended job. - _change_pended_download(clientinfo_list[searchindex].clientinfo); - TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]", - searchslot, MAX_CLIENT); - } else - _create_download_thread(&clientinfo_list[searchindex]); - } else - ipc_send_request_stateinfo(clientinfo_list[searchindex].clientinfo); - return 0; - } - } - - // new request. - searchslot = get_empty_slot_index(clientinfo_list); - if (searchslot < 0) { - TRACE_DEBUG_MSG("download-provider is busy, try later"); - clear_clientinfo(request_clientinfo); - sleep(5); // provider need the time of refresh. - return -1; - } - // create new unique id, and insert info to DB. - if (request_clientinfo->requestinfo - && request_clientinfo->requestinfo->requestid <= 0) { - request_clientinfo->requestinfo->requestid = - get_download_request_id(); - if (download_provider_db_requestinfo_new - (request_clientinfo) < 0) { - clear_clientinfo(request_clientinfo); - sleep(5); // provider need the time of refresh. - return -1; - } - } - - clientinfo_list[searchslot].clientinfo = request_clientinfo; - - active_count = get_downloading_count(clientinfo_list); - - TRACE_DEBUG_INFO_MSG("New Connection slot [%d/%d] active [%d/%d]", - searchslot, - MAX_CLIENT, - active_count, - DA_MAX_DOWNLOAD_REQ_AT_ONCE); - - if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) { - // deal as pended job. - _change_pended_download(clientinfo_list[searchslot].clientinfo); - TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]", - searchslot, MAX_CLIENT); - } else { - // Pending First - unsigned free_slot_count - = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count; - int pendedslot = get_pended_slot_index(clientinfo_list); - if(pendedslot >= 0) { - TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count); - for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) { - TRACE_DEBUG_INFO_MSG ("Start pended job [%d]", pendedslot); - _create_download_thread(&clientinfo_list[pendedslot]); - pendedslot = get_pended_slot_index(clientinfo_list); - } - } - - if (free_slot_count <= 0) { // change to PENDED - // start pended job, deal this job to pended - _change_pended_download(clientinfo_list[searchslot].clientinfo); - TRACE_DEBUG_INFO_MSG ("Pended Request is saved to [%d/%d]", - searchslot, MAX_CLIENT); - } else - _create_download_thread(&clientinfo_list[searchslot]); - } - return 0; -} - -int _handle_client_request(download_clientinfo* clientinfo) -{ - int da_ret = 0; - int msgType = 0; - - // NULL - checking - if (!clientinfo) { - TRACE_DEBUG_MSG("NULL-CHECK"); - return -1; - } - - switch (msgType = ipc_receive_header(clientinfo->clientfd)) { - case DOWNLOAD_CONTROL_STOP: - if (clientinfo->state >= DOWNLOAD_STATE_FINISHED) { - // clear slot requested by client after finished download - TRACE_DEBUG_INFO_MSG("request Free slot to main thread"); - clear_socket(clientinfo); - break; - } - TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_STOP"); - da_ret = da_cancel_download(clientinfo->req_id); - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - if (da_ret != DA_RESULT_OK) { - /* FIXME : need to seperate in detail according to error return values */ - clientinfo->state = DOWNLOAD_STATE_FAILED; - clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - TRACE_DEBUG_MSG("Fail to request cancel [%d]", da_ret); - } else { - clientinfo->state = DOWNLOAD_STATE_STOPPED; - clientinfo->err = DOWNLOAD_ERROR_NONE; - if (clientinfo->requestinfo) { - if (clientinfo->requestinfo->notification) - set_downloadedinfo_appfw_notification(clientinfo); - download_provider_db_requestinfo_remove(clientinfo-> - requestinfo->requestid); - } - download_provider_db_history_new(clientinfo); - } - ipc_send_stateinfo(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - break; - case DOWNLOAD_CONTROL_PAUSE: - TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_PAUSE"); - da_ret = da_suspend_download(clientinfo->req_id); - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - if (da_ret != DA_RESULT_OK) { - /* FIXME : need to seperate in detail according to error return values */ - clientinfo->state = DOWNLOAD_STATE_FAILED; - clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - TRACE_DEBUG_MSG("Fail to request suspend [%d]", da_ret); - } else { - clientinfo->state = DOWNLOAD_STATE_PAUSE_REQUESTED; - clientinfo->err = DOWNLOAD_ERROR_NONE; - } - ipc_send_stateinfo(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - break; - case DOWNLOAD_CONTROL_RESUME: - TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_RESUME"); - da_ret = da_resume_download(clientinfo->req_id); - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - if (da_ret != DA_RESULT_OK) { - /* FIXME : need to seperate in detail according to error return values */ - clientinfo->state = DOWNLOAD_STATE_FAILED; - clientinfo->err = DOWNLOAD_ERROR_INVALID_PARAMETER; - TRACE_DEBUG_MSG("Fail to request resume [%d]", da_ret); - } else { - clientinfo->state = DOWNLOAD_STATE_DOWNLOADING; - clientinfo->err = DOWNLOAD_ERROR_NONE; - } - ipc_send_stateinfo(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - break; - case DOWNLOAD_CONTROL_GET_STATE_INFO: // sync call - TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_STATE_INFO"); - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - ipc_send_stateinfo(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - break; - case DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO: // sync call - TRACE_DEBUG_INFO_MSG("DOWNLOAD_CONTROL_GET_DOWNLOAD_INFO"); - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - ipc_send_downloadinfo(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - break; - case -1: - case 0: - TRACE_DEBUG_MSG("(Closed Socket ) terminate event thread (%d)", - msgType); - // bloken socket... it seems the client is dead or closed by agent thread. - // close socket, this will break the loop. and terminate this thread. - clear_socket(clientinfo); - return -1; - default: - TRACE_DEBUG_MSG("Unknow message [%d]", msgType); - return -1; - } - return 0; -} - -void *run_manage_download_server(void *args) -{ - int listenfd = 0; // main socket to be albe to listen the new connection - int maxfd; - int ret = 0; - fd_set rset, exceptset; - struct timeval timeout; - long flexible_timeout; - download_clientinfo_slot *clientinfo_list; - int searchslot = 0; - unsigned active_count = 0; - download_clientinfo *request_clientinfo; - int check_retry = 1; - int i = 0; - int is_timeout = 0; - - socklen_t clientlen; - struct sockaddr_un listenaddr, clientaddr; - - GMainLoop *mainloop = (GMainLoop *) args; - - ret = _init_agent(); - if (ret != DOWNLOAD_ERROR_NONE) { - TRACE_DEBUG_MSG("failed to init agent"); - TerminateDaemon(SIGTERM); - return 0; - } - clear_downloadinginfo_appfw_notification(); - - if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - TRACE_DEBUG_MSG("failed to create socket"); - TerminateDaemon(SIGTERM); - return 0; - } - - bzero(&listenaddr, sizeof(listenaddr)); - listenaddr.sun_family = AF_UNIX; - strcpy(listenaddr.sun_path, DOWNLOAD_PROVIDER_IPC); - - if (bind(listenfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) != - 0) { - TRACE_DEBUG_MSG("failed to call bind"); - TerminateDaemon(SIGTERM); - return 0; - } - - if (chmod(listenaddr.sun_path, 0777) < 0) { - TRACE_DEBUG_MSG - ("failed to change the permission of socket file"); - TerminateDaemon(SIGTERM); - return 0; - } - - if (listen(listenfd, MAX_CLIENT) != 0) { - TRACE_DEBUG_MSG("failed to call listen"); - TerminateDaemon(SIGTERM); - return 0; - } - - maxfd = listenfd; - TRACE_DEBUG_INFO_MSG("Ready to listen IPC [%d][%s]", listenfd, - DOWNLOAD_PROVIDER_IPC); - - // allocation the array structure for managing the clients. - clientinfo_list = - (download_clientinfo_slot *) calloc(MAX_CLIENT, - sizeof(download_clientinfo_slot)); - if (clientinfo_list == NULL) { - TRACE_DEBUG_MSG("failed to allocate the memory for client list"); - TerminateDaemon(SIGTERM); - return 0; - } - - if (pthread_attr_init(&g_download_provider_thread_attr) != 0) { - TRACE_DEBUG_MSG("failed to call pthread_attr_init for client"); - TerminateDaemon(SIGTERM); - return 0; - } - if (pthread_attr_setdetachstate(&g_download_provider_thread_attr, - PTHREAD_CREATE_DETACHED) != 0) { - TRACE_DEBUG_MSG("failed to set detach option"); - TerminateDaemon(SIGTERM); - return 0; - } - - flexible_timeout = DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL; - - FD_ZERO(&g_download_provider_socket_readset); - FD_ZERO(&g_download_provider_socket_exceptset); - FD_SET(listenfd, &g_download_provider_socket_readset); - FD_SET(listenfd, &g_download_provider_socket_exceptset); - - while (g_main_loop_is_running(mainloop)) { - - // clean slots - for (i = 0; i < MAX_CLIENT; i++) { - if (!clientinfo_list[i].clientinfo) - continue; - // clear slot. - if (clientinfo_list[i].clientinfo->state >= DOWNLOAD_STATE_FINISHED) { - if (clientinfo_list[i].clientinfo->clientfd <= 0) - clear_clientinfoslot(&clientinfo_list[i]); - continue; - } - } - - is_timeout = 1; - rset = g_download_provider_socket_readset; - exceptset = g_download_provider_socket_exceptset; - - memset(&timeout, 0x00, sizeof(struct timeval)); - timeout.tv_sec = flexible_timeout; - - if (select((maxfd + 1), &rset, 0, &exceptset, &timeout) < 0) { - TRACE_DEBUG_MSG - ("select error, provider can't receive any request from client."); - TerminateDaemon(SIGTERM); - break; - } - - for (i = 0; i < MAX_CLIENT; i++) { // find the socket received the packet. - if (!clientinfo_list[i].clientinfo) - continue; - //Even if no socket, downloading should be progressed. - if (clientinfo_list[i].clientinfo->clientfd <= 0) - continue; - if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &rset) > 0) { - // ignore it is not started yet. - if (clientinfo_list[i].clientinfo->state <= DOWNLOAD_STATE_READY) - continue; - TRACE_DEBUG_INFO_MSG("FD_ISSET [%d] readset slot[%d]", - clientinfo_list[i].clientinfo->clientfd, i); - _handle_client_request(clientinfo_list[i].clientinfo); - if (is_timeout) - is_timeout = 0; - } else if (FD_ISSET(clientinfo_list[i].clientinfo->clientfd, &exceptset) > 0) { - TRACE_DEBUG_MSG("FD_ISSET [%d] exceptset slot[%d]", clientinfo_list[i].clientinfo->clientfd, i); - clear_clientinfoslot(&clientinfo_list[i]); - } - } // MAX_CLIENT - - if (FD_ISSET(listenfd, &exceptset) > 0) { - TRACE_DEBUG_MSG("meet listenfd Exception of socket"); - TerminateDaemon(SIGTERM); - break; - } else if (FD_ISSET(listenfd, &rset) > 0) { // new connection - TRACE_DEBUG_INFO_MSG("FD_ISSET listenfd rset"); - if (is_timeout) - is_timeout = 0; - // reset timeout. - flexible_timeout = - DOWNLOAD_PROVIDER_CARE_CLIENT_MIN_INTERVAL; - // ready the buffer. - request_clientinfo = - (download_clientinfo *) calloc(1, - sizeof(download_clientinfo)); - if (!request_clientinfo) { - TRACE_DEBUG_MSG - ("download-provider can't allocate the memory, try later"); - clientlen = sizeof(clientaddr); - int clientfd = accept(listenfd, - (struct sockaddr *)&clientaddr, &clientlen); - close(clientfd); // disconnect. - sleep(5); // provider need the time of refresh. - continue; - } - // accept client. - clientlen = sizeof(clientaddr); - request_clientinfo->clientfd = accept(listenfd, - (struct sockaddr*)&clientaddr, - &clientlen); - if (request_clientinfo->clientfd < 0) { - clear_clientinfo(request_clientinfo); - sleep(5); // provider need the time of refresh. - continue; - } - if (_handle_new_connection(clientinfo_list, request_clientinfo) < 0) { - sleep(1); - continue; - } - // after starting the download by DA, event thread will start to get the event from client. - if (request_clientinfo && request_clientinfo->clientfd > 0) { - FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_readset); // add new descriptor to set - FD_SET(request_clientinfo->clientfd, &g_download_provider_socket_exceptset); - if (request_clientinfo->clientfd > maxfd ) - maxfd = request_clientinfo->clientfd; /* for select */ - } - } - - if (is_timeout) { // timeout - // If there is better solution to be able to know - // the number of downloading threads, replace below rough codes. - active_count = get_downloading_count(clientinfo_list); - // check whether the number of downloading is already maximum. - if (active_count >= DA_MAX_DOWNLOAD_REQ_AT_ONCE) - continue; - - unsigned free_slot_count - = DA_MAX_DOWNLOAD_REQ_AT_ONCE - active_count; - int pendedslot = get_pended_slot_index(clientinfo_list); - if(pendedslot >= 0) { - TRACE_DEBUG_INFO_MSG ("Free Space [%d]", free_slot_count); - for (;free_slot_count > 0 && pendedslot >= 0; free_slot_count--) { - TRACE_DEBUG_INFO_MSG ("start pended job [%d]", pendedslot); - if (_create_download_thread(&clientinfo_list[pendedslot]) > 0) - active_count++; - pendedslot = get_pended_slot_index(clientinfo_list); - } - } - - if (check_retry && free_slot_count > 0) { - // Auto re-download feature. - // ethernet may be connected with other downloading items. - if (get_network_status() < 0) - continue; - - // check auto-retrying list regardless state. pended state is also included to checking list. - int i = 0; - download_dbinfo_list *db_list = - download_provider_db_get_list(DOWNLOAD_STATE_NONE); - if (!db_list || db_list->count <= 0) { - TRACE_DEBUG_INFO_MSG - ("provider does not need to check DB anymore. in this life."); - // provider does not need to check DB anymore. in this life. - check_retry = 0; - if (db_list) - download_provider_db_list_free(db_list); - continue; - } - for (i = 0; - active_count < - DA_MAX_DOWNLOAD_REQ_AT_ONCE - && i < db_list->count; i++) { - if (db_list->item[i].requestid <= 0) - continue; - if (get_same_request_slot_index - (clientinfo_list,db_list->item[i].requestid) < 0) { - // not found requestid in memory - TRACE_DEBUG_INFO_MSG - ("Retry download [%d]", - db_list->item[i].requestid); - //search empty slot. copy db info to slot. - searchslot = - get_empty_slot_index(clientinfo_list); - if (searchslot < 0) { - TRACE_DEBUG_INFO_MSG - ("download-provider is busy, try later"); - flexible_timeout = - flexible_timeout * 2; - break; - } - // allocte requestinfo to empty slot. - request_clientinfo = - (download_clientinfo *) - calloc(1, sizeof(download_clientinfo)); - if (!request_clientinfo) - continue; - request_clientinfo->requestinfo - = - download_provider_db_get_requestinfo - (&db_list->item[i]); - if (!request_clientinfo->requestinfo) { - free(request_clientinfo); - request_clientinfo = NULL; - continue; - } - - CLIENT_MUTEX_INIT(&(request_clientinfo->client_mutex), NULL); - request_clientinfo->state = DOWNLOAD_STATE_READY; - clientinfo_list[searchslot].clientinfo = - request_clientinfo; - - TRACE_DEBUG_INFO_MSG - ("Retry download [%d/%d][%d/%d]", - searchslot, MAX_CLIENT, - active_count, - DA_MAX_DOWNLOAD_REQ_AT_ONCE); - if (_create_download_thread(&clientinfo_list[searchslot]) > 0) - active_count++; - } - } - if (i >= db_list->count) // do not search anymore. - check_retry = 0; - download_provider_db_list_free(db_list); - } - - // save system resource (CPU) - if (check_retry == 0 && active_count == 0 - && flexible_timeout < - DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL) - flexible_timeout = flexible_timeout * 2; - if (flexible_timeout > - DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL) - flexible_timeout = - DOWNLOAD_PROVIDER_CARE_CLIENT_MAX_INTERVAL; - TRACE_DEBUG_INFO_MSG("Next Timeout after [%ld] sec", - flexible_timeout); - - } // if (i >= MAX_CLIENT) { // timeout - } - - FD_CLR(listenfd, &rset); - FD_CLR(listenfd, &exceptset); - FD_CLR(listenfd, &g_download_provider_socket_readset); - FD_CLR(listenfd, &g_download_provider_socket_exceptset); - - // close accept socket. - if (listenfd) - close(listenfd); - - _deinit_agent(); - - // close all sockets for client. .. - // client thread will terminate by itself through catching this closing. - for (searchslot = 0; searchslot < MAX_CLIENT; searchslot++) - if (clientinfo_list[searchslot].clientinfo) - clear_clientinfoslot(&clientinfo_list[searchslot]); - - if (clientinfo_list) - free(clientinfo_list); - - pthread_exit(NULL); - return 0; -} - -void __download_info_cb(user_download_info_t *download_info, void *user_data) -{ - int len = 0; - if (!user_data) { - TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL"); - return; - } - download_clientinfo_slot *clientinfoslot = - (download_clientinfo_slot *) user_data; - download_clientinfo *clientinfo = - (download_clientinfo *) clientinfoslot->clientinfo; - if (!clientinfo) { - TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL"); - return; - } - TRACE_DEBUG_INFO_MSG("id[%d],size[%lu]", - download_info->da_dl_req_id, download_info->file_size); - - if (clientinfo->req_id != download_info->da_dl_req_id) { - TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}", - clientinfo->req_id, - download_info->da_dl_req_id); - return; - } - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - if (!clientinfo->downloadinfo) - clientinfo->downloadinfo = - (download_content_info *) calloc(1, sizeof(download_content_info)); - if (clientinfo->downloadinfo) - clientinfo->downloadinfo->file_size = download_info->file_size; - if (download_info->file_type) { - TRACE_DEBUG_INFO_MSG("mime[%s]", download_info->file_type); - - len = strlen(download_info->file_type); - if (len > (DP_MAX_STR_LEN - 1)) - len = DP_MAX_STR_LEN - 1; - if (clientinfo->downloadinfo) { - strncpy(clientinfo->downloadinfo->mime_type, - download_info->file_type, len); - download_provider_db_requestinfo_update_column - (clientinfo, DOWNLOAD_DB_MIMETYPE); - } - } - if (download_info->tmp_saved_path) { - char *str = NULL; - TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->tmp_saved_path); - clientinfo->tmp_saved_path = - strdup(download_info->tmp_saved_path); - download_provider_db_requestinfo_update_column(clientinfo, - DOWNLOAD_DB_SAVEDPATH); - str = strrchr(download_info->tmp_saved_path, '/'); - if (str) { - str++; - len = strlen(str); - if (len > (DP_MAX_STR_LEN - 1)) - len = DP_MAX_STR_LEN - 1; - if (clientinfo->downloadinfo) { - strncpy(clientinfo->downloadinfo->content_name, - str, len); - download_provider_db_requestinfo_update_column - (clientinfo, DOWNLOAD_DB_FILENAME); - TRACE_DEBUG_INFO_MSG("content_name[%s]", - clientinfo->downloadinfo-> - content_name); - } - } - } - - if (clientinfo->requestinfo->callbackinfo.started) - ipc_send_downloadinfo(clientinfo); - - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); -} - -void __downloading_info_cb(user_downloading_info_t *download_info, - void *user_data) -{ - int len = 0; - if (!user_data) { - TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL"); - return; - } - download_clientinfo_slot *clientinfoslot = - (download_clientinfo_slot *) user_data; - download_clientinfo *clientinfo = - (download_clientinfo *) clientinfoslot->clientinfo; - if (!clientinfo) { - TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL"); - return; - } - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - if (clientinfo->req_id != download_info->da_dl_req_id) { - TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}", - clientinfo->req_id, - download_info->da_dl_req_id); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - return; - } - if (!clientinfo->downloadinginfo) - clientinfo->downloadinginfo = (downloading_state_info *) calloc(1, - sizeof(downloading_state_info)); - if (clientinfo->downloadinginfo) - clientinfo->downloadinginfo->received_size = - download_info->total_received_size; - if (download_info->saved_path) { - TRACE_DEBUG_INFO_MSG("tmp path[%s]", download_info->saved_path); - len = strlen(download_info->saved_path); - if (len > (DP_MAX_PATH_LEN - 1)) - len = DP_MAX_PATH_LEN - 1; - if (clientinfo->downloadinginfo) - strncpy(clientinfo->downloadinginfo->saved_path, - download_info->saved_path, len); - /* FIXME : This should be reviewd again after smack rules is applied */ - if (chown(clientinfo->downloadinginfo->saved_path, - clientinfo->credentials.uid, - clientinfo->credentials.gid) < 0) - TRACE_DEBUG_INFO_MSG("Fail to chown [%s]", strerror(errno)); - } - - static size_t updated_second; - time_t tt = time(NULL); - struct tm *localTime = localtime(&tt); - - if (updated_second != localTime->tm_sec || download_info->saved_path) { // every 1 second. - if (clientinfo->requestinfo - && clientinfo->requestinfo->notification) - set_downloadinginfo_appfw_notification(clientinfo); - if (clientinfo->requestinfo->callbackinfo.progress) - ipc_send_downloadinginfo(clientinfo); - updated_second = localTime->tm_sec; - } - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); -} - -void __notify_cb(user_notify_info_t *notify_info, void *user_data) -{ - if (!user_data) { - TRACE_DEBUG_MSG("[CRITICAL] clientinfoslot is NULL"); - return; - } - download_clientinfo_slot *clientinfoslot = - (download_clientinfo_slot *) user_data; - download_clientinfo *clientinfo = - (download_clientinfo *) clientinfoslot->clientinfo; - if (!clientinfo) { - TRACE_DEBUG_MSG("[CRITICAL] clientinfo is NULL"); - return; - } - - TRACE_DEBUG_INFO_MSG("id[%d],state[%d],err[%d]", - notify_info->da_dl_req_id, - notify_info->state, notify_info->err); - if (clientinfo->req_id != notify_info->da_dl_req_id) { - TRACE_DEBUG_MSG("[CRITICAL] req_id[%d] da_dl_req_id[%d}", - clientinfo->req_id, notify_info->da_dl_req_id); - return; - } - - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - - clientinfo->state = __change_state(notify_info->state); - clientinfo->err = __change_error(notify_info->err); - if (clientinfo->state == DOWNLOAD_STATE_FINISHED || - clientinfo->state == DOWNLOAD_STATE_FAILED) { - if (clientinfo->requestinfo) { - if (clientinfo->requestinfo->notification) - set_downloadedinfo_appfw_notification(clientinfo); - download_provider_db_requestinfo_remove(clientinfo-> - requestinfo->requestid); - } - download_provider_db_history_new(clientinfo); - TRACE_DEBUG_INFO_MSG("[TEST]Finish clientinfo[%p], fd[%d]", - clientinfo, clientinfo->clientfd); - } - - TRACE_DEBUG_INFO_MSG("state[%d]", clientinfo->state); - ipc_send_stateinfo(clientinfo); - - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); -} - -int __change_state(da_state state) -{ - int ret = DOWNLOAD_STATE_NONE; - switch (state) { - case DA_STATE_WAITING: - case DA_STATE_DOWNLOAD_STARTED: - TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOAD_STARTED"); - ret = DOWNLOAD_STATE_READY; - break; - case DA_STATE_DOWNLOADING: - TRACE_DEBUG_INFO_MSG("DA_STATE_DOWNLOADING"); - ret = DOWNLOAD_STATE_DOWNLOADING; - break; - case DA_STATE_DOWNLOAD_COMPLETE: - TRACE_DEBUG_INFO_MSG("DA_STATE_COMPLETE"); - ret = DOWNLOAD_STATE_INSTALLING; - break; - case DA_STATE_CANCELED: - TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED"); - ret = DOWNLOAD_STATE_STOPPED; - break; - case DA_STATE_CANCELED_ALL: - TRACE_DEBUG_INFO_MSG("DA_STATE_CANCELED_ALL"); - break; - case DA_STATE_SUSPENDED: - TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED"); - ret = DOWNLOAD_STATE_PAUSED; - break; - case DA_STATE_SUSPENDED_ALL: - TRACE_DEBUG_INFO_MSG("DA_STATE_SUSPENDED_ALL"); - break; - case DA_STATE_RESUMED: - TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED"); - ret = DOWNLOAD_STATE_DOWNLOADING; - break; - case DA_STATE_RESUMED_ALL: - TRACE_DEBUG_INFO_MSG("DA_STATE_RESUMED_ALL"); - break; - case DA_STATE_FINISHED: - TRACE_DEBUG_INFO_MSG("DA_STATE_FINISHED"); - ret = DOWNLOAD_STATE_FINISHED; - break; - case DA_STATE_FAILED: - TRACE_DEBUG_INFO_MSG("DA_STATE_FAILED"); - ret = DOWNLOAD_STATE_FAILED; - break; - default: - break; - } - return ret; -} - -int __change_error(int err) -{ - int ret = DOWNLOAD_ERROR_UNKOWN; - switch (err) { - case DA_RESULT_OK: - ret = DOWNLOAD_ERROR_NONE; - break; - case DA_ERR_INVALID_ARGUMENT: - ret = DOWNLOAD_ERROR_INVALID_PARAMETER; - break; - case DA_ERR_FAIL_TO_MEMALLOC: - ret = DOWNLOAD_ERROR_OUT_OF_MEMORY; - break; - case DA_ERR_UNREACHABLE_SERVER: - ret = DOWNLOAD_ERROR_NETWORK_UNREACHABLE; - break; - case DA_ERR_HTTP_TIMEOUT: - ret = DOWNLOAD_ERROR_CONNECTION_TIMED_OUT; - break; - case DA_ERR_DISK_FULL: - ret = DOWNLOAD_ERROR_NO_SPACE; - break; - case DA_ERR_INVALID_STATE: - ret = DOWNLOAD_ERROR_INVALID_STATE; - break; - case DA_ERR_NETWORK_FAIL: - ret = DOWNLOAD_ERROR_CONNECTION_FAILED; - break; - case DA_ERR_INVALID_URL: - ret = DOWNLOAD_ERROR_INVALID_URL; - break; - case DA_ERR_INVALID_INSTALL_PATH: - ret = DOWNLOAD_ERROR_INVALID_DESTINATION; - break; - case DA_ERR_ALREADY_MAX_DOWNLOAD: - ret = DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS; - break; - case DA_ERR_FAIL_TO_INSTALL_FILE: - ret = DOWNLOAD_ERROR_INSTALL_FAIL; - break; - case DA_ERR_FAIL_TO_CREATE_THREAD: - case DA_ERR_FAIL_TO_OBTAIN_MUTEX: - case DA_ERR_FAIL_TO_ACCESS_FILE: - case DA_ERR_FAIL_TO_GET_CONF_VALUE: - case DA_ERR_FAIL_TO_ACCESS_STORAGE: - case DA_ERR_DLOPEN_FAIL: - ret = DOWNLOAD_ERROR_IO_ERROR; - break; - } - return ret; -} - -int _init_agent() -{ - int da_ret = 0; - da_client_cb_t da_cb = { - __notify_cb, - __download_info_cb, - __downloading_info_cb - }; - da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO); - if (da_ret != DA_RESULT_OK) { - return DOWNLOAD_ERROR_FAIL_INIT_AGENT; - } - return DOWNLOAD_ERROR_NONE; -} - -void _deinit_agent() -{ - da_deinit(); -} diff --git a/src/download-provider-utils.c b/src/download-provider-utils.c deleted file mode 100644 index b513569..0000000 --- a/src/download-provider-utils.c +++ /dev/null @@ -1,231 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "download-provider-config.h" -#include "download-provider-notification.h" -#include "download-provider-pthread.h" -#include "download-provider-log.h" - -extern fd_set g_download_provider_socket_readset; -extern fd_set g_download_provider_socket_exceptset; - -int get_download_request_id(void) -{ - int uniquetime = 0; - struct timeval tval; - static int last_uniquetime = 0; - - do { - uniquetime = (int)time(NULL); - gettimeofday(&tval, NULL); - if (tval.tv_usec == 0) - uniquetime = uniquetime + (tval.tv_usec + 1) % 0xfffff; - else - uniquetime = uniquetime + tval.tv_usec; - TRACE_DEBUG_INFO_MSG("ID : %d", uniquetime); - } while (last_uniquetime == uniquetime); - last_uniquetime = uniquetime; // store - return uniquetime; -} - -void clear_socket(download_clientinfo *clientinfo) -{ - if (!clientinfo) - return; - if (clientinfo->clientfd) { - FD_CLR(clientinfo->clientfd, &g_download_provider_socket_readset); - FD_CLR(clientinfo->clientfd, &g_download_provider_socket_exceptset); - shutdown(clientinfo->clientfd, 0); - fdatasync(clientinfo->clientfd); - close(clientinfo->clientfd); - clientinfo->clientfd = 0; - } -} - -void clear_clientinfo(download_clientinfo *clientinfo) -{ - TRACE_DEBUG_INFO_MSG("[TEST] clear [%p]",clientinfo); - // clear this slot - if (!clientinfo) - return; - - clear_socket(clientinfo); - - CLIENT_MUTEX_LOCK(&(clientinfo->client_mutex)); - if (clientinfo->requestinfo) { - clientinfo->requestinfo->requestid = 0; - if (clientinfo->requestinfo->client_packagename.length > 0 - && clientinfo->requestinfo->client_packagename.str) - free(clientinfo->requestinfo->client_packagename.str); - clientinfo->requestinfo->client_packagename.str = NULL; - if (clientinfo->requestinfo->url.str) - free(clientinfo->requestinfo->url.str); - clientinfo->requestinfo->url.str = NULL; - if (clientinfo->requestinfo->install_path.str) - free(clientinfo->requestinfo->install_path.str); - clientinfo->requestinfo->install_path.str = NULL; - if (clientinfo->requestinfo->filename.str) - free(clientinfo->requestinfo->filename.str); - clientinfo->requestinfo->filename.str = NULL; - if (clientinfo->requestinfo->service_data.str) - free(clientinfo->requestinfo->service_data.str); - clientinfo->requestinfo->service_data.str = NULL; - if (clientinfo->requestinfo->headers.rows) { - int i = 0; - for (i = 0; i < clientinfo->requestinfo->headers.rows; - i++) { - if (clientinfo->requestinfo->headers.str[i].str) - free(clientinfo->requestinfo->headers. - str[i].str); - clientinfo->requestinfo->headers.str[i].str = - NULL; - } - free(clientinfo->requestinfo->headers.str); - clientinfo->requestinfo->headers.str = NULL; - } - free(clientinfo->requestinfo); - clientinfo->requestinfo = NULL; - } - if (clientinfo->downloadinginfo) - free(clientinfo->downloadinginfo); - clientinfo->downloadinginfo = NULL; - if (clientinfo->downloadinfo) - free(clientinfo->downloadinfo); - clientinfo->downloadinfo = NULL; - if (clientinfo->tmp_saved_path) - free(clientinfo->tmp_saved_path); - clientinfo->tmp_saved_path = NULL; - if (clientinfo->ui_notification_handle || clientinfo->service_handle) - destroy_appfw_notification(clientinfo); - CLIENT_MUTEX_UNLOCK(&(clientinfo->client_mutex)); - CLIENT_MUTEX_DESTROY(&(clientinfo->client_mutex)); - memset(clientinfo, 0x00, sizeof(download_clientinfo)); - free(clientinfo); - clientinfo = NULL; -} - -void clear_clientinfoslot(download_clientinfo_slot *clientinfoslot) -{ - // clear this slot - if (!clientinfoslot) - return; - download_clientinfo *clientinfo = - (download_clientinfo *) clientinfoslot->clientinfo; - clear_clientinfo(clientinfo); - clientinfoslot->clientinfo = NULL; -} - -int get_downloading_count(download_clientinfo_slot *clientinfo_list) -{ - int count = 0; - int i = 0; - for (i = 0; i < MAX_CLIENT; i++) { - if (clientinfo_list[i].clientinfo) { - if (clientinfo_list[i].clientinfo->state == - DOWNLOAD_STATE_DOWNLOADING - || clientinfo_list[i].clientinfo->state == - DOWNLOAD_STATE_INSTALLING - || clientinfo_list[i].clientinfo->state == - DOWNLOAD_STATE_READY) - count++; - } - } - return count; -} - -int get_same_request_slot_index(download_clientinfo_slot *clientinfo_list, - int requestid) -{ - int i = 0; - - if (!clientinfo_list || !requestid) - return -1; - - for (i = 0; i < MAX_CLIENT; i++) { - if (clientinfo_list[i].clientinfo - && clientinfo_list[i].clientinfo->requestinfo) { - if (clientinfo_list[i].clientinfo->requestinfo-> - requestid == requestid) { - return i; - } - } - } - return -1; -} - -int get_empty_slot_index(download_clientinfo_slot *clientinfo_list) -{ - int i = 0; - - if (!clientinfo_list) - return -1; - - for (i = 0; i < MAX_CLIENT; i++) - if (!clientinfo_list[i].clientinfo) - return i; - return -1; -} - -int get_pended_slot_index(download_clientinfo_slot *clientinfo_list) -{ - int i = 0; - - if (!clientinfo_list) - return -1; - - for (i = 0; i < MAX_CLIENT; i++) - if (clientinfo_list[i].clientinfo - && clientinfo_list[i].clientinfo->state - == DOWNLOAD_STATE_PENDED) - return i; - return -1; -} - -int get_network_status() -{ - connection_h network_handle = NULL; - if (connection_create(&network_handle) < 0) { - TRACE_DEBUG_MSG("Failed connection_create"); - return -1; - } - - connection_ethernet_state_e system_network_state - = CONNECTION_ETHERNET_STATE_DISCONNECTED; - if (connection_get_ethernet_state(network_handle, - &system_network_state) != CONNECTION_ERROR_NONE) - TRACE_DEBUG_MSG("Failed connection_get_ethernet_state"); - TRACE_DEBUG_INFO_MSG - ("ethernet check result : [%d]", (int)system_network_state); - - connection_cellular_state_e system_cellular_state - = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE; - if (connection_get_cellular_state(network_handle, - &system_cellular_state) != CONNECTION_ERROR_NONE) - TRACE_DEBUG_MSG("Failed connection_get_ethernet_state"); - TRACE_DEBUG_INFO_MSG - ("cellula check result : [%d]", (int)system_cellular_state); - - connection_wifi_state_e system_wifi_state - = CONNECTION_WIFI_STATE_DEACTIVATED; - if (connection_get_wifi_state(network_handle, - &system_wifi_state) != CONNECTION_ERROR_NONE) - TRACE_DEBUG_MSG("Failed connection_get_ethernet_state"); - TRACE_DEBUG_INFO_MSG - ("wifi check result : [%d]", (int)system_wifi_state); - - if (connection_destroy(network_handle) != CONNECTION_ERROR_NONE) - TRACE_DEBUG_MSG("Failed connection_destroy"); - - if (!(system_network_state == CONNECTION_ETHERNET_STATE_CONNECTED - || system_cellular_state == CONNECTION_CELLULAR_STATE_AVAILABLE - || system_wifi_state == CONNECTION_WIFI_STATE_CONNECTED)) - return -1; - return 0; - } diff --git a/systemd/download-provider.service b/systemd/download-provider.service new file mode 100644 index 0000000..911dce9 --- /dev/null +++ b/systemd/download-provider.service @@ -0,0 +1,13 @@ +[Unit] +Description=Download provider service +After=check-mount.service + +[Service] +Type=simple +ExecStart=/usr/bin/download-provider +MemoryLimit=100M +SmackProcessLabel=download-provider + +[Install] +WantedBy=graphical.target + diff --git a/systemd/download-provider.socket b/systemd/download-provider.socket new file mode 100644 index 0000000..6a1e99c --- /dev/null +++ b/systemd/download-provider.socket @@ -0,0 +1,10 @@ +[Socket] +ListenStream=/opt/data/download-provider/download-provider.sock +SocketMode=0777 +PassCredentials=yes +Accept=false +SmackLabelIPIn=download-provider::ipc +SmackLabelIPOut=download-provider::ipc + +[Install] +WantedBy=sockets.target -- 2.7.4