Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:55:17 +0000 (01:55 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:55:17 +0000 (01:55 +0900)
75 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0755]
LICENSE.APLv2 [new file with mode: 0644]
NOTICE [new file with mode: 0644]
download-provider-service [new file with mode: 0644]
download-provider-service.service.in [new file with mode: 0644]
download-provider.manifest [new file with mode: 0755]
download-provider.pc.in [new file with mode: 0644]
packaging/download-provider.service [new file with mode: 0644]
packaging/download-provider.spec [new file with mode: 0755]
res/images/Q02_Notification_Download_failed.png [new file with mode: 0644]
script/commit-template [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0755]
src/agent/CMakeLists.txt [new file with mode: 0755]
src/agent/download-agent-basic.c [new file with mode: 0755]
src/agent/download-agent-client-mgr.c [new file with mode: 0755]
src/agent/download-agent-debug.c [new file with mode: 0755]
src/agent/download-agent-dl-info-util.c [new file with mode: 0755]
src/agent/download-agent-dl-mgr.c [new file with mode: 0755]
src/agent/download-agent-encoding.c [new file with mode: 0755]
src/agent/download-agent-file.c [new file with mode: 0755]
src/agent/download-agent-http-mgr.c [new file with mode: 0755]
src/agent/download-agent-http-misc.c [new file with mode: 0755]
src/agent/download-agent-http-msg-handler.c [new file with mode: 0755]
src/agent/download-agent-http-queue.c [new file with mode: 0755]
src/agent/download-agent-interface.c [new file with mode: 0755]
src/agent/download-agent-mime-util.c [new file with mode: 0755]
src/agent/download-agent-plugin-conf.c [new file with mode: 0755]
src/agent/download-agent-plugin-libsoup.c [new file with mode: 0755]
src/agent/download-agent-utils-dl-id-history.c [new file with mode: 0755]
src/agent/download-agent-utils.c [new file with mode: 0755]
src/agent/include/download-agent-basic.h [new file with mode: 0755]
src/agent/include/download-agent-client-mgr.h [new file with mode: 0755]
src/agent/include/download-agent-debug.h [new file with mode: 0755]
src/agent/include/download-agent-defs.h [new file with mode: 0755]
src/agent/include/download-agent-dl-info-util.h [new file with mode: 0755]
src/agent/include/download-agent-dl-mgr.h [new file with mode: 0755]
src/agent/include/download-agent-encoding.h [new file with mode: 0755]
src/agent/include/download-agent-file.h [new file with mode: 0755]
src/agent/include/download-agent-http-mgr.h [new file with mode: 0755]
src/agent/include/download-agent-http-misc.h [new file with mode: 0755]
src/agent/include/download-agent-http-msg-handler.h [new file with mode: 0755]
src/agent/include/download-agent-http-queue.h [new file with mode: 0755]
src/agent/include/download-agent-interface.h [new file with mode: 0755]
src/agent/include/download-agent-mime-util.h [new file with mode: 0755]
src/agent/include/download-agent-plugin-conf.h [new file with mode: 0755]
src/agent/include/download-agent-plugin-http-interface.h [new file with mode: 0755]
src/agent/include/download-agent-plugin-libsoup.h [new file with mode: 0755]
src/agent/include/download-agent-pthread.h [new file with mode: 0755]
src/agent/include/download-agent-type.h [new file with mode: 0755]
src/agent/include/download-agent-utils-dl-id-history.h [new file with mode: 0755]
src/agent/include/download-agent-utils.h [new file with mode: 0755]
src/download-provider-da-interface.c [new file with mode: 0755]
src/download-provider-db.c [new file with mode: 0755]
src/download-provider-main.c [new file with mode: 0755]
src/download-provider-network.c [new file with mode: 0755]
src/download-provider-notification.c [new file with mode: 0755]
src/download-provider-pid.c [new file with mode: 0755]
src/download-provider-request.c [new file with mode: 0755]
src/download-provider-slots.c [new file with mode: 0755]
src/download-provider-socket.c [new file with mode: 0755]
src/download-provider-thread-queue.c [new file with mode: 0755]
src/download-provider-thread-request.c [new file with mode: 0755]
src/include/download-provider-config.h [new file with mode: 0755]
src/include/download-provider-da-interface.h [new file with mode: 0755]
src/include/download-provider-db.h [new file with mode: 0755]
src/include/download-provider-log.h [new file with mode: 0755]
src/include/download-provider-network.h [new file with mode: 0755]
src/include/download-provider-notification.h [new file with mode: 0755]
src/include/download-provider-pthread.h [new file with mode: 0755]
src/include/download-provider-queue.h [new file with mode: 0755]
src/include/download-provider-request.h [new file with mode: 0755]
src/include/download-provider-slots.h [new file with mode: 0755]
src/include/download-provider-socket.h [new file with mode: 0755]
src/include/download-provider.h [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..707ec6f
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Kwangmin Bang <justine.bang@samsung.com>\r
+Jungki Kwak <jungki.kwak@samsung.com>\r
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..51cd43a
--- /dev/null
@@ -0,0 +1,23 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+
+ADD_SUBDIRECTORY(src/agent)
+ADD_SUBDIRECTORY(src/)
+
+PROJECT(download-provider C)
+
+CONFIGURE_FILE(download-provider.pc.in download-provider.pc @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider.pc DESTINATION lib/pkgconfig)
+
+INSTALL(PROGRAMS download-provider-service DESTINATION /etc/rc.d/init.d)
+
+CONFIGURE_FILE(download-provider-service.service.in download-provider-service.service @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/download-provider-service.service DESTINATION /usr/share/dbus-1/services)
+
+# install images
+INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/res/images/ DESTINATION share/download-provider/
+               FILES_MATCHING
+               PATTERN "*.png"
+               )
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.APLv2 share/license/${PROJECT_NAME})
+INSTALL(FILES share/license/${PROJECT_NAME} DESTINATION share/license)
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 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/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..6220b80
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
diff --git a/download-provider-service b/download-provider-service
new file mode 100644 (file)
index 0000000..40fa113
--- /dev/null
@@ -0,0 +1,9 @@
+#!/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-service.service.in b/download-provider-service.service.in
new file mode 100644 (file)
index 0000000..198f496
--- /dev/null
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.download-provider
+Exec=/bin/sh -c 'if [ -x /usr/bin/download-provider ]; then /usr/bin/download-provider service & fi'
+User=root
diff --git a/download-provider.manifest b/download-provider.manifest
new file mode 100755 (executable)
index 0000000..b2cca84
--- /dev/null
@@ -0,0 +1,21 @@
+<manifest>
+       <define>
+               <domain name="download-provider" />
+               <provide>
+                       <label name="download-provider::db" />
+               </provide>
+               <request>
+                       <smack request="download-provider::db" type="rw" />
+               </request>
+       </define>
+       <request>
+               <domain name="download-provider" />
+       </request>
+       <assign>
+               <filesystem path="/usr/lib/libdownloadagent2.so" label="_" />
+               <filesystem path="/usr/lib/libdownloadagent2.so.0.0.1" label="_" />
+               <filesystem path="/etc/rc.d/init.d/download-provider-service" label="_" exec_label="none" />
+               <filesystem path="/etc/rc.d/rc3.d/S70download-provider-service" label="_" exec_label="none" />
+               <filesystem path="/etc/rc.d/rc5.d/S70download-provider-service" label="_" exec_label="none" />
+       </assign>
+</manifest>
diff --git a/download-provider.pc.in b/download-provider.pc.in
new file mode 100644 (file)
index 0000000..5ec2085
--- /dev/null
@@ -0,0 +1,9 @@
+# Package Information (download-provider daemon style)
+
+prefix=/usr
+includedir=${prefix}/include
+
+Name: Download Provider
+Description: Download Provider Daemon
+Version: @VERSION@
+Cflags: -I${includedir}/download-provider
diff --git a/packaging/download-provider.service b/packaging/download-provider.service
new file mode 100644 (file)
index 0000000..da1ea5f
--- /dev/null
@@ -0,0 +1,10 @@
+[Unit]
+Description=Download provider service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/download-provider
+
+[Install]
+WantedBy=tizen-middleware.target
+
diff --git a/packaging/download-provider.spec b/packaging/download-provider.spec
new file mode 100755 (executable)
index 0000000..9fca5cc
--- /dev/null
@@ -0,0 +1,416 @@
+
+Name:       download-provider
+Summary:    download the contents in background.
+Version:    1.0.2
+Release:    15
+Group:      Development/Libraries
+License:    Apache License, Version 2.0
+Source0:    %{name}-%{version}.tar.gz
+Source1:    download-provider.service
+Requires(post): /usr/bin/sqlite3
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(gobject-2.0)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(libsoup-2.4)
+BuildRequires:  pkgconfig(xdgmime)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(db-util)
+BuildRequires:  pkgconfig(sqlite3)
+BuildRequires:  pkgconfig(bundle)
+BuildRequires:  pkgconfig(capi-appfw-app-manager)
+BuildRequires:  pkgconfig(capi-network-connection)
+BuildRequires:  pkgconfig(notification)
+BuildRequires:  pkgconfig(appsvc)
+BuildRequires:  pkgconfig(dbus-1)
+
+%description
+Description: download the contents in background
+
+%package devel
+Summary:    download-provider
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+Description: download the contents in background (developement files)
+
+%prep
+%setup -q
+
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+%build
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/usr/share/license
+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}%{_libdir}/systemd/user/tizen-middleware.target.wants
+install %{SOURCE1} %{buildroot}%{_libdir}/systemd/user/
+ln -s ../download-provider.service %{buildroot}%{_libdir}/systemd/user/tizen-middleware.target.wants/
+
+mkdir -p %{buildroot}/opt/data/download-provider
+mkdir -p %{buildroot}/opt/usr/dbspace/
+if [ ! -f %{buildroot}/opt/usr/dbspace/.download-provider.db ];
+then
+sqlite3 %{buildroot}/opt/usr/dbspace/.download-provider.db 'PRAGMA journal_mode=PERSIST;
+PRAGMA foreign_keys=ON;
+CREATE TABLE logging
+(
+id INTEGER UNIQUE PRIMARY KEY,
+state INTEGER DEFAULT 0,
+errorcode INTEGER DEFAULT 0,
+startcount INTEGER DEFAULT 0,
+packagename TEXT DEFAULT NULL,
+createtime DATE,
+accesstime DATE
+);
+
+CREATE TABLE requestinfo
+(
+id INTEGER UNIQUE PRIMARY KEY,
+auto_download BOOLEAN DEFAULT 0,
+state_event BOOLEAN DEFAULT 0,
+progress_event BOOLEAN DEFAULT 0,
+network_type TINYINT DEFAULT 0,
+filename TEXT DEFAULT NULL,
+destination TEXT DEFAULT NULL,
+url TEXT DEFAULT NULL,
+FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE
+);
+
+CREATE TABLE downloadinfo
+(
+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
+);
+
+CREATE TABLE httpheaders
+(
+id INTEGER NOT NULL,
+header_field TEXT DEFAULT NULL,
+header_data TEXT DEFAULT NULL,
+FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE
+);
+
+CREATE TABLE notification
+(
+id INTEGER UNIQUE PRIMARY KEY,
+noti_enable BOOLEAN DEFAULT 0,
+extra_key TEXT DEFAULT NULL,
+extra_data TEXT DEFAULT NULL,
+FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE
+);
+
+CREATE UNIQUE INDEX requests_index ON logging (id, state, errorcode, packagename, createtime, accesstime);
+'
+fi
+
+%files
+%defattr(-,root,root,-)
+%dir %attr(0775,root,app) /opt/data/download-provider
+%manifest download-provider.manifest
+/usr/share/download-provider/*.png
+%{_libdir}/libdownloadagent2.so.0.0.1
+%{_libdir}/libdownloadagent2.so
+%{_libdir}/systemd/user/download-provider.service
+%{_libdir}/systemd/user/tizen-middleware.target.wants/download-provider.service
+%{_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
+/usr/share/license/%{name}
+/usr/share/dbus-1/services/download-provider-service.service
+%attr(660,root,app) /opt/usr/dbspace/.download-provider.db
+%attr(660,root,app) /opt/usr/dbspace/.download-provider.db-journal
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/libdownloadagent2.so.0.0.1
+%{_libdir}/libdownloadagent2.so
+%{_bindir}/download-provider
+%{_includedir}/download-provider/download-provider.h
+%{_libdir}/pkgconfig/download-provider.pc
+
+%changelog
+* Fri Feb 01 2013 Kwangmin Bang <justine.bang@samsung.com>
+- [smack] manifest for booting-script
+- [prevent defect] Dereference after null check
+
+* Thu Jan 31 2013 Kwangmin Bang <justine.bang@samsung.com>
+- add the state which means is connecting to remote
+
+* Wed Jan 30 2013 Kwangmin Bang <justine.bang@samsung.com>
+- [smack] labeling for booting script
+- [prevent defect] Dereference before/after null check 
+
+* Tue Jan 29 2013 Jungki Kwak <jungki.kwak@samsung.com>
+- Add to check invalid state when setting the callback
+- Resolve prevent defects
+- Remove the dependancy with unnecessary package
+- Remove the dependancy with dbus-glib
+- Modify smack label of shared library
+
+* Mon Jan 28 2013 Kwangmin Bang <justine.bang@samsung.com>
+- recognize who launch me by parameter of main function
+- ready the socket first before initializing dbus service
+
+* Fri Jan 25 2013 Jungki Kwak <jungki.kwak@samsung.com>
+- Resolve compile error with GCC-4.7
+- Convert error value in case the download start is failed
+- Add to check the user's install direcoty
+- Modify the name of license and add notice file
+- Call sqlite3 in install section in spec file
+- Terminate Only when support DBUS-Activation
+
+* Fri Jan 11 2013 Kwangmin Bang <justine.bang@samsung.com>
+- crash when terminated after clear requests all in timeout
+- Change the flow of playready download
+- audo_download need start_time
+
+* Tue Jan 08 2013 Jungki Kwak <jungki.kwak@samsung.com>
+- Resolve prevent defects
+- [Title] Fixed a bug that the icon of txt file can't be recognized and the txt file can't be opend
+- Modify to check returned value of sqlite API
+- Show error string in case of download CAPI failure
+
+* Fri Dec 21 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Send file_size from memory first
+- Add error code about libsoup error message
+- Change the session time-out to 60 seconds
+- Remove duplicated dlog message
+- Modify a bug to get mime type from db
+- Modify license information at spec file
+- Resolve prevent defects
+- Add missed existed db file when creaing db table
+- The temporary file is not used any more
+- Use SQL without MUTEX LOCK
+- Support ECHO command
+- Reduce SQL query to prevent SQL Error
+- replace snprintf to sqlite3_mprintf for prepare sqlite3_stmt
+
+* Fri Dec 14 2012 Kwangmin Bang <justine.bang@samsung.com>
+- add credential in request structure
+- change to ORDER BY createtime ASC from DESC in getting old list
+- Resolve prevent defects
+- Add boiler plates
+- Remove old source codes
+- apply the authentication by packagename for all commands
+- fix memory leak in error case of DB query
+- Add micro seconds value for temporary file name
+- apply the limit count and sorting in SQL query
+- do not load PAUSED request in booting time
+- Add define statement for OMA DRM
+- call IPC for sending event at the tail of function
+- maintain DB info in DESTROY command
+- Separate DB Table, reduce the amount of memory
+
+* Fri Dec 07 2012 Kwangmin Bang <justine.bang@samsung.com>
+- fix the crash when terminating by itself
+
+* Thu Dec 06 2012 Kwangmin Bang <justine.bang@samsung.com>
+- Fix the crash when accessing the history
+
+* Fri Nov 30 2012 Kwangmin Bang <justine.bang@samsung.com>
+- support DBUS-activation
+- apply int64 for file size
+- most API support ID_NOT_FOUND errorcode
+- fix crash and memory leak in SET_EXTRA_PARAM
+- fix memory leak in HTTP_HEADER case
+- remove servicedata column
+- Add to update the last received size
+
+* Tue Nov 27 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Change to parse the content name
+- Change the policy for temporary file name
+- Change to get etag when download is failed
+- DP_ERROR_ID_NOT_FOUND for set_url COMMAND
+- new common sql function for getting/setting a column
+- Add operation when registering notification
+- disable flexible timeout, use 60 sec for timeout
+- allow set_url even if unloaded from memory
+- Add functions for notification extra param
+- Block to can not re-use the request is completed
+- send errorcode to client why failed to create request
+- unload the request which not setted auto_download when client is terminated
+- call da_agent_cancel after free slot
+- Add debug message for event queue of client mgr
+- Modify abort flow in case of deinit
+
+* Fri Nov 16 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Resolve a bug about execute option API of ongoing notification
+- load all request in queue in booting time
+- stay on the memory although no client
+- Dead default in switch
+- Enable to register notification message
+- Add to add, get and remove http header values
+- Change functions to pause and resume which is based on download ID
+- Unchecked return value
+- clear history if registered before 48 hours or total of histories is over 1000.
+- stay on memory if client is connected with provider
+- advance auto-download feature
+- remove __thread keyword for sqlite handle
+- update regdate after copy history from queue
+- concede network is connected although detail get API is failed in connection state changed callback.
+- read pid from client when no support SO_PEERCRED
+- wake up Queue thread only when exist ready request
+- Add functions to save and submit http status code to client
+- detect network changes using connection callback
+
+* Thu Nov 08 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- In Offline state, do not search queue
+- Apply changed enum value of connection CAPI
+
+* Wed Oct 31 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- change the limitaiton count can download at once
+- support Cancel after Pause
+- Change the installation directory according to guide
+- deal as error if write() return 0
+
+* Mon Oct 28 2012 Kwangmin Bang <justine.bang@samsung.com>
+- increase the timout of socket
+- enhance socket update feature
+
+* Thu Oct 25 2012 Kwangmin Bang <justine.bang@samsung.com>
+- prevent defects
+- change the limitation of length
+- improve the performance logging to DB
+- check packagename for resume call
+- refresh FD_SET when only new socket is accepted
+- Fix the socket error when a client is crashed
+
+* Tue Oct 23 2012 Kwangmin Bang <justine.bang@samsung.com>
+- terminate daemon in main socket error
+- apply reading timeout for socket
+
+* Mon Oct 22 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Resolve the lockup when client app is crashed
+- Check the state before starting download
+- Support paused callback
+
+* Fri Oct 19 2012 Kwangmin Bang <justine.bang@samsung.com>
+ - replace ID based download-provider to Major Process
+
+* Tue Oct 16 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Install LICENSE file
+
+* Fri Oct 12 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Install LICENSE file
+
+* Thu Oct 11 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Use mutex when calling xdgmime API
+- Do not use fsync function
+
+* Mon Oct 08 2012 Kwangmin Bang <justine.bang@samsung.com>
+- Fix the crash when come many stop with terminating App
+
+* Fri Sep 28 2012 Kwangmin Bang <justine.bang@samsung.com>
+- Add exception code about content-dispostion
+- wait to free till callback is finished
+
+* Mon Sep 24 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Add to define for db an library in manifest file
+
+* Fri Sep 21 2012 Kwangmin Bang <justine.bang@samsung.com>
+- prevent free slot till called notify_cb
+- socket descriptor can be zero
+
+* Fri Sep 21 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Apply manifest file in which the domain is defined
+- Change way to pass extension data
+
+* Fri Sep 14 2012 Kwangmin Bang <justine.bang@samsung.com>
+- fix the crash by assert of pthread_mutex_lock
+- NULL-check before free
+- guarantee instant download for pended requests
+- add descriptor
+- fix the memory leak in error case of ipc_receive_request_msg
+- guarantee one instant download per app
+- call pthread_exit to terminate the currently running thread
+- Remove pthread_cancel function
+
+* Fri Sep 07 2012 Kwangmin Bang <justine.bang@samsung.com>
+- add LICENSE
+- Add to search download id from history db
+
+* Thu Sep 06 2012 Kwangmin Bang <justine.bang@samsung.com>
+- 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 <justine.bang@samsung.com>
+- fix timeout error
+
+* Mon Sep 03 2012 Kwangmin Bang <justine.bang@samsung.com>
+- free slot after getting event from url-download
+- fix INTEGER OVERFLOW
+
+* Thu Aug 30 2012 Kwangmin Bang <justine.bang@samsung.com>
+- initialize mutex for auto-redownloading
+- support Pause/Resume with new connection
+- fix the memory leak
+
+* Mon Aug 27 2012 Kwangmin Bang <justine.bang@samsung.com>
+- 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 <justine.bang@samsung.com>
+- 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 <jungki.kwak@samsung.com>
+- 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 <jungki.kwak@samsung.com>
+- Enable to use destination path
+- Add to handle invalid id
+
+* Tue Aug 16 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Change socket close timing
+
+* Mon Aug 13 2012 Kwangmin Bang <justine.bang@samsung.com>
+- Disable default dlog in launching script.
+
+* Tue Aug 09 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- The function to init dbus glib is removed
+
+* Tue Aug 08 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- The function to init dbus glib is added for connection network CAPI
+
+* Tue Aug 07 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Change the name of temp direcoty.
+- When add requestinfo to slot, save it to DB.
+
+* Mon Aug 06 2012 Jungki Kwak <jungki.kwak@samsung.com>
+- Initial version is updated.
+
diff --git a/res/images/Q02_Notification_Download_failed.png b/res/images/Q02_Notification_Download_failed.png
new file mode 100644 (file)
index 0000000..04ec4f0
Binary files /dev/null and b/res/images/Q02_Notification_Download_failed.png differ
diff --git a/script/commit-template b/script/commit-template
new file mode 100644 (file)
index 0000000..e398cc3
--- /dev/null
@@ -0,0 +1,10 @@
+[Title]
+
+[Issue#] N/A
+[Problem] N/A
+[Cause] N/A
+[Solution] N/A
+
+# please fill the each items.
+# If this is the commit to fix issue, please replace N/A to the number of issue.
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..66ca5cb
--- /dev/null
@@ -0,0 +1,69 @@
+
+## 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_FILE "/opt/usr/dbspace/.download-provider.db")
+SET(IMAGE_DIR "/usr/share/download-provider")
+
+INCLUDE(FindPkgConfig)
+
+pkg_check_modules(dp2_pkgs REQUIRED glib-2.0
+               gobject-2.0
+               db-util
+               sqlite3
+               capi-appfw-app-manager
+               capi-network-connection
+               notification
+               appsvc
+               dbus-1
+               bundle
+               dlog)
+
+FOREACH(flag ${dp2_pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+## INCLUDES
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/agent/include)
+
+set(DP2_LINK_LIBRARIES ${GLIB-2_LIBRARIES}
+               ${GOBJECT-2_LIBRARIES}
+               pthread
+               capi-appfw-app-manager
+               downloadagent2
+       )
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -D_REENTRANT")
+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,-pie,--hash-style=both")
+
+ADD_DEFINITIONS(
+       -DDATABASE_FILE=\"${DATABASE_FILE}\"
+       -DIMAGE_DIR=\"${IMAGE_DIR}\"
+       )
+
+ADD_DEFINITIONS(-DDP_SUPPORT_DBUS_ACTIVATION)
+
+ADD_EXECUTABLE(${PROJECT_NAME}
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-pid.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-socket.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-slots.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-network.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-db.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-request.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-da-interface.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-thread-request.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-thread-queue.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-notification.c
+       ${CMAKE_CURRENT_SOURCE_DIR}/download-provider-main.c )
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dp2_pkgs_LDFLAGS} ${DP2_LINK_LIBRARIES})
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
+
+INSTALL(FILES include/download-provider.h DESTINATION include/download-provider/)
diff --git a/src/agent/CMakeLists.txt b/src/agent/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..ead1561
--- /dev/null
@@ -0,0 +1,86 @@
+PROJECT(downloadagent2 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 -fPIC")
+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-id-history.c
+        ${SRCS_PATH}/download-agent-basic.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-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
new file mode 100755 (executable)
index 0000000..03f3a8a
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * 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 <stdlib.h>
+
+#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-pthread.h"
+#include "download-agent-file.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 , int *dl_id)
+{
+       DA_LOG_FUNC_START(Default);
+       return start_download_with_extension(url, dl_id, NULL);
+}
+
+da_result_t start_download_with_extension(
+               const char *url,
+               int *dl_id,
+               extension_data_t *extension_data)
+{
+       da_result_t  ret = DA_RESULT_OK;
+       int slot_id = 0;
+       const char **request_header = DA_NULL;
+       const char *install_path = DA_NULL;
+       const char *file_name = DA_NULL;
+       const char *etag = DA_NULL;
+       const char *temp_file_path = 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;
+               etag = extension_data->etag;
+               temp_file_path = extension_data->temp_file_path;
+       }
+
+       ret = get_available_slot_id(&slot_id);
+       if (DA_RESULT_OK != ret)
+               return ret;
+
+       *dl_id = GET_DL_ID(slot_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(install_path_len+1, sizeof(char));
+                       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(strlen(file_name)+1, sizeof(char));
+                       if (client_input->file_name)
+                               strncpy(client_input->file_name, file_name, strlen(file_name));
+               }
+
+               if (etag) {
+                       client_input->etag = (char *)calloc(strlen(etag)+1, sizeof(char));
+                       if (client_input->etag)
+                               strncpy(client_input->etag, etag, strlen(etag));
+
+               }
+
+               if (temp_file_path) {
+                       client_input->temp_file_path = (char *)calloc(strlen(temp_file_path)+1, sizeof(char));
+                       if (client_input->temp_file_path)
+                               strncpy(client_input->temp_file_path, temp_file_path, strlen(temp_file_path));
+               }
+
+               client_input_basic = &(client_input->client_input_basic);
+               client_input_basic->req_url = (char *)calloc(strlen(url)+1, sizeof(char));
+               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->slot_id = slot_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(slot_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(slot_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 slot_id[%d] thread id[%lu]",
+                       slot_id,GET_DL_THREAD_ID(slot_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(slot_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;
+       download_state_t download_state = 0;
+
+       int slot_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 {
+               slot_id = thread_info->slot_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_slot_id(slot_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(slot_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(slot_id) = client_input->user_data;
+       client_input->user_data = DA_NULL;
+       GET_DL_USER_INSTALL_PATH(slot_id) = client_input->install_path;
+       client_input->install_path = DA_NULL;
+       GET_DL_USER_FILE_NAME(slot_id) = client_input->file_name;
+       client_input->file_name = DA_NULL;
+       GET_DL_USER_ETAG(slot_id) = client_input->etag;
+       client_input->etag = DA_NULL;
+       GET_DL_USER_TEMP_FILE_PATH(slot_id) = client_input->temp_file_path;
+       client_input->temp_file_path = 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) {
+               char *installed_path = NULL;
+               char *etag = DA_NULL;
+               req_dl_info *request_info = NULL;
+               file_info *file_storage = NULL;
+               DA_LOG_CRITICAL(Default, "Whole download flow is finished.");
+               _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_ABORTED) {
+                       DA_LOG(Default, "Abort case. Do not call client callback");
+#ifdef PAUSE_EXIT
+               } else if (download_state == DOWNLOAD_STATE_PAUSED) {
+                       DA_LOG(Default, "Finish case from paused state");
+                       destroy_download_info(slot_id);
+#endif
+               } else {
+                       request_info = GET_STAGE_TRANSACTION_INFO(stage);
+                       etag = GET_REQUEST_HTTP_HDR_ETAG(request_info);
+                       file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
+                       installed_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage);
+                       send_user_noti_and_finish_download_flow(slot_id, installed_path,
+                                       etag);
+               }
+       } else {
+               char *etag = DA_NULL;
+               req_dl_info *request_info = NULL;
+               request_info = GET_STAGE_TRANSACTION_INFO(stage);
+               DA_LOG_CRITICAL(Default, "Download Failed -Return = %d", ret);
+               if (request_info) {
+                       etag = GET_REQUEST_HTTP_HDR_ETAG(request_info);
+                       send_client_finished_info(slot_id, GET_DL_ID(slot_id),
+                                       DA_NULL, etag, ret, get_http_status(slot_id));
+               }
+               destroy_download_info(slot_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 slot_id = DA_INVALID_ID;
+
+       DA_LOG_FUNC_START(Default);
+
+       slot_id = GET_STAGE_DL_ID(stage);
+       CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_NEW_DOWNLOAD, stage);
+
+       do {
+               stage = GET_DL_CURRENT_STAGE(slot_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 ||
+                                       download_state == DOWNLOAD_STATE_ABORTED ||
+                                       download_state == DOWNLOAD_STATE_PAUSED) {
+                               break;
+                       } else {
+                               if (DA_RESULT_OK == ret) {
+                                       ret = handle_after_download(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
new file mode 100755 (executable)
index 0000000..e4268ac
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * 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 <unistd.h>
+
+#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.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_result_t reg_client_app(
+               da_client_cb_t *da_client_callback)
+{
+       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);
+
+       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->slot_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!!!");
+               }
+               free(client_noti);
+       } 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. */
+       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_paused_info(int slot_id)
+{
+       client_noti_t *client_noti = DA_NULL;
+       user_paused_info_t *paused_info = DA_NULL;
+       download_state_t state = GET_DL_STATE_ON_ID(slot_id);
+
+       DA_LOG_FUNC_START(ClientNoti);
+
+       if (!GET_DL_ENABLE_PAUSE_UPDATE(slot_id)) {
+               DA_LOG(ClientNoti, "Do not call pause cb");
+               return DA_RESULT_OK;
+       }
+       if (!is_valid_slot_id(slot_id)) {
+               DA_LOG_ERR(ClientNoti, "Download ID is not valid");
+               return DA_RESULT_OK;
+       }
+
+       DA_LOG_VERBOSE(ClientNoti, "slot_id[%d]", slot_id);
+       if ((DOWNLOAD_STATE_PAUSED != state)) {
+               DA_LOG(ClientNoti, "The state is not paused. state:%d", state);
+               return DA_ERR_INVALID_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->slot_id = slot_id;
+       client_noti->user_data = GET_DL_USER_DATA(slot_id);
+       client_noti->noti_type = Q_CLIENT_NOTI_TYPE_PAUSED_INFO;
+       client_noti->next = DA_NULL;
+
+       paused_info = (user_paused_info_t *)&(client_noti->type.paused_info);
+       paused_info->download_id= GET_DL_ID(slot_id);
+       DA_LOG(ClientNoti, "pushing paused info. slot_id=%d, dl_id=%d",
+                       slot_id, GET_DL_ID(slot_id));
+
+       push_client_noti(client_noti);
+
+       return DA_RESULT_OK;
+}
+
+da_result_t  send_client_update_progress_info (
+               int slot_id,
+               int dl_id,
+               unsigned long int received_size
+               )
+{
+       client_noti_t *client_noti = DA_NULL;
+       user_progress_info_t *progress_info = DA_NULL;
+
+       //DA_LOG_FUNC_START(ClientNoti);
+
+       if (!is_valid_slot_id(slot_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->slot_id = slot_id;
+       client_noti->user_data = GET_DL_USER_DATA(slot_id);
+       client_noti->noti_type = Q_CLIENT_NOTI_TYPE_PROGRESS_INFO;
+       client_noti->next = DA_NULL;
+
+       progress_info = (user_progress_info_t *)&(client_noti->type.update_progress_info);
+       progress_info->download_id= dl_id;
+       progress_info->received_size = received_size;
+
+       DA_LOG_VERBOSE(ClientNoti, "pushing received_size=%lu, slot_id=%d, dl_id=%d",
+                       received_size, slot_id, dl_id);
+
+       push_client_noti(client_noti);
+
+       return DA_RESULT_OK;
+}
+
+da_result_t  send_client_update_dl_info (
+               int slot_id,
+               int dl_id,
+               char *file_type,
+               unsigned long int file_size,
+               char *tmp_saved_path,
+               char *pure_file_name,
+               char *etag,
+               char *extension)
+{
+       client_noti_t *client_noti = DA_NULL;
+       user_download_info_t *update_dl_info = DA_NULL;
+       int len = 0;
+
+       DA_LOG_FUNC_START(ClientNoti);
+
+       if (!is_valid_slot_id(slot_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->slot_id = slot_id;
+       client_noti->user_data = GET_DL_USER_DATA(slot_id);
+       client_noti->noti_type = Q_CLIENT_NOTI_TYPE_STARTED_INFO;
+       client_noti->next = DA_NULL;
+
+       update_dl_info = (user_download_info_t *)&(client_noti->type.update_dl_info);
+       update_dl_info->download_id = dl_id;
+       update_dl_info->file_size = file_size;
+       if (pure_file_name && extension) {
+               len = strlen(pure_file_name) + strlen(extension) + 1;
+               update_dl_info->content_name = (char *)calloc(len + 1, sizeof(char));
+               if (!update_dl_info->content_name) {
+                       free(client_noti);
+                       return DA_ERR_FAIL_TO_MEMALLOC;
+               }
+               snprintf(update_dl_info->content_name, len + 1, "%s.%s",
+                               pure_file_name, extension);
+       }
+
+       /* 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 (etag)
+               update_dl_info->etag = strdup(etag);
+       DA_LOG(ClientNoti, "pushing file_size=%lu, slot_id=%d, dl_id=%d",
+                       file_size, slot_id, dl_id);
+
+       push_client_noti(client_noti);
+
+       return DA_RESULT_OK;
+}
+
+da_result_t  send_client_finished_info (
+               int slot_id,
+               int dl_id,
+               char *saved_path,
+               char *etag,
+               int error,
+               int http_status
+               )
+{
+       client_noti_t *client_noti = DA_NULL;
+       user_finished_info_t *finished_info = DA_NULL;
+
+       DA_LOG_FUNC_START(ClientNoti);
+
+       if (!is_valid_slot_id(slot_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->slot_id = slot_id;
+       client_noti->user_data = GET_DL_USER_DATA(slot_id);
+       client_noti->noti_type = Q_CLIENT_NOTI_TYPE_FINISHED_INFO;
+       client_noti->next = DA_NULL;
+
+       finished_info = (user_finished_info_t *)&(client_noti->type.finished_info);
+       finished_info->download_id = dl_id;
+       finished_info->err = error;
+       finished_info->http_status = http_status;
+
+       if (saved_path) {
+               finished_info->saved_path = strdup(saved_path);
+               DA_LOG(ClientNoti, "saved path=%s", saved_path);
+       }
+       if (etag) {
+               finished_info->etag = strdup(etag);
+               DA_LOG(ClientNoti, "pushing finished info. etag[%s]", etag);
+       }
+       DA_LOG(ClientNoti, "user_data=%p", client_noti->user_data);
+       DA_LOG(ClientNoti, "http_status=%d", http_status);
+       DA_LOG(ClientNoti, "pushing slot_id=%d, dl_id=%d err=%d", slot_id, dl_id, error);
+
+       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_STARTED_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->etag) {
+                               free(update_dl_info->etag);
+                               update_dl_info->etag = DA_NULL;
+                       }
+               } else if (client_noti->noti_type ==
+                               Q_CLIENT_NOTI_TYPE_FINISHED_INFO) {
+                       user_finished_info_t *finished_info = DA_NULL;
+                       finished_info = (user_finished_info_t*)
+                               &(client_noti->type.finished_info);
+                       if (finished_info->saved_path) {
+                               free(finished_info->saved_path);
+                               finished_info->saved_path = DA_NULL;
+                       }
+                       if (finished_info->etag) {
+                               free(finished_info->etag);
+                               finished_info->etag = 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); */
+
+       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 0
+               if (cur->noti_type == Q_CLIENT_NOTI_TYPE_PROGRESS_INFO) {
+                       /* For UI performance. If the update noti info is existed at queue,
+                          replace it with new update noti info */
+                       if (cur->slot_id == client_noti->slot_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;
+                       }
+               } else {
+                       cur->next = client_noti;
+               }
+#else
+       cur->next = client_noti;
+#endif
+       }
+
+       queue->having_data = DA_TRUE;
+
+       __client_q_wake_up_without_lock();
+       if (queue->client_q_head->next) {
+               DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti[%p]",
+                               queue->client_q_head, queue->client_q_head->next);
+       } else {
+               DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti is NULL",
+                               queue->client_q_head);
+       }
+
+       _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;
+               if (queue->client_q_head) {
+                       DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti[%p]",
+                                       *out_client_noti, queue->client_q_head);
+               } else {
+                       DA_LOG_VERBOSE(ClientNoti, "client noti[%p] next noti is NULL",
+                                       *out_client_noti);
+               }
+       } 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_VERBOSE(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_VERBOSE(Thread, "Sleep @ thread_for_client_noti!");
+                       __client_q_goto_sleep_without_lock();
+                       DA_LOG_VERBOSE(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 {
+                               DA_LOG_VERBOSE(ClientNoti, "noti type[%d]",
+                                               client_noti->noti_type);
+                               switch (client_noti->noti_type) {
+                               case Q_CLIENT_NOTI_TYPE_STARTED_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);
+                                               if (update_dl_info->etag)
+                                                       DA_LOG(ClientNoti, "Etag:[%s]", update_dl_info->etag);
+                                               DA_LOG(ClientNoti, "Update download info for slot_id=%d, dl_id=%d, received size=%lu- DONE",
+                                                               client_noti->slot_id,
+                                                               update_dl_info->download_id,
+                                                               update_dl_info->file_size
+                                                               );
+                                       }
+                               }
+                               break;
+                               case Q_CLIENT_NOTI_TYPE_PROGRESS_INFO:
+                               {
+                                       user_progress_info_t *progress_info = DA_NULL;;
+                                       progress_info = (user_progress_info_t*)(&(client_noti->type.update_progress_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(progress_info, client_noti->user_data);
+                                               DA_LOG_VERBOSE(ClientNoti, "Update downloading info for slot_id=%d, dl_id=%d, received size=%lu - DONE",
+                                                               client_noti->slot_id,
+                                                               progress_info->download_id,
+                                                               progress_info->received_size);
+                                       }
+                               }
+                               break;
+                               case Q_CLIENT_NOTI_TYPE_FINISHED_INFO:
+                               {
+                                       user_finished_info_t *finished_info = DA_NULL;;
+                                       finished_info = (user_finished_info_t*)(&(client_noti->type.finished_info));
+                                       if (client_app_mgr.client_app_info.client_callback.finished_info_cb) {
+                                               client_app_mgr.client_app_info.client_callback.finished_info_cb(
+                                                       finished_info, client_noti->user_data);
+                                               DA_LOG(ClientNoti, "Completed info for slot_id=%d, dl_id=%d, saved_path=%s etag=%s err=%d http_state=%d user_data=%p- DONE",
+                                                               client_noti->slot_id,
+                                                               finished_info->download_id,
+                                                               finished_info->saved_path,
+                                                               finished_info->etag,
+                                                               finished_info->err,
+                                                               finished_info->http_status,
+                                                               client_noti->user_data);
+                                       }
+                               }
+                               break;
+                               case Q_CLIENT_NOTI_TYPE_PAUSED_INFO:
+                               {
+                                       user_paused_info_t *da_paused_info = DA_NULL;
+                                       da_paused_info = (user_paused_info_t *)(&(client_noti->type.paused_info));
+
+                                       if (client_app_mgr.client_app_info.client_callback.paused_info_cb) {
+                                               DA_LOG(ClientNoti, "User Paused info for slot_id=%d, dl_id=%d - Done",
+                                                               client_noti->slot_id,
+                                                               da_paused_info->download_id);
+                                               client_app_mgr.client_app_info.client_callback.paused_info_cb(
+                                                       da_paused_info, client_noti->user_data);
+                                       }
+                               }
+                               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;
+}
+
+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
new file mode 100755 (executable)
index 0000000..07078b3
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#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 FileManager:
+               return STRING_IT(FileManager);
+       case DRMManager:
+               return STRING_IT(DRMManager);
+       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
new file mode 100755 (executable)
index 0000000..8e3bb78
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * 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 <string.h>
+
+#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 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);
+
+       _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_dl_id_history(&(download_mgr.dl_id_history));
+       }
+
+       _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;
+               dl_info_t *dl_info = DA_NULL;
+               void *t_return = NULL;
+               for (i = 0; i < DA_MAX_DOWNLOAD_ID; i++) {
+                       dl_info = &(download_mgr.dl_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;
+               deinit_dl_id_history(&(download_mgr.dl_id_history));
+       }
+       _da_thread_mutex_unlock(&mutex_download_mgr);
+       return ret;
+}
+
+void init_download_info(int slot_id)
+{
+       dl_info_t *dl_info = DA_NULL;
+
+//     DA_LOG_FUNC_START(Default);
+
+       _da_thread_mutex_lock(&mutex_download_state[slot_id]);
+//     DA_LOG_VERBOSE(Default, "Init slot_id [%d] Info", slot_id);
+       dl_info = &(download_mgr.dl_info[slot_id]);
+
+       dl_info->is_using = DA_FALSE;
+       dl_info->state = DOWNLOAD_STATE_IDLE;
+       dl_info->download_stage_data = DA_NULL;
+       dl_info->dl_id = 0;
+       dl_info->http_status = 0;
+       dl_info->enable_pause_update = DA_FALSE;
+       dl_info->user_install_path = DA_NULL;
+       dl_info->user_file_name = DA_NULL;
+       dl_info->user_etag = DA_NULL;
+       dl_info->user_temp_file_path = DA_NULL;
+       dl_info->user_data = DA_NULL;
+
+       Q_init_queue(&(dl_info->queue));
+
+       DA_LOG_VERBOSE(Default, "Init slot_id [%d] Info END", slot_id);
+       _da_thread_mutex_unlock(&mutex_download_state[slot_id]);
+
+       return;
+}
+
+void destroy_download_info(int slot_id)
+{
+       dl_info_t *dl_info = DA_NULL;
+
+       DA_LOG_FUNC_START(Default);
+
+       DA_LOG(Default, "Destroying slot_id [%d] Info", slot_id);
+
+       if (slot_id == DA_INVALID_ID) {
+               DA_LOG_ERR(Default, "invalid slot_id");
+               return;
+       }
+
+       dl_info = &(download_mgr.dl_info[slot_id]);
+       if (DA_FALSE == dl_info->is_using) {
+/*             DA_LOG_ERR(Default, "invalid slot_id"); */
+               return;
+       }
+
+       _da_thread_mutex_lock (&mutex_download_state[slot_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(slot_id, dl_info->download_stage_data);
+               dl_info->download_stage_data = DA_NULL;
+       }
+       dl_info->dl_id = 0;
+       dl_info->enable_pause_update = DA_FALSE;
+       if (dl_info->user_install_path) {
+               free(dl_info->user_install_path);
+               dl_info->user_install_path = DA_NULL;
+       }
+
+       if (dl_info->user_file_name) {
+               free(dl_info->user_file_name);
+               dl_info->user_file_name = DA_NULL;
+       }
+
+       if (dl_info->user_etag) {
+               free(dl_info->user_etag);
+               dl_info->user_etag = DA_NULL;
+       }
+
+       if (dl_info->user_temp_file_path ) {
+               free(dl_info->user_temp_file_path );
+               dl_info->user_temp_file_path  = DA_NULL;
+       }
+
+       dl_info->user_data = DA_NULL;
+
+       Q_destroy_queue(&(dl_info->queue));
+       dl_info->http_status = 0;
+
+       dl_info->is_using = DA_FALSE;
+
+       DA_LOG(Default, "Destroying slot_id [%d] Info END", slot_id);
+       _da_thread_mutex_unlock (&mutex_download_state[slot_id]);
+       return;
+}
+
+void *Add_new_download_stage(int slot_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 = slot_id;
+       download_stage_data = GET_DL_CURRENT_STAGE(slot_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(slot_id) = new_download_stage_data;
+       }
+       DA_LOG(Default, "NEW STAGE ADDED FOR DOWNLOAD ID[%d] new_stage[%p]", slot_id,new_download_stage_data);
+
+ERR:
+       return new_download_stage_data;
+}
+
+void remove_download_stage(int slot_id, stage_info *in_stage)
+{
+       stage_info *stage = DA_NULL;
+
+       DA_LOG_FUNC_START(Default);
+
+       stage = GET_DL_CURRENT_STAGE(slot_id);
+       if (DA_NULL == stage) {
+               DA_LOG_VERBOSE(Default, "There is no stage field on slot_id = %d", slot_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(slot_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_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;
+               }
+
+               if (client_input->etag) {
+                       free(client_input->etag);
+                       client_input->etag = DA_NULL;
+               }
+
+               if (client_input->temp_file_path) {
+                       free(client_input->temp_file_path);
+                       client_input->temp_file_path = 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_slot_id_for_dl_id(
+        int dl_id,
+        int* slot_id)
+{
+       da_result_t ret = DA_ERR_INVALID_DL_REQ_ID;
+       int iter = 0;
+
+       if (dl_id < 0) {
+               DA_LOG_ERR(Default, "dl_id is less than 0 - %d", dl_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.dl_info[iter].is_using == DA_TRUE) {
+                       if (download_mgr.dl_info[iter].dl_id ==
+                               dl_id) {
+                               *slot_id = iter;
+                               ret = DA_RESULT_OK;
+                               break;
+                       }
+               }
+       }
+       _da_thread_mutex_unlock(&mutex_download_mgr);
+
+       return ret;
+}
+
+
+da_result_t get_available_slot_id(int *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.dl_info[i].is_using == DA_FALSE) {
+                       init_download_info(i);
+
+                       download_mgr.dl_info[i].is_using = DA_TRUE;
+
+                       download_mgr.dl_info[i].dl_id
+                               = get_available_dl_id(&(download_mgr.dl_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_slot_id(int slot_id)
+{
+       da_bool_t ret = DA_FALSE;
+
+       if (slot_id >= 0 && slot_id < DA_MAX_DOWNLOAD_ID) {
+               if (download_mgr.dl_info[slot_id].is_using == DA_TRUE)
+                       ret = DA_TRUE;
+       }
+
+       return ret;
+}
+
+void store_http_status(int dl_id, int status)
+{
+       if (status < 100 || status > 599) {
+               DA_LOG_ERR(Default, "Invalid status code [%d]", status);
+               return;
+       }
+       DA_LOG_VERBOSE(Default, "store_http_status id[%d]status[%d] ",dl_id, status);
+       download_mgr.dl_info[dl_id].http_status = status;
+}
+
+int get_http_status(int slot_id)
+{
+       if (!download_mgr.dl_info[slot_id].is_using) {
+               DA_LOG_ERR(Default, "Invalid slot_id [%d]", slot_id);
+               return 0;
+       }
+       return download_mgr.dl_info[slot_id].http_status;
+}
diff --git a/src/agent/download-agent-dl-mgr.c b/src/agent/download-agent-dl-mgr.c
new file mode 100755 (executable)
index 0000000..cf3ad52
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * 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-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-file.h"
+#include "download-agent-plugin-conf.h"
+
+
+static da_result_t __cancel_download_with_slot_id(int slot_id);
+static da_result_t __suspend_download_with_slot_id(int slot_id);
+
+
+da_result_t requesting_download(stage_info *stage)
+{
+       da_result_t ret = DA_RESULT_OK;
+       req_dl_info *request_session = DA_NULL;
+
+       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;
+       }
+ERR:
+       return ret;
+}
+
+da_result_t handle_after_download(stage_info *stage)
+{
+       da_result_t ret = DA_RESULT_OK;
+       da_mime_type_id_t mime_type = DA_MIME_TYPE_NONE;
+
+       DA_LOG_FUNC_START(Default);
+
+       mime_type = get_mime_type_id(
+                       GET_CONTENT_STORE_CONTENT_TYPE(GET_STAGE_CONTENT_STORE_INFO(stage)));
+
+       switch (mime_type) {
+               case DA_MIME_TYPE_NONE:
+                       DA_LOG(Default, "DA_MIME_TYPE_NONE");
+                       ret = DA_ERR_MISMATCH_CONTENT_TYPE;
+                       break;
+               default:
+                       CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_FINISH, stage);
+                       break;
+       } /* end of switch */
+
+       return ret;
+}
+
+static da_result_t __cancel_download_with_slot_id(int slot_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[slot_id]);
+       download_state = GET_DL_STATE_ON_ID(slot_id);
+       DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(slot_id));
+
+       if (download_state == DOWNLOAD_STATE_FINISH ||
+                       download_state == DOWNLOAD_STATE_CANCELED) {
+               DA_LOG_CRITICAL(Default, "Already download is finished. Do not send cancel request");
+               _da_thread_mutex_unlock (&mutex_download_state[slot_id]);
+               return ret;
+       }
+       _da_thread_mutex_unlock (&mutex_download_state[slot_id]);
+
+       stage = GET_DL_CURRENT_STAGE(slot_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", slot_id);
+ERR:
+       return ret;
+}
+
+da_result_t cancel_download(int dl_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       int slot_id = DA_INVALID_ID;
+
+       DA_LOG_FUNC_START(Default);
+
+       ret = get_slot_id_for_dl_id(dl_id, &slot_id);
+       if (ret != DA_RESULT_OK) {
+               DA_LOG_ERR(Default, "dl req ID is not Valid");
+               goto ERR;
+       }
+
+       if (DA_FALSE == is_valid_slot_id(slot_id)) {
+               DA_LOG_ERR(Default, "Download ID is not Valid");
+               ret = DA_ERR_INVALID_ARGUMENT;
+               goto ERR;
+       }
+
+       ret = __cancel_download_with_slot_id(slot_id);
+
+ERR:
+       return ret;
+
+}
+
+static da_result_t __suspend_download_with_slot_id(int slot_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[slot_id]);
+       download_state = GET_DL_STATE_ON_ID(slot_id);
+       DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(slot_id));
+       _da_thread_mutex_unlock (&mutex_download_state[slot_id]);
+
+       stage = GET_DL_CURRENT_STAGE(slot_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", slot_id);
+ERR:
+       return ret;
+}
+
+da_result_t suspend_download(int dl_id, da_bool_t is_enable_cb)
+{
+       da_result_t ret = DA_RESULT_OK;
+       int slot_id = DA_INVALID_ID;
+
+       DA_LOG_FUNC_START(Default);
+
+       ret = get_slot_id_for_dl_id(dl_id, &slot_id);
+       if (ret != DA_RESULT_OK) {
+               DA_LOG_ERR(Default, "dl req ID is not Valid");
+               goto ERR;
+       }
+       GET_DL_ENABLE_PAUSE_UPDATE(slot_id) = is_enable_cb;
+       if (DA_FALSE == is_valid_slot_id(slot_id)) {
+               DA_LOG_ERR(Default, "Download ID is not Valid");
+               ret = DA_ERR_INVALID_ARGUMENT;
+               goto ERR;
+       }
+
+       ret = __suspend_download_with_slot_id(slot_id);
+
+ERR:
+       return ret;
+
+}
+
+static da_result_t __resume_download_with_slot_id(int slot_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[slot_id]);
+       download_state = GET_DL_STATE_ON_ID(slot_id);
+       DA_LOG(Default, "download_state = %d", GET_DL_STATE_ON_ID(slot_id));
+       _da_thread_mutex_unlock (&mutex_download_state[slot_id]);
+
+       stage = GET_DL_CURRENT_STAGE(slot_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", slot_id);
+ERR:
+       return ret;
+}
+
+da_result_t resume_download(int dl_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+       int slot_id = DA_INVALID_ID;
+
+       DA_LOG_FUNC_START(Default);
+
+       ret = get_slot_id_for_dl_id(dl_id, &slot_id);
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+       if (DA_FALSE == is_valid_slot_id(slot_id)) {
+               DA_LOG_ERR(Default, "Download ID is not Valid");
+               ret = DA_ERR_INVALID_DL_REQ_ID;
+               goto ERR;
+       }
+
+       ret = __resume_download_with_slot_id(slot_id);
+
+ERR:
+       return ret;
+}
+
+da_result_t send_user_noti_and_finish_download_flow(
+               int slot_id, char *installed_path, char *etag)
+{
+       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[slot_id]);
+       download_state = GET_DL_STATE_ON_ID(slot_id);
+       DA_LOG(Default, "state = %d", download_state);
+       _da_thread_mutex_unlock (&mutex_download_state[slot_id]);
+
+       switch (download_state) {
+       case DOWNLOAD_STATE_FINISH:
+               send_client_finished_info(slot_id, GET_DL_ID(slot_id),
+                       installed_path, DA_NULL, DA_RESULT_OK,
+                       get_http_status(slot_id));
+               need_destroy_download_info = DA_TRUE;
+               break;
+       case DOWNLOAD_STATE_CANCELED:
+               send_client_finished_info(slot_id, GET_DL_ID(slot_id),
+                               installed_path, etag, DA_RESULT_USER_CANCELED,
+                               get_http_status(slot_id));
+               need_destroy_download_info = DA_TRUE;
+               break;
+#ifdef PAUSE_EXIT
+       case DOWNLOAD_STATE_PAUSED:
+               need_destroy_download_info = DA_TRUE;
+               break;
+#endif
+       default:
+               DA_LOG(Default, "download state = %d", download_state);
+               break;
+       }
+
+       if (need_destroy_download_info == DA_TRUE) {
+               destroy_download_info(slot_id);
+       } else {
+               DA_LOG_CRITICAL(Default, "download info is not destroyed");
+       }
+
+       return ret;
+}
+
+da_bool_t is_valid_download_id(int dl_id)
+{
+
+       da_bool_t ret = DA_TRUE;
+       int slot_id = DA_INVALID_ID;
+
+       DA_LOG_VERBOSE(Default, "[is_valid_download_id]download_id : %d", dl_id);
+
+       ret = get_slot_id_for_dl_id(dl_id, &slot_id);
+       if (ret != DA_RESULT_OK) {
+               DA_LOG_ERR(Default, "dl req ID is not Valid");
+               ret = DA_FALSE;
+               goto ERR;
+       } else {
+               ret = DA_TRUE;
+       }
+
+       if (DA_FALSE == is_valid_slot_id(slot_id)) {
+               DA_LOG_ERR(Default, "Download ID is not Valid");
+               ret = DA_FALSE;
+               goto ERR;
+       }
+       if (GET_DL_THREAD_ID(slot_id) < 1) {
+               DA_LOG_ERR(Default, "Download thread is not alive");
+               ret = DA_FALSE;
+               goto ERR;
+       }
+
+ERR:
+       return ret;
+}
diff --git a/src/agent/download-agent-encoding.c b/src/agent/download-agent-encoding.c
new file mode 100755 (executable)
index 0000000..ae2fdf4
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#include "download-agent-encoding.h"
+#include "download-agent-debug.h"
+
+da_result_t _parsing_base64_encoded_str(const char *in_encoded_str,
+       char **out_charset_type,
+       char *out_encoding_type,
+       char **out_raw_encoded_str);
+
+da_bool_t is_base64_encoded_word(const char *in_str)
+{
+       const char *haystack = DA_NULL;
+       char first_needle[8] = {0,};
+       char second_needle[8] = {0,};
+       char *found_str = DA_NULL;
+
+       if (!in_str) {
+               DA_LOG_ERR(Default, "input string is NULL");
+               return DA_FALSE;
+       }
+
+       haystack = in_str;
+       if (haystack[0] == '"') {
+               snprintf(first_needle, sizeof(first_needle), "%s", "\"=?");     // "=?
+               snprintf(second_needle, sizeof(second_needle), "%s", "?=\"");   // ?="
+       } else {
+               snprintf(first_needle, sizeof(first_needle), "%s", "=?");       // =?
+               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;
+               }
+       }
+       return DA_FALSE;
+}
+
+da_result_t decode_base64_encoded_str(const char *in_encoded_str,
+       char **out_decoded_ascii_str)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       const char *org_str = DA_NULL;
+       char *charset_type = NULL;
+       char encoding_type = '\0';
+       char *raw_encoded_str = NULL;
+       char *decoded_str = NULL;
+       const gchar *g_encoded_text = NULL;
+       guchar *g_decoded_text = NULL;
+       gsize g_decoded_text_len = 0;
+
+       DA_LOG(Default, "input str = [%s]", in_encoded_str);
+
+       org_str = in_encoded_str;
+       if(!org_str) {
+               DA_LOG_ERR(Default, "Input string is NULL");
+               ret = DA_ERR_INVALID_ARGUMENT;
+               goto ERR;
+       }
+
+       ret = _parsing_base64_encoded_str(org_str, &charset_type,
+               &encoding_type, &raw_encoded_str);
+       if(ret != DA_RESULT_OK) {
+               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);
+               ret = DA_ERR_INVALID_ARGUMENT;
+               goto ERR;
+       }
+
+       /*
+        * on glib/gtype.h
+        * typedef char   gchar;
+        * typedef unsigned char   guchar;
+        *
+        */
+       g_encoded_text = (const gchar*)raw_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);
+               decoded_str = (char*)calloc(1, g_decoded_text_len+1);
+               if(!decoded_str) {
+                       DA_LOG_ERR(Default, "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);
+
+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,
+       char **out_charset_type,
+       char *out_encoding_type,
+       char **out_raw_encoded_str)
+{
+       da_result_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;
+       char *wanted_str_end = DA_NULL;
+
+       org_str = in_encoded_str;
+       if (!org_str) {
+               DA_LOG_ERR(Default, "Input string is NULL");
+               ret = DA_ERR_INVALID_ARGUMENT;
+               goto ERR;
+       }
+
+       // strip "=?"
+       haystack = (char*)org_str;
+       snprintf(needle, sizeof(needle), "=?");
+       wanted_str_end = strstr(haystack, needle);
+       if (!wanted_str_end) {
+               DA_LOG_ERR(Default, "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
+       haystack = wanted_str_start = wanted_str;
+       needle[0] = '?';
+       wanted_str_end = strchr(haystack, needle[0]);
+       if (!wanted_str_end) {
+               DA_LOG_ERR(Default, "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");
+                       ret = DA_ERR_FAIL_TO_MEMALLOC;
+                       goto ERR;
+               } else {
+                       snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start);
+                       charset_type = wanted_str;
+                       wanted_str = DA_NULL;
+               }
+
+               DA_LOG(Default, "charset [%s]", charset_type);
+       }
+
+
+       // for encoding
+       encoding_type = *(++wanted_str_end);
+       DA_LOG(Default, "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");
+               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");
+                       ret = DA_ERR_FAIL_TO_MEMALLOC;
+                       goto ERR;
+               } else {
+                       snprintf(wanted_str, wanted_str_len+1, "%s", wanted_str_start);
+                       raw_encoded_str = wanted_str;
+                       wanted_str = NULL;
+               }
+
+               DA_LOG(Default, "raw encoded str [%s]", raw_encoded_str);
+       }
+
+ERR:
+       if (ret != DA_RESULT_OK) {
+               if (charset_type) {
+                       free(charset_type);
+                       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 *out = NULL;
+       *out_str = calloc(1, strlen(in_encoded_str) + 1);
+       if (*out_str == NULL)
+               return;
+    out = *out_str;
+    in = (char *)in_encoded_str;
+       while (*in)
+       {
+               if (*in == '%') {
+                       int hex = 0;
+                       in++;
+                       if (sscanf(in, "%2x", &hex) <= 0) {
+                               return;
+                       } else {
+                               *out = hex;
+                               in++;
+                       }
+               } else if (*in == '+') {
+                       *out = ' ';
+               } else {
+                       *out = *in;
+               }
+               in++;
+               out++;
+       }
+}
+
diff --git a/src/agent/download-agent-file.c b/src/agent/download-agent-file.c
new file mode 100755 (executable)
index 0000000..a048c23
--- /dev/null
@@ -0,0 +1,1244 @@
+/*
+ * 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 <dirent.h>
+#include <unistd.h>
+#include <math.h>
+
+#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-mime-util.h"
+#include "download-agent-http-mgr.h"
+#include "download-agent-plugin-conf.h"
+
+#ifdef _ENABLE_OMA_DRM
+#include "download-agent-plugin-drm.h"
+#endif
+
+
+#define NO_NAME_TEMP_STR "No name"
+
+static da_result_t  __set_file_size(stage_info *stage);
+static da_result_t  __saved_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_saved_dir(void)
+{
+       da_result_t ret = DA_RESULT_OK;
+       char *tmp_default_path = DA_NULL;
+
+       DA_LOG_FUNC_START(FileManager);
+
+       ret = get_default_install_dir(&tmp_default_path);
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+       if (!is_dir_exist(tmp_default_path)) {
+               ret = create_dir(tmp_default_path);
+       }
+
+ERR:
+       if (tmp_default_path) {
+               free(tmp_default_path);
+               tmp_default_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)
+               return DA_ERR_INVALID_ARGUMENT;
+
+       if (is_dir_exist(dir_path)) {
+               dir = opendir(dir_path);
+               if (DA_NULL == dir) {
+                       DA_LOG_ERR(FileManager, "opendir() for %s is failed.", dir_path);
+                       ret = DA_ERR_INVALID_INSTALL_PATH;
+               } 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");
+                       }
+               }
+       }
+       return ret;
+}
+
+/* Priority to obtain MIME Type
+ * 1. HTTP response header's <Content-Type> field
+ * 2. from OMA descriptor file's <content-type> 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, unsigned long long *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 __saved_file_open(stage_info *stage)
+{
+       da_result_t ret = DA_RESULT_OK;
+       file_info *file_storage = DA_NULL;
+       char *actual_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;
+
+
+       fd = fopen(actual_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 saving = %s",
+                       GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage));
+
+ERR:
+       if (DA_RESULT_OK != ret) {
+               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 <Content-Disposition> 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_file_path(stage_info *stage)
+{
+       da_result_t ret = DA_RESULT_OK;
+       char *temp_dir = DA_NULL;
+       char *extension = DA_NULL;
+       char *file_name_without_extension = DA_NULL;
+       char *tmp_file_path = DA_NULL;
+       char *user_install_path = DA_NULL;
+       file_info *file_info_data = DA_NULL;
+       int len = 0;
+       DA_LOG_FUNC_START(FileManager);
+
+       file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage);
+       if (!file_info_data)
+               return DA_ERR_INVALID_ARGUMENT;
+
+
+       /* If the installed path which user want is set, the temporary directory is same to the installation directory.
+        * Otherwise, the default temporary directory is used.
+        */
+       user_install_path = GET_DL_USER_INSTALL_PATH(GET_STAGE_DL_ID(stage));
+       if (user_install_path) {
+               len = strlen(user_install_path);
+               temp_dir = (char *)calloc(len + 1, sizeof(char));
+               if (!temp_dir) {
+                       ret = DA_ERR_FAIL_TO_MEMALLOC;
+                       goto ERR;
+               }
+               memcpy(temp_dir, user_install_path, len);
+               temp_dir[len] = '\0';
+
+       } else {
+               ret = get_default_install_dir(&temp_dir);
+               if (DA_RESULT_OK != ret || DA_NULL == temp_dir) {
+                       goto ERR;
+               }
+       }
+
+       ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension);
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+       // for resume
+       tmp_file_path = get_full_path_avoided_duplication(temp_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 (temp_dir) {
+               free(temp_dir);
+               temp_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);
+       /* 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_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);
+       /* FIXME : This can be necessary later due to progressive download.
+        * The solution for reducing fflush is needed */
+       //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);
+
+       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);
+
+       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) {
+               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);
+
+       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_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 = __saved_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);
+
+       ret = __saved_file_open(stage);
+
+       return ret;
+}
+
+// for resume with new download request
+da_result_t start_file_writing_append_with_new_download(stage_info *stage)
+{
+       da_result_t ret = DA_RESULT_OK;
+       file_info *file_storage = DA_NULL;
+       char *original_file_path = DA_NULL;
+       char *temp_file_path = DA_NULL;
+       char *extension = DA_NULL;
+       char *file_name_without_extension = DA_NULL;
+       req_dl_info *request_info = DA_NULL;
+       unsigned long long temp_file_size = 0;
+
+       DA_LOG_FUNC_START(FileManager);
+
+       file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
+       if (!file_storage)
+               return DA_ERR_INVALID_ARGUMENT;
+       request_info = GET_STAGE_TRANSACTION_INFO(stage);
+       if (!request_info)
+               return DA_ERR_INVALID_ARGUMENT;
+       temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(request_info);
+       if (!temp_file_path)
+               return DA_ERR_INVALID_ARGUMENT;
+       original_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage);
+
+       GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = strdup(temp_file_path);
+
+       if (original_file_path)
+               free(original_file_path);
+
+       ret = get_mime_type(stage,
+                       &GET_CONTENT_STORE_CONTENT_TYPE(file_storage));
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+       ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension);
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+       if (file_name_without_extension) {
+               if (!GET_CONTENT_STORE_PURE_FILE_NAME(file_storage)) {
+                       GET_CONTENT_STORE_PURE_FILE_NAME(file_storage) = file_name_without_extension;
+                       file_name_without_extension = DA_NULL;
+               } else {
+                       free(file_name_without_extension);
+                       file_name_without_extension = DA_NULL;
+               }
+       }
+
+       if (extension) {
+               if (!GET_CONTENT_STORE_EXTENSION(file_storage)) {
+                       GET_CONTENT_STORE_EXTENSION(file_storage) = extension;
+                       extension = DA_NULL;
+               } else {
+                       free(extension);
+                       extension = DA_NULL;
+               }
+       }
+
+       ret = __set_file_size(stage);
+       if (DA_RESULT_OK != ret)
+               goto ERR;
+       get_file_size(temp_file_path, &temp_file_size);
+       if (temp_file_size < 1)
+               goto ERR;
+
+       GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
+                       = temp_file_size;
+
+       ret = __saved_file_open(stage);
+       return ret;
+ERR:
+       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;
+}
+
+da_result_t discard_download(stage_info *stage)
+{
+       da_result_t ret = DA_RESULT_OK;
+       file_info *file_storage = 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;
+       }
+       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;
+               }
+       }
+
+       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;
+}
+
+
+da_result_t get_default_dir(char **out_path)
+{
+       char *tmp_default_path = DA_NULL;
+       int len = 0;
+
+       if (!out_path) {
+               DA_LOG_ERR(ClientNoti, "DA_ERR_INVALID_ARGUMENT");
+               return DA_ERR_INVALID_ARGUMENT;
+       }
+
+       len = strlen(DA_DEFAULT_FILE_DIR_PATH);
+       tmp_default_path = calloc(len + 1, sizeof(char));
+       if (!tmp_default_path) {
+               return DA_ERR_FAIL_TO_MEMALLOC;
+       }
+
+       memcpy(tmp_default_path, DA_DEFAULT_FILE_DIR_PATH, len);
+       tmp_default_path[len] = '\0';
+
+       *out_path = tmp_default_path;
+
+       DA_LOG_VERBOSE(FileManager, "default temp path = [%s]", *out_path);
+
+       return DA_RESULT_OK;
+}
+
+da_result_t get_default_install_dir(char **out_path)
+{
+       char *default_path = DA_NULL;
+       da_storage_type_t type;
+       da_result_t ret = DA_RESULT_OK;
+       int len = 0;
+
+       if (!out_path) {
+               DA_LOG_ERR(ClientNoti, "DA_ERR_INVALID_ARGUMENT");
+               return DA_ERR_INVALID_ARGUMENT;
+       }
+       ret = get_storage_type(&type);
+       if (DA_RESULT_OK != ret)
+               return ret;
+       if (type == DA_STORAGE_MMC)
+               len = strlen(DA_DEFAULT_INSTALL_PATH_FOR_MMC);
+       else
+               len = strlen(DA_DEFAULT_INSTALL_PATH_FOR_PHONE);
+
+       default_path = calloc(len + 1, sizeof(char));
+       if (!default_path) {
+               return DA_ERR_FAIL_TO_MEMALLOC;
+       }
+       if (type == DA_STORAGE_MMC)
+               memcpy(default_path, DA_DEFAULT_INSTALL_PATH_FOR_MMC, len);
+       else // DA_STROAGE_PHONE
+               memcpy(default_path, DA_DEFAULT_INSTALL_PATH_FOR_PHONE, len);
+       default_path[len] = '\0';
+
+       *out_path = default_path;
+
+       DA_LOG_VERBOSE(FileManager, "default temp path = [%s]", *out_path);
+       return DA_RESULT_OK;
+}
diff --git a/src/agent/download-agent-http-mgr.c b/src/agent/download-agent-http-mgr.c
new file mode 100755 (executable)
index 0000000..52d72c9
--- /dev/null
@@ -0,0 +1,1796 @@
+/*
+ * 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-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-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,
+               char *user_request_etag,
+               char *user_request_temp_file_path);
+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_resume_download_is_available(stage_info *stage,
+               http_msg_response_t *new_http_msg_response);
+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 slot_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);
+
+       slot_id = GET_STAGE_DL_ID(stage);
+       queue = GET_DL_QUEUE(slot_id);
+       req_info = GET_STAGE_TRANSACTION_INFO(stage);
+
+       DA_LOG(HTTPManager, "queue = %p", GET_DL_QUEUE(slot_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_VERBOSE(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);
+                       break;
+
+               case HTTP_STATE_CANCELED:
+               case HTTP_STATE_DOWNLOAD_FINISH:
+               case HTTP_STATE_ABORTED:
+#ifdef PAUSE_EXIT
+               case HTTP_STATE_PAUSED:
+#endif
+                       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,
+               char *user_request_etag,
+               char *user_request_temp_file_path)
+{
+       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 {
+                               if (field) {
+                                       free(field);
+                                       field = NULL;
+                               }
+                               if (value) {
+                                       free(value);
+                                       value= NULL;
+                               }
+                               DA_LOG_ERR(HTTPManager, "Fail to parse user request header");
+                       }
+               }
+       } else
+               DA_LOG(HTTPManager, "no user reqeust header inserted");
+
+       if (user_request_etag) {
+               char buff[64] = {0,};
+               unsigned long long size = 0;
+               http_msg_request_add_field(http_msg_request,
+                               HTTP_FIELD_IF_RANGE, user_request_etag);
+               get_file_size(user_request_temp_file_path, &size);
+               snprintf(buff, sizeof(buff)-1, "bytes=%llu-", size);
+               http_msg_request_add_field(http_msg_request,
+                                               HTTP_FIELD_RANGE, buff);
+       }
+
+       *out_http_msg_request = http_msg_request;
+
+ERR:
+       if (ret != DA_RESULT_OK)
+               http_msg_request_destroy(&http_msg_request);
+       if (user_agent)
+               free(user_agent);
+       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;
+       char *user_request_etag = DA_NULL;
+       char *user_request_temp_file_path = DA_NULL;
+       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);
+       user_request_etag = GET_REQUEST_HTTP_USER_REQUEST_ETAG(
+                       request_info);
+       user_request_temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(
+                               request_info);
+       if (user_request_etag) {
+               DA_LOG(HTTPManager, "user_request_etag[%s]",user_request_etag);
+       } else {
+               DA_LOG_ERR(HTTPManager, "user_request_etag is NULL");
+       }
+       ret = make_default_http_request_hdr(url, user_request_header,
+               user_request_header_count, &http_msg_request,
+               user_request_etag, user_request_temp_file_path);
+       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 slot_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);
+
+       slot_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(slot_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;
+       char *user_request_etag = DA_NULL;
+       char *user_request_temp_file_path = DA_NULL;
+       int dl_id = -1;
+       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;
+       dl_id = source_info->source_info_type.source_info_basic->dl_id;
+       user_request_etag = GET_DL_USER_ETAG(GET_STAGE_DL_ID(stage));
+       user_request_temp_file_path = GET_DL_USER_TEMP_FILE_PATH(GET_STAGE_DL_ID(stage));
+
+       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;
+               GET_REQUEST_HTTP_USER_REQUEST_ETAG(out_info) =
+                                       user_request_etag;
+               GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(out_info) =
+                                       user_request_temp_file_path;
+       } 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_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:
+               /* IF the network session is terminated due to some error,
+                * the state can be aborted.(data aborted case) */
+               CHANGE_HTTP_STATE(HTTP_STATE_ABORTED,stage);
+               CHANGE_DOWNLOAD_STATE(DOWNLOAD_STATE_ABORTED, 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_paused_info(GET_STAGE_DL_ID(stage));
+               break;
+
+       default:
+               //send_client_paused_info(GET_STAGE_DL_ID(stage));
+               _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, NULL, NULL);
+       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 slot_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(slot_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;
+
+       case Q_EVENT_TYPE_DATA_DRM:
+               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 slot_id = DA_INVALID_ID;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       slot_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_progress_info(
+                               slot_id,
+                               GET_DL_ID(slot_id),
+                               GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
+                               );
+               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_progress_info(
+                                       slot_id,
+                                       GET_DL_ID(slot_id),
+                                       GET_CONTENT_STORE_CURRENT_FILE_SIZE(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_paused_info(GET_STAGE_DL_ID(stage));
+               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_paused_info(GET_STAGE_DL_ID(stage));
+               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 slot_id = DA_INVALID_ID;
+       http_state_t http_state = 0;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       slot_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:
+               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 slot_id = DA_INVALID_ID;
+       req_dl_info *request_info = DA_NULL;
+       http_state_t http_state = 0;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       slot_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)));
+
+       store_http_status(slot_id, http_status);
+
+       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);
+               /* 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(stage,
+                                       http_msg_response);
+                       if (ret != DA_RESULT_OK)
+                               goto ERR;
+                       CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOAD_STARTED,stage);
+
+               } else if (http_state == HTTP_STATE_REQUEST_RESUME) {
+                       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);
+               } else {
+                       DA_LOG_ERR(HTTPManager, "This download is not resumed, revoke");
+                       ret = DA_ERR_INVALID_STATE;
+                       goto ERR;
+               }
+               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 slot_id = DA_INVALID_ID;
+
+       //      DA_LOG_FUNC_START(HTTPManager);
+
+       slot_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) {
+               // resume case
+               if (GET_REQUEST_HTTP_USER_REQUEST_ETAG(GET_STAGE_TRANSACTION_INFO(stage)))
+                       ret = start_file_writing_append_with_new_download(stage);
+               else
+                       ret = start_file_writing(stage);
+               if (DA_RESULT_OK != ret)
+                       goto ERR;
+
+               CHANGE_HTTP_STATE(HTTP_STATE_DOWNLOADING, stage);
+               send_client_update_dl_info(
+                               slot_id,
+                               GET_DL_ID(slot_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_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
+                               GET_CONTENT_STORE_PURE_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
+                               GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)),
+                               GET_CONTENT_STORE_EXTENSION(GET_STAGE_CONTENT_STORE_INFO(stage))
+                               );
+       } 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_update_dl_info(
+                               slot_id,
+                               GET_DL_ID(slot_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_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
+                               GET_CONTENT_STORE_PURE_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage)),
+                               GET_REQUEST_HTTP_HDR_ETAG(GET_STAGE_TRANSACTION_INFO(stage)),
+                               GET_CONTENT_STORE_EXTENSION(GET_STAGE_CONTENT_STORE_INFO(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:
+               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_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage)))) {
+                       send_client_update_progress_info(
+                                       slot_id,
+                                       GET_DL_ID(slot_id),
+                                       GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
+                                       );
+
+                       IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(GET_STAGE_CONTENT_STORE_INFO(stage))
+                                       = DA_FALSE;
+               }
+               break;
+
+       case HTTP_STATE_REQUEST_PAUSE:
+               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;
+       unsigned long long size = 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_VERBOSE(HTTPManager, "[Content-Type][%s] - stored", GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info));
+       }
+
+       b_ret = http_msg_response_get_content_length(http_msg_response,
+                       &size);
+       if (b_ret) {
+               GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) = size;
+               size = 0;
+               DA_LOG_VERBOSE(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_VERBOSE(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: %llu",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;
+       unsigned long long remained_content_len = 0;
+       da_storage_size_t memory;
+       char *value = NULL;
+       unsigned long long size = 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,
+                       &size);
+       if (b_ret) {
+               remained_content_len = size;
+               size = 0;
+               DA_LOG(HTTPManager, "[remained_content_len][%lu]", 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 (origin_ETag && new_ETag &&
+                       0 != strncmp(origin_ETag, new_ETag, strlen(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: %llu",
+                                       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_resume_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;
+       unsigned long long remained_content_len = 0;
+       da_storage_size_t memory;
+       char *value = NULL;
+       unsigned long long size = 0;
+       char *temp_file_path = DA_NULL;
+       req_dl_info *request_info = DA_NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       request_info = GET_STAGE_TRANSACTION_INFO(stage);
+       origin_ETag
+                       = GET_REQUEST_HTTP_USER_REQUEST_ETAG(request_info);
+
+       b_ret = http_msg_response_get_content_length(new_http_msg_response,
+                       &size);
+       if (b_ret) {
+               remained_content_len = size;
+               size = 0;
+               DA_LOG(HTTPManager, "[remained_content_len][%lu]", 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 (origin_ETag && new_ETag &&
+                       0 != strncmp(origin_ETag, new_ETag, strlen(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: %llu",
+                                       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;
+                       }
+               }
+       }
+       b_ret = http_msg_response_get_content_type(new_http_msg_response, &value);
+       if (b_ret) {
+               GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info) = value;
+               value = NULL;
+               DA_LOG(HTTPManager, "[Content-Type][%s]",
+                               GET_REQUEST_HTTP_HDR_CONT_TYPE(request_info));
+       }
+       temp_file_path = GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(request_info);
+       get_file_size(temp_file_path, &size);
+       GET_REQUEST_HTTP_HDR_CONT_LEN(request_info) =   remained_content_len + size;
+       DA_LOG(HTTPManager, "[Content-Length][%d]",
+                       GET_REQUEST_HTTP_HDR_CONT_LEN(request_info));
+
+
+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;
+       unsigned long long content_size_from_real_file = 0;
+       unsigned long long content_size_from_http_header = 0;
+
+       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_ACTUAL_FILE_NAME(file_info_data);
+
+               get_file_size(real_file_path,
+                               &content_size_from_real_file);
+
+               if (content_size_from_real_file
+                               != content_size_from_http_header) {
+                       DA_LOG_ERR(HTTPManager, "size from header = %llu, real size = %llu, 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 slot_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
new file mode 100755 (executable)
index 0000000..67483b0
--- /dev/null
@@ -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.
+ */
+
+#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) {
+               da_result_t ret = DA_RESULT_OK;
+               ret = get_user_agent_string(&uagent_str);
+               if (ret != DA_RESULT_OK)
+                       return NULL;
+       }
+       return uagent_str;
+}
+
+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-msg-handler.c b/src/agent/download-agent-http-msg-handler.c
new file mode 100755 (executable)
index 0000000..05a0a68
--- /dev/null
@@ -0,0 +1,1343 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#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) )
+
+enum parsing_type {
+       WITH_PARSING_OPTION,
+       WITHOUT_PARSING_OPTION
+};
+
+static da_result_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(
+       http_msg_response_t *http_msg_response, const char *in_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)
+{
+       http_msg_request_t *temp_http_msg_request = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       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");
+               return DA_ERR_FAIL_TO_MEMALLOC;
+       }
+
+       temp_http_msg_request->http_method = NULL;
+       temp_http_msg_request->url = NULL;
+       temp_http_msg_request->head = NULL;
+       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));
+
+       return DA_RESULT_OK;
+}
+
+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);
+
+       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,
+       const char *url)
+{
+       DA_LOG_FUNC_START(HTTPManager);
+
+       if (!http_msg_request) {
+               DA_LOG_ERR(HTTPManager, "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");
+               return DA_ERR_INVALID_URL;
+       }
+
+       http_msg_request->url = strdup(url);
+
+       DA_LOG(HTTPManager, "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,
+       const char **url)
+{
+       //      DA_LOG_FUNC_START(HTTPManager);
+
+       if (!http_msg_request) {
+               DA_LOG_ERR(HTTPManager, "http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
+               return DA_ERR_INVALID_ARGUMENT;
+       }
+
+       if (http_msg_request->url) {
+               *url = http_msg_request->url;
+               return DA_RESULT_OK;
+       } else {
+               *url = DA_NULL;
+               return DA_ERR_INVALID_ARGUMENT;
+       }
+}
+
+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,
+       const char *field, const char *value)
+{
+       //      DA_LOG_FUNC_START(HTTPManager);
+
+       if (!http_msg_request) {
+               DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
+               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)
+{
+       http_msg_response_t *temp_http_msg_response = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       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");
+               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;
+       }
+}
+
+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);
+       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,
+       const char *field, const char *value)
+{
+       //      DA_LOG_FUNC_START(HTTPManager);
+
+       if (!http_msg_response) {
+               DA_LOG_ERR(HTTPManager, "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,
+       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);
+
+       pre = cur = *head;
+       while (cur) {
+               pre = cur;
+               /* Replace default value with user wanted value
+                * 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);
+                       if (cur->field) {
+                               free(cur->field);
+                               cur->field = NULL;
+                       }
+                       if (cur->raw_value) {
+                               free(cur->raw_value);
+                               cur->raw_value= NULL;
+                       }
+               }
+               cur = cur->next;
+       }
+
+       cur = (http_header_t *)calloc(1, sizeof(http_header_t));
+       if (cur) {
+               cur->field = strdup(field);
+               cur->raw_value = strdup(value);
+               cur->options = NULL;
+               cur->next = NULL;
+
+               if (type == WITHOUT_PARSING_OPTION) {
+                       cur->value = strdup(value);
+                       cur->options = NULL;
+               } else {
+                       __parsing_raw_value(cur);
+               }
+
+               if (pre)
+                       pre->next = cur;
+               else
+                       *head = cur;
+       } else {
+               DA_LOG_ERR(HTTPManager, "DA_ERR_FAIL_TO_MEMALLOC");
+               return DA_ERR_FAIL_TO_MEMALLOC;
+       }
+
+       return DA_RESULT_OK;
+}
+
+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_VERBOSE(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));
+
+               pre = cur;
+               cur = cur->next;
+
+               free(pre);
+       }
+
+       *head = DA_NULL;
+}
+
+http_header_options_t *__create_http_header_option(const char *field,
+       const char *value)
+{
+       http_header_options_t *option = NULL;
+
+       option = (http_header_options_t *)calloc(1,
+               sizeof(http_header_options_t));
+       if (option) {
+               if (field)
+                       option->field = strdup(field);
+
+               if (value)
+                       option->value = strdup(value);
+
+               option->next = NULL;
+       }
+
+       return option;
+}
+
+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);
+
+       cur = *head;
+
+       while (cur) {
+               if (cur->field) {
+                       DA_LOG_VERBOSE(HTTPManager, "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,
+       http_msg_iter_t *http_msg_iter)
+{
+       DA_LOG_FUNC_START(HTTPManager);
+
+       if (!http_msg_request) {
+               DA_LOG_ERR(HTTPManager, "DA_ERR_INVALID_ARGUMENT");
+               return DA_ERR_INVALID_ARGUMENT;
+       }
+
+       *http_msg_iter = http_msg_request->head;
+
+       return DA_RESULT_OK;
+}
+
+da_result_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");
+               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;
+}
+
+da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter,
+       char **out_field, char **out_value)
+{
+       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;
+       }
+}
+
+da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter,
+       char **out_field, http_header_t **out_header)
+{
+       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;
+       }
+}
+
+http_header_options_t *__parsing_N_create_option_str(char *org_str)
+{
+       char *option_field = NULL;
+       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);
+
+       if (!org_str)
+               return NULL;
+
+       org_str_len = strlen(org_str);
+       if (org_str_len <= 0)
+               return NULL;
+
+       working_str = (char *)calloc(1, org_str_len + 1);
+       if (!working_str)
+               return NULL;
+
+       org_pos = org_str;
+       working_pos_field_start = working_pos = working_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;
+                       is_working_for_field ? option_field_len++
+                               : option_value_len++;
+                       working_pos++;
+                       org_pos++;
+               } else {
+                       if (*org_pos == ' ') {
+                               org_pos++;
+                       } else if (*org_pos == '=') {
+                               if (is_working_for_field) {
+                                       is_working_for_field = DA_FALSE;
+                                       working_pos_value_start = working_pos;
+                               }
+
+                               org_pos++;
+                       } else {
+                               *working_pos = *org_pos;
+                               is_working_for_field ? option_field_len++
+                                       : option_value_len++;
+                               working_pos++;
+                               org_pos++;
+                       }
+               }
+       }
+
+       if (option_field_len > 0 && working_pos_field_start) {
+               option_field = (char *)calloc(1, option_field_len + 1);
+               if (option_field)
+                       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]",
+               option_field, option_value);
+
+       if (option_field || option_value) {
+               option = __create_http_header_option(
+                       option_field, option_value);
+               if (option_field) {
+                       free(option_field);
+                       option_field = NULL;
+               }
+
+               if (option_value) {
+                       free(option_value);
+                       option_value = NULL;
+               }
+       }
+       return option;
+}
+
+http_header_options_t *__parsing_options(char *org_str)
+{
+       da_result_t ret = DA_RESULT_OK;
+       http_header_options_t *head = NULL;
+       http_header_options_t *pre = NULL;
+       http_header_options_t *cur = NULL;
+
+       int wanted_str_len = 0;
+       char *wanted_str = NULL;
+       char *wanted_str_start = NULL;
+       char *wanted_str_end = NULL;
+       char *cur_pos = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       if (!org_str)
+               return NULL;
+
+       /* Do Not use strtok(). It's not thread safe. */
+       //      DA_LOG_CRITICAL(HTTPManager, "org_str = %s", org_str);
+
+       cur_pos = org_str;
+
+       while (cur_pos) {
+               wanted_str_start = cur_pos;
+               wanted_str_end = strchr(cur_pos, ';');
+               if (wanted_str_end) {
+                       cur_pos = wanted_str_end + 1;
+               } else {
+                       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");
+                       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);
+               cur = __parsing_N_create_option_str(wanted_str);
+               if (pre) {
+                       pre->next = cur;
+                       pre = cur;
+               } else {
+                       head = pre = cur;
+               }
+
+               free(wanted_str);
+               wanted_str = NULL;
+       }
+
+ERR:
+       if (ret != DA_RESULT_OK)
+               __http_header_destroy_all_option(&head);
+
+       return head;
+}
+
+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);
+
+       if (!raw_value)
+               return;
+
+       trimed_value_start = raw_value;
+
+       trimed_value_end = strchr(raw_value, ';');
+       if (!trimed_value_end) {
+               // No options
+               http_header_field->value = strdup(raw_value);
+               http_header_field->options = NULL;
+
+               return;
+       }
+
+       // 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");
+               return;
+       }
+       strncpy(trimed_value, trimed_value_start, trimed_value_len);
+       http_header_field->value = trimed_value;
+
+       // 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);
+               cur = cur->next;
+       }
+
+}
+
+da_bool_t __get_http_header_option_for_field(
+       http_header_options_t *header_option, const char *in_field,
+       char **out_value)
+{
+       http_header_options_t *cur = NULL;
+
+       //      DA_LOG_FUNC_START(HTTPManager);
+
+       if (!header_option) {
+               DA_LOG_ERR(HTTPManager, "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)) &&
+                                       cur->value) {
+                               DA_LOG(HTTPManager, "[%s][%s]", cur->field, cur->value);
+                               *out_value = cur->value;
+                               return DA_TRUE;
+                       }
+
+               }
+               cur = cur->next;
+       }
+
+       return DA_FALSE;
+}
+
+da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response,
+       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_LOG_FUNC_START(HTTPManager);
+
+       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_VERBOSE(HTTPManager, "[%s][%s]", field, header->value);
+                       *out_header = header;
+                       return DA_TRUE;
+               }
+       }
+
+       return DA_FALSE;
+}
+
+void __exchange_header_value(http_header_t *header, const char *in_raw_value)
+{
+       DA_LOG_FUNC_START(HTTPManager);
+
+       if (!header || !in_raw_value)
+               return;
+
+       __http_header_destroy_all_option(&(header->options));
+
+       if (header->value) {
+               free(header->value);
+               header->value = DA_NULL;
+       }
+
+       if (header->raw_value)
+               free(header->raw_value);
+       header->raw_value = strdup(in_raw_value);
+
+       __parsing_raw_value(header);
+}
+
+da_bool_t http_msg_response_get_content_type(
+       http_msg_response_t *http_msg_response, char **out_type)
+{
+       da_bool_t b_ret = DA_FALSE;
+       http_header_t *header = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       b_ret = __get_http_header_for_field(http_msg_response, "Content-Type",
+               &header);
+       if (!b_ret) {
+               DA_LOG(HTTPManager, "no Content-Type");
+               return DA_FALSE;
+       }
+
+       if (out_type)
+               *out_type = strdup(header->value);
+
+       return DA_TRUE;
+}
+
+void http_msg_response_set_content_type(http_msg_response_t *http_msg_response,
+       const char *in_type)
+{
+       da_bool_t b_ret = DA_FALSE;
+       http_header_t *header = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       if (!http_msg_response || !in_type)
+               return;
+
+       b_ret = __get_http_header_for_field(http_msg_response, "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);
+               __exchange_header_value(header, in_type);
+       } else {
+               __http_header_add_field(&(http_msg_response->head),
+                       "Content-Type", in_type, WITH_PARSING_OPTION);
+       }
+}
+
+da_bool_t http_msg_response_get_content_length(
+       http_msg_response_t *http_msg_response, unsigned long long *out_length)
+{
+       da_bool_t b_ret = DA_FALSE;
+       http_header_t *header = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       b_ret = __get_http_header_for_field(http_msg_response,
+               "Content-Length", &header);
+       if (!b_ret) {
+               DA_LOG(HTTPManager, "no Content-Length");
+               return DA_FALSE;
+       }
+
+       if (out_length)
+               *out_length = atoll(header->value);
+
+       return DA_TRUE;
+}
+
+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 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);
+
+       b_ret = __get_http_header_for_field(http_msg_response,
+               "Content-Disposition", &header);
+       if (!b_ret) {
+               DA_LOG(HTTPManager, "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");
+               return DA_FALSE;
+       }
+
+       // eliminate double quotation mark if it exists on derived value
+       wanted_str_start = strchr(file_name, '"');
+       if (!wanted_str_start) {
+               *out_file_name = strdup(file_name);
+               return DA_TRUE;
+       } else {
+               //              DA_LOG(HTTPManager, "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");
+                               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");
+                               if (DA_RESULT_OK == decode_base64_encoded_str(
+                                       wanted_str, &decoded_str)) {
+                                       DA_LOG(HTTPManager, "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.");
+                               }
+                       } else {
+                               DA_LOG(HTTPManager, "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);
+                               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);
+
+                       return DA_TRUE;
+               } else {
+                       DA_LOG_ERR(HTTPManager, "Not matched \" !");
+                       return DA_FALSE;
+               }
+       }
+}
+
+da_bool_t http_msg_response_get_ETag(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);
+
+       b_ret = __get_http_header_for_field(http_msg_response, "ETag", &header);
+       if (!b_ret) {
+               DA_LOG(HTTPManager, "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,
+       char **out_value)
+{
+       da_bool_t b_ret = DA_FALSE;
+       http_header_t *header = NULL;
+
+       DA_LOG_FUNC_START(HTTPManager);
+
+       b_ret = __get_http_header_for_field(http_msg_response, "Date", &header);
+       if (!b_ret) {
+               DA_LOG(HTTPManager, "no Date");
+               return DA_FALSE;
+       }
+
+       if (out_value)
+               *out_value = strdup(header->value);
+
+       return DA_TRUE;
+}
+
+da_bool_t http_msg_response_get_location(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);
+
+       b_ret = __get_http_header_for_field(http_msg_response, "Location", &header);
+       if (!b_ret) {
+               DA_LOG(HTTPManager, "no Location");
+               return DA_FALSE;
+       }
+       if (out_value)
+               *out_value = strdup(header->value);
+
+       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)
+{
+       http_msg_iter_t http_msg_iter;
+       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);
+
+       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;
+       }
+}
+
+char *_stristr(const char *long_str, const char *find_str)
+{
+       int i = 0;
+       int length_long = 0;
+       int length_find = 0;
+       char *ret_ptr = NULL;
+       char *org_ptr = NULL;
+       char *look_ptr = NULL;
+
+       if (long_str == NULL || find_str == NULL) {
+               DA_LOG_ERR(Default,"INVALID ARGUMENT");
+               return NULL;
+       }
+
+       length_long = strlen(long_str);
+       length_find = strlen(find_str);
+
+       org_ptr = (char*)calloc(1, length_long + 1);
+
+       if (org_ptr == NULL) {
+               DA_LOG_ERR(Default,"INVALID ARGUMENT");
+               return NULL;
+       }
+
+       look_ptr = (char*)calloc(1, length_find + 1);
+
+       if (look_ptr == NULL) {
+               DA_LOG_ERR(Default,"INVALID ARGUMENT");
+               free(org_ptr);
+               return NULL;
+       }
+
+       while (i < length_long) {
+               if (isalpha(long_str[i]) != 0) {
+                       if (isupper(long_str[i]) != 0) {
+                               org_ptr[i] = long_str[i];
+                       } else {
+                               org_ptr[i] = toupper(long_str[i]);
+                       }
+               } else {
+                       org_ptr[i] = long_str[i];
+               }
+
+               i++;
+       }
+
+       i = 0;
+
+       while (i < length_find) {
+               if (isalpha(find_str[i]) != 0) {
+                       if (isupper(find_str[i]) != 0) {
+                               look_ptr[i] = find_str[i];
+                       } else {
+                               look_ptr[i] = toupper(find_str[i]);
+                       }
+               } else {
+                       look_ptr[i] = find_str[i];
+               }
+
+               i++;
+       }
+
+       ret_ptr = strstr(org_ptr, look_ptr);
+
+       if (ret_ptr == 0) {
+               free(org_ptr);
+               free(look_ptr);
+               return NULL;
+       } else {
+               i = ret_ptr - org_ptr;
+       }
+
+       free(org_ptr);
+       free(look_ptr);
+
+       return (char*)(long_str + i);
+}
+
+/* This is not used. But it can be needed if there is no http header parser at http library.*/
+da_bool_t extract_attribute_from_header(
+        char *szHeadStr,
+        const char *szFindStr,
+        char **ppRtnValue)
+{
+
+       char *pValuePos = NULL;
+       int index = 0;
+       int startPos = 0;
+       int strLen = 0;
+       int need_to_end_quataion_mark = 0;
+
+       if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
+               DA_LOG_ERR(Default,"INVALID ARGUMENT");
+               return DA_FALSE;
+       }
+
+       if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
+               DA_LOG_ERR(Default,"INVALID ARGUMENT");;
+
+               return DA_FALSE;
+       }
+
+       if (ppRtnValue == NULL) {
+               return DA_FALSE;
+       }
+
+       pValuePos = _stristr(szHeadStr, (char*)szFindStr);
+       if (pValuePos == NULL) {
+               *ppRtnValue = NULL;
+               goto ERR;
+       }
+
+       index = strlen(szFindStr);
+
+       while (pValuePos[index] != ':' && pValuePos[index] != '=') {
+               index++;
+
+               if (pValuePos[index] == '\0') {
+                       return DA_FALSE;
+               }
+       }
+
+       index++;
+
+       /* jump space */
+       while (pValuePos[index] == ' ') {
+               index++;
+       }
+
+       /* jump quatation mark */
+       while (pValuePos[index] == '"') {
+               need_to_end_quataion_mark = 1;
+               index++;
+       }
+
+       startPos = index;
+
+       /* Find the end of data. */
+       if (0 == strcmp(szFindStr, "Location"))//terminate character list does not contain ';' in case of URI
+       {
+               while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) {
+                       index++;
+               }
+       } else if (need_to_end_quataion_mark) {
+               while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index])) {
+                       index++;
+               }
+       } else {
+               while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index])) {
+                       index++;
+               }
+       }
+
+       strLen = index - startPos;
+
+       if (strLen < 1) {
+               DA_LOG_ERR(Default," strLen is < 1");
+               goto ERR;
+       }
+
+       *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
+
+       if (*ppRtnValue == NULL) {
+               DA_LOG_ERR(Default," *ppRtnValue is NULL");
+               goto ERR;
+       }
+
+       strncpy(*ppRtnValue, pValuePos + startPos, strLen);
+       *(*ppRtnValue + strLen) = '\0';
+
+       return DA_TRUE;
+
+ERR:
+
+       if (*ppRtnValue) {
+               free(*ppRtnValue);
+               *ppRtnValue = NULL;
+       }
+
+       return DA_FALSE;
+}
+
diff --git a/src/agent/download-agent-http-queue.c b/src/agent/download-agent-http-queue.c
new file mode 100755 (executable)
index 0000000..b81f9d8
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * 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-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_DATA_DRM:
+                       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_DATA_DRM:
+                       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_VERBOSE(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_VERBOSE(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-interface.c b/src/agent/download-agent-interface.c
new file mode 100755 (executable)
index 0000000..2ac32dd
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * 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-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"
+
+int da_init(
+        da_client_cb_t *da_client_callback)
+{
+       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);
+       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_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;
+
+       DA_LOG_FUNC_START(Default);
+
+       deinit_http_mgr();
+       deinit_download_mgr();
+       /* Do not clean temporary download path
+        * The client can resume or restart download with temporary file in case of failed download.
+        */
+       dereg_client_app();
+       DA_LOG(Default, "====== da_deinit EXIT =====");
+
+       return ret;
+}
+
+int da_start_download(
+        const char *url,
+        int *download_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       DA_LOG_FUNC_START(Default);
+
+       *download_id = DA_INVALID_ID;
+
+       if (DA_FALSE == is_valid_url(url, &ret))
+               goto ERR;
+
+       DA_LOG(Default, "url = %s", url);
+
+       ret = start_download(url, download_id);
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+ERR:
+       DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *download_id, ret);
+       return ret;
+}
+
+int da_start_download_with_extension(
+       const char              *url,
+       extension_data_t *extension_data,
+       int     *download_id
+)
+{
+       da_result_t ret = DA_RESULT_OK;
+       int req_header_count = 0;
+       int i = 0;
+
+       DA_LOG_FUNC_START(Default);
+
+       *download_id = DA_INVALID_ID;
+
+       if (DA_FALSE == is_valid_url(url, &ret))
+               goto ERR;
+
+       DA_LOG(Default, "url = %s", url);
+
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+       if (!extension_data) {
+               ret = DA_ERR_INVALID_ARGUMENT;
+               goto ERR;
+       }
+
+       if (extension_data->request_header_count > 0) {
+               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 = 0;
+                       ret = DA_ERR_INVALID_ARGUMENT;
+                       goto ERR;
+               }
+       }
+
+       if (extension_data->install_path) {
+               if (!is_dir_exist(extension_data->install_path))
+                       return DA_ERR_INVALID_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);
+       if (extension_data->temp_file_path)
+               DA_LOG_VERBOSE(Default, "temp_file_path = [%s]", extension_data->temp_file_path);
+       if (extension_data->etag)
+               DA_LOG_VERBOSE(Default, "etag = [%s]", extension_data->etag);
+
+       if (extension_data->user_data)
+               DA_LOG_VERBOSE(Default, "user_data = [%p]", extension_data->user_data);
+
+       ret = start_download_with_extension(url, download_id, extension_data);
+
+ERR:
+       DA_LOG_CRITICAL(Default, "Return: Dl req id = %d, ret = %d", *download_id, ret);
+       return ret;
+}
+
+int da_cancel_download(int download_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       DA_LOG_VERBOSE(Default, "Cancel for dl_id = %d", download_id);
+
+       ret = cancel_download(download_id);
+
+       DA_LOG_CRITICAL(Default, "Return: Cancel id = %d, ret = %d", download_id, ret);
+       return ret;
+}
+
+int da_suspend_download(int download_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       DA_LOG_VERBOSE(Default, "Suspend for dl_id = %d", download_id);
+
+       ret = suspend_download(download_id, DA_TRUE);
+
+       DA_LOG_CRITICAL(Default, "Return: Suspend id = %d, ret = %d", download_id, ret);
+       return ret;
+}
+
+int da_suspend_download_without_update(int download_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       DA_LOG_VERBOSE(Default, "Suspend for dl_id = %d", download_id);
+
+       ret = suspend_download(download_id, DA_FALSE);
+
+       DA_LOG_CRITICAL(Default, "Return: Suspend id = %d, ret = %d", download_id, ret);
+       return ret;
+}
+
+
+int da_resume_download(int download_id)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       DA_LOG_VERBOSE(Default, "Resume for dl_id = %d", download_id);
+
+       ret = resume_download(download_id);
+
+       DA_LOG_CRITICAL(Default, "Return: Resume 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);
+       return ret;
+}
diff --git a/src/agent/download-agent-mime-util.c b/src/agent/download-agent-mime-util.c
new file mode 100755 (executable)
index 0000000..ef7f4ed
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+
+#include <xdgmime.h>
+
+#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 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"},
+               {"*.pot",                       "*.ppt"},
+               {"*.xsl",                       "*.xml"},
+               {"*.spl",                       "*.swf"},
+               {"*.oga",                       "*.ogg"},
+               {"*.jpe",                       "*.jpg"},//5
+               {"*.CSSL",                      "*.css"},
+               {"*.htm",                       "*.html"},
+               {"*.hxx",                       "*.hpp"},
+               {"*.c++",                       "*.cpp"},
+               {"CMakeLists.txt",      "*.cmake"},//10
+               {"*.ime",                       "*.imy"},
+               {"Makefile",            "makefile"},
+               {"*.3g2",                       "*.3gp"},
+               {"*.mp2",                       "*.mpg"},
+               {"*.divx",                      "*.avi"},//15
+       };
+/* This is samsung mime policy
+ * 1. if the mime is audio/m4a, the extension name is defined as "m4a" for launching music player
+*/
+#ifdef _SAMSUNG_MIME_POLICY
+#define MAX_SEC_MIME_TABLE_INDEX 1
+struct sec_mime_table_t {
+       char *mime;
+       char *ext;
+};
+struct sec_mime_table_t sec_mime_table [MAX_SEC_MIME_TABLE_INDEX] = {
+       {"audio/m4a",           "m4a"},
+};
+#endif
+
+const char *ambiguous_MIME_Type_list[] = {
+               "text/plain",
+               "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;
+
+       int index = 0;
+       int list_size = sizeof(ambiguous_MIME_Type_list) / sizeof(const char *);
+       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]);
+                       return DA_TRUE;
+               }
+       }
+
+       return DA_FALSE;
+}
+
+da_result_t da_mime_get_ext_name(char *mime, char **ext)
+{
+       da_result_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);
+
+       if (DA_NULL == mime || DA_NULL == ext) {
+               ret = DA_ERR_INVALID_ARGUMENT;
+               DA_LOG_ERR(Default,"Invalid mime type");
+               goto ERR;
+       }
+       DA_LOG_VERBOSE(Default,"mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime));
+       /* unaliased_mimetype means representative mime among similar types */
+       _da_thread_mutex_lock(&mutex_for_xdgmime);
+       unaliased_mimetype = xdg_mime_unalias_mime_type(mime);
+       _da_thread_mutex_unlock(&mutex_for_xdgmime);
+
+       if (unaliased_mimetype == DA_NULL) {
+               ret = DA_ERR_INVALID_MIME_TYPE;
+               DA_LOG_ERR(Default,"Invalid mime type : No unsaliased mime type");
+               goto ERR;
+       }
+       DA_LOG(Default,"unaliased_mimetype[%s]\n",unaliased_mimetype);
+
+       /* Get extension name from shared-mime-info */
+       _da_thread_mutex_lock(&mutex_for_xdgmime);
+       extlist = xdg_mime_get_file_names_from_mime_type(unaliased_mimetype);
+       _da_thread_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");
+#ifdef _SAMSUNG_MIME_POLICY
+               for (i = 0; i < MAX_SEC_MIME_TABLE_INDEX; i++)
+               {
+                       if (strncmp(sec_mime_table[i].mime, mime, strlen(mime)) == 0) {
+                               strncpy(ext_temp, sec_mime_table[i].ext, DA_MAX_STR_LEN-1);
+                               ret = DA_RESULT_OK;
+                               break;
+                       }
+               }
+#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);
+               /* If only one extension name is existed, don't enter here */
+               while (*extlist != NULL) {
+                       int i = 0;
+                       /* If there are existed many extension names,
+                        *  try to search common extension name from table
+                        *  with first mime type at extension list*/
+                       for (i = 0; i < MAX_EXT_TABLE_INDEX; i++)
+                       {
+                               if (strncmp(ext_trans_table[i].standard,*extlist,
+                                               strlen(*extlist)) == 0) {
+                                       memset(ext_temp, 0x00, DA_MAX_STR_LEN);
+                                       strncpy(ext_temp,ext_trans_table[i].normal, DA_MAX_STR_LEN-1);
+                                       break;
+                               }
+                       }
+                       DA_LOG(Default,"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);
+                       extlist++;
+               }
+               DA_LOG(Default,"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);
+                       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);
+                       /* 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");
+               }
+       }
+       if (ret != DA_RESULT_OK)
+               goto ERR;
+
+       temp = strchr(ext_temp,'.');
+       if (temp == NULL)
+               temp = ext_temp;
+       else
+               temp++;
+
+       DA_LOG(Default,"final extension name:[%s]",temp);
+       *ext = (char*)calloc(1, strlen(temp) + 1);
+       if (*ext != DA_NULL) {
+               strncpy(*ext, temp,strlen(temp));
+       } else  {
+               ret = DA_ERR_FAIL_TO_MEMALLOC ;
+               goto ERR ;
+       }
+ERR:
+       return ret;
+}
+
+da_bool_t da_get_extension_name_from_url(char *url, char **ext)
+{
+       da_bool_t ret = DA_TRUE;
+       char *buff = DA_NULL;
+       char *temp_str = DA_NULL;
+       int buf_len = 0;
+
+       DA_LOG_FUNC_START(Default);
+
+       if (DA_NULL == url || DA_NULL == ext) {
+               ret = DA_FALSE;
+               DA_LOG_ERR(Default,"Invalid Argument");
+               return ret;
+       }
+
+       if ((temp_str = strrchr(url,'/'))) {
+               if ((buff = strrchr(temp_str,'.'))) {
+                       char *q = DA_NULL;
+                       buff++;
+                       /* check to exist "?" after extension name */
+                       q = strrchr(buff,'?');
+                       if (q) {
+                               buf_len = strlen(buff) - strlen(q);
+                       } else {
+                               buf_len = strlen(buff);
+                       }
+                       *ext = (char*) calloc(1, buf_len + 1) ;
+
+                       if (DA_NULL == *ext) {
+                               ret = DA_FALSE;
+                               DA_LOG_ERR(Default,"Memory Fail");
+                               goto ERR;
+                       }
+                       strncpy(*ext,buff,buf_len);
+                       DA_LOG(Default,"extention name[%s]",*ext);
+                       return ret;
+               }
+       }
+ERR:
+       if (*ext) {
+               free(*ext);
+               *ext = DA_NULL;
+       }
+       return ret;
+}
+
+/* FIXME move this function to another file */
+da_bool_t da_get_file_name_from_url(char *url, char **name)
+{
+       da_bool_t ret = DA_TRUE;
+       char *buff = DA_NULL;
+       char *Start = NULL;
+       char *End = NULL;
+       char c = 0;
+       int i = 0;
+       int j = 0;
+       int len_name = 0;
+       char name_buff[DA_MAX_FILE_PATH_LEN] = {0,};
+
+       DA_LOG_FUNC_START(Default);
+
+       if (DA_NULL == url || DA_NULL == name) {
+               ret = DA_FALSE;
+               DA_LOG_ERR(Default,"Invalid Argument");
+               goto ERR;
+       }
+       *name = DA_NULL;
+       if (!strstr(url, "http") && !strstr(url, "https")) {
+               ret = DA_FALSE;
+               DA_LOG_ERR(Default,"Invalid Argument");
+               goto ERR;
+    }
+
+       buff = (char*) calloc(1, strlen(url) +1);
+       if(DA_NULL == buff) {
+               ret = DA_FALSE;
+               DA_LOG_ERR(Default,"Memory Fail");
+               goto ERR;
+    }
+
+       while((c = url[i++]) != 0) {
+               if(c == '%') {
+                       char buffer[3] = {0,};
+                       buffer[0] = url[i++];
+                       buffer[1] = url[i++];
+                       buff[j++] = (char)strtol(buffer,NULL,16);
+               } else {
+                       buff[j++] = c;
+               }
+       }
+       End = strstr(buff, "?");
+       if (DA_NULL != End) {
+               Start = End -1;
+               while(*(Start) != '/') {
+                       Start--;
+               }
+               if ((*(Start) == '/') && ((len_name = (End - Start)) > 1)) {
+                       Start++;
+                       if (DA_MAX_FILE_PATH_LEN <= len_name)   {
+                               strncpy(name_buff, Start, DA_MAX_FILE_PATH_LEN-1);
+                               name_buff[DA_MAX_FILE_PATH_LEN-1] = '\0';
+                       } else {
+                               strncpy(name_buff, Start, len_name);
+                               name_buff[len_name] = '\0';
+                       }
+               } else {
+                       ret = DA_FALSE;
+                       goto ERR ; /*Name not found*/
+               }
+       } else {
+               int urlLen = strlen (buff);
+               int Start_pos = 0;
+               Start_pos = urlLen - 1;
+
+               while(Start_pos > 0) {
+                       if(buff[Start_pos] == '/')
+                               break;
+                       Start_pos--;
+               }
+               Start_pos++;
+               if (Start_pos == 0 || urlLen - Start_pos <= 0) {
+                       ret = DA_FALSE;
+                       goto ERR;
+               }
+               while(Start_pos < urlLen) {
+                       name_buff[len_name++] = buff[Start_pos++];
+                       if (DA_MAX_FILE_PATH_LEN <= len_name) {
+                               name_buff[DA_MAX_FILE_PATH_LEN-1] ='\0';
+                               break;
+                       }
+               }
+       }
+
+       if (len_name) {
+               End = strrchr(name_buff, '.');
+               if (End != NULL) {
+                       *End = '\0';
+               }
+               DA_LOG(Default,"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);
+ERR:
+       if (buff) {
+               free (buff);
+               buff = DA_NULL;
+    }
+       return ret;
+}
+
+void delete_prohibited_char(char *szTarget, int str_len)
+{
+       char *chk_str = NULL;
+       int i = 0;
+       int j = 0;
+       int tar_len = 0;
+
+       if(szTarget == NULL || str_len <= 0 || strlen(szTarget) != str_len) {
+               DA_LOG_ERR(Default,"Invaild Parameter\n");
+               return;
+       }
+
+       chk_str = (char *)calloc(1, str_len + 1);
+       if(chk_str == NULL)
+               return;
+
+       while(szTarget[j] != '\0') {
+               if(IS_PROHIBITED_CHAR(szTarget[j]) == DA_FALSE &&
+                                       IS_SPACE_CHARACTER(szTarget[j]) == DA_FALSE) {
+                       chk_str[i] = szTarget[j];
+                       i++;
+               }
+               j++;
+       }
+
+       chk_str[i] = '\0';
+       tar_len = strlen(chk_str);
+
+       if(tar_len <= 0)
+               szTarget[0] = '\0';
+       else {
+               for(i = 0; i < tar_len; i++)
+               {
+                       szTarget[i] = chk_str[i];
+               }
+               szTarget[i] = '\0';
+       }
+
+       if(chk_str != NULL)     {
+               free(chk_str);
+       }
+       return;
+}
+
diff --git a/src/agent/download-agent-plugin-conf.c b/src/agent/download-agent-plugin-conf.c
new file mode 100755 (executable)
index 0000000..f0ce27f
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <glib-object.h>
+
+#ifdef _EFL_PLATFORM
+#include <vconf.h>
+#include <vconf-keys.h>
+#include <net_connection.h>
+#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_BROWSER_USER_AGENT;
+       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-libsoup.c b/src/agent/download-agent-plugin-libsoup.c
new file mode 100755 (executable)
index 0000000..fe4b015
--- /dev/null
@@ -0,0 +1,961 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+
+#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_VERBOSE(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_VERBOSE(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_VERBOSE(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)
+{
+       DA_LOG_CRITICAL(HTTPManager, "soup error code[%d]", 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:
+               return DA_ERR_NETWORK_FAIL;
+       case SOUP_STATUS_SSL_FAILED:
+               return DA_ERR_SSL_FAIL;
+       case SOUP_STATUS_REQUEST_TIMEOUT:
+               return DA_ERR_HTTP_TIMEOUT;
+       case SOUP_STATUS_TOO_MANY_REDIRECTS:
+               return DA_ERR_TOO_MANY_REDIECTS;
+       default:
+               return DA_ERR_NETWORK_FAIL;
+       }
+}
+
+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, DA_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-id-history.c b/src/agent/download-agent-utils-dl-id-history.c
new file mode 100755 (executable)
index 0000000..1d06722
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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-type.h"
+#include "download-agent-utils.h"
+#include "download-agent-utils-dl-id-history.h"
+
+da_result_t init_dl_id_history(dl_id_history_t *dl_id_history)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       /* Initial dl_id_history will be starting number for dl_id.
+        * dl_id will be sequentially increased from the dl_id_history,
+        * then dl_id_history will be updated. */
+       _da_thread_mutex_init(&(dl_id_history->mutex), DA_NULL);
+       _da_thread_mutex_lock(&(dl_id_history->mutex));
+       get_random_number(&(dl_id_history->starting_num));
+       dl_id_history->cur_dl_id = DA_INVALID_ID;
+       _da_thread_mutex_unlock(&(dl_id_history->mutex));
+
+       DA_LOG_CRITICAL(Default,"starting num = %d", dl_id_history->starting_num);
+       return ret;
+}
+
+da_result_t deinit_dl_id_history(dl_id_history_t *dl_id_history)
+{
+       da_result_t ret = DA_RESULT_OK;
+
+       _da_thread_mutex_lock(&(dl_id_history->mutex));
+       dl_id_history->starting_num = DA_INVALID_ID;
+       dl_id_history->cur_dl_id = DA_INVALID_ID;
+       _da_thread_mutex_unlock(&(dl_id_history->mutex));
+
+       _da_thread_mutex_destroy(&(dl_id_history->mutex));
+
+       return ret;
+}
+
+int get_available_dl_id(dl_id_history_t *dl_id_history)
+{
+       int dl_id = 0;
+
+       _da_thread_mutex_lock(&(dl_id_history->mutex));
+
+       if (dl_id_history->cur_dl_id == DA_INVALID_ID)
+               dl_id_history->cur_dl_id = dl_id_history->starting_num;
+       else if (dl_id_history->cur_dl_id > 254)
+               dl_id_history->cur_dl_id = 1;
+       else
+               dl_id_history->cur_dl_id++;
+
+       dl_id = dl_id_history->cur_dl_id;
+
+       _da_thread_mutex_unlock(&(dl_id_history->mutex));
+
+       DA_LOG_CRITICAL(Default,"dl_id = %d", dl_id);
+       return dl_id;
+}
diff --git a/src/agent/download-agent-utils.c b/src/agent/download-agent-utils.c
new file mode 100755 (executable)
index 0000000..3ac9710
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * 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 <sys/vfs.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <glib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#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-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)
+
+typedef struct _da_descriptor_mime_table_t {
+       char *content_type;
+       da_mime_type_id_t mime_type;
+} da_descriptor_mime_table_t;
+
+da_descriptor_mime_table_t
+        descriptor_mime_table[] = {
+               {"", DA_MIME_TYPE_NONE},
+               /* DRM1.0 */
+               {"application/vnd.oma.drm.message",
+                               DA_MIME_TYPE_DRM1_MESSATE}, /* drm1.0 FL.CD*/
+               {"", DA_MIME_TYPE_END}};
+
+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;
+       unsigned long long file_size = -1;
+       char *buffer = NULL;
+       int buffer_len = 0;
+       size_t 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 [%llu]", 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 get_available_memory(
+        da_storage_type_t storage_type,
+        da_storage_size_t *avail_memory)
+{
+       da_result_t ret = DA_RESULT_OK;
+       int fs_ret = 0;
+       struct statfs filesys_info = {0, };
+       char *default_install_dir = NULL;
+
+       DA_LOG_FUNC_START(Default);
+
+       if (!avail_memory)
+               return DA_ERR_INVALID_ARGUMENT;
+
+       ret = get_default_install_dir(&default_install_dir);
+
+       if (ret == DA_RESULT_OK && default_install_dir) {
+               fs_ret = statfs(default_install_dir, &filesys_info);
+       } else {
+               return DA_ERR_FAIL_TO_ACCESS_STORAGE;
+       }
+
+       if (fs_ret != 0) {
+               DA_LOG_ERR(Default,"Phone file path :statfs error - [%d]", errno);
+               free(default_install_dir);
+               return DA_ERR_INVALID_INSTALL_PATH;
+       }
+
+       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_VERBOSE(Default, "Available Memory(f_bavail) : %lu", filesys_info.f_bavail);
+       DA_LOG_VERBOSE(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);
+
+       free(default_install_dir);
+       return DA_RESULT_OK;
+}
+
+da_mime_type_id_t get_mime_type_id(char *content_type)
+{
+       int i = 0;
+
+       DA_LOG_FUNC_START(Default);
+
+       DA_LOG(Default,"received content_type = %s", content_type);
+
+       if (content_type == NULL) {
+               DA_LOG_ERR(Default, "No Mime Type\n");
+               return DA_MIME_TYPE_NONE;
+       }
+
+       while(descriptor_mime_table[i].mime_type != DA_MIME_TYPE_END)
+       {
+               if (!strcmp(descriptor_mime_table[i].content_type, content_type)) {
+                       break;
+               }
+               i++;
+       }
+       DA_LOG(Default, "dd mime type check: index[%d] type[%d]", i, descriptor_mime_table[i].mime_type);
+       return descriptor_mime_table[i].mime_type;
+}
+
+
+
+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 && is_file_exist(file_path)) {
+               DA_LOG(FileManager,"remove file [%s]", file_path);
+               if (unlink(file_path) < 0) {
+                       DA_LOG_ERR(FileManager,"file removing failed.");
+               }
+       }
+}
diff --git a/src/agent/include/download-agent-basic.h b/src/agent/include/download-agent-basic.h
new file mode 100755 (executable)
index 0000000..340a34a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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 <string.h>
+
+#include "download-agent-type.h"
+#include "download-agent-interface.h"
+#include "download-agent-dl-mgr.h"
+
+da_result_t start_download(const char *url, int *dl_id);
+da_result_t start_download_with_extension(const char *url , int *dl_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
new file mode 100755 (executable)
index 0000000..f4c6234
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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 <string.h>
+
+#include "download-agent-type.h"
+#include "download-agent-interface.h"
+
+#include "download-agent-pthread.h"
+
+typedef enum {
+       Q_CLIENT_NOTI_TYPE_STARTED_INFO = 0,
+       Q_CLIENT_NOTI_TYPE_PROGRESS_INFO,
+       Q_CLIENT_NOTI_TYPE_PAUSED_INFO,
+       Q_CLIENT_NOTI_TYPE_FINISHED_INFO,
+       Q_CLIENT_NOTI_TYPE_TERMINATE,
+} client_noti_type;
+
+typedef struct _client_noti_t client_noti_t;
+struct _client_noti_t {
+       int slot_id;
+       void *user_data;
+       client_noti_type noti_type;
+       union _client_type {
+               user_download_info_t update_dl_info;
+               user_progress_info_t update_progress_info;
+               user_paused_info_t paused_info;
+               user_finished_info_t finished_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_client_cb_t client_callback;
+       char *client_user_agent;
+} client_app_info_t;
+
+typedef struct _client_app_mgr_t {
+       da_bool_t is_init;
+       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_result_t dereg_client_app(void);
+
+da_result_t send_client_paused_info (int slot_id);
+da_result_t send_client_update_dl_info (int slot_id, int dl_id,
+               char *file_type, unsigned long int file_size, char *tmp_saved_path,
+               char *pure_file_name, char *etag, char *extension);
+da_result_t send_client_update_progress_info (int slot_id, int dl_id,
+               unsigned long int received_size);
+da_result_t send_client_finished_info (int slot_id, int dl_id,
+               char *saved_path, char *etag, int error, int http_status);
+
+char *get_client_user_agent_string(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
new file mode 100755 (executable)
index 0000000..e12a40b
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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"
+
+#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,
+       FileManager,
+       DRMManager,
+       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 <stdio.h>
+#include <stdarg.h>
+#include <pthread.h>
+
+#ifdef DA_DEBUG_USING_DLOG
+       #include <dlog.h>
+       #ifdef LOG_TAG
+       #undef LOG_TAG
+       #endif /*  LOG_TAG */
+       #define LOG_TAG "DOWNLOAD_AGENT"
+
+       #define DA_LOG(channel, format, ...) LOGD_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__);
+       #define DA_LOG_CRITICAL(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__);
+       #define DA_LOG_VERBOSE(channel, format, ...) LOGV_IF(IS_LOG_ON(channel), format, ##__VA_ARGS__);
+       #define DA_LOG_ERR(channel, format, ...) LOGE_IF(IS_LOG_ON(channel), "ERR! "format, ##__VA_ARGS__);
+       #define DA_LOG_FUNC_START(channel, ...) LOGV_IF(IS_LOG_ON(channel), "starting...");
+#else /* DA_DEBUG_USING_DLOG */
+       #include <unistd.h>
+       #include <syscall.h>
+
+       #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
new file mode 100755 (executable)
index 0000000..3b2e77b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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_RESULT_OK   0
+
+#define DA_TRUE                1
+#define DA_FALSE               0
+#define DA_NULL                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_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
+#define DA_ERR_TOO_MANY_REDIECTS               -440
+
+// 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
+
+// DRM error - not conforming with DRM spec (-700 ~ -799)
+#define DA_ERR_DRM_FAIL                        -700
+#define DA_ERR_DRM_FILE_FAIL   -710
+
+// 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
new file mode 100755 (executable)
index 0000000..e78491f
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * 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_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-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 = 10, /* stage */
+       DOWNLOAD_STATE_FINISH = 50, /* stage */
+       DOWNLOAD_STATE_PAUSED = 60, /* http */
+       DOWNLOAD_STATE_CANCELED = 70, /* http */
+       DOWNLOAD_STATE_ABORTED = 80 /* satge */
+} 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;
+       char *etag;
+       char *temp_file_path;
+       client_input_basic_t client_input_basic;
+} client_input_t;
+
+typedef struct _download_thread_input {
+       int slot_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;
+       char *user_request_etag;
+       char *user_request_temp_file_path;
+
+       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_USER_REQUEST_ETAG(REQUEST)            (REQUEST->user_request_etag)
+#define GET_REQUEST_HTTP_USER_REQUEST_TEMP_FILE_PATH(REQUEST)                  (REQUEST->user_request_temp_file_path)
+#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_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 <size> */
+       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_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 {
+       da_bool_t is_using;
+       int slot_id;
+       int dl_id;
+       pthread_t active_dl_thread_id;
+       download_state_t state;
+       stage_info *download_stage_data;
+       queue_t queue;
+       int http_status;
+       da_bool_t enable_pause_update;
+       // FIXME have client_input itself, not to have each of them
+       char *user_install_path;
+       char *user_file_name;
+       char *user_etag;
+       char *user_temp_file_path;
+       void *user_data;
+} dl_info_t;
+
+#define GET_DL_THREAD_ID(ID)           (download_mgr.dl_info[ID].active_dl_thread_id)
+#define GET_DL_STATE_ON_ID(ID)         (download_mgr.dl_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.dl_info[ID].download_stage_data)
+#define GET_DL_ID(ID)          (download_mgr.dl_info[ID].dl_id)
+#define GET_DL_QUEUE(ID)               &(download_mgr.dl_info[ID].queue)
+#define GET_DL_ENABLE_PAUSE_UPDATE(ID)         (download_mgr.dl_info[ID].enable_pause_update)
+#define GET_DL_USER_INSTALL_PATH(ID)           (download_mgr.dl_info[ID].user_install_path)
+#define GET_DL_USER_FILE_NAME(ID)              (download_mgr.dl_info[ID].user_file_name)
+#define GET_DL_USER_ETAG(ID)           (download_mgr.dl_info[ID].user_etag)
+#define GET_DL_USER_TEMP_FILE_PATH(ID)         (download_mgr.dl_info[ID].user_temp_file_path)
+#define GET_DL_USER_DATA(ID)           (download_mgr.dl_info[ID].user_data)
+#define IS_THIS_DL_ID_USING(ID)        (download_mgr.dl_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 struct _download_mgr_t {
+       da_bool_t is_init;
+       dl_info_t dl_info[DA_MAX_DOWNLOAD_ID];
+       dl_id_history_t dl_id_history;
+       /* 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;
+} 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 slot_id);
+void destroy_download_info(int slot_id);
+void *Add_new_download_stage(int slot_id);
+void remove_download_stage(int slot_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_slot_id(int *available_id);
+da_result_t  get_slot_id_for_dl_id(int dl_id , int* slot_id);
+da_bool_t is_valid_slot_id(int slot_id);
+void store_http_status(int dl_id, int status);
+int get_http_status(int dl_id);
+#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
new file mode 100755 (executable)
index 0000000..b273fd8
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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_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_id);
+da_result_t  suspend_download(int dl_id, da_bool_t is_enable_cb);
+da_result_t  resume_download (int dl_id);
+
+da_result_t  requesting_download(stage_info *stage);
+da_result_t  handle_after_download(stage_info *stage);
+da_result_t  send_user_noti_and_finish_download_flow(
+               int slot_id, char *installed_path, char *etag);
+
+da_bool_t is_valid_download_id(int dl_id);
+#endif
diff --git a/src/agent/include/download-agent-encoding.h b/src/agent/include/download-agent-encoding.h
new file mode 100755 (executable)
index 0000000..c5c7fe5
--- /dev/null
@@ -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_Encoding_H
+#define _Download_Agent_Encoding_H
+
+#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,
+       char **out_decoded_ascii_str);
+void decode_url_encoded_str(const char *in_encoded_str, char **out_str);
+
+#endif // _Download_Agent_Encoding_H
diff --git a/src/agent/include/download-agent-file.h b/src/agent/include/download-agent-file.h
new file mode 100755 (executable)
index 0000000..3bada44
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "download-agent-type.h"
+#include "download-agent-dl-mgr.h"
+
+#define DA_DEFAULT_FILE_DIR_PATH       "/opt/usr/media/.tmp_download"
+#define DA_DEFAULT_INSTALL_PATH_FOR_PHONE "/opt/usr/media/Downloads"
+#define DA_DEFAULT_INSTALL_PATH_FOR_MMC "/opt/storage/sdcard/Downloads"
+
+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, unsigned long long *out_file_size);
+
+da_result_t clean_files_from_dir(char *dir_path);
+da_result_t create_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 start_file_writing_append_with_new_download(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_tmp_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);
+da_result_t get_default_dir(char **out_path);
+da_result_t get_default_install_dir(char **out_path);
+
+#endif
diff --git a/src/agent/include/download-agent-http-mgr.h b/src/agent/include/download-agent-http-mgr.h
new file mode 100755 (executable)
index 0000000..6653af0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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 <string.h>
+
+#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
new file mode 100755 (executable)
index 0000000..3bf137b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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_Misc_H
+#define _Download_Agent_Http_Misc_H
+
+#include <string.h>
+
+#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
new file mode 100755 (executable)
index 0000000..29d0ae4
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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"
+
+#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, unsigned long long *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
new file mode 100755 (executable)
index 0000000..68bb910
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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_Queue_H
+#define _Download_Agent_Http_Queue_H
+
+
+#include "download-agent-type.h"
+#include "download-agent-http-msg-handler.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+
+#define        MAX_QUEUE_SIZE  1024*64
+
+typedef enum
+{
+       Q_EVENT_TYPE_DATA_HTTP,
+       Q_EVENT_TYPE_DATA_DRM,
+       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-interface.h b/src/agent/include/download-agent-interface.h
new file mode 100755 (executable)
index 0000000..d51aed6
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * 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
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "download-agent-defs.h"
+#include <stdarg.h>
+
+/**
+ * @struct user_paused_info_t
+ * @brief Download Agent will send its state through this structure.
+ * @see da_paused_info_cb
+ * @par
+ *   This is used only by callback /a user_paused_info_t. \n
+ */
+typedef struct {
+       /// download request id for this notification
+       int download_id;
+} user_paused_info_t;
+
+/**
+ * @struct user_progress_info_t
+ * @brief Download Agent will send current downloading file's information through this structure.
+ * @see da_progress_info_cb
+ * @par
+ *   This is used only by callback /a da_progress_info_cb. \n
+ */
+typedef struct {
+       /// download request id for this updated download information
+       int download_id;
+       /// received size of chunked data.
+       unsigned long int received_size;
+} user_progress_info_t;
+
+/**
+ * @struct user_download_info_t
+ * @brief Download Agent will send current download's information through this structure.
+ * @see da_started_info_cb
+ * @par
+ *   This is used only by callback /a da_started_info_cb. \n
+ */
+typedef struct {
+       /// download request id for this updated download information
+       int download_id;
+       /// file's mime type from http header.
+       char *file_type;
+       /// file size from http header.
+       unsigned long int file_size;
+       /// This is temporary file path.
+       char *tmp_saved_path;
+       /// This is the file name for showing to user.
+       char *content_name;
+       /// etag string value for resume download,
+       char *etag;
+} user_download_info_t;
+
+typedef struct {
+       /// download request id for this updated download information
+       int download_id;
+       /// This has only file name for now.
+       char *saved_path;
+       /// etag string value for resume download,
+       /// This is returned when the download is failed and the etag is received from content server
+       char *etag;
+       /// convey error code if necessary, or it is zero.
+       int err;
+       /// http status code if necessary, or it is zero.
+       int http_status;
+} user_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; /* For resume download, the "etag" value should be existed together */
+       const char *etag; /* For resume download */
+       void *user_data;
+} extension_data_t;
+
+/**
+ * @typedef da_paused_cb
+ * @brief Download Agent will call this function to paused 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.
+ *
+ * @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_paused_info_cb) (user_paused_info_t *paused_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]          progress_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_progress_info_cb) (user_progress_info_t *progress_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_started_info_cb) (user_download_info_t *download_info, void *user_param);
+
+typedef void (*da_finished_info_cb) (user_finished_info_t *finished_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 download information
+       da_started_info_cb update_dl_info_cb;
+       /// callback to convey downloading information while downloading including received file size
+       da_progress_info_cb update_progress_info_cb;
+       /// callback to convey saved path
+       da_finished_info_cb finished_info_cb;
+       /// callback to convey etag value
+       da_paused_info_cb paused_info_cb;
+} da_client_cb_t;
+
+/**
+ * @fn int da_init (da_client_cb_t *da_client_callback)
+ * @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.
+ * @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 <download-agent-interface.h>
+ *
+ * void da_started_info_cb(user_download_info_t *download_info,void *user_param);
+ * void da_progress_info_cb(user_downloading_info_t *downloading_info,void *user_param);
+ * void da_finished_cb(user_finished_info_t *complted_info, void *user_param);
+ * void da_paused_info_cb(user_paused_info_t *paused_info, void *user_param);
+ *
+ * int download_initialize()
+ * {
+ *     int da_ret;
+ *     da_client_cb_t da_cb = {0};
+ *
+ *     da_cb.update_dl_info_cb = &update_download_info_cb;
+ *     da_cb.update_progress_info_cb = &progress_info_cb;
+ *     da_cb.finished_info_cb = &finished_info_cb;
+ *     da_cb.paused_info_cb = &paused_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);
+
+ /**
+ * @fn int da_deinit ()
+ * @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 <download-agent-interface.h>
+ *
+ *
+ * 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, int *download_id)
+ * @brief This function starts to download a content on passed URL.
+ *
+ * Useful information and result are conveyed through following callbacks.
+ * @li da_started_info_cb
+ * @li da_progress_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] download_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 <download-agent-interface.h>
+ *
+ * int da_ret;
+ * int download_id;
+ * char *url = "http://www.test.com/sample.mp3";
+ *
+ * da_ret = da_start_download(url,&download_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, int *download_id);
+
+/**
+* @fn int da_start_download_with_extension(const char *url, extension_data_t ext_data, int *download_id)
+* @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_started_info_cb
+* @li da_progress_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
+*
+* @param[in]   url     url to start download
+* @param[in]   ext_data extension data
+* @param[out]  download_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.
+*
+*
+* @par Example
+* @code
+  #include <download-agent-interface.h>
+
+       int da_ret;
+       int download_id;
+       extension_data_t ext_data = {0,};
+       const char *url = "https://www.test.com/sample.mp3";
+       const char *install_path = "/myFiles/music";
+       const char *my_data = strdup("data");
+       ext_data.install_path = install_path;
+       ext_data.user_data = (void *)my_data;
+
+       da_ret = da_start_download_with_extension(url, &download_id, &ext_data);
+       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,
+       extension_data_t *ext_data,
+       int *download_id
+);
+
+
+/**
+ * @fn int da_cancel_download(int download_id)
+ * @brief This function cancels a download for passed download_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 download_id will be deleted. So, client cannot request anything for the download_id.
+ *
+ * @pre There should be exist ongoing or suspended download for download_id.
+ * @post None.
+ *
+ * @param[in]          download_id             download request id
+ * @return             DA_RESULT_OK for success, or DA_ERR_XXX for fail
+ *
+ * @see None.
+ *
+ * @par Example
+ * @code
+   #include <download-agent-interface.h>
+
+   int da_ret;
+   int download_id;
+
+   da_ret = da_cancel_download(download_id);
+   if(da_ret == DA_RESULT_OK) {
+               // printf("download with [%d] is successfully canceled.\n", download_id);
+   }
+   else {
+               // in this case, downloading with download_id is keep ongoing.
+               printf("failed to cancel with error code %d\n", da_ret);
+   }
+ @endcode
+ */
+int da_cancel_download(int download_id);
+
+
+/**
+ * @fn int da_suspend_download(int download_id)
+ * @brief This function suspends downloading for passed download_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 download_id will be remained. So, client can request resume for the download_id.
+ * @remarks Client should cancel or resume for this download_id, or all information for the download_id will be leaved forever.
+ *
+ * @pre There should be exist ongoing download for download_id.
+ * @post None.
+ *
+ * @param[in]          download_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 <download-agent-interface.h>
+
+   int da_ret;
+   int download_id;
+
+   da_ret = da_suspend_download(download_id);
+   if(da_ret == DA_RESULT_OK) {
+               // printf("download with [%d] is successfully suspended.\n", download_id);
+   }
+   else {
+               // in this case, downloading with download_id is keep ongoing.
+               printf("failed to suspend with error code %d\n", da_ret);
+   }
+ @endcode
+ */
+int da_suspend_download(int download_id);
+
+int da_suspend_download_without_update(int download_id);
+/**
+ * @fn int da_resume_download(int download_id)
+ * @brief This function resumes downloading for passed download_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 download_id.
+ * @post None.
+ *
+ * @param[in]          download_id             download request id
+ * @return             DA_RESULT_OK for success, or DA_ERR_XXX for fail
+ *
+ * @see da_suspend_download()
+ *
+ * @par Example
+ * @code
+   #include <download-agent-interface.h>
+
+   int da_ret;
+   int download_id;
+
+   da_ret = da_resume_download(download_id);
+   if(da_ret == DA_RESULT_OK) {
+               // printf("download with [%d] is successfully resumed.\n", download_id);
+   }
+   else {
+               // in this case, downloading with download_id is keep suspended.
+               printf("failed to resume with error code %d\n", da_ret);
+   }
+ @endcode
+ */
+int da_resume_download(int download_id);
+
+/**
+ * @fn int da_is_valid_download_id(int download_id)
+ * @brief This function return the download id is valid and the download thread is still alive.
+ *
+ * Client can use this function if user wants to resume download.
+ * If the download id is vaild and the download thread is alive, it can resume download with using da_resume_download()
+ * If the the download thread was already terminated due to restarting the process,
+ *  it can resume download with using da_start_download_with_extension()
+ *
+ *
+ *
+ * @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 download_id.
+ * @post None.
+ *
+ * @param[in]          download_id             download request id
+ * @return             1 for success, or 0 for fail
+  *
+  */
+int da_is_valid_download_id(int download_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
new file mode 100755 (executable)
index 0000000..2e03c80
--- /dev/null
@@ -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_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
new file mode 100755 (executable)
index 0000000..a549c23
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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"
+#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
new file mode 100755 (executable)
index 0000000..b9698bb
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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_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-libsoup.h b/src/agent/include/download-agent-plugin-libsoup.h
new file mode 100755 (executable)
index 0000000..8160042
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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_Libsoup_H
+#define _Download_Agent_Plugin_Libsoup_H
+
+#include <string.h>
+#include <libsoup/soup.h>
+
+#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            60      // 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
new file mode 100755 (executable)
index 0000000..8523567
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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 <pthread.h>
+#include <errno.h>
+#include <time.h>
+
+#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
new file mode 100755 (executable)
index 0000000..86fa5ca
--- /dev/null
@@ -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_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-id-history.h b/src/agent/include/download-agent-utils-dl-id-history.h
new file mode 100755 (executable)
index 0000000..3e32048
--- /dev/null
@@ -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_Utils_Hash_Table_H
+#define _Download_Agent_Utils_Hash_Table_H
+
+#include "download-agent-pthread.h"
+
+typedef struct _dl_id_history_t dl_id_history_t;
+struct _dl_id_history_t {
+       int starting_num;
+       int cur_dl_id;
+       pthread_mutex_t mutex;
+};
+
+da_result_t init_dl_id_history(dl_id_history_t *dl_id_history);
+da_result_t deinit_dl_id_history(dl_id_history_t *dl_id_history);
+
+int get_available_dl_id(dl_id_history_t *dl_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
new file mode 100755 (executable)
index 0000000..4361ad5
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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_Utils_H
+#define _Download_Agent_Utils_H
+
+#include <time.h>
+#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_DRM_MESSAGE       "application/vnd.oma.drm.message"
+#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;
+
+typedef enum {
+       DA_MIME_TYPE_NONE,
+       DA_MIME_TYPE_DRM1_MESSATE,
+       DA_MIME_TYPE_END
+} da_mime_type_id_t;
+
+void get_random_number(int *out_num);
+da_result_t  get_available_dd_id(int *available_id);
+da_result_t  get_extension_from_mime_type(char *mime_type, char **extension);
+da_mime_type_id_t get_mime_type_id(char *content_type);
+da_result_t  get_available_memory(da_storage_type_t storage_type, da_storage_size_t *avail_memory);
+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 *_stristr(const char *long_str, const char *find_str);
+
+#endif
diff --git a/src/download-provider-da-interface.c b/src/download-provider-da-interface.c
new file mode 100755 (executable)
index 0000000..2d875c3
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "download-provider.h"
+#include "download-provider-log.h"
+#include "download-provider-pthread.h"
+#include "download-provider-socket.h"
+#include "download-provider-db.h"
+#include "download-provider-queue.h"
+#include "download-provider-notification.h"
+#include "download-provider-request.h"
+
+#include "download-agent-defs.h"
+#include "download-agent-interface.h"
+
+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;
+}
+
+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_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_OBTAIN_MUTEX:
+       case DA_ERR_FAIL_TO_ACCESS_FILE:
+       case DA_ERR_FAIL_TO_GET_CONF_VALUE:
+       case DA_ERR_FAIL_TO_ACCESS_STORAGE:
+               ret = DP_ERROR_IO_ERROR;
+               break;
+       }
+       return ret;
+}
+
+static void __download_info_cb(user_download_info_t *info, void *user_data)
+{
+       if (!info) {
+               TRACE_ERROR("[NULL-CHECK] Agent info");
+               return ;
+       }
+       if (!user_data) {
+               TRACE_ERROR("[NULL-CHECK] user_data");
+               return ;
+       }
+       dp_request *request = (dp_request *) user_data;
+       if (request->id < 0 || (request->agent_id != info->download_id)) {
+               TRACE_ERROR("[NULL-CHECK] agent_id : %d req_id %d",
+                       request->agent_id, info->download_id);
+               return ;
+       }
+
+       int request_id = request->id;
+
+       // update info before sending event
+       if (info->file_type) {
+               TRACE_INFO("[STARTED][%d] [%s]", request_id, info->file_type);
+               if (dp_db_replace_column(request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                               DP_DB_COL_MIMETYPE,
+                               DP_DB_COL_TYPE_TEXT, info->file_type) == 0) {
+
+                       if (info->tmp_saved_path) {
+                               TRACE_INFO("[PATH][%d] being written to [%s]",
+                                       request_id, info->tmp_saved_path);
+                               if (dp_db_set_column
+                                               (request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                                               DP_DB_COL_TMP_SAVED_PATH, DP_DB_COL_TYPE_TEXT,
+                                               info->tmp_saved_path) < 0)
+                                       TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+                       }
+
+                       if (info->file_size > 0) {
+                               TRACE_INFO
+                                       ("[FILE-SIZE][%d] [%lld]", request_id, info->file_size);
+                               CLIENT_MUTEX_LOCK(&(request->mutex));
+                               request->file_size = info->file_size;
+                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                               if (dp_db_set_column
+                                               (request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                                               DP_DB_COL_CONTENT_SIZE,
+                                               DP_DB_COL_TYPE_INT64, &info->file_size) < 0)
+                                       TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+                       }
+
+                       if (info->content_name) {
+                               TRACE_INFO
+                                       ("[CONTENTNAME][%d] [%s]", request_id, info->content_name);
+                               if (dp_db_set_column
+                                               (request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                                               DP_DB_COL_CONTENT_NAME,
+                                               DP_DB_COL_TYPE_TEXT, info->content_name) < 0)
+                                       TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+                       }
+                       if (info->etag) {
+                               TRACE_INFO("[ETAG][%d] [%s]", request_id, info->etag);
+                               if (dp_db_replace_column
+                                               (request_id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_ETAG,
+                                               DP_DB_COL_TYPE_TEXT, info->etag) < 0)
+                                       TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+                       }
+               } else {
+                       TRACE_ERROR
+                               ("[ERROR][%d][SQL] failed to insert downloadinfo",
+                               request_id);
+               }
+       }
+
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+
+       request->state = DP_STATE_DOWNLOADING;
+       if (dp_db_set_column(request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                       DP_DB_COL_TYPE_INT, &request->state) < 0)
+               TRACE_ERROR("[ERROR][%d][SQL]", request->id);
+
+       if (request->group && request->group->event_socket >= 0 &&
+               request->state_cb)
+               dp_ipc_send_event(request->group->event_socket,
+                       request->id, DP_STATE_DOWNLOADING, DP_ERROR_NONE, 0);
+
+       if (request->auto_notification)
+               request->noti_priv_id =
+                       dp_set_downloadinginfo_notification
+                               (request->id, request->packagename);
+
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+}
+
+static void __progress_cb(user_progress_info_t *info, void *user_data)
+{
+       if (!info) {
+               TRACE_ERROR("[NULL-CHECK] Agent info");
+               return ;
+       }
+       if (!user_data) {
+               TRACE_ERROR("[NULL-CHECK] user_data");
+               return ;
+       }
+       dp_request *request = (dp_request *) user_data;
+       if (request->id < 0 || (request->agent_id != info->download_id)) {
+               TRACE_ERROR("[NULL-CHECK][%d] agent_id : %d req_id %d",
+                       request->id, request->agent_id, info->download_id);
+               return ;
+       }
+
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+       if (request->state == DP_STATE_DOWNLOADING) {
+               request->received_size = info->received_size;
+               time_t tt = time(NULL);
+               struct tm *localTime = localtime(&tt);
+               // send event every 1 second.
+               if (request->progress_lasttime != localTime->tm_sec) {
+                       request->progress_lasttime = localTime->tm_sec;
+                       if (request->progress_cb && request->group &&
+                               request->group->event_socket >= 0 &&
+                               request->received_size > 0)
+                               dp_ipc_send_event(request->group->event_socket,
+                                       request->id, request->state, request->error,
+                                       request->received_size);
+                       if (request->auto_notification)
+                               dp_update_downloadinginfo_notification
+                                       (request->noti_priv_id,
+                                       (double)request->received_size,
+                                       (double)request->file_size);
+               }
+       }
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+}
+
+static void __finished_cb(user_finished_info_t *info, void *user_data)
+{
+       if (!info) {
+               TRACE_ERROR("[NULL-CHECK] Agent info");
+               return ;
+       }
+       TRACE_INFO("Agent ID[%d] err[%d] http_status[%d]",
+               info->download_id, info->err, info->http_status);
+       if (!user_data) {
+               TRACE_ERROR("[NULL-CHECK] user_data");
+               return ;
+       }
+       dp_request *request = (dp_request *) user_data;
+       if (request->id < 0 || (request->agent_id != info->download_id)) {
+               TRACE_ERROR("[NULL-CHECK][%d] agent_id : %d req_id %d",
+                       request->id, request->agent_id, info->download_id);
+               return ;
+       }
+
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+       int request_id = request->id;
+       dp_credential cred = request->credential;
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+       dp_state_type state = DP_STATE_NONE;
+       dp_error_type errorcode = DP_ERROR_NONE;
+
+       // update info before sending event
+       if (dp_db_update_date
+                       (request_id, DP_DB_TABLE_LOG, DP_DB_COL_ACCESS_TIME) < 0)
+               TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+
+       if (info->http_status > 0)
+               if (dp_db_replace_column(request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                               DP_DB_COL_HTTP_STATUS,
+                               DP_DB_COL_TYPE_INT, &info->http_status) < 0)
+                       TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+
+       if (info->err == DA_RESULT_OK) {
+               if (info->saved_path) {
+                       char *str = NULL;
+                       char *content_name = NULL;
+
+                       str = strrchr(info->saved_path, '/');
+                       if (str) {
+                               str++;
+                               content_name = dp_strdup(str);
+                               TRACE_INFO("[PARSE][%d] content_name [%s]",
+                                       request_id, content_name);
+                       }
+                       TRACE_INFO
+                               ("[chown][%d] [%d][%d]", request_id, cred.uid, cred.gid);
+                       if (chown(info->saved_path, cred.uid, cred.gid) < 0)
+                               TRACE_STRERROR("[ERROR][%d] chown", request_id);
+                       if (dp_db_replace_column
+                                       (request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                                       DP_DB_COL_SAVED_PATH,
+                                       DP_DB_COL_TYPE_TEXT, info->saved_path) == 0) {
+                               if (content_name != NULL) {
+                                       if (dp_db_set_column
+                                                       (request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                                                       DP_DB_COL_CONTENT_NAME,
+                                                       DP_DB_COL_TYPE_TEXT, content_name) < 0)
+                                               TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+                               }
+                       } else {
+                               TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+                       }
+                       if (content_name != NULL)
+                               free(content_name);
+
+                       errorcode = DP_ERROR_NONE;
+                       state = DP_STATE_COMPLETED;
+
+                       TRACE_INFO("[COMPLETED][%d] saved to [%s]",
+                                       request_id, info->saved_path);
+               } else {
+                       TRACE_ERROR("Cannot enter here");
+                       TRACE_ERROR("[ERROR][%d] No SavedPath", request_id);
+                       errorcode = DP_ERROR_INVALID_DESTINATION;
+                       state = DP_STATE_FAILED;
+               }
+               CLIENT_MUTEX_LOCK(&(request->mutex));
+               if (request->file_size == 0) {
+                       request->file_size = request->received_size;
+                       if (dp_db_replace_column
+                                       (request_id, DP_DB_TABLE_DOWNLOAD_INFO,
+                                       DP_DB_COL_CONTENT_SIZE,
+                                       DP_DB_COL_TYPE_INT64, &request->file_size ) < 0)
+                               TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+               }
+               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+       } else if (info->err == DA_RESULT_USER_CANCELED) {
+               state = DP_STATE_CANCELED;
+               errorcode = DP_ERROR_NONE;
+               TRACE_INFO("[CANCELED][%d]", request_id);
+       } else {
+               state = DP_STATE_FAILED;
+               errorcode = __change_error(info->err);
+               TRACE_INFO("[FAILED][%d][%s]", request_id,
+                               dp_print_errorcode(errorcode));
+       }
+
+       if (dp_db_set_column
+                       (request_id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                       DP_DB_COL_TYPE_INT, &state) < 0)
+               TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+
+       if (errorcode != DP_ERROR_NONE) {
+               if (dp_db_set_column(request_id, DP_DB_TABLE_LOG,
+                               DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
+                               &errorcode) < 0)
+                       TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+       }
+
+       // need MUTEX LOCK
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+
+       request->state = state;
+       request->error = errorcode;
+
+       // stay on memory till called destroy by client or timeout
+       if (request->group != NULL && request->group->event_socket >= 0) {
+               /* update the received file size.
+               * The last received file size cannot update
+               * because of reducing update algorithm*/
+               if (request->received_size > 0)
+                       dp_ipc_send_event(request->group->event_socket,
+                               request->id, DP_STATE_DOWNLOADING, request->error,
+                               request->received_size);
+               if (request->state_cb)
+                       dp_ipc_send_event(request->group->event_socket,
+                               request->id, request->state, request->error, 0);
+               request->group->queued_count--;
+       }
+
+       // to prevent the crash . check packagename of request
+       if (request->auto_notification && request->packagename != NULL)
+               request->noti_priv_id =
+                       dp_set_downloadedinfo_notification(request->noti_priv_id,
+                               request->id, request->packagename, request->state);
+
+       request->stop_time = (int)time(NULL);
+
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+
+       dp_thread_queue_manager_wake_up();
+}
+
+static void __paused_cb(user_paused_info_t *info, void *user_data)
+{
+       TRACE_INFO("");
+       dp_request *request = (dp_request *) user_data;
+       if (!request) {
+               TRACE_ERROR("[NULL-CHECK] request");
+               return ;
+       }
+       if (request->id < 0 || (request->agent_id != info->download_id)) {
+               TRACE_ERROR("[NULL-CHECK][%d] agent_id : %d req_id %d",
+                       request->id, request->agent_id, info->download_id);
+               return ;
+       }
+
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+       int request_id = request->id;
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+
+       if (dp_db_update_date
+                       (request_id, DP_DB_TABLE_LOG, DP_DB_COL_ACCESS_TIME) < 0)
+               TRACE_ERROR("[ERROR][%d][SQL]", request_id);
+
+       // need MUTEX LOCK
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+
+       request->state = DP_STATE_PAUSED;
+
+       if (dp_db_set_column
+                       (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                       DP_DB_COL_TYPE_INT, &request->state) < 0) {
+               TRACE_ERROR("[ERROR][%d][SQL]", request->id);
+       }
+
+       if (request->group &&
+               request->group->event_socket >= 0 && request->state_cb)
+               dp_ipc_send_event(request->group->event_socket,
+                       request->id, request->state, request->error, 0);
+
+       if (request->group)
+               request->group->queued_count--;
+
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+
+       dp_thread_queue_manager_wake_up();
+}
+
+int dp_init_agent()
+{
+       int da_ret = 0;
+       da_client_cb_t da_cb = {
+               __download_info_cb,
+               __progress_cb,
+               __finished_cb,
+               __paused_cb
+       };
+       da_ret = da_init(&da_cb);
+       if (da_ret != DA_RESULT_OK) {
+               return DP_ERROR_OUT_OF_MEMORY;
+       }
+       return DP_ERROR_NONE;
+}
+
+void dp_deinit_agent()
+{
+       da_deinit();
+}
+
+// 0 : success
+// -1 : failed
+dp_error_type dp_cancel_agent_download(int req_id)
+{
+       if (req_id < 0) {
+               TRACE_ERROR("[NULL-CHECK] req_id");
+               return -1;
+       }
+       if (da_cancel_download(req_id) == DA_RESULT_OK)
+               return 0;
+       return -1;
+}
+
+// 0 : success
+// -1 : failed
+dp_error_type dp_pause_agent_download(int req_id)
+{
+       if (req_id < 0) {
+               TRACE_ERROR("[NULL-CHECK] req_id");
+               return -1;
+       }
+       if (da_suspend_download(req_id) == DA_RESULT_OK)
+               return 0;
+       return -1;
+}
+
+
+// 0 : success
+// -1 : failed
+// -2 : pended
+dp_error_type dp_start_agent_download(dp_request *request)
+{
+       int da_ret = -1;
+       int req_dl_id = -1;
+       dp_error_type errorcode = DP_ERROR_NONE;
+       extension_data_t ext_data = {0,};
+
+       TRACE_INFO("");
+       if (!request) {
+               TRACE_ERROR("[NULL-CHECK] download_clientinfo_slot");
+               return DP_ERROR_INVALID_PARAMETER;
+       }
+
+       char *url = dp_request_get_url(request->id, request, &errorcode);
+       if (url == NULL) {
+               TRACE_ERROR("[ERROR][%d] URL is NULL", request->id);
+               return DP_ERROR_INVALID_URL;
+       }
+       char *destination =
+               dp_request_get_destination(request->id, request, &errorcode);
+       if (destination != NULL)
+               ext_data.install_path = destination;
+
+       char *filename =
+               dp_request_get_filename(request->id, request, &errorcode);
+       if (filename != NULL)
+               ext_data.file_name = filename;
+
+       // call start_download() of download-agent
+
+       char *tmp_saved_path =
+               dp_request_get_tmpsavedpath(request->id, request, &errorcode);
+       if (tmp_saved_path) {
+               char *etag = dp_request_get_etag(request->id, request, &errorcode);
+               if (etag) {
+                       TRACE_INFO("[RESUME][%d]", request->id);
+                       ext_data.etag = etag;
+                       ext_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_INFO("[RESTART][%d] try to remove tmp file [%s]",
+                               request->id, tmp_saved_path);
+                       if (dp_is_file_exist(tmp_saved_path) == 0)
+                               if (unlink(tmp_saved_path) != 0)
+                                       TRACE_STRERROR
+                                               ("[ERROR][%d] remove file", request->id);
+               }
+       }
+
+       // get headers list from httpheaders table(DB)
+       int headers_count = dp_db_get_cond_rows_count
+                       (request->id, DP_DB_TABLE_HTTP_HEADERS, NULL, 0, NULL);
+       if (headers_count > 0) {
+               ext_data.request_header = calloc(headers_count, sizeof(char*));
+               if (ext_data.request_header != NULL) {
+                       ext_data.request_header_count = dp_db_get_http_headers_list
+                               (request->id, (char**)ext_data.request_header);
+               }
+       }
+
+       ext_data.user_data = (void *)request;
+
+       // call start API of agent lib
+       da_ret =
+               da_start_download_with_extension(url, &ext_data, &req_dl_id);
+       if (ext_data.request_header_count > 0) {
+               int len = 0;
+               int i = 0;
+               len = ext_data.request_header_count;
+               for (i = 0; i < len; i++) {
+                       if (ext_data.request_header[i])
+                               free((void *)(ext_data.request_header[i]));
+               }
+               free(ext_data.request_header);
+       }
+       free(url);
+       free(destination);
+       free(filename);
+       free(tmp_saved_path);
+
+       // 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_INFO("[PENDING][%d] DA_ERR_ALREADY_MAX_DOWNLOAD [%d]",
+                       request->id, da_ret);
+               return DP_ERROR_TOO_MANY_DOWNLOADS;
+       } else if (da_ret != DA_RESULT_OK) {
+               TRACE_ERROR("[ERROR][%d] DP_ERROR_CONNECTION_FAILED [%d]",
+                       request->id, da_ret);
+               return __change_error(da_ret);
+       }
+       TRACE_INFO("[SUCCESS][%d] agent_id [%d]", request->id, req_dl_id);
+       request->agent_id = req_dl_id;
+       return DP_ERROR_NONE;
+}
+
+dp_error_type 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;
+       }
+       da_ret = da_resume_download(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);
+}
+
+// 1 : alive
+// 0 : not alive
+int dp_is_alive_download(int req_id)
+{
+       int da_ret = 0;
+       if (req_id < 0) {
+               TRACE_ERROR("[NULL-CHECK] req_id");
+               return 0;
+       }
+       da_ret = da_is_valid_download_id(req_id);
+       return da_ret;
+}
+
diff --git a/src/download-provider-db.c b/src/download-provider-db.c
new file mode 100755 (executable)
index 0000000..0c9d5b6
--- /dev/null
@@ -0,0 +1,1319 @@
+/*
+ * 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 <db-util.h>
+
+#include <string.h>
+#include <errno.h>
+
+#include "download-provider-config.h"
+#include "download-provider-db.h"
+#include "download-provider-slots.h"
+#include "download-provider-log.h"
+#include "download-provider-pthread.h"
+
+//BASIC
+#define DP_DB_BASIC_GET_QUERY_FORMAT "SELECT %s FROM %s WHERE id = ?"
+#define DP_DB_BASIC_SET_QUERY_FORMAT "UPDATE %s SET %s = ? WHERE id = ?"
+#define DP_DB_BASIC_INSERT_QUERY_FORMAT "INSERT INTO %s (id, %s) VALUES (?, ?)"
+#define DP_DB_BASIC_NOW_DATE_QUERY_FORMAT "UPDATE %s SET %s = DATETIME('now') WHERE id = ?"
+
+// COND
+#define DP_DB_COND_GET_QUERY_FORMAT "SELECT %s FROM %s WHERE id = ? AND %s = ?"
+#define DP_DB_COND_SET_QUERY_FORMAT "UPDATE %s SET %s = ? WHERE id = ? AND %s = ?"
+
+typedef enum {
+       DP_DB_QUERY_TYPE_GET = 10,
+       DP_DB_QUERY_TYPE_SET = 20,
+       DP_DB_QUERY_TYPE_INSERT = 30,
+       DP_DB_QUERY_TYPE_NOW_DATE = 40
+} db_query_type;
+
+sqlite3 *g_dp_db_handle = 0;
+
+// called when terminating process
+void dp_db_close()
+{
+       if (g_dp_db_handle)
+               db_util_close(g_dp_db_handle);
+       g_dp_db_handle = 0;
+}
+
+// called when launching process or in every API
+int dp_db_open()
+{
+       if (g_dp_db_handle == 0) {
+               if (db_util_open(DATABASE_FILE, &g_dp_db_handle,
+                               DB_UTIL_REGISTER_HOOK_METHOD) != SQLITE_OK) {
+                       TRACE_ERROR("failed db_util_open [%s][%s]", DATABASE_FILE,
+                               sqlite3_errmsg(g_dp_db_handle));
+                       dp_db_close();
+                       return -1;
+               }
+               sqlite3_exec(g_dp_db_handle, "PRAGMA journal_mode=PERSIST;", 0, 0, 0);
+               sqlite3_exec(g_dp_db_handle, "PRAGMA foreign_keys=ON;", 0, 0, 0);
+       }
+       return g_dp_db_handle ? 0 : -1;
+}
+
+static int __dp_sql_open()
+{
+       return dp_db_open();
+}
+
+static void __dp_finalize(sqlite3_stmt *stmt)
+{
+       if (sqlite3_finalize(stmt) != SQLITE_OK)
+               TRACE_ERROR("failed sqlite3_finalize [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+}
+
+int dp_db_get_count_by_limit_time()
+{
+       int errorcode = SQLITE_OK;
+       sqlite3_stmt *stmt = NULL;
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("db_util_open is failed [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       errorcode =
+               sqlite3_prepare_v2(g_dp_db_handle,
+                       "SELECT count(id) FROM logging \
+                       WHERE createtime < DATETIME('now','-48 hours')",
+                       -1, &stmt, NULL);
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_ROW) {
+               int count = sqlite3_column_int(stmt, 0);
+               __dp_finalize(stmt);
+               return count;
+       }
+       __dp_finalize(stmt);
+       return 0;
+}
+
+int dp_db_get_list_by_limit_time(dp_request_slots *requests, int limit)
+{
+       int errorcode = SQLITE_OK;
+       int i = 0;
+       sqlite3_stmt *stmt = NULL;
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("db_util_open is failed [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       errorcode =
+               sqlite3_prepare_v2(g_dp_db_handle,
+                       "SELECT id, state FROM logging WHERE \
+                       createtime < DATETIME('now','-48 hours') \
+                       ORDER BY createtime ASC LIMIT ?",
+                       -1, &stmt, NULL);
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (sqlite3_bind_int(stmt, 1, limit)
+               != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int[%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW && i < limit) {
+               // allocation & initialization
+               requests[i].request = dp_request_new();
+               // ID
+               requests[i].request->id = sqlite3_column_int(stmt, 0);
+               // state
+               requests[i].request->state = sqlite3_column_int(stmt, 1);
+
+               TRACE_INFO("ID : %d",  requests[i].request->id);
+               TRACE_INFO("state : %d",  requests[i].request->state);
+               i++;
+       }
+
+       __dp_finalize(stmt);
+       return i;
+}
+
+int dp_db_crashed_list(dp_request_slots *requests, int limit)
+{
+       int errorcode = SQLITE_OK;
+       int i = 0;
+       int buffer_length = 0;
+       sqlite3_stmt *stmt = NULL;
+       char *buffer = NULL;
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("db_util_open is failed [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       errorcode =
+               sqlite3_prepare_v2(g_dp_db_handle,
+                       "SELECT id, state, packagename FROM logging WHERE \
+                       (state = ? OR state = ? OR state = ?) \
+                       AND createtime > DATETIME('now','-48 hours') LIMIT ?",
+                       -1, &stmt, NULL);
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (sqlite3_bind_int(stmt, 1, DP_STATE_QUEUED) != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (sqlite3_bind_int(stmt, 2, DP_STATE_DOWNLOADING) != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (sqlite3_bind_int(stmt, 3, DP_STATE_CONNECTING) != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (sqlite3_bind_int(stmt, 4, limit)
+               != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int[%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       while ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) {
+               // allocation & initialization
+               requests[i].request = dp_request_new();
+               // ID
+               requests[i].request->id = sqlite3_column_int(stmt, 0);
+               // state
+               requests[i].request->state = sqlite3_column_int(stmt, 1);
+               // packagename
+               buffer = (char *)(sqlite3_column_text(stmt, 2));
+               requests[i].request->packagename = NULL;
+               if (buffer) {
+                       buffer_length = strlen(buffer);
+                       if (buffer_length > 1) {
+                               requests[i].request->packagename
+                                       = (char *)calloc(buffer_length + 1, sizeof(char));
+                               memcpy(requests[i].request->packagename, buffer,
+                                       buffer_length * sizeof(char));
+                               requests[i].request->packagename[buffer_length] = '\0';
+                       }
+               }
+
+               TRACE_INFO("ID : %d",  requests[i].request->id);
+               TRACE_INFO("state : %d",  requests[i].request->state);
+               TRACE_INFO("packagename : %s",  requests[i].request->packagename);
+               i++;
+       }
+
+       __dp_finalize(stmt);
+       return i;
+}
+
+int dp_db_limit_rows(int limit)
+{
+       int errorcode = SQLITE_OK;
+       sqlite3_stmt *stmt = NULL;
+
+       if (limit <= 0) {
+               TRACE_ERROR("[CHECK LIMIT] %d", limit);
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       // apply "ON DELETE CASCADE"
+       errorcode =
+               sqlite3_prepare_v2(g_dp_db_handle,
+                       "DELETE FROM logging WHERE id NOT IN \
+                       (SELECT id FROM logging ORDER BY createtime ASC LIMIT ?)",
+                       -1, &stmt, NULL);
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_prepare_v2 [%s]",
+                               sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (sqlite3_bind_int(stmt, 1, limit)
+               != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int[%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+dp_request *dp_db_load_logging_request(int id)
+{
+       int errorcode = SQLITE_OK;
+       int buffer_length = 0;
+       sqlite3_stmt *stmt = NULL;
+       char *buffer = NULL;
+       dp_request *request = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return NULL;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("db_util_open is failed [%s]",
+                               sqlite3_errmsg(g_dp_db_handle));
+               return NULL;
+       }
+
+       errorcode =
+               sqlite3_prepare_v2(g_dp_db_handle,
+                       "SELECT state, errorcode, startcount, packagename \
+                       FROM logging WHERE id = ?",
+                       -1, &stmt, NULL);
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]",
+                               sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int is failed. [%s]",
+                               sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+
+       if ((errorcode = sqlite3_step(stmt)) == SQLITE_ROW) {
+               request = dp_request_new();
+               if (request == NULL) {
+                       TRACE_ERROR("dp_request_new failed");
+                       __dp_finalize(stmt);
+                       return NULL;
+               }
+               request->id = id;
+               request->state = sqlite3_column_int(stmt, 0);
+               request->error = sqlite3_column_int(stmt, 1);
+               request->startcount = sqlite3_column_int(stmt, 2);
+
+               buffer = (char *)(sqlite3_column_text(stmt, 3));
+               if (buffer) {
+                       buffer_length = strlen(buffer);
+                       if (buffer_length > 1) {
+                               request->packagename
+                                       = (char *)calloc(buffer_length + 1, sizeof(char));
+                               memcpy(request->packagename, buffer,
+                                       buffer_length * sizeof(char));
+                               request->packagename[buffer_length] = '\0';
+                       }
+               }
+       } else {
+               TRACE_ERROR("sqlite3_step is failed. [%s] errorcode[%d]",
+                               sqlite3_errmsg(g_dp_db_handle), errorcode);
+               __dp_finalize(stmt);
+               return NULL;
+       }
+       __dp_finalize(stmt);
+       return request;
+}
+
+int dp_db_remove_all(int id)
+{
+       #if 0
+       dp_db_remove(id, DP_DB_TABLE_REQUEST_INFO);
+       dp_db_remove(id, DP_DB_TABLE_DOWNLOAD_INFO);
+       dp_db_remove(id, DP_DB_TABLE_HTTP_HEADERS);
+       dp_db_remove(id, DP_DB_TABLE_NOTIFICATION);
+       #endif
+       // apply "ON DELETE CASCADE"
+       dp_db_remove(id, DP_DB_TABLE_LOG);
+       return -1;
+}
+
+int dp_db_remove(int id, char *table)
+{
+       int errorcode = SQLITE_OK;
+       int query_len = 0;
+       int ret = -1;
+       sqlite3_stmt *stmt = NULL;
+       char *query_format = NULL;
+       char *query = NULL;
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       query_format = "DELETE FROM %s WHERE id = ? ";
+       // 2 means the length of one %s
+       query_len = strlen(query_format) - 2 + strlen(table);
+       if (query_len < strlen(query_format)) {
+               TRACE_ERROR("[CHECK QUERY FORMAT] [%s][%s]",
+                               query_format, table);
+               return -1;
+       }
+
+       query = (char *)calloc((query_len + 1), sizeof(char));
+       if (query == NULL) {
+               TRACE_STRERROR("[CALLOC]");
+               return -1;
+       }
+       query[query_len] = '\0';
+
+       ret = snprintf(query, query_len + 1, query_format, table);
+
+       if (ret < 0) {
+               TRACE_STRERROR("[CHECK COMBINE] [%s]", query);
+               free(query);
+               return -1;
+       }
+
+       // check error of sqlite3_prepare_v2
+       if (sqlite3_prepare_v2
+                       (g_dp_db_handle, query, -1, &stmt, NULL) != SQLITE_OK) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               free(query);
+               return -1;
+       }
+       free(query);
+
+       if (sqlite3_bind_int(stmt, 1, id)
+               != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int[%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+static sqlite3_stmt *__prepare_query(sqlite3 *handle,
+               db_query_type type, char *table, char *column)
+{
+       sqlite3_stmt *stmt = NULL;
+       char *query_format = NULL;
+       char *query = NULL;
+       int ret = -1;
+
+       if (type == DP_DB_QUERY_TYPE_GET) {
+               query_format = DP_DB_BASIC_GET_QUERY_FORMAT;
+       } else if (type == DP_DB_QUERY_TYPE_SET) {
+               query_format = DP_DB_BASIC_SET_QUERY_FORMAT;
+       } else if (type == DP_DB_QUERY_TYPE_INSERT) {
+               query_format = DP_DB_BASIC_INSERT_QUERY_FORMAT;
+       } else if (type == DP_DB_QUERY_TYPE_NOW_DATE) {
+               query_format = DP_DB_BASIC_NOW_DATE_QUERY_FORMAT;
+       } else {
+               TRACE_ERROR("[CHECK QUERY TYPE] [%d]", type);
+               return NULL;
+       }
+
+       if (type == DP_DB_QUERY_TYPE_GET)
+               query = sqlite3_mprintf(query_format, column, table);
+       else
+               query = sqlite3_mprintf(query_format, table, column);
+       if (query == NULL) {
+               TRACE_ERROR("[CHECK COMBINE] [%s]", query_format);
+               return NULL;
+       }
+
+       TRACE_INFO("[QUERY] %s", query);
+
+       ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
+       sqlite3_free(query);
+       if ( ret != SQLITE_OK) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+       return stmt;
+}
+
+int dp_db_insert_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value)
+{
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       stmt = __prepare_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_INSERT, table, column);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       int errorcode = SQLITE_OK;
+       if (datatype == DP_DB_COL_TYPE_INT) {
+               int *cast_value = value;
+               errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+       } else if (datatype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+               sqlite3_int64 *cast_value = value;
+               errorcode = sqlite3_bind_int64(stmt, 2, *cast_value);
+#else
+               int *cast_value = value;
+               errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+#endif
+       } else if (datatype == DP_DB_COL_TYPE_TEXT) {
+               errorcode = sqlite3_bind_text(stmt, 2, (char*)value, -1, NULL);
+       } else {
+               TRACE_ERROR("[CHECK TYPE] Not Support [%d]", datatype);
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%d] [%s]",
+                       datatype, sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       // VALUES ( id )
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+int dp_db_set_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value)
+{
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       stmt = __prepare_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_SET, table, column);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       int errorcode = SQLITE_OK;
+       if (datatype == DP_DB_COL_TYPE_INT) {
+               int *cast_value = value;
+               errorcode = sqlite3_bind_int(stmt, 1, *cast_value);
+       } else if (datatype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+               sqlite3_int64 *cast_value = value;
+               errorcode = sqlite3_bind_int64(stmt, 1, *cast_value);
+#else
+               int *cast_value = value;
+               errorcode = sqlite3_bind_int(stmt, 1, *cast_value);
+#endif
+       } else if (datatype == DP_DB_COL_TYPE_TEXT) {
+               errorcode = sqlite3_bind_text(stmt, 1, (char*)value, -1, NULL);
+       } else {
+               TRACE_ERROR("[CHECK TYPE] Not Support [%d]", datatype);
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%d] [%s]",
+                       datatype, sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 2, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+int dp_db_replace_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value)
+{
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       int check_id = dp_db_get_int_column(id, table, DP_DB_COL_ID);
+       if (check_id != id) // INSERT
+               return dp_db_insert_column(id, table, column, datatype, value);
+       // UPDATE
+       return dp_db_set_column(id, table, column, datatype, value);
+}
+
+// success : 0
+// error   : -1
+char *dp_db_get_text_column(int id, char *table, char *column)
+{
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return NULL;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return NULL;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return NULL;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return NULL;
+       }
+
+       stmt = __prepare_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return NULL;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+
+       if (sqlite3_step(stmt) == SQLITE_ROW) {
+               int buffer_length = 0;
+               char *columntext = NULL;
+               char *buffer = (char *)(sqlite3_column_text(stmt, 0));
+               if (buffer && (buffer_length = strlen(buffer)) > 1) {
+                       columntext = (char *)calloc(buffer_length + 1, sizeof(char));
+                       memcpy(columntext, buffer, buffer_length * sizeof(char));
+                       columntext[buffer_length] = '\0';
+               }
+               __dp_finalize(stmt);
+               return columntext;
+       }
+       __dp_finalize(stmt);
+       return NULL;
+}
+
+int dp_db_get_int_column(int id, char *table, char *column)
+{
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       stmt = __prepare_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (sqlite3_step(stmt) == SQLITE_ROW) {
+               int columnvalue = sqlite3_column_int(stmt, 0);
+               __dp_finalize(stmt);
+               return columnvalue;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+long long dp_db_get_int64_column(int id, char *table, char *column)
+{
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       stmt = __prepare_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (sqlite3_step(stmt) == SQLITE_ROW) {
+               long long columnvalue = sqlite3_column_int64(stmt, 0);
+               __dp_finalize(stmt);
+               return columnvalue;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+int dp_db_update_date(int id, char *table, char *column)
+{
+       int errorcode = SQLITE_OK;
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("__dp_sql_open [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       stmt = __prepare_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_NOW_DATE, table, column);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       TRACE_ERROR("Failed : [%s]", sqlite3_errmsg(g_dp_db_handle));
+       __dp_finalize(stmt);
+       return -1;
+}
+
+static sqlite3_stmt *__prepare_cond_query(sqlite3 *handle,
+               db_query_type type, char *table,
+               char *column, char *cond_column)
+{
+       sqlite3_stmt *stmt = NULL;
+       char *query_format = NULL;
+       char *query = NULL;
+       int ret = -1;
+
+       if (type == DP_DB_QUERY_TYPE_GET) {
+               query_format = DP_DB_COND_GET_QUERY_FORMAT;
+       } else if (type == DP_DB_QUERY_TYPE_SET) {
+               query_format = DP_DB_COND_SET_QUERY_FORMAT;
+       } else {
+               TRACE_ERROR("[CHECK QUERY TYPE] [%d]", type);
+               return NULL;
+       }
+
+       if (type == DP_DB_QUERY_TYPE_GET)
+               query = sqlite3_mprintf(query_format, column, table, cond_column);
+       else
+               query = sqlite3_mprintf(query_format, table, column, cond_column);
+       if (query == NULL) {
+               TRACE_ERROR("[CHECK COMBINE] [%s]", query_format);
+               return NULL;
+       }
+
+       TRACE_INFO("[QUERY] %s", query);
+
+       ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
+       sqlite3_free(query);
+       if ( ret != SQLITE_OK) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+       return stmt;
+
+}
+
+int dp_db_cond_set_column(int id, char *table, char *column,
+               db_column_data_type datatype, void *value,
+               char *condcolumn, db_column_data_type condtype, void *condvalue)
+{
+       int errorcode = SQLITE_OK;
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (!condcolumn) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       stmt = __prepare_cond_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_SET, table, column, condcolumn);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       if (datatype == DP_DB_COL_TYPE_INT) {
+               int *cast_value = value;
+               errorcode = sqlite3_bind_int(stmt, 1, *cast_value);
+       } else if (datatype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+               sqlite3_int64 *cast_value = value;
+               errorcode = sqlite3_bind_int64(stmt, 1, *cast_value);
+#else
+               int *cast_value = value;
+               errorcode = sqlite3_bind_int(stmt, 1, *cast_value);
+#endif
+       } else if (datatype == DP_DB_COL_TYPE_TEXT) {
+               errorcode = sqlite3_bind_text(stmt, 1, (char*)value, -1, NULL);
+       } else {
+               TRACE_ERROR("[CHECK TYPE] Not Support [%d]", datatype);
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%d] [%s]",
+                       datatype, sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (condtype == DP_DB_COL_TYPE_INT) {
+               int *cast_value = condvalue;
+               errorcode = sqlite3_bind_int(stmt, 3, *cast_value);
+       } else if (condtype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+               sqlite3_int64 *cast_value = condvalue;
+               errorcode = sqlite3_bind_int64(stmt, 3, *cast_value);
+#else
+               int *cast_value = condvalue;
+               errorcode = sqlite3_bind_int(stmt, 3, *cast_value);
+#endif
+       } else if (condtype == DP_DB_COL_TYPE_TEXT) {
+               errorcode = sqlite3_bind_text(stmt, 3, (char*)condvalue, -1, NULL);
+       } else {
+               TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype);
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%d] [%s]",
+                       datatype, sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 2, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+char *dp_db_cond_get_text_column(int id, char *table, char *column,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue)
+{
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return NULL;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return NULL;
+       }
+
+       if (!column) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return NULL;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("[OPEN] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return NULL;
+       }
+
+       stmt = __prepare_cond_query
+                       (g_dp_db_handle, DP_DB_QUERY_TYPE_GET, table, column, condcolumn);
+       if (stmt == NULL) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               return NULL;
+       }
+
+       int errorcode = SQLITE_OK;
+       if (condtype == DP_DB_COL_TYPE_INT) {
+               int *cast_value = condvalue;
+               errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+       } else if (condtype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+               sqlite3_int64 *cast_value = condvalue;
+               errorcode = sqlite3_bind_int64(stmt, 2, *cast_value);
+#else
+               int *cast_value = condvalue;
+               errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+#endif
+       } else if (condtype == DP_DB_COL_TYPE_TEXT) {
+               errorcode = sqlite3_bind_text(stmt, 2, (char*)condvalue, -1, NULL);
+       } else {
+               TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype);
+               __dp_finalize(stmt);
+               return NULL;
+       }
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%d] [%s]",
+                       condtype, sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+
+       // WHERE id = ?
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return NULL;
+       }
+
+       if (sqlite3_step(stmt) == SQLITE_ROW) {
+               int buffer_length = 0;
+               char *columntext = NULL;
+               char *buffer = (char *)(sqlite3_column_text(stmt, 0));
+               if (buffer && (buffer_length = strlen(buffer)) > 1) {
+                       columntext = (char *)calloc(buffer_length + 1, sizeof(char));
+                       memcpy(columntext, buffer, buffer_length * sizeof(char));
+                       columntext[buffer_length] = '\0';
+               }
+               __dp_finalize(stmt);
+               return columntext;
+       }
+       __dp_finalize(stmt);
+       return NULL;
+}
+
+int dp_db_cond_remove(int id, char *table,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue)
+{
+       int errorcode = SQLITE_OK;
+       int ret = -1;
+       sqlite3_stmt *stmt = NULL;
+       char *query_format = NULL;
+       char *query = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (!condcolumn) {
+               TRACE_ERROR("[CHECK COLUMN NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("__dp_sql_open[%s]", sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       query_format = "DELETE FROM %s WHERE id = ? AND %s = ?";
+
+       query = sqlite3_mprintf(query_format, table, condcolumn);
+       if (query == NULL) {
+               TRACE_ERROR("[CHECK COMBINE] [%s]", query_format);
+               return -1;
+       }
+
+       TRACE_INFO("[QUERY] %s", query);
+
+       ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL);
+       sqlite3_free(query);
+       if ( ret != SQLITE_OK) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (condtype == DP_DB_COL_TYPE_INT) {
+               int *cast_value = condvalue;
+               errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+       } else if (condtype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+               sqlite3_int64 *cast_value = condvalue;
+               errorcode = sqlite3_bind_int64(stmt, 2, *cast_value);
+#else
+               int *cast_value = condvalue;
+               errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+#endif
+       } else if (condtype == DP_DB_COL_TYPE_TEXT) {
+               errorcode = sqlite3_bind_text(stmt, 2, (char*)condvalue, -1, NULL);
+       } else {
+               TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype);
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("[BIND] [%d] [%s]",
+                       condtype, sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (sqlite3_bind_int(stmt, 1, id)
+               != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int[%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_OK || errorcode == SQLITE_DONE) {
+               __dp_finalize(stmt);
+               return 0;
+       }
+       __dp_finalize(stmt);
+       return -1;
+}
+
+int dp_db_get_cond_rows_count(int id, char *table,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue)
+{
+       int errorcode = SQLITE_OK;
+       int ret = -1;
+       sqlite3_stmt *stmt = NULL;
+       char *query = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (!table) {
+               TRACE_ERROR("[CHECK TABLE NAME]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("db_util_open is failed [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       if (condcolumn)
+               query =
+                       sqlite3_mprintf
+                               ("SELECT count(id) FROM %s WHERE id = ? AND %s = ?",
+                               table, condcolumn);
+       else
+               query =
+                       sqlite3_mprintf
+                               ("SELECT count(id) FROM %s WHERE id = ?", table);
+
+       if (query == NULL) {
+               TRACE_ERROR("[CHECK COMBINE]");
+               return -1;
+       }
+
+       TRACE_INFO("[QUERY] %s", query);
+
+       ret = sqlite3_prepare_v2(g_dp_db_handle, query, -1, &stmt, NULL);
+       sqlite3_free(query);
+       if ( ret != SQLITE_OK) {
+               TRACE_ERROR("[PREPARE] [%s]", sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       if (condcolumn) {
+               if (condtype == DP_DB_COL_TYPE_INT) {
+                       int *cast_value = condvalue;
+                       errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+               } else if (condtype == DP_DB_COL_TYPE_INT64) {
+#ifdef SQLITE_INT64_TYPE
+                       sqlite3_int64 *cast_value = condvalue;
+                       errorcode = sqlite3_bind_int64(stmt, 2, *cast_value);
+#else
+                       int *cast_value = condvalue;
+                       errorcode = sqlite3_bind_int(stmt, 2, *cast_value);
+#endif
+               } else if (condtype == DP_DB_COL_TYPE_TEXT) {
+                       errorcode = sqlite3_bind_text(stmt, 2, (char*)condvalue, -1, NULL);
+               } else {
+                       TRACE_ERROR("[CHECK TYPE] Not Support [%d]", condtype);
+                       __dp_finalize(stmt);
+                       return -1;
+               }
+               if (errorcode != SQLITE_OK) {
+                       TRACE_ERROR("[BIND] [%d] [%s]",
+                               condtype, sqlite3_errmsg(g_dp_db_handle));
+                       __dp_finalize(stmt);
+                       return -1;
+               }
+       }
+
+       if (sqlite3_bind_int(stmt, 1, id)
+               != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int[%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       errorcode = sqlite3_step(stmt);
+       if (errorcode == SQLITE_ROW) {
+               int count = sqlite3_column_int(stmt, 0);
+               __dp_finalize(stmt);
+               return count;
+       }
+       __dp_finalize(stmt);
+       return 0;
+}
+
+int dp_db_get_http_headers_list(int id, char **headers)
+{
+       int errorcode = SQLITE_OK;
+       int i = 0;
+       int headers_index = 0;
+       sqlite3_stmt *stmt = NULL;
+
+       if (id <= 0) {
+               TRACE_ERROR("[CHECK ID]");
+               return -1;
+       }
+
+       if (__dp_sql_open() < 0) {
+               TRACE_ERROR("db_util_open is failed [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               return -1;
+       }
+
+       errorcode =
+               sqlite3_prepare_v2(g_dp_db_handle,
+                       "SELECT header_field, header_data FROM httpheaders WHERE id = ?",
+                       -1, &stmt, NULL);
+       if (errorcode != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_prepare_v2 is failed. [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+       if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+               TRACE_ERROR("sqlite3_bind_int [%s]",
+                       sqlite3_errmsg(g_dp_db_handle));
+               __dp_finalize(stmt);
+               return -1;
+       }
+
+       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));
+               i++;
+               // 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/src/download-provider-main.c b/src/download-provider-main.c
new file mode 100755 (executable)
index 0000000..79968ba
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <pthread.h>
+
+#ifdef DP_SUPPORT_DBUS_ACTIVATION
+#include <dbus/dbus.h>
+#endif
+
+#include "download-provider-config.h"
+#include "download-provider-log.h"
+#include "download-provider-socket.h"
+#include "download-provider-pthread.h"
+#include "download-provider-slots.h"
+#include "download-provider-db.h"
+#include "download-provider-network.h"
+#include "download-provider-queue.h"
+#include "download-provider-notification.h"
+#include "download-provider-da-interface.h"
+
+// declare functions
+int dp_lock_pid(char *path);
+void *dp_thread_requests_manager(void *arg);
+
+// declare global variables
+// need for libsoup, decided the life-time by mainloop.
+GMainLoop *g_main_loop_handle = 0;
+
+#ifdef DP_SUPPORT_DBUS_ACTIVATION
+static int __register_dbus_service(void)
+{
+       DBusError dbus_error;
+       DBusConnection *dp_dbus_connection = NULL;
+
+       dbus_error_init(&dbus_error);
+
+       dp_dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
+       if (dp_dbus_connection == NULL) {
+               TRACE_ERROR("[DBUS] dbus_bus_get: %s", dbus_error.message);
+               dbus_error_free(&dbus_error);
+               return -1;
+       }
+
+       if (dbus_bus_request_name
+                       (dp_dbus_connection, DP_DBUS_SERVICE_DBUS, 0, &dbus_error) < 0 ||
+                       dbus_error_is_set(&dbus_error)) {
+               TRACE_ERROR("[DBUS] request_name %s", dbus_error.message);
+               dbus_error_free(&dbus_error);
+               dbus_connection_unref(dp_dbus_connection);
+               dp_dbus_connection = NULL;
+               return -1;
+       }
+       dbus_connection_unref(dp_dbus_connection);
+       dp_dbus_connection = NULL;
+       return 0;
+}
+
+#endif
+
+void dp_terminate(int signo)
+{
+       TRACE_INFO("Received SIGTERM");
+       if (g_main_loop_is_running(g_main_loop_handle))
+               g_main_loop_quit(g_main_loop_handle);
+}
+
+static gboolean __dp_idle_start_service(void *data)
+{
+       TRACE_INFO("Launch threads .....");
+
+       // declare all resources
+       pthread_t thread_pid;
+       pthread_attr_t thread_attr;
+
+       // initialize
+       if (pthread_attr_init(&thread_attr) != 0) {
+               TRACE_STRERROR("failed to init pthread attr");
+               dp_terminate(SIGTERM);
+               return FALSE;
+       }
+       if (pthread_attr_setdetachstate(&thread_attr,
+                                                                       PTHREAD_CREATE_DETACHED) != 0) {
+               TRACE_STRERROR("failed to set detach option");
+               dp_terminate(SIGTERM);
+               return FALSE;
+       }
+
+       // create thread for managing QUEUEs
+       if (pthread_create
+               (&thread_pid, &thread_attr, dp_thread_queue_manager,
+               data) != 0) {
+               TRACE_STRERROR
+                       ("failed to create pthread for run_manage_download_server");
+               dp_terminate(SIGTERM);
+       }
+
+       // start service, accept url-download ( client package )
+       if (pthread_create
+               (&thread_pid, &thread_attr, dp_thread_requests_manager,
+               data) != 0) {
+               TRACE_STRERROR
+                       ("failed to create pthread for run_manage_download_server");
+               dp_terminate(SIGTERM);
+       }
+       return FALSE;
+}
+
+int main(int argc, char **argv)
+{
+       dp_privates *privates = NULL;
+       int lock_fd = -1;
+
+       if (chdir("/") < 0) {
+               TRACE_STRERROR("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, dp_terminate) == SIG_ERR) {
+               TRACE_ERROR("failed to register signal callback");
+               exit(EXIT_FAILURE);
+       }
+       // write IPC_FD_PATH. and lock
+       if ((lock_fd = dp_lock_pid(DP_LOCK_PID)) < 0) {
+               TRACE_ERROR
+                       ("It need to check download-provider is already alive");
+               TRACE_ERROR("Or fail to create pid file in (%s)",
+                               DP_LOCK_PID);
+               exit(EXIT_FAILURE);
+       }
+       // if exit socket file, delete it
+       if (access(DP_IPC, F_OK) == 0) {
+               unlink(DP_IPC);
+       }
+
+       g_type_init();
+
+       privates = (dp_privates *) calloc(1, sizeof(dp_privates));
+       if (!privates) {
+               TRACE_ERROR("[CRITICAL] failed to alloc for private info");
+               goto DOWNLOAD_EXIT;
+       }
+       privates->groups = dp_client_group_slots_new(DP_MAX_GROUP);
+       if (privates->groups == NULL) {
+               TRACE_ERROR("[CRITICAL]  failed to alloc for groups");
+               goto DOWNLOAD_EXIT;
+       }
+       privates->requests = dp_request_slots_new(DP_MAX_REQUEST);
+       if (privates->requests == NULL) {
+               TRACE_ERROR("[CRITICAL]  failed to alloc for requests");
+               goto DOWNLOAD_EXIT;
+       }
+
+       // ready socket ( listen )
+       privates->listen_fd = dp_accept_socket_new();
+       if (privates->listen_fd < 0) {
+               TRACE_ERROR("[CRITICAL] failed to bind SOCKET");
+               goto DOWNLOAD_EXIT;
+       }
+
+#ifdef DP_SUPPORT_DBUS_ACTIVATION
+       TRACE_INFO("SUPPORT DBUS-ACTIVATION");
+       if (__register_dbus_service() < 0) {
+               TRACE_ERROR("[LAUNCH ERROR] __register_dbus_service");
+               goto DOWNLOAD_EXIT;
+       }
+#else
+       TRACE_INFO("Not SUPPORT DBUS-ACTIVATION");
+#endif
+
+       dp_db_open();
+
+       // convert to request type, insert all to privates->requests
+       // timeout of request thread will start these jobs by queue thread
+       // load all list from (queue table)
+       if (dp_db_crashed_list(privates->requests, DP_MAX_REQUEST) > 0) {
+               int i = 0;
+               for (i = 0; i < DP_MAX_REQUEST; i++) {
+                       if (!privates->requests[i].request)
+                               continue;
+                       dp_request *request = privates->requests[i].request;
+                       TRACE_INFO
+                               ("ID [%d] state[%d]", request->id, request->state);
+
+                       // load to memory, Can be started automatically.
+                       if (request->state == DP_STATE_DOWNLOADING ||
+                               request->state == DP_STATE_CONNECTING) {
+                               request->state = DP_STATE_QUEUED;
+                               if (dp_db_set_column
+                                               (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                                               DP_DB_COL_TYPE_INT, &request->state) < 0) {
+                                       TRACE_ERROR("[CHECK SQL]");
+                               }
+                       }
+
+                       if (request->state == DP_STATE_QUEUED) {
+                               int auto_download = dp_db_get_int_column(request->id,
+                                                                       DP_DB_TABLE_REQUEST_INFO,
+                                                                       DP_DB_COL_AUTO_DOWNLOAD);
+                               if (auto_download == 1) {
+                                       // auto retry... defaultly, show notification
+                                       request->auto_notification = 1;
+                                       request->start_time = (int)time(NULL);
+                                       continue;
+                               }
+                               // do not retry this request
+                               request->state = DP_STATE_FAILED;
+                               request->error = DP_ERROR_SYSTEM_DOWN;
+                               if (dp_db_set_column
+                                               (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                                               DP_DB_COL_TYPE_INT, &request->state) < 0) {
+                                       TRACE_ERROR("[CHECK SQL]");
+                               }
+                               if (dp_db_set_column
+                                               (request->id, DP_DB_TABLE_LOG,
+                                               DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
+                                               &request->error) < 0) {
+                                       TRACE_ERROR("[CHECK SQL]");
+                               }
+                       }
+
+                       // if wanna restart, call continue before this line.
+                       // default. update state/error. move to history. unload memory
+                       // remove from memory
+                       dp_request_free(request);
+                       privates->requests[i].request = NULL;
+               }
+       } // query crashed_list
+
+       if (argc != 2 || memcmp(argv[1], "service", 7) != 0) {
+               // in first launch in booting time, not request. terminate by self
+               if (dp_get_request_count(privates->requests) <= 0) {
+                       TRACE_INFO("First Boot, No Request");
+                       goto DOWNLOAD_EXIT;
+               }
+       }
+
+       dp_clear_downloadinginfo_notification();
+
+       if (dp_init_agent() != DP_ERROR_NONE) {
+               TRACE_ERROR("[CRITICAL] failed to init agent");
+               goto DOWNLOAD_EXIT;
+       }
+
+       privates->connection = 0;
+       privates->network_status = DP_NETWORK_TYPE_OFF;
+       if (dp_network_connection_init(privates) < 0) {
+               TRACE_INFO("use instant network check");
+               privates->connection = 0;
+       }
+
+       // libsoup need mainloop.
+       g_main_loop_handle = g_main_loop_new(NULL, 0);
+
+       g_idle_add(__dp_idle_start_service, privates);
+
+       g_main_loop_run(g_main_loop_handle);
+
+DOWNLOAD_EXIT :
+
+       TRACE_INFO("Download-Provider will be terminated.");
+
+       dp_deinit_agent();
+
+       if (privates != NULL) {
+
+               if (privates->connection)
+                       dp_network_connection_destroy(privates->connection);
+
+               if (privates->listen_fd >= 0) {
+                       dp_socket_free(privates->listen_fd);
+                       privates->listen_fd = -1;
+               }
+               dp_request_slots_free(privates->requests, DP_MAX_REQUEST);
+               privates->requests = NULL;
+               dp_client_group_slots_free(privates->groups, DP_MAX_GROUP);
+               privates->groups = NULL;
+               free(privates);
+               privates = NULL;
+       }
+       dp_db_close();
+
+       //send signal to queue thread
+       dp_thread_queue_manager_wake_up();
+
+       // if exit socket file, delete it
+       if (access(DP_IPC, F_OK) == 0) {
+               unlink(DP_IPC);
+       }
+       // delete pid file
+       if (access(DP_LOCK_PID, F_OK) == 0) {
+               close(lock_fd);
+               unlink(DP_LOCK_PID);
+       }
+       exit(EXIT_SUCCESS);
+}
diff --git a/src/download-provider-network.c b/src/download-provider-network.c
new file mode 100755 (executable)
index 0000000..699e8de
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * 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-log.h"
+#include "download-provider-config.h"
+#include "download-provider-pthread.h"
+#include "download-provider-network.h"
+
+extern pthread_mutex_t g_dp_queue_mutex;
+extern pthread_cond_t g_dp_queue_cond;
+
+#if 0
+typedef enum
+{
+    CONNECTION_TYPE_DISCONNECTED = 0,  /**< Disconnected */
+    CONNECTION_TYPE_WIFI = 1,  /**< Wi-Fi type */
+    CONNECTION_TYPE_CELLULAR = 2,  /**< Cellular type */
+    CONNECTION_TYPE_ETHERNET = 3,  /**< Ethernet type */
+    CONNECTION_TYPE_BT = 4,  /**< Bluetooth type */
+} connection_type_e;
+typedef enum
+{
+    CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE = 0,  /**< Out of service */
+    CONNECTION_CELLULAR_STATE_FLIGHT_MODE = 1,  /**< Flight mode */
+    CONNECTION_CELLULAR_STATE_ROAMING_OFF = 2,  /**< Roaming is turned off */
+    CONNECTION_CELLULAR_STATE_CALL_ONLY_AVAILABLE = 3,  /**< Call is only available */
+    CONNECTION_CELLULAR_STATE_AVAILABLE = 4,  /**< Available but not connected yet */
+    CONNECTION_CELLULAR_STATE_CONNECTED = 5,  /**< Connected */
+} connection_cellular_state_e
+typedef enum
+{
+    CONNECTION_WIFI_STATE_DEACTIVATED = 0,  /**< Deactivated state */
+    CONNECTION_WIFI_STATE_DISCONNECTED = 1,  /**< disconnected state */
+    CONNECTION_WIFI_STATE_CONNECTED = 2,  /**< Connected state */
+} connection_wifi_state_e;
+typedef enum
+{
+    CONNECTION_ETHERNET_STATE_DEACTIVATED = 0,  /**< Deactivated state */
+    CONNECTION_ETHERNET_STATE_DISCONNECTED = 1,  /**< disconnected state */
+    CONNECTION_ETHERNET_STATE_CONNECTED = 2,  /**< Connected state */
+} connection_ethernet_state_e;
+typedef enum
+{
+    CONNECTION_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+    CONNECTION_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+    CONNECTION_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory error */
+    CONNECTION_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid Operation */
+    CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED = TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED, /**< Address family not supported */
+    CONNECTION_ERROR_OPERATION_FAILED = TIZEN_ERROR_NETWORK_CLASS|0x0401, /**< Operation failed */
+    CONNECTION_ERROR_ITERATOR_END = TIZEN_ERROR_NETWORK_CLASS|0x0402, /**< End of iteration */
+    CONNECTION_ERROR_NO_CONNECTION = TIZEN_ERROR_NETWORK_CLASS|0x0403, /**< There is no connection */
+    CONNECTION_ERROR_NOW_IN_PROGRESS = TIZEN_ERROR_NOW_IN_PROGRESS, /** Now in progress */
+    CONNECTION_ERROR_ALREADY_EXISTS = TIZEN_ERROR_NETWORK_CLASS|0x0404, /**< Already exists */
+    CONNECTION_ERROR_OPERATION_ABORTED = TIZEN_ERROR_NETWORK_CLASS|0x0405, /**< Operation is aborted */
+    CONNECTION_ERROR_DHCP_FAILED = TIZEN_ERROR_NETWORK_CLASS|0x0406, /**< DHCP failed  */
+    CONNECTION_ERROR_INVALID_KEY = TIZEN_ERROR_NETWORK_CLASS|0x0407, /**< Invalid key  */
+    CONNECTION_ERROR_NO_REPLY = TIZEN_ERROR_NETWORK_CLASS|0x0408, /**< No reply */
+} connection_error_e;
+
+
+static void __print_connection_errorcode_to_string(connection_error_e errorcode)
+{
+       switch(errorcode)
+       {
+               case CONNECTION_ERROR_INVALID_PARAMETER :
+                       TRACE_INFO("CONNECTION_ERROR_INVALID_PARAMETER");
+                       break;
+               case CONNECTION_ERROR_OUT_OF_MEMORY :
+                       TRACE_INFO("CONNECTION_ERROR_OUT_OF_MEMORY");
+                       break;
+               case CONNECTION_ERROR_INVALID_OPERATION :
+                       TRACE_INFO("CONNECTION_ERROR_INVALID_OPERATION");
+                       break;
+               case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED :
+                       TRACE_INFO("CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED");
+                       break;
+               case CONNECTION_ERROR_OPERATION_FAILED :
+                       TRACE_INFO("CONNECTION_ERROR_OPERATION_FAILED");
+                       break;
+               case CONNECTION_ERROR_ITERATOR_END :
+                       TRACE_INFO("CONNECTION_ERROR_ITERATOR_END");
+                       break;
+               case CONNECTION_ERROR_NO_CONNECTION :
+                       TRACE_INFO("CONNECTION_ERROR_NO_CONNECTION");
+                       break;
+               case CONNECTION_ERROR_NOW_IN_PROGRESS :
+                       TRACE_INFO("CONNECTION_ERROR_NOW_IN_PROGRESS");
+                       break;
+               case CONNECTION_ERROR_ALREADY_EXISTS :
+                       TRACE_INFO("CONNECTION_ERROR_ALREADY_EXISTS");
+                       break;
+               case CONNECTION_ERROR_OPERATION_ABORTED :
+                       TRACE_INFO("CONNECTION_ERROR_OPERATION_ABORTED");
+                       break;
+               case CONNECTION_ERROR_DHCP_FAILED :
+                       TRACE_INFO("CONNECTION_ERROR_DHCP_FAILED");
+                       break;
+               case CONNECTION_ERROR_INVALID_KEY :
+                       TRACE_INFO("CONNECTION_ERROR_INVALID_KEY");
+                       break;
+               case CONNECTION_ERROR_NO_REPLY :
+                       TRACE_INFO("CONNECTION_ERROR_NO_REPLY");
+                       break;
+               default :
+                       TRACE_INFO("CONNECTION_ERROR_NONE");
+                       break;
+       }
+}
+#endif
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             check the status in more detail by connection type
+/// @return    dp_network_type
+static dp_network_type __dp_get_network_connection_status(connection_h connection, connection_type_e type)
+{
+       dp_network_type network_type = DP_NETWORK_TYPE_OFF;
+       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");
+               if (wifi_state == CONNECTION_WIFI_STATE_CONNECTED) {
+                       TRACE_INFO("[CONNECTION_WIFI] CONNECTED");
+                       network_type = DP_NETWORK_TYPE_WIFI;
+               } else {
+                       TRACE_INFO("[CONNECTION_WIFI] [%d]", wifi_state);
+               }
+       } 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");
+               if (cellular_state == CONNECTION_CELLULAR_STATE_CONNECTED) {
+                       TRACE_INFO("[CONNECTION_CELLULAR] DATA NETWORK CONNECTED");
+                       network_type = DP_NETWORK_TYPE_DATA_NETWORK;
+               } else {
+                       TRACE_INFO("[CONNECTION_CELLULAR] [%d]", cellular_state);
+               }
+       } else if (type == CONNECTION_TYPE_ETHERNET) {
+               connection_ethernet_state_e ethernet_state;
+               ethernet_state = CONNECTION_ETHERNET_STATE_DISCONNECTED;
+               if (connection_get_ethernet_state
+                       (connection, &ethernet_state) != CONNECTION_ERROR_NONE)
+                       TRACE_ERROR("Failed connection_get_ethernet_state");
+               if (ethernet_state == CONNECTION_ETHERNET_STATE_CONNECTED) {
+                       TRACE_INFO("[CONNECTION_ETHERNET] ETHERNET CONNECTED");
+                       network_type = DP_NETWORK_TYPE_ETHERNET;
+               } else {
+                       TRACE_INFO("[CONNECTION_ETHERNET] [%d]", ethernet_state);
+               }
+       } else {
+               TRACE_INFO("[DISCONNECTED]");
+               network_type = DP_NETWORK_TYPE_OFF;
+       }
+       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)
+{
+       TRACE_INFO("type[%d]", type);
+       dp_privates *privates = (dp_privates*)data;
+       if (!privates) {
+               TRACE_ERROR("[CRITICAL] Invalid data");
+               return ;
+       }
+       CLIENT_MUTEX_LOCK(&(g_dp_queue_mutex));
+       #if 1 // this callback guarantee that already connectdd
+       if (type == CONNECTION_TYPE_WIFI) {
+               TRACE_INFO("[CONNECTION_WIFI] CONNECTED");
+               privates->network_status = DP_NETWORK_TYPE_WIFI;
+       } else if (type == CONNECTION_TYPE_CELLULAR) {
+               TRACE_INFO("[CONNECTION_CELLULAR] DATA NETWORK CONNECTED");
+               privates->network_status = DP_NETWORK_TYPE_DATA_NETWORK;
+       } else if (type == CONNECTION_TYPE_ETHERNET) {
+               TRACE_INFO("[CONNECTION_ETHERNET] ETHERNET CONNECTED");
+               privates->network_status = DP_NETWORK_TYPE_ETHERNET;
+       } else {
+               TRACE_INFO("[DISCONNECTED]");
+               privates->network_status = DP_NETWORK_TYPE_OFF;
+       }
+       if (privates->network_status != DP_NETWORK_TYPE_OFF)
+               pthread_cond_signal(&g_dp_queue_cond);
+       #else
+       privates->network_status =
+               __dp_get_network_connection_status(privates->connection, type);
+       #endif
+       CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex));
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             create connection handle & regist callback
+/// @return    0 : success -1 : failed
+int dp_network_connection_init(dp_privates *privates)
+{
+       int retcode = 0;
+
+       TRACE_INFO("");
+       if (!privates) {
+               TRACE_ERROR("[CRITICAL] Invalid data");
+               return -1;
+       }
+       if ((retcode = connection_create(&privates->connection)) !=
+                       CONNECTION_ERROR_NONE) {
+               TRACE_ERROR("Failed connection_create [%d]", retcode);
+               return -1;
+       }
+       if ((retcode = connection_set_type_changed_cb
+                       (privates->connection, __dp_network_connection_type_changed_cb,
+                               privates)) != CONNECTION_ERROR_NONE) {
+               TRACE_ERROR("Failed connection_set_type_changed_cb [%d]", retcode);
+               connection_destroy(privates->connection);
+               return -1;
+       }
+       connection_type_e type = CONNECTION_TYPE_DISCONNECTED;
+       if ((retcode = connection_get_type(privates->connection, &type)) !=
+                       CONNECTION_ERROR_NONE) {
+               TRACE_ERROR("Failed connection_get_type [%d]", retcode);
+               connection_destroy(privates->connection);
+               return -1;
+       }
+       privates->network_status =
+               __dp_get_network_connection_status(privates->connection, type);
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             destroy connection handle
+void dp_network_connection_destroy(connection_h connection)
+{
+       TRACE_INFO("");
+       connection_unset_type_changed_cb (connection);
+       connection_destroy(connection);
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             check network status using connection API
+/// @todo              the standard of enabled networking can be changed later
+/// @return    Network type
+dp_network_type dp_get_network_connection_instant_status()
+{
+       int retcode = 0;
+       connection_h network_handle = NULL;
+       dp_network_type network_type = DP_NETWORK_TYPE_OFF;
+       if ((retcode = connection_create(&network_handle)) !=
+                       CONNECTION_ERROR_NONE) {
+               TRACE_ERROR("Failed connection_create [%d]", retcode);
+               return DP_NETWORK_TYPE_OFF;
+       }
+
+       connection_type_e type = CONNECTION_TYPE_DISCONNECTED;
+       if ((retcode = connection_get_type(network_handle, &type)) !=
+                       CONNECTION_ERROR_NONE) {
+               TRACE_ERROR("Failed connection_get_type [%d]", retcode);
+               connection_destroy(network_handle);
+               return DP_NETWORK_TYPE_OFF;
+       }
+       network_type =
+               __dp_get_network_connection_status(network_handle, type);
+
+       if (connection_destroy(network_handle) != CONNECTION_ERROR_NONE)
+               TRACE_ERROR("Failed connection_destroy");
+
+       return network_type;
+}
diff --git a/src/download-provider-notification.c b/src/download-provider-notification.c
new file mode 100755 (executable)
index 0000000..f04b010
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * 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 <time.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+#include "bundle.h"
+#include "notification.h"
+#include "appsvc.h"
+
+#include "download-provider-notification.h"
+#include "download-provider-request.h"
+#include "download-provider-db.h"
+#include "download-provider-log.h"
+
+#include <libintl.h>
+#define S_(s) dgettext("sys_string", s)
+
+#define DP_NOTIFICATION_ICON_PATH IMAGE_DIR"/Q02_Notification_Download_failed.png"
+/* This should be same value of SERVICE_OPERATION_DOWNLOAD_NOTIFICATION from download.h */
+#define DP_DOWNLOAD_NOTI_OPERATION "http://tizen.org/appcontrol/operation/download_notification"
+
+static void __print_app_error_message(int ret)
+{
+       switch (ret) {
+       case APPSVC_RET_OK:
+               TRACE_INFO("APPSVC_RET_OK");
+               break;
+       case APPSVC_RET_ELAUNCH:
+               TRACE_ERROR("APPSVC_RET_ELAUNCH");
+               break;
+       case APPSVC_RET_ENOMATCH:
+               TRACE_ERROR("APPSVC_RET_ENOMATCH");
+               break;
+       case APPSVC_RET_EINVAL:
+               TRACE_ERROR("APPSVC_RET_EINVAL");
+               break;
+       case APPSVC_RET_ERROR:
+               TRACE_ERROR("APPSVC_RET_ERROR");
+               break;
+       }
+}
+
+static void __print_notification_error_message(int ret)
+{
+       switch (ret) {
+       case NOTIFICATION_ERROR_INVALID_DATA:
+               TRACE_ERROR("NOTIFICATION_ERROR_INVALID_DATA");
+               break;
+       case NOTIFICATION_ERROR_NO_MEMORY:
+               TRACE_ERROR("NOTIFICATION_ERROR_NO_MEMORY");
+               break;
+       case NOTIFICATION_ERROR_FROM_DB:
+               TRACE_ERROR("NOTIFICATION_ERROR_FROM_DB");
+               break;
+       case NOTIFICATION_ERROR_ALREADY_EXIST_ID:
+               TRACE_ERROR("NOTIFICATION_ERROR_ALREADY_EXIST_ID");
+               break;
+       case NOTIFICATION_ERROR_FROM_DBUS:
+               TRACE_ERROR("NOTIFICATION_ERROR_FROM_DBUS");
+               break;
+       case NOTIFICATION_ERROR_NOT_EXIST_ID:
+               TRACE_ERROR("NOTIFICATION_ERROR_NOT_EXIST_ID");
+               break;
+       default:
+               TRACE_ERROR("Unknown error");
+               break;
+       }
+}
+
+static char *__get_string_status(dp_state_type state)
+{
+       char *message = NULL;
+       switch (state) {
+       case DP_STATE_COMPLETED:
+               //message = S_("IDS_COM_POP_SUCCESS");
+               message = "Completed";
+               break;
+       case DP_STATE_CANCELED:
+               //message = S_("IDS_COM_POP_CANCELLED");
+               message = "Canceled";
+               break;
+       case DP_STATE_FAILED:
+               //message = S_("IDS_COM_POP_FAILED");
+               message = "Failed";
+               break;
+       default:
+               break;
+       }
+       return message;
+}
+
+int dp_set_downloadinginfo_notification(int id, char *packagename)
+{
+       notification_h noti_handle = NULL;
+       notification_error_e err = NOTIFICATION_ERROR_NONE;
+       int privId = 0;
+       bundle *b = NULL;
+
+#ifdef NOTI_NEW_VERSION_API
+       noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING);
+#else
+       noti_handle = notification_new(NOTIFICATION_TYPE_ONGOING,
+               NOTIFICATION_GROUP_ID_NONE, NOTIFICATION_PRIV_ID_NONE);
+#endif
+
+       if (!noti_handle) {
+               TRACE_ERROR("[FAIL] create notification handle");
+               return -1;
+       }
+
+       char *content_name =
+               dp_db_get_text_column
+                       (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME);
+
+       if (content_name == NULL)
+               content_name = strdup("No Name");
+
+       err = notification_set_text(noti_handle,
+                       NOTIFICATION_TEXT_TYPE_TITLE, content_name, NULL,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
+       if (content_name)
+               free(content_name);
+
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set title [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       err = notification_set_image(noti_handle,
+                       NOTIFICATION_IMAGE_TYPE_ICON, DP_NOTIFICATION_ICON_PATH);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set icon [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       b = bundle_create();
+       if (!b) {
+               TRACE_ERROR("[FAIL] create bundle");
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       if (packagename &&
+               appsvc_set_pkgname(b, packagename) != APPSVC_RET_OK) {
+               TRACE_ERROR("[FAIL] set pkg name");
+               bundle_free(b);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       if (appsvc_set_operation(b, DP_DOWNLOAD_NOTI_OPERATION) !=
+               APPSVC_RET_OK) {
+               TRACE_ERROR("[FAIL] set noti operation");
+               bundle_free(b);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       char *extra_key =
+               dp_db_get_text_column(id, DP_DB_TABLE_NOTIFICATION,
+                       DP_DB_COL_EXTRA_KEY);
+       char *extra_value =
+               dp_db_get_text_column(id, DP_DB_TABLE_NOTIFICATION,
+                       DP_DB_COL_EXTRA_VALUE);
+
+       if (extra_key && extra_value) {
+               if (appsvc_add_data(b, extra_key, extra_value) != APPSVC_RET_OK) {
+                       TRACE_ERROR("[FAIL] set add data");
+                       free(extra_key);
+                       free(extra_value);
+                       bundle_free(b);
+                       notification_free(noti_handle);
+                       return -1;
+               }
+       }
+       if (extra_key)
+               free(extra_key);
+       if (extra_value)
+               free(extra_value);
+
+       err = notification_set_execute_option(noti_handle,
+                       NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b);
+
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set execute option [%d]", err);
+               bundle_free(b);
+               notification_free(noti_handle);
+               return -1;
+       }
+       bundle_free(b);
+
+       err = notification_set_property(noti_handle,
+                       NOTIFICATION_PROP_DISABLE_TICKERNOTI);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set property [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       err = notification_insert(noti_handle, &privId);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set insert [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       TRACE_INFO("m_noti_id [%d]", privId);
+       notification_free(noti_handle);
+       return privId;
+}
+
+int dp_set_downloadedinfo_notification(int priv_id, int id, char *packagename, dp_state_type state)
+{
+       notification_h noti_handle = NULL;
+       notification_error_e err = NOTIFICATION_ERROR_NONE;
+       int privId = 0;
+       bundle *b = NULL;
+
+       if (priv_id >= 0) {
+               err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_ONGOING,
+                               priv_id);
+               if (err != NOTIFICATION_ERROR_NONE) {
+                       TRACE_ERROR("[FAIL] delete notification handle, err", err);
+               }
+       }
+
+#ifdef NOTI_NEW_VERSION_API
+       noti_handle = notification_create(NOTIFICATION_TYPE_NOTI);
+#else
+       noti_handle = notification_new(NOTIFICATION_TYPE_NOTI,
+               NOTIFICATION_GROUP_ID_NONE, NOTIFICATION_PRIV_ID_NONE);
+#endif
+
+       if (!noti_handle) {
+               TRACE_ERROR("[FAIL] create notification handle");
+               return -1;
+       }
+
+       char *content_name =
+               dp_db_get_text_column
+                       (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME);
+
+       if (content_name == NULL)
+               content_name = strdup("No Name");
+
+       err = notification_set_text(noti_handle,
+                       NOTIFICATION_TEXT_TYPE_TITLE, content_name,
+                       NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+       if (content_name)
+               free(content_name);
+
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set title [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       err = notification_set_text(noti_handle,
+                       NOTIFICATION_TEXT_TYPE_CONTENT,
+                       __get_string_status(state), NULL,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set text [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+       time_t tt = time(NULL);
+
+       err = notification_set_time(noti_handle, tt);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set time [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       b = bundle_create();
+       if (!b) {
+               TRACE_ERROR("[FAIL] create bundle");
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       if (state == DP_STATE_COMPLETED) {
+               if (appsvc_set_operation(b, APPSVC_OPERATION_VIEW) != APPSVC_RET_OK) {
+                       TRACE_ERROR("[FAIL] appsvc set operation");
+                       bundle_free(b);
+                       notification_free(noti_handle);
+                       return -1;
+               }
+               
+               char *savedpath =
+                       dp_db_get_text_column
+                               (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_SAVED_PATH);
+               if (savedpath && appsvc_set_uri(b, savedpath) !=
+                               APPSVC_RET_OK) {
+                       TRACE_ERROR("[FAIL] appsvc set uri");
+                       free(savedpath);
+                       bundle_free(b);
+                       notification_free(noti_handle);
+                       return -1;
+               }
+               if (savedpath)
+                       free(savedpath);
+               err = notification_set_execute_option(noti_handle,
+                               NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b);
+       } else if (state == DP_STATE_CANCELED || state == DP_STATE_FAILED) {
+               if (appsvc_set_operation(b, DP_DOWNLOAD_NOTI_OPERATION) !=
+                       APPSVC_RET_OK) {
+                       TRACE_ERROR("[FAIL] set noti operation [%d]", err);
+                       bundle_free(b);
+                       notification_free(noti_handle);
+                       return -1;
+               }
+
+               char *extra_key =
+                       dp_db_get_text_column(id, DP_DB_TABLE_NOTIFICATION,
+                               DP_DB_COL_EXTRA_KEY);
+               char *extra_value =
+                       dp_db_get_text_column(id, DP_DB_TABLE_NOTIFICATION,
+                               DP_DB_COL_EXTRA_VALUE);
+               if (extra_key && extra_value) {
+                       if (appsvc_add_data(b, extra_key, extra_value) !=
+                               APPSVC_RET_OK) {
+                               TRACE_ERROR("[FAIL] set add data");
+                               free(extra_key);
+                               free(extra_value);
+                               bundle_free(b);
+                               notification_free(noti_handle);
+                               return -1;
+                       }
+               }
+               if (extra_key)
+                       free(extra_key);
+               if (extra_value)
+                       free(extra_value);
+
+               if (packagename &&
+                       appsvc_set_pkgname(b, packagename) !=
+                       APPSVC_RET_OK) {
+                       TRACE_ERROR("[FAIL] set pkg name");
+                       bundle_free(b);
+                       notification_free(noti_handle);
+                       return -1;
+               }
+               err = notification_set_execute_option(noti_handle,
+                               NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b);
+       } else {
+               TRACE_ERROR("[CRITICAL] invalid state");
+               bundle_free(b);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set time [%d]", err);
+               notification_free(noti_handle);
+               bundle_free(b);
+               return -1;
+       }
+
+       bundle_free(b);
+
+       err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON,
+                       DP_NOTIFICATION_ICON_PATH);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set icon [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       err = notification_set_property(noti_handle,
+                       NOTIFICATION_PROP_DISABLE_TICKERNOTI);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set property [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       err = notification_insert(noti_handle, &privId);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] set insert [%d]", err);
+               notification_free(noti_handle);
+               return -1;
+       }
+
+       TRACE_INFO("m_noti_id [%d]", privId);
+       notification_free(noti_handle);
+       return privId;
+}
+
+void dp_update_downloadinginfo_notification(int priv_id, double received_size, double file_size)
+{
+       notification_error_e err = NOTIFICATION_ERROR_NONE;
+       if (priv_id < 0) {
+               TRACE_ERROR("[FAIL] Invalid priv_id[%d]", priv_id);
+               return;
+       }
+
+       if (file_size > 0) {
+               double progress;
+               progress = received_size / file_size;
+               err = notification_update_progress(NULL, priv_id, progress);
+               if (err != NOTIFICATION_ERROR_NONE)
+                       TRACE_ERROR("[FAIL] update noti progress[%d]", err);
+       } else {
+               err = notification_update_size(NULL, priv_id, received_size);
+               if (err != NOTIFICATION_ERROR_NONE)
+                       TRACE_ERROR("[FAIL]  update noti progress[%d]", err);
+       }
+}
+
+void dp_clear_downloadinginfo_notification()
+{
+       notification_error_e err = NOTIFICATION_ERROR_NONE;
+       err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_ONGOING);
+       if (err != NOTIFICATION_ERROR_NONE) {
+               TRACE_ERROR("[FAIL] clear noti [%d]", err);
+       }
+       return;
+}
diff --git a/src/download-provider-pid.c b/src/download-provider-pid.c
new file mode 100755 (executable)
index 0000000..bd1a223
--- /dev/null
@@ -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.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief check whether daemon is alive
+/// @warning lockfd should be managed without close()
+/// @param the patch for locking the file
+int dp_lock_pid(char *path)
+{
+       int lockfd = -1;
+       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 lockfd;
+}
diff --git a/src/download-provider-request.c b/src/download-provider-request.c
new file mode 100755 (executable)
index 0000000..869a9e5
--- /dev/null
@@ -0,0 +1,720 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include "download-provider.h"
+#include "download-provider-log.h"
+
+#include "download-provider-slots.h"
+#include "download-provider-socket.h"
+#include "download-provider-db.h"
+#include "download-provider-pthread.h"
+
+
+///////// below functions are called by main thread of thread-request.c
+
+
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             create unique id as integer type
+/// @return    unique id combined local time and the special calculation
+static 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_INFO("ID : %d", uniquetime);
+       } while (last_uniquetime == uniquetime);
+       last_uniquetime = uniquetime;   // store
+       return uniquetime;
+}
+
+char *dp_print_state(dp_state_type 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_PAUSE_REQUESTED :
+                       return "PAUSE_REQUESTED";
+               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(dp_error_type 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_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_ID_NOT_FOUND :
+                       return "ID_NOT_FOUND";
+               default :
+                       break;
+       }
+       return "UNKNOWN";
+}
+
+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;
+}
+
+// check param
+// create new slot
+// fill info to new slot
+// make new id
+// save info to QUEUE(DB)
+dp_error_type dp_request_create(int id, dp_client_group *group, dp_request **empty_slot)
+{
+       if (id != -1) {
+               TRACE_ERROR("[CHECK PROTOCOL] ID not -1");
+               return DP_ERROR_INVALID_STATE;
+       }
+       if (!group || !empty_slot) {
+               TRACE_ERROR("[CHECK INTERNAL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       // New allocation Slot
+       dp_request *new_request = dp_request_new();
+       if (!new_request) {
+               TRACE_STRERROR("[CHECK MEMORY][%d]", id);
+               return DP_ERROR_OUT_OF_MEMORY;
+       }
+
+       new_request->id = __get_download_request_id();
+       new_request->group = group;
+       if (group->pkgname && strlen(group->pkgname) > 1)
+               new_request->packagename = dp_strdup(group->pkgname);
+       new_request->credential = group->credential;
+       if (new_request->packagename == NULL) {
+               dp_request_free(new_request);
+               TRACE_ERROR("[ERROR][%d] OUT_OF_MEMORY [PACKAGENAME]", id);
+               return DP_ERROR_OUT_OF_MEMORY;
+       }
+       new_request->state = DP_STATE_READY;
+       new_request->error = DP_ERROR_NONE;
+       if (dp_db_insert_column
+                       (new_request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                       DP_DB_COL_TYPE_INT, &new_request->state) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               dp_request_free(new_request);
+               return DP_ERROR_OUT_OF_MEMORY;
+       }
+       if (dp_db_set_column
+                       (new_request->id, DP_DB_TABLE_LOG, DP_DB_COL_PACKAGENAME,
+                       DP_DB_COL_TYPE_TEXT, new_request->packagename) < 0)
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+       if (dp_db_update_date
+                       (new_request->id, DP_DB_TABLE_LOG, DP_DB_COL_CREATE_TIME) < 0)
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+
+       new_request->create_time = (int)time(NULL);
+
+       *empty_slot = new_request;
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_url(int id, dp_request *request, char *url)
+{
+       int length = 0;
+       if (!url || (length = strlen(url)) <= 1)
+               return DP_ERROR_INVALID_URL;
+
+       if (request != NULL) {
+               if (request->state == DP_STATE_CONNECTING ||
+                       request->state == DP_STATE_DOWNLOADING ||
+                       request->state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       } else {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+               // check again from logging table
+               if (state == DP_STATE_CONNECTING ||
+                       state == DP_STATE_DOWNLOADING ||
+                       state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       }
+
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_URL,
+                       DP_DB_COL_TYPE_TEXT, url) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_destination(int id, dp_request *request, char *dest)
+{
+       int length = 0;
+       if (!dest || (length = strlen(dest)) <= 1)
+               return DP_ERROR_INVALID_DESTINATION;
+
+       if (request != NULL) {
+               if (request->state == DP_STATE_CONNECTING ||
+                       request->state == DP_STATE_DOWNLOADING ||
+                       request->state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       } else {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+               // check again from logging table
+               if (state == DP_STATE_CONNECTING ||
+                       state == DP_STATE_DOWNLOADING ||
+                       state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       }
+
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_DESTINATION,
+                       DP_DB_COL_TYPE_TEXT, dest) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_filename(int id, dp_request *request, char *filename)
+{
+       int length = 0;
+       if (!filename || (length = strlen(filename)) <= 1)
+               return DP_ERROR_INVALID_PARAMETER;
+
+       if (request != NULL) {
+               if (request->state == DP_STATE_CONNECTING ||
+                       request->state == DP_STATE_DOWNLOADING ||
+                       request->state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       } else {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+               // check again from logging table
+               if (state == DP_STATE_CONNECTING ||
+                       state == DP_STATE_DOWNLOADING ||
+                       state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       }
+
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_FILENAME,
+                       DP_DB_COL_TYPE_TEXT, filename) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+
+       TRACE_INFO("ID [%d] Filename[%s]", id, filename);
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_notification(int id, dp_request *request, unsigned enable)
+{
+       if (request != NULL) {
+               if (request->state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       } else {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+               // check again from logging table
+               if (state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       }
+
+       // update queue DB
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_NOTIFICATION,
+                       DP_DB_COL_NOTIFICATION_ENABLE, DP_DB_COL_TYPE_INT,
+                       &enable) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       // update memory
+       if (request)
+               request->auto_notification = enable;
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_auto_download(int id, dp_request *request, unsigned enable)
+{
+       if (request != NULL) {
+               if (request->state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       } else {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+               // check again from logging table
+               if (state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       }
+
+       // update queue DB
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_AUTO_DOWNLOAD,
+                       DP_DB_COL_TYPE_INT, &enable) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_state_event(int id, dp_request *request, unsigned enable)
+{
+       if (request == NULL) {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+       }
+
+       // update queue DB
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_STATE_EVENT,
+                       DP_DB_COL_TYPE_INT, &enable) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       // update memory
+       if (request)
+               request->state_cb = enable;
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_progress_event(int id, dp_request *request, unsigned enable)
+{
+       if (request == NULL) {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+       }
+
+       // update queue DB
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_PROGRESS_EVENT,
+                       DP_DB_COL_TYPE_INT, &enable) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       // update memory
+       if (request)
+               request->progress_cb = enable;
+       return DP_ERROR_NONE;
+}
+
+dp_error_type dp_request_set_network_type(int id, dp_request *request, int type)
+{
+       if (request != NULL) {
+               if (request->state == DP_STATE_CONNECTING ||
+                       request->state == DP_STATE_DOWNLOADING ||
+                       request->state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       } else {
+               // check id in logging table.
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       return DP_ERROR_ID_NOT_FOUND;
+               }
+               // check again from logging table
+               if (state == DP_STATE_CONNECTING ||
+                       state == DP_STATE_DOWNLOADING ||
+                       state == DP_STATE_COMPLETED) {
+                       TRACE_ERROR("[ERROR][%d] now[%s]", id, dp_print_state(state));
+                       return DP_ERROR_INVALID_STATE;
+               }
+       }
+
+       // update queue DB
+       if (dp_db_replace_column
+                       (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_NETWORK_TYPE,
+                       DP_DB_COL_TYPE_INT, &type) < 0) {
+               TRACE_ERROR("[CHECK SQL][%d]", id);
+               return DP_ERROR_IO_ERROR;
+       }
+       // update memory
+       if (request)
+               request->network_type = type;
+       return DP_ERROR_NONE;
+}
+
+char *dp_request_get_url(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *url = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       url = dp_db_get_text_column
+                               (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_URL);
+       if (url == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return url;
+}
+
+char *dp_request_get_destination(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *dest = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       dest = dp_db_get_text_column
+                               (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_DESTINATION);
+       if (dest == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return dest;
+}
+
+char *dp_request_get_filename(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *filename = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       filename = dp_db_get_text_column
+                               (id, DP_DB_TABLE_REQUEST_INFO, DP_DB_COL_FILENAME);
+       if (filename == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return filename;
+}
+
+char *dp_request_get_contentname(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *content = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       content = dp_db_get_text_column
+                               (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME);
+       if (content == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return content;
+}
+
+char *dp_request_get_etag(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *etag = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       etag = dp_db_get_text_column
+                               (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_ETAG);
+       if (etag == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return etag;
+}
+
+char *dp_request_get_savedpath(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *savedpath = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       savedpath = dp_db_get_text_column
+                               (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_SAVED_PATH);
+       if (savedpath == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return savedpath;
+}
+
+char *dp_request_get_tmpsavedpath(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *tmppath = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       tmppath = dp_db_get_text_column
+                               (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_TMP_SAVED_PATH);
+       if (tmppath == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return tmppath;
+}
+
+char *dp_request_get_mimetype(int id, dp_request *request, dp_error_type *errorcode)
+{
+       char *mimetype = NULL;
+
+       if (request == NULL) {
+               dp_state_type state =
+                       dp_db_get_int_column(id, DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+
+               if (state <= DP_STATE_NONE) {
+                       TRACE_ERROR("[ERROR][%d] state[%s]", id, dp_print_state(state));
+                       *errorcode = DP_ERROR_ID_NOT_FOUND;
+                       return NULL;
+               }
+       }
+       mimetype = dp_db_get_text_column
+                               (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_MIMETYPE);
+       if (mimetype == NULL) {
+               *errorcode = DP_ERROR_NO_DATA;
+               return NULL;
+       }
+       return mimetype;
+}
+
+dp_request *dp_request_load_from_log(int id, dp_error_type *errorcode)
+{
+       dp_request *request = NULL;
+
+       request = dp_db_load_logging_request(id);
+       if (request == NULL) {
+               *errorcode = DP_ERROR_ID_NOT_FOUND;
+               return NULL;
+       }
+       if (request->state == DP_STATE_COMPLETED) {
+               TRACE_ERROR
+                       ("[ERROR][%d] now[%s]", id, dp_print_state(request->state));
+               *errorcode =  DP_ERROR_INVALID_STATE;
+               dp_request_free(request);
+               return NULL;
+       }
+       return request;
+}
+
diff --git a/src/download-provider-slots.c b/src/download-provider-slots.c
new file mode 100755 (executable)
index 0000000..208f993
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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 <stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include "download-provider.h"
+#include "download-provider-log.h"
+#include "download-provider-pthread.h"
+
+#include "download-provider-slots.h"
+#include "download-provider-socket.h"
+
+dp_group_slots *dp_client_group_slots_new(int size)
+{
+       TRACE_INFO("");
+       dp_group_slots *slots = NULL;
+       if (size <= 0)
+               return NULL;
+       slots = (dp_group_slots *) calloc(size,
+                       sizeof(dp_group_slots));
+       return slots;
+}
+
+dp_request_slots *dp_request_slots_new(int size)
+{
+       TRACE_INFO("");
+       dp_request_slots *slots = NULL;
+       if (size <= 0)
+               return NULL;
+       slots = (dp_request_slots *) calloc(size,
+                       sizeof(dp_request_slots));
+       return slots;
+}
+
+void dp_request_init(dp_request *request)
+{
+       TRACE_INFO("");
+       if (!request)
+               return ;
+
+       request->id = -1;
+       request->agent_id = -1;
+       request->create_time = 0;
+       request->start_time = 0;
+       request->pause_time = 0;
+       request->stop_time = 0;
+       request->state = DP_STATE_NONE;
+       request->error = DP_ERROR_NONE;
+       request->state_cb = 0;
+       request->progress_cb = 0;
+       request->progress_lasttime = 0;
+       request->received_size = 0;
+       request->file_size = 0;
+       request->network_type = DP_NETWORK_TYPE_ALL;
+       request->startcount = 0;
+       request->auto_notification = 0;
+       request->noti_priv_id = -1;
+       request->packagename = NULL;
+       request->group = NULL;
+}
+
+dp_request *dp_request_new()
+{
+       dp_request *request = NULL;
+       request = (dp_request *) calloc(1,
+                       sizeof(dp_request));
+       if (!request)
+               return NULL;
+       CLIENT_MUTEX_INIT(&(request->mutex), NULL);
+       dp_request_init(request);
+       return request;
+}
+
+int dp_request_free(dp_request *request)
+{
+       TRACE_INFO("");
+
+       if (!request)
+               return -1;
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+       if (request->packagename)
+               free(request->packagename);
+       dp_request_init(request);
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+       CLIENT_MUTEX_DESTROY(&(request->mutex));
+       free(request);
+       return 0;
+}
+
+int dp_client_group_free(dp_client_group *group)
+{
+       TRACE_INFO("");
+       if (!group)
+               return -1;
+
+       if (group->cmd_socket > 0)
+               dp_socket_free(group->cmd_socket);
+       group->cmd_socket = -1;
+       if (group->event_socket > 0)
+               dp_socket_free(group->event_socket);
+       group->event_socket = -1;
+       group->queued_count = 0;
+       if (group->pkgname)
+               free(group->pkgname);
+       free(group);
+       group = NULL;
+       return 0;
+}
+
+int dp_client_group_slots_free(dp_group_slots *slots, int size)
+{
+       TRACE_INFO("");
+       int i = 0;
+       if (slots) {
+               for (; i < size; i++) {
+                       if (slots->group)
+                               dp_client_group_free(slots->group);
+                       slots->group = NULL;
+               }
+               free(slots);
+       }
+       slots = NULL;
+       return 0;
+}
+
+int dp_request_slots_free(dp_request_slots *slots, int size)
+{
+       TRACE_INFO("");
+       int i = 0;
+       if (slots) {
+               for (; i < size; i++) {
+                       if (slots->request)
+                               dp_request_free(slots->request);
+                       slots->request = NULL;
+               }
+               free(slots);
+       }
+       slots = NULL;
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief     return count of requests in slot
+int dp_get_request_count(dp_request_slots *slots)
+{
+       int i = 0;
+       int count = 0;
+
+       if (!slots)
+               return -1;
+
+       for (i = 0; i < DP_MAX_REQUEST; i++)
+               if (slots[i].request)
+                       count++;
+       return count;
+}
diff --git a/src/download-provider-socket.c b/src/download-provider-socket.c
new file mode 100755 (executable)
index 0000000..0899ffe
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <pthread.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+
+#include "download-provider.h"
+#include "download-provider-log.h"
+#include "download-provider-socket.h"
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief write the error to socket
+/// @return if success, return 0
+int dp_ipc_send_errorcode(int fd, dp_error_type errorcode)
+{
+       if (fd < 0) {
+               TRACE_ERROR("[ERROR] CHECK FD[%d]", fd);
+               return -1;
+       }
+
+       if (fd >= 0 && write(fd, &errorcode, sizeof(dp_error_type)) <= 0) {
+               TRACE_STRERROR("[ERROR] write FD[%d]", fd);
+               return -1;
+       }
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief write the progressinfo to socket
+/// @return if success, return 0
+int dp_ipc_send_event(int fd, int id, dp_state_type state,
+       dp_error_type errorcode, unsigned long long received_size)
+{
+       if (fd < 0) {
+               TRACE_ERROR("[ERROR][%d] CHECK FD[%d]", id, fd);
+               return -1;
+       }
+
+       dp_event_info eventinfo;
+       eventinfo.id = id;
+       eventinfo.state = state;
+       eventinfo.err = errorcode;
+       eventinfo.received_size = received_size;
+
+       // write
+       if (fd >= 0 && write(fd, &eventinfo, sizeof(dp_event_info)) <= 0) {
+               TRACE_STRERROR("[ERROR][%d] write FD[%d]", id, fd);
+               return -1;
+       }
+       return 0;
+}
+
+// keep the order/ unsigned , str
+char *dp_ipc_read_string(int fd)
+{
+       unsigned length = 0;
+       char *str = NULL;
+
+       if (fd < 0) {
+               TRACE_ERROR("[ERROR] CHECK FD[%d]", fd);
+               return NULL;
+       }
+
+       // read flexible URL from client.
+       if (read(fd, &length, sizeof(unsigned)) < 0) {
+               TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length);
+               return NULL;
+       }
+       if (length < 1 || length > DP_MAX_URL_LEN) {
+               TRACE_ERROR("[STRING LEGNTH] [%d]", length);
+               return NULL;
+       }
+       str = (char *)calloc((length + 1), sizeof(char));
+       if (read(fd, str, length * sizeof(char)) < 0) {
+               TRACE_STRERROR("[ERROR] read FD[%d]", fd);
+               free(str);
+               str = NULL;
+               return NULL;
+       }
+       str[length] = '\0';
+       return str;
+}
+
+// keep the order/ unsigned , str
+int dp_ipc_send_string(int fd, const char *str)
+{
+       unsigned length = 0;
+
+       if (fd < 0) {
+               TRACE_ERROR("[ERROR] CHECK FD[%d]", fd);
+               return -1;
+       }
+       if (!str) {
+               TRACE_ERROR("[ERROR] CHECK STRING FD[%d]", fd);
+               return -1;
+       }
+
+       length = strlen(str);
+       if (length < 1) {
+               TRACE_ERROR("[ERROR] CHECK LENGTH FD[%d]", fd);
+               return -1;
+       }
+       if (fd >= 0 && write(fd, &length, sizeof(unsigned)) <= 0) {
+               TRACE_STRERROR("[ERROR] read FD[%d] length[%d]", fd, length);
+               return -1;
+       }
+       if (fd >= 0 && write(fd, str, length * sizeof(char)) <= 0) {
+               TRACE_STRERROR("[ERROR] write FD[%d]", fd);
+               return -1;
+       }
+       return 0;
+}
+
+int dp_ipc_send_custom_type(int fd, void *value, size_t type_size)
+{
+       if (fd < 0) {
+               TRACE_ERROR("[ERROR] CHECK FD[%d]", fd);
+               return -1;
+       }
+       if (!value) {
+               TRACE_ERROR("[ERROR] CHECK VALUE FD[%d]", fd);
+               return -1;
+       }
+       if (fd >= 0 && write(fd, value, type_size) <= 0) {
+               TRACE_STRERROR("[ERROR] write FD[%d]", fd);
+               return -1;
+       }
+       return 0;
+}
+
+int dp_ipc_read_custom_type(int fd, void *value, size_t type_size)
+{
+       if (fd < 0) {
+               TRACE_ERROR("[ERROR] CHECK FD[%d]", fd);
+               return -1;
+       }
+
+       if (read(fd, value, type_size) < 0) {
+               TRACE_STRERROR("[ERROR] read FD[%d]", fd);
+               return -1;
+       }
+       return 0;
+}
+
+int dp_accept_socket_new()
+{
+       int sockfd = -1;
+       struct sockaddr_un listenaddr;
+
+       if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+               TRACE_STRERROR("failed to create socket");
+               return -1;
+       }
+
+       bzero(&listenaddr, sizeof(listenaddr));
+       listenaddr.sun_family = AF_UNIX;
+       strcpy(listenaddr.sun_path, DP_IPC);
+
+       if (bind(sockfd, (struct sockaddr *)&listenaddr, sizeof listenaddr) !=
+               0) {
+               TRACE_STRERROR("[CRITICAL] bind");
+               close(sockfd);
+               return -1;
+       }
+
+       if (chmod(listenaddr.sun_path, 0777) < 0) {
+               TRACE_STRERROR("[CRITICAL] chmod");
+               close(sockfd);
+               return -1;
+       }
+
+       // need 3 socket per a group
+       if (listen(sockfd, DP_MAX_GROUP * 3) != 0) {
+               TRACE_STRERROR("[CRITICAL] listen");
+               close(sockfd);
+               return -1;
+       }
+       return sockfd;
+}
+
+int dp_socket_free(int sockfd)
+{
+       if (sockfd < 0)
+               return -1;
+       shutdown(sockfd, 0);
+       close(sockfd);
+       return 0;
+}
diff --git a/src/download-provider-thread-queue.c b/src/download-provider-thread-queue.c
new file mode 100755 (executable)
index 0000000..746d512
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <signal.h>
+
+#include "download-provider.h"
+#include "download-provider-log.h"
+#include "download-provider-config.h"
+#include "download-provider-slots.h"
+#include "download-provider-socket.h"
+#include "download-provider-pthread.h"
+#include "download-provider-db.h"
+#include "download-provider-queue.h"
+#include "download-provider-network.h"
+#include "download-provider-da-interface.h"
+
+void dp_terminate(int signo);
+
+pthread_mutex_t g_dp_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t g_dp_queue_cond = PTHREAD_COND_INITIALIZER;
+
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             check network status is matched with the type setted by user
+/// @return    matched : 0 mispatch : -1
+static int __is_matched_network(dp_network_type now_state, dp_network_type setted_state)
+{
+       if (now_state == setted_state
+               || now_state == DP_NETWORK_TYPE_ETHERNET
+               || setted_state == DP_NETWORK_TYPE_ALL)
+               return 0;
+       #if 0
+       if (setted_state == DP_NETWORK_TYPE_ALL
+               || setted_state == DP_NETWORK_TYPE_DATA_NETWORK
+               || now_state == DP_NETWORK_TYPE_WIFI
+               || now_state == DP_NETWORK_TYPE_ETHERNET
+               || (setted_state == DP_NETWORK_TYPE_WIFI
+                       && (now_state == DP_NETWORK_TYPE_WIFI
+                               || now_state == DP_NETWORK_TYPE_ETHERNET))
+               )
+               return 0;
+       #endif
+       return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             the count of slot downloading currently
+static unsigned __get_active_count(dp_request_slots *requests)
+{
+       unsigned count = 0;
+       unsigned i = 0;
+
+       if (!requests)
+               return 0;
+
+       for (i = 0; i < DP_MAX_REQUEST; i++) {
+               if (requests[i].request) {
+                       if (requests[i].request->state == DP_STATE_CONNECTING ||
+                               requests[i].request->state == DP_STATE_DOWNLOADING)
+                               count++;
+               }
+       }
+       return count;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief             index of slot which last time is oldest
+static int __get_oldest_request_with_network(dp_request_slots *requests, dp_state_type state, dp_network_type now_state)
+{
+       int i = 0;
+       int oldest_time = (int)time(NULL);
+       oldest_time++; // most last time
+       int oldest_index = -1;
+
+       if (!requests)
+               return -1;
+
+       for (i = 0; i < DP_MAX_REQUEST; i++) {
+               if (requests[i].request) {
+                       if (requests[i].request->state == state &&
+                               requests[i].request->start_time > 0 &&
+                               requests[i].request->start_time < oldest_time &&
+                               __is_matched_network
+                                       (now_state, requests[i].request->network_type)
+                               == 0) {
+                               oldest_time = requests[i].request->start_time;
+                               oldest_index = i;
+                       }
+               }
+       }
+       return oldest_index;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief THREAD function for calling da_start_download_with_extension.
+/// @warning da_start_download_with_extension can take long time
+/// @param the pointer of memory slot allocated for this request.
+/// @todo simplify da_start_download_with_extension
+static void *__request_download_start_agent(void *args)
+{
+       dp_error_type errcode = DP_ERROR_NONE;
+
+       dp_request *request = (dp_request *) args;
+       if (!request) {
+               TRACE_ERROR("[NULL-CHECK] download_clientinfo_slot");
+               pthread_exit(NULL);
+               return 0;
+       }
+
+       if (dp_is_alive_download(request->agent_id)) {
+               errcode = dp_resume_agent_download(request->agent_id);
+       } else {
+               // call agent start function
+               errcode = dp_start_agent_download(request);
+       }
+
+       CLIENT_MUTEX_LOCK(&(request->mutex));
+       // send to state callback.
+       if (errcode == DP_ERROR_NONE) {
+               // CONNECTING
+               request->state = DP_STATE_CONNECTING;
+               request->error = DP_ERROR_NONE;
+               request->startcount++;
+               if (dp_db_set_column
+                               (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STARTCOUNT,
+                               DP_DB_COL_TYPE_INT, &request->startcount) < 0)
+                       TRACE_ERROR("[ERROR][%d][SQL]", request->id);
+       } else if (errcode == DP_ERROR_TOO_MANY_DOWNLOADS) {
+               // PENDED
+               request->state = DP_STATE_QUEUED;
+               request->error = DP_ERROR_TOO_MANY_DOWNLOADS;
+       } else if (errcode == DP_ERROR_CONNECTION_FAILED) {
+               // FAILED
+               request->state = DP_STATE_FAILED;
+               request->error = DP_ERROR_CONNECTION_FAILED;
+               dp_ipc_send_event(request->group->event_socket,
+                       request->id, request->state, request->error, 0);
+               dp_thread_queue_manager_wake_up();
+       } else {
+               request->state = DP_STATE_FAILED;
+               request->error = errcode;
+               dp_ipc_send_event(request->group->event_socket,
+                       request->id, request->state, request->error, 0);
+               dp_thread_queue_manager_wake_up();
+       }
+       if (dp_db_set_column
+                       (request->id, DP_DB_TABLE_LOG, DP_DB_COL_STATE,
+                       DP_DB_COL_TYPE_INT, &request->state) < 0)
+               TRACE_ERROR("[ERROR][%d][SQL]", request->id);
+
+       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+       pthread_exit(NULL);
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief create thread.
+/// @warning if failed to create thread, change to PENED.
+/// @param the pointer of memory slot allocated for this request.
+static int __request_download_start_thread(dp_request *request)
+{
+       // declare all resources
+       pthread_t thread_pid;
+       pthread_attr_t thread_attr;
+
+       TRACE_INFO("");
+       if (!request) {
+               TRACE_ERROR("[CRITICAL] Invalid Address");
+               return -1;
+       }
+
+       // initialize
+       if (pthread_attr_init(&thread_attr) != 0) {
+               TRACE_STRERROR("[ERROR][%d] pthread_attr_init", request->id);
+               return -1;
+       }
+       if (pthread_attr_setdetachstate(&thread_attr,
+                                                                       PTHREAD_CREATE_DETACHED) != 0) {
+               TRACE_STRERROR
+                       ("[ERROR][%d] pthread_attr_setdetachstate", request->id);
+               return -1;
+       }
+
+       request->state = DP_STATE_CONNECTING;
+       if (pthread_create(&thread_pid, &thread_attr,
+                                       __request_download_start_agent, request) != 0) {
+               TRACE_STRERROR("[ERROR][%d] pthread_create", request->id);
+               pthread_attr_destroy(&thread_attr);
+               request->state = DP_STATE_QUEUED;
+               return -1;
+       }
+       pthread_attr_destroy(&thread_attr);
+       return 0;
+}
+
+
+void dp_thread_queue_manager_wake_up()
+{
+       TRACE_INFO("");
+       CLIENT_MUTEX_LOCK(&(g_dp_queue_mutex));
+       pthread_cond_signal(&g_dp_queue_cond);
+       CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex));
+}
+
+
+// Main role : start download, check status of queue.
+// No timeout. Wake up by Signal be sent from other thread
+void *dp_thread_queue_manager(void *arg)
+{
+       int i;
+       int active_count;
+       dp_client_group *group = NULL;
+       dp_request *request = NULL;
+
+       TRACE_INFO("Start Queue Thread");
+
+       dp_privates *privates = (dp_privates*)arg;
+       if (!privates) {
+               TRACE_ERROR("[CRITICAL] Invalid Address");
+               dp_terminate(SIGTERM);
+               pthread_exit(NULL);
+               return 0;
+       }
+
+       pthread_cond_init(&g_dp_queue_cond, NULL);
+       while (privates != NULL && privates->listen_fd >= 0) {
+
+               CLIENT_MUTEX_LOCK(&(g_dp_queue_mutex));
+               pthread_cond_wait(&g_dp_queue_cond, &g_dp_queue_mutex);
+
+               if (privates == NULL || privates->requests == NULL ||
+                       privates->listen_fd < 0) {
+                       TRACE_INFO("Terminate Thread");
+                       CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex));
+                       break;
+               }
+
+               if (!privates->connection)
+                       privates->network_status =
+                               dp_get_network_connection_instant_status();
+
+               if (privates->network_status == DP_NETWORK_TYPE_OFF) {
+                       TRACE_INFO("[CHECK NETWORK STATE]");
+                       CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex));
+                       continue;
+               }
+
+               active_count = __get_active_count(privates->requests);
+
+               // Start Conditions
+               // 1. state is QUEUED
+               // 2. 1 QUEUED per 1 Group : need not to check max limitation.!!
+               //    if no group, it will be started later.
+               // 3. most old last time : below conditions need max limitation.
+               // 4. match network connection type
+
+               // search group having 1 queued_count
+               // guarantee 1 instant download per 1 group
+               if (active_count >= DP_MAX_DOWNLOAD_AT_ONCE) {
+                       for (i = 0; i < DP_MAX_REQUEST; i++) {
+                               request = privates->requests[i].request;
+                               if (request && request->state == DP_STATE_QUEUED) {
+                                       group = privates->requests[i].request->group;
+                                       if (group && group->queued_count == 1 &&
+                                                       __is_matched_network(privates->network_status,
+                                                                       request->network_type) == 0 &&
+                                                                       __request_download_start_thread(request) ==
+                                                                                       0) {
+                                               TRACE_INFO
+                                                       ("[Guarantee Intant Download] Group [%s]",
+                                                       group->pkgname);
+                                               active_count++;
+                                       }
+                               }
+                       }
+               }
+
+               if (active_count >= DP_MAX_DOWNLOAD_AT_ONCE) {
+                       TRACE_INFO("[BUSY] Active[%d] Max[%d]",
+                               active_count, DP_MAX_DOWNLOAD_AT_ONCE);
+                       CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex));
+                       continue;
+               }
+
+               // can start download more.
+               // search oldest request
+               while(active_count < DP_MAX_DOWNLOAD_AT_ONCE) {
+                       i = __get_oldest_request_with_network(privates->requests,
+                                       DP_STATE_QUEUED, privates->network_status);
+                       if (i < 0) {
+                               TRACE_INFO
+                                       ("No Request to can start now Active[%d] Max[%d]",
+                                       active_count, DP_MAX_DOWNLOAD_AT_ONCE);
+                               break;
+                       }
+                       TRACE_INFO
+                               ("QUEUE Status now %d active %d/%d", i, active_count,
+                               DP_MAX_DOWNLOAD_AT_ONCE);
+                       request = privates->requests[i].request;
+                       __request_download_start_thread(request);
+                       active_count++;
+               }
+               CLIENT_MUTEX_UNLOCK(&(g_dp_queue_mutex));
+       }
+       pthread_cond_destroy(&g_dp_queue_cond);
+       pthread_exit(NULL);
+       return 0;
+}
diff --git a/src/download-provider-thread-request.c b/src/download-provider-thread-request.c
new file mode 100755 (executable)
index 0000000..a4ae548
--- /dev/null
@@ -0,0 +1,1926 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+
+#include <app_manager.h>
+
+#include "download-provider.h"
+#include "download-provider-log.h"
+#include "download-provider-config.h"
+#include "download-provider-slots.h"
+#include "download-provider-socket.h"
+#include "download-provider-pthread.h"
+#include "download-provider-db.h"
+#include "download-provider-queue.h"
+#include "download-provider-request.h"
+#include "download-provider-da-interface.h"
+
+void dp_terminate(int signo);
+
+static char *__print_command(dp_command_type cmd)
+{
+       switch(cmd)
+       {
+               case DP_CMD_CREATE :
+                       return "CREATE";
+               case DP_CMD_START :
+                       return "START";
+               case DP_CMD_PAUSE :
+                       return "PAUSE";
+               case DP_CMD_CANCEL :
+                       return "CANCEL";
+               case DP_CMD_DESTROY :
+                       return "DESTROY";
+               case DP_CMD_FREE :
+                       return "FREE";
+               case DP_CMD_ECHO :
+                       return "ECHO";
+               case DP_CMD_SET_URL :
+                       return "SET_URL";
+               case DP_CMD_SET_DESTINATION :
+                       return "SET_DESTINATION";
+               case DP_CMD_SET_FILENAME :
+                       return "SET_FILENAME";
+               case DP_CMD_SET_NOTIFICATION :
+                       return "SET_NOTIFICATION";
+               case DP_CMD_SET_STATE_CALLBACK :
+                       return "SET_STATE_CALLBACK";
+               case DP_CMD_SET_PROGRESS_CALLBACK :
+                       return "SET_PROGRESS_CALLBACK";
+               case DP_CMD_SET_AUTO_DOWNLOAD :
+                       return "SET_AUTO_DOWNLOAD";
+               case DP_CMD_SET_NETWORK_TYPE :
+                       return "SET_NETWORK_TYPE";
+               case DP_CMD_SET_HTTP_HEADER :
+                       return "SET_HTTP_HEADER";
+               case DP_CMD_SET_EXTRA_PARAM :
+                       return "SET_EXTRA_PARAM";
+               case DP_CMD_DEL_HTTP_HEADER :
+                       return "DEL_HTTP_HEADER";
+               case DP_CMD_GET_HTTP_HEADER :
+                       return "GET_HTTP_HEADER";
+               case DP_CMD_GET_URL :
+                       return "GET_URL";
+               case DP_CMD_GET_DESTINATION :
+                       return "GET_DESTINATION";
+               case DP_CMD_GET_FILENAME :
+                       return "GET_FILENAME";
+               case DP_CMD_GET_NOTIFICATION :
+                       return "GET_NOTIFICATION";
+               case DP_CMD_GET_STATE_CALLBACK :
+                       return "GET_STATE_CALLBACK";
+               case DP_CMD_GET_PROGRESS_CALLBACK :
+                       return "GET_PROGRESS_CALLBACK";
+               case DP_CMD_GET_HTTP_HEADERS :
+                       return "GET_HTTP_HEADERS";
+               case DP_CMD_GET_EXTRA_PARAM :
+                       return "GET_EXTRA_PARAM";
+               case DP_CMD_GET_AUTO_DOWNLOAD :
+                       return "GET_AUTO_DOWNLOAD";
+               case DP_CMD_GET_NETWORK_TYPE :
+                       return "GET_NETWORK_TYPE";
+               case DP_CMD_GET_SAVED_PATH :
+                       return "GET_SAVED_PATH";
+               case DP_CMD_GET_TEMP_SAVED_PATH :
+                       return "GET_TEMP_SAVED_PATH";
+               case DP_CMD_GET_MIME_TYPE :
+                       return "GET_MIME_TYPE";
+               case DP_CMD_GET_RECEIVED_SIZE :
+                       return "GET_RECEIVED_SIZE";
+               case DP_CMD_GET_TOTAL_FILE_SIZE :
+                       return "GET_TOTAL_FILE_SIZE";
+               case DP_CMD_GET_CONTENT_NAME :
+                       return "GET_CONTENT_NAME";
+               case DP_CMD_GET_HTTP_STATUS :
+                       return "GET_HTTP_STATUS";
+               case DP_CMD_GET_ETAG :
+                       return "DP_CMD_GET_ETAG";
+               case DP_CMD_GET_STATE :
+                       return "GET_STATE";
+               case DP_CMD_GET_ERROR :
+                       return "ERROR";
+               case DP_CMD_SET_COMMAND_SOCKET :
+                       return "SET_COMMAND_SOCKET";
+               case DP_CMD_SET_EVENT_SOCKET :
+                       return "SET_EVENT_SOCKET";
+               default :
+                       break;
+       }
+       return "UNKNOWN COMMAND";
+}
+
+/* compare two string */
+static int __cmp_string(char *s1, char *s2)
+{
+       size_t s1_len = 0;
+       size_t s2_len = 0;
+
+       if (!s1 || !s2) {
+               TRACE_ERROR("[CHECK PARAM]");
+               return -1;
+       }
+
+       s1_len = strlen(s1);
+       if (s1_len <= 0) {
+               TRACE_ERROR("[CHECK PARAM] len[%d]", s1_len);
+               return -1;
+       }
+
+       s2_len = strlen(s2);
+       if (s2_len <= 0) {
+               TRACE_ERROR("[CHECK PARAM] len[%d]", s2_len);
+               return -1;
+       }
+
+       if (s1_len != s2_len) {
+               TRACE_ERROR("[DIFF] len[%d:%d]", s1_len, s2_len);
+               return -1;
+       }
+
+       if (strncmp(s1, s2, s1_len) != 0) {
+               TRACE_ERROR("[DIFF] cmp[%s:%s]", s1, s2);
+               return -1;
+       }
+
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief     return index of empty slot
+static int __get_empty_request_index(dp_request_slots *slots)
+{
+       int i = 0;
+
+       if (!slots)
+               return -1;
+
+       for (i = 0; i < DP_MAX_REQUEST; i++)
+               if (!slots[i].request)
+                       return i;
+       return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief     return index of slot having same ID
+/// @param     ID want to search
+static int __get_same_request_index(dp_request_slots *slots, int id)
+{
+       int i = 0;
+
+       if (!slots || id < 0)
+               return -1;
+
+       for (i = 0; i < DP_MAX_REQUEST; i++) {
+               if (slots[i].request) {
+                       if (slots[i].request->id == id) {
+                               return i;
+                       }
+               }
+       }
+       return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief     return string via IPC
+static void __send_return_string(int fd, dp_error_type errcode, char* str)
+{
+       if (fd < 0 || !str)
+               return ;
+       dp_ipc_send_errorcode(fd, errcode);
+       dp_ipc_send_string(fd, str);
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief     return custom value via IPC
+static void __send_return_custom_type(int fd, dp_error_type errcode, void *value, size_t type_size)
+{
+       dp_ipc_send_errorcode(fd, errcode);
+       dp_ipc_send_custom_type(fd, value, type_size);
+}
+
+// in url-download, make 3 connection before send CREATE command.
+// after accepting, fill info to pacakgelist.
+// 3 socket per 1 package ( info/request/progress )
+void *dp_thread_requests_manager(void *arg)
+{
+       fd_set rset, eset, listen_fdset, except_fdset;
+       struct timeval timeout; // for timeout of select
+       long flexible_timeout = DP_CARE_CLIENT_MAX_INTERVAL;
+       int listenfd, clientfd, maxfd;
+       socklen_t clientlen;
+       struct sockaddr_un clientaddr;
+       dp_credential credential;
+       unsigned i, is_timeout;
+       int prev_timeout = 0;
+       dp_error_type errorcode = DP_ERROR_NONE;
+
+       dp_privates *privates = (dp_privates*)arg;
+       if (!privates || !privates->groups) {
+               TRACE_ERROR("[CRITICAL] Invalid Address");
+               dp_terminate(SIGTERM);
+               pthread_exit(NULL);
+               return 0;
+       }
+
+       listenfd = privates->listen_fd;
+       maxfd = listenfd;
+
+       TRACE_INFO("Ready to listen [%d][%s]", listenfd, DP_IPC);
+
+       FD_ZERO(&listen_fdset);
+       FD_ZERO(&except_fdset);
+       FD_SET(listenfd, &listen_fdset);
+       FD_SET(listenfd, &except_fdset);
+
+       while (privates && privates->listen_fd) {
+
+               // select with timeout
+               // initialize timeout structure for calling timeout exactly
+               memset(&timeout, 0x00, sizeof(struct timeval));
+               timeout.tv_sec = flexible_timeout;
+               clientfd = -1;
+               credential.pid = -1;
+               credential.uid = -1;
+               credential.gid = -1;
+               is_timeout = 1;
+
+               rset = listen_fdset;
+               eset = except_fdset;
+
+               if (select((maxfd + 1), &rset, 0, &eset, &timeout) < 0) {
+                       TRACE_STRERROR("[CRITICAL] select");
+                       break;
+               }
+
+               if (!privates) {
+                       TRACE_INFO("Terminate Thread");
+                       break;
+               }
+
+               if (FD_ISSET(listenfd, &eset) > 0) {
+                       TRACE_ERROR("[CRITICAL] listenfd Exception of socket");
+                       break;
+               } else if (FD_ISSET(listenfd, &rset) > 0) {
+                       // new client(package) called url_download_create API.
+                       // update g_dp_request_max_fd & g_dp_info_max_fd
+                       // add to socket to g_dp_request_rset & g_dp_info_rset
+
+                       is_timeout = 0;
+
+                       // Anyway accept client.
+                       clientlen = sizeof(clientaddr);
+                       clientfd = accept(listenfd,
+                                                       (struct sockaddr*)&clientaddr,
+                                                       &clientlen);
+
+                       TRACE_INFO("[New Connection]");
+
+                       if (clientfd < 0) {
+                               TRACE_ERROR("[CRITICAL] accept provider was crashed ?");
+                               // provider need the time of refresh.
+                               break;
+                       }
+
+                       dp_command_type connect_cmd = DP_CMD_NONE;
+                       if (dp_ipc_read_custom_type(clientfd,
+                                       &connect_cmd, sizeof(dp_command_type)) < 0) {
+                               TRACE_ERROR("[CRITICAL] CAPI not support CONNECT CMD");
+                               close(clientfd);
+                               continue;
+                       }
+                       if (connect_cmd <= 0) {
+                               TRACE_ERROR("[CRITICAL] peer terminate ?");
+                               close(clientfd);
+                               continue;
+                       }
+                       if (connect_cmd != DP_CMD_SET_COMMAND_SOCKET
+                               && connect_cmd != DP_CMD_SET_EVENT_SOCKET) {
+                               TRACE_ERROR("[CRITICAL] Bad access, ignore this client");
+                               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_INFO
+                                       ("credential : pid=%d, uid=%d, gid=%d",
+                                       credential.pid, credential.uid, credential.gid);
+                       }
+                       #else // In case of not supported SO_PEERCRED
+                       int client_pid = 0;
+                       if (dp_ipc_read_custom_type(clientfd,
+                                       &client_pid, sizeof(int)) < 0) {
+                               TRACE_ERROR("[CRITICAL] not support SO_PEERCRED");
+                               close(clientfd);
+                               continue;
+                       }
+                       if (client_pid <= 0) {
+                               TRACE_ERROR("[CRITICAL] not support SO_PEERCRED");
+                               close(clientfd);
+                               continue;
+                       }
+                       credential.pid = client_pid;
+                       credential.uid = 5000;
+                       credential.gid = 5000;
+                       #endif
+
+                       struct timeval tv_timeo; // 2.5 sec
+                       tv_timeo.tv_sec = 2;
+                       tv_timeo.tv_usec = 500000;
+                       if (setsockopt(clientfd, SOL_SOCKET, SO_SNDTIMEO, &tv_timeo,
+                               sizeof( tv_timeo ) ) < 0) {
+                               TRACE_STRERROR("[CRITICAL] setsockopt SO_SNDTIMEO");
+                               close(clientfd);
+                               continue;
+                       }
+                       if (setsockopt(clientfd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo,
+                               sizeof( tv_timeo ) ) < 0) {
+                               TRACE_STRERROR("[CRITICAL] setsockopt SO_SNDTIMEO");
+                               close(clientfd);
+                               continue;
+                       }
+
+                       if (connect_cmd == DP_CMD_SET_COMMAND_SOCKET) {
+
+                               // search in groups.
+                               // if same group. update it.
+                               // search same pkg or pid in groups
+                               int group_index = -1;
+                               int pkgname_length = 0;
+                               char *client_pkgname = NULL;
+
+                               // getting the package name via pid
+                               int errcode =
+                               app_manager_get_package(credential.pid, &client_pkgname);
+                               if (errcode == APP_MANAGER_ERROR_NONE && client_pkgname
+                                       && strlen(client_pkgname) < DP_MAX_STR_LEN) {
+                                       TRACE_INFO("package : %s", client_pkgname);
+                               } else
+                                       TRACE_ERROR("[CRITICAL] app_manager_get_package");
+
+                               if (client_pkgname
+                                       && (pkgname_length = strlen(client_pkgname)) > 1) {
+                                       for (i = 0; i < DP_MAX_GROUP; i++) {
+                                               if (privates->groups[i].group) {
+                                                       if (privates->groups[i].group->cmd_socket
+                                                               <= 0
+                                                               || !privates->groups[i].group->pkgname) {
+                                                               dp_client_group_free
+                                                                       (privates->groups[i].group);
+                                                               privates->groups[i].group = NULL;
+                                                               continue;
+                                                       }
+                                                       if (strlen
+                                                                       (privates->groups[i].group->pkgname)
+                                                                       == pkgname_length
+                                                               && strncmp
+                                                                       (privates->groups[i].group->pkgname,
+                                                                       client_pkgname, pkgname_length)
+                                                                       == 0 ) {
+                                                               // Found Same Group
+                                                               TRACE_INFO
+                                                               ("UPDATE Group : I %d [%s] PID [%d] cmd_socket[%d]",
+                                                               i, client_pkgname, credential.pid, clientfd);
+                                                               if (privates->groups[i].group->cmd_socket
+                                                                       > 0
+                                                                       && privates->groups[i].group->cmd_socket
+                                                                       != clientfd) {
+                                                                       FD_CLR
+                                                                       (privates->groups[i].group->cmd_socket,
+                                                                       &listen_fdset);
+                                                                       dp_socket_free
+                                                                       (privates->groups[i].group->cmd_socket);
+                                                               }
+                                                               privates->groups[i].group->cmd_socket = clientfd;
+                                                               FD_SET(privates->groups[i].group->cmd_socket, &listen_fdset);
+                                                               if (privates->groups[i].group->cmd_socket > maxfd)
+                                                               maxfd = privates->groups[i].group->cmd_socket;
+                                                               group_index = i;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (group_index == -1) { // search emtpy slot in groups
+                                       // search empty slot in groups
+                                       for (i = 0; i < DP_MAX_GROUP; i++)
+                                               if (!privates->groups[i].group)
+                                                       break;
+                                       if (i >= DP_MAX_GROUP) {
+                                               TRACE_ERROR("[CRITICAL] No space in groups");
+                                               close(clientfd); // how to deal in url-download ?
+                                               if (client_pkgname)
+                                                       free(client_pkgname);
+                                               continue;
+                                       }
+
+                                       //// TEST CODE ... to allow sample client ( no package name ).
+                                       if (!client_pkgname) {
+                                               client_pkgname = dp_strdup("unknown_app");
+                                               TRACE_INFO("package : %s", client_pkgname);
+                                       }
+
+                                       TRACE_INFO
+                                       ("New Group : GI %d [%s] PID [%d] cmd_socket[%d]",
+                                       i, client_pkgname, credential.pid, clientfd);
+
+                                       // allocation
+                                       privates->groups[i].group =
+                                               (dp_client_group *) calloc(1,
+                                                       sizeof(dp_client_group));
+                                       if (!privates->groups[i].group) {
+                                               TRACE_ERROR
+                                                       ("[CRITICAL] calloc, ignore this client");
+                                               close(clientfd);
+                                               if (client_pkgname)
+                                                       free(client_pkgname);
+                                               continue;
+                                       }
+                                       // fill info
+                                       privates->groups[i].group->cmd_socket = clientfd;
+                                       privates->groups[i].group->event_socket = -1;
+                                       privates->groups[i].group->queued_count = 0;
+                                       privates->groups[i].group->pkgname =
+                                               dp_strdup(client_pkgname);
+                                       privates->groups[i].group->credential.pid =
+                                               credential.pid;
+                                       privates->groups[i].group->credential.uid =
+                                               credential.uid;
+                                       privates->groups[i].group->credential.gid =
+                                               credential.gid;
+                                       FD_SET(privates->groups[i].group->cmd_socket,
+                                               &listen_fdset);
+                                       if (privates->groups[i].group->cmd_socket > maxfd)
+                                               maxfd = privates->groups[i].group->cmd_socket;
+                                       TRACE_INFO
+                                               ("Group : GI [%d] [%s] S [%d] Max [%d]",
+                                               i, client_pkgname,
+                                               privates->groups[i].group->cmd_socket, maxfd);
+                               }
+                               if (client_pkgname)
+                                       free(client_pkgname);
+
+                       } else if (connect_cmd == DP_CMD_SET_EVENT_SOCKET) {
+
+                               // search same pid in groups. have same life-cycle with cmd_socket
+                               TRACE_INFO
+                                       ("Group event IPC: PID [%d] cmd_socket[%d]",
+                                       credential.pid, clientfd);
+                               // search same pkg or pid in groups
+                               for (i = 0; i < DP_MAX_GROUP; i++) {
+                                       if (privates->groups[i].group) {
+                                               dp_client_group *group =
+                                                       privates->groups[i].group;
+                                               if (group->credential.pid == credential.pid) {
+                                                       TRACE_INFO
+                                                       ("Found Group : I %d [%s] PID [%d] \
+                                                       socket (%d/%d)", i,
+                                                       group->pkgname, credential.pid,
+                                                       group->cmd_socket, group->event_socket);
+                                                       if (group->event_socket > 0
+                                                               && group->event_socket != clientfd)
+                                                               dp_socket_free(group->event_socket);
+                                                       group->event_socket = clientfd;
+                                                       TRACE_INFO
+                                                       ("Found Group : I %d PID [%d] \
+                                                       event_socket[%d]",
+                                                       i, credential.pid, clientfd);
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (i >= DP_MAX_GROUP) {
+                                       TRACE_ERROR
+                                               ("[CRITICAL] Not found group for PID [%d]",
+                                               credential.pid);
+                                       close(clientfd);
+                                       continue;
+                               }
+                       }
+               } // New Connection
+
+               // listen cmd_socket of all group
+               for (i = 0; i < DP_MAX_GROUP; i++) {
+                       if (!privates->groups[i].group)
+                               continue;
+                       if (privates->groups[i].group->cmd_socket < 0) {
+                               continue;
+                       }
+                       if (FD_ISSET(privates->groups[i].group->cmd_socket, &rset)
+                               > 0) {
+                               dp_client_group *group = privates->groups[i].group;
+                               dp_command client_cmd;
+                               int index = -1;
+
+                               is_timeout = 0;
+                               client_cmd.cmd = DP_CMD_NONE;
+                               client_cmd.id = -1;
+
+                               if (dp_ipc_read_custom_type(group->cmd_socket,
+                                                       &client_cmd, sizeof(dp_command)) < 0) {
+                                       TRACE_STRERROR("failed to read cmd");
+                                       //Resource temporarily unavailable
+                                       continue;
+                               }
+
+                               // print detail info
+                               TRACE_INFO
+                                       ("[%s][%d] FD[%d] CLIENT[%s] PID[%d] GINDEX[%d]",
+                                       __print_command(client_cmd.cmd), client_cmd.id,
+                                       group->cmd_socket, group->pkgname,
+                                       group->credential.pid, i);
+
+                               if (client_cmd.cmd == 0) { // Client meet some Error.
+                                       TRACE_INFO
+                                       ("[Closed Peer] group[%d][%s] socket[%d]",
+                                       i, group->pkgname, group->cmd_socket);
+                                       // check all request included to this group
+                                       for (index = 0; index < DP_MAX_REQUEST; index++) {
+                                               if (!privates->requests[index].request)
+                                                       continue;
+                                               if (!privates->requests[index].request->group)
+                                                       continue;
+                                               if (privates->requests[index].request->id <= 0)
+                                                       continue;
+                                               dp_request *request =
+                                                       privates->requests[index].request;
+
+                                               CLIENT_MUTEX_LOCK(&request->mutex);
+                                               if (request->group != group ||
+                                                       request->group->cmd_socket !=
+                                                       group->cmd_socket) {
+                                                       CLIENT_MUTEX_UNLOCK(&request->mutex);
+                                                       continue;
+                                               }
+                                               int auto_download =
+                                                       dp_db_get_int_column(request->id,
+                                                                       DP_DB_TABLE_REQUEST_INFO,
+                                                                       DP_DB_COL_AUTO_DOWNLOAD);
+                                               if (auto_download <= 0) {
+                                                       int agentid = request->agent_id;
+                                                       int requestid = request->id;
+                                                       int state = request->state;
+                                                       TRACE_INFO("[CANCEL][%d] [%s] fd[%d]",
+                                                               requestid, request->group->pkgname,
+                                                               request->group->cmd_socket);
+
+                                                       if ((state == DP_STATE_READY ||
+                                                               state == DP_STATE_QUEUED ||
+                                                               state == DP_STATE_CONNECTING ||
+                                                               state == DP_STATE_DOWNLOADING ||
+                                                               state == DP_STATE_PAUSE_REQUESTED ||
+                                                               state == DP_STATE_PAUSED)) {
+                                                               request->state = DP_STATE_FAILED;
+                                                               request->error = DP_ERROR_CLIENT_DOWN;
+                                                               if (dp_db_set_column
+                                                                               (request->id, DP_DB_TABLE_LOG,
+                                                                               DP_DB_COL_STATE,
+                                                                               DP_DB_COL_TYPE_INT,
+                                                                               &request->state) < 0) {
+                                                                       TRACE_ERROR("[ERROR][%d][SQL]",
+                                                                               requestid);
+                                                                       dp_db_remove_all(request->id);
+                                                               } else {
+                                                                       if (dp_db_set_column
+                                                                               (request->id, DP_DB_TABLE_LOG,
+                                                                               DP_DB_COL_ERRORCODE,
+                                                                               DP_DB_COL_TYPE_INT,
+                                                                               &request->error) < 0) {
+                                                                       TRACE_ERROR("[ERROR][%d][SQL]",
+                                                                               requestid);
+                                                                       }
+                                                               }
+                                                       }
+                                                       CLIENT_MUTEX_UNLOCK(&request->mutex);
+                                                       dp_request_free(request);
+                                                       privates->requests[index].request = NULL;
+
+                                                       // call cancel_agent after free.
+                                                       if (agentid > 0 &&
+                                                               dp_is_alive_download(agentid)) {
+                                                               TRACE_INFO
+                                                                       ("[CANCEL-AGENT][%d] state [%s]",
+                                                                       requestid, dp_print_state(state));
+                                                               if (dp_cancel_agent_download(agentid) <
+                                                                       0)
+                                                                       TRACE_INFO("[CANCEL FAILURE]");
+                                                       }
+
+                                                       continue;
+                                               }
+
+
+                                               TRACE_INFO("[DISCONNECT][%d] [%s] fd[%d]",
+                                                       request->id, request->group->pkgname,
+                                                       request->group->cmd_socket);
+
+                                               request->group = NULL;
+                                               request->state_cb = 0;
+                                               request->progress_cb = 0;
+
+                                               CLIENT_MUTEX_UNLOCK(&request->mutex);
+                                               // yield to agent thread before free
+                                               CLIENT_MUTEX_LOCK(&request->mutex);
+                                               // free finished slot without client process
+                                               if (request->state == DP_STATE_COMPLETED
+                                                       || request->state == DP_STATE_FAILED
+                                                       || request->state == DP_STATE_CANCELED) {
+                                                       TRACE_INFO
+                                                               ("[FREE][%d] state[%s]", request->id,
+                                                               dp_print_state(request->state));
+                                                       CLIENT_MUTEX_UNLOCK(&request->mutex);
+                                                       dp_request_free(request);
+                                                       privates->requests[index].request = NULL;
+                                                       continue;
+                                               }
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       }
+                                       // clear this group
+                                       FD_CLR(group->cmd_socket, &listen_fdset);
+                                       dp_client_group_free(group);
+                                       privates->groups[i].group = NULL;
+                                       continue;
+                               }
+
+                               // Echo .client can check whether provider is busy
+                               if (client_cmd.cmd == DP_CMD_ECHO) {
+                                       // provider can clear read buffer here
+                                       TRACE_INFO("[ECHO] fd[%d]", group->cmd_socket);
+                                       dp_ipc_send_errorcode
+                                               (group->cmd_socket, DP_ERROR_NONE);
+                                       continue;
+                               }
+
+                               if (client_cmd.cmd == DP_CMD_CREATE) {
+                                       // search empty slot in privates->requests
+                                       index = __get_empty_request_index(privates->requests);
+                                       if (index < 0) {
+                                               TRACE_ERROR("[CHECK] [DP_ERROR_QUEUE_FULL]");
+                                               // Busy, No Space in slot
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_QUEUE_FULL);
+                                       } else {
+                                               dp_error_type ret = DP_ERROR_NONE;
+                                               ret = dp_request_create(client_cmd.id, group,
+                                                       &privates->requests[index].request);
+                                               if (ret == DP_ERROR_NONE) {
+                                                       TRACE_INFO
+                                                               ("[CREATE] GOOD ID[%d] SLOT[%d]",
+                                                               privates->requests[index].request->id,
+                                                               index);
+                                                       __send_return_custom_type(group->cmd_socket,
+                                                               DP_ERROR_NONE,
+                                                               &privates->requests[index].request->id,
+                                                               sizeof(int));
+                                               } else {
+                                                       TRACE_ERROR
+                                                               ("[ERROR][%s]", dp_print_errorcode(ret));
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, ret);
+                                               }
+                                       }
+                                       continue;
+                               }
+
+                               // below commands must need ID
+                               // check exception before searching slots.
+                               if (client_cmd.id < 0) {
+                                       TRACE_ERROR("[CHECK PROTOCOL] ID should not be -1");
+                                       dp_ipc_send_errorcode(group->cmd_socket,
+                                               DP_ERROR_INVALID_PARAMETER);
+                                       // disconnect this group, bad client
+                                       FD_CLR(group->cmd_socket, &listen_fdset);
+                                       dp_client_group_free(group);
+                                       privates->groups[i].group = NULL;
+                                       continue;
+                               }
+
+                               // search id in requests slot
+                               index = __get_same_request_index
+                                                       (privates->requests, client_cmd.id);
+
+                               dp_request *request = NULL;
+                               if (index >= 0)
+                                       request = privates->requests[index].request;
+
+                               char *auth_pkgname = NULL;
+                               if (request != NULL) {
+                                       auth_pkgname = dp_strdup(request->packagename);
+                               } else {
+                                       auth_pkgname = dp_db_get_text_column(client_cmd.id,
+                                                       DP_DB_TABLE_LOG, DP_DB_COL_PACKAGENAME);
+                                       if (auth_pkgname == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                               (group->cmd_socket, DP_ERROR_ID_NOT_FOUND);
+                                               continue;
+                                       }
+                               }
+
+                               // auth by pkgname
+                               if (__cmp_string
+                                       (group->pkgname, auth_pkgname) < 0) {
+                                       TRACE_ERROR
+                                               ("[ERROR][%d] Auth [%s]/[%s]", client_cmd.id,
+                                               group->pkgname, auth_pkgname);
+                                       dp_ipc_send_errorcode
+                                       (group->cmd_socket, DP_ERROR_INVALID_PARAMETER);
+                                       free(auth_pkgname);
+                                       continue;
+                               }
+                               if (auth_pkgname != NULL)
+                                       free(auth_pkgname);
+
+                               if (request != NULL && request->group == NULL) {
+                                       // if no group, update group.
+                                       request->group = group;
+                               }
+
+                               if (client_cmd.cmd == DP_CMD_DESTROY) {
+                                       if (request != NULL) {
+                                               CLIENT_MUTEX_LOCK(&(request->mutex));
+                                               // call download_cancel API
+                                               if (request->agent_id > 0 &&
+                                                       dp_is_alive_download(request->agent_id)) {
+                                                       TRACE_INFO("[CANCEL-AGENT][%d] agent_id[%d]",
+                                                               client_cmd.id, request->agent_id);
+                                                       if (dp_cancel_agent_download
+                                                                       (request->agent_id) < 0)
+                                                               TRACE_INFO("[CANCEL FAILURE][%d]",
+                                                                       client_cmd.id);
+                                                       request->state = DP_STATE_CANCELED;
+                                                       if (dp_db_set_column
+                                                                       (request->id, DP_DB_TABLE_LOG,
+                                                                       DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                                       &request->state) < 0) {
+                                                               TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
+                                                                       client_cmd.id,
+                                                                       dp_print_state(request->state));
+                                                               dp_db_remove_all(request->id);
+                                                       }
+                                               }
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       }
+                                       // Always return GOOD
+                                       dp_ipc_send_errorcode
+                                               (group->cmd_socket, DP_ERROR_NONE);
+                                       #if 0
+                                       // remove tmp file
+                                       char *tmp_path =
+                                               dp_request_get_tmpsavedpath
+                                                       (client_cmd.id, &errorcode);
+                                       if ((tmp_path != NULL && strlen(tmp_path) > 0) &&
+                                               dp_is_file_exist(tmp_path) == 0) {
+                                               TRACE_INFO("[REMOVE][%d] TEMP FILE [%s]",
+                                                       client_cmd.id, tmp_path);
+                                               if (unlink(tmp_path) != 0)
+                                                       TRACE_STRERROR("[ERROR][%d] remove file",
+                                                               client_cmd.id);
+                                               free(tmp_path);
+                                       }
+                                       // in DESTROY, clear all info
+                                       dp_db_remove_all(client_cmd.id);
+                                       #else
+                                       // in DESTROY, maintain DB logging
+                                       if (request != NULL) {
+                                               CLIENT_MUTEX_LOCK(&(request->mutex));
+                                               // change state to CANCELED.
+                                               if (request->state == DP_STATE_NONE ||
+                                                       request->state == DP_STATE_READY ||
+                                                       request->state == DP_STATE_QUEUED ||
+                                                       request->state == DP_STATE_CONNECTING ||
+                                                       request->state == DP_STATE_DOWNLOADING ||
+                                                       request->state == DP_STATE_PAUSE_REQUESTED ||
+                                                       request->state == DP_STATE_PAUSED) {
+                                                       request->state = DP_STATE_CANCELED;
+                                                       if (dp_db_set_column
+                                                                       (request->id, DP_DB_TABLE_LOG,
+                                                                       DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                                       &request->state) < 0) {
+                                                               TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
+                                                                       client_cmd.id,
+                                                                       dp_print_state(request->state));
+                                                       }
+                                               }
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       }
+                                       #endif
+                               } else if (client_cmd.cmd == DP_CMD_FREE) {
+                                       // [destory]-[return]-[free]
+                                       // No return errorcode
+                                       if (request != NULL) {
+                                               dp_request_free(request);
+                                               privates->requests[index].request = NULL;
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_START) {
+                                       if (request == NULL) { // Support Re-download
+                                               index =
+                                                       __get_empty_request_index(privates->requests);
+                                               if (index < 0) {
+                                                       TRACE_ERROR
+                                                               ("[ERROR][%d] DP_ERROR_QUEUE_FULL",
+                                                               client_cmd.id);
+                                                       // Busy, No Space in slot
+                                                       dp_ipc_send_errorcode(group->cmd_socket,
+                                                               DP_ERROR_QUEUE_FULL);
+                                                       continue;
+                                               }
+                                               request = dp_request_load_from_log
+                                                                       (client_cmd.id, &errorcode);
+                                               if (request == NULL) {
+                                                       TRACE_ERROR("[ERROR][%d] [%s]",
+                                                               client_cmd.id,
+                                                               dp_print_errorcode(errorcode));
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, errorcode);
+                                                       continue;
+                                               }
+                                               // restore callback info
+                                               request->state_cb = 
+                                                       dp_db_get_int_column(client_cmd.id,
+                                                                       DP_DB_TABLE_REQUEST_INFO,
+                                                                       DP_DB_COL_STATE_EVENT);
+                                               request->progress_cb = 
+                                                       dp_db_get_int_column(client_cmd.id,
+                                                                       DP_DB_TABLE_REQUEST_INFO,
+                                                                       DP_DB_COL_PROGRESS_EVENT);
+                                               privates->requests[index].request = request;
+                                       }
+                                       // Check URL
+                                       char *url = dp_request_get_url
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (url == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] DP_ERROR_INVALID_URL",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_INVALID_URL);
+                                               continue;
+                                       } else {
+                                               free(url);
+                                       }
+                                       if (request->state == DP_STATE_QUEUED ||
+                                               request->state == DP_STATE_CONNECTING ||
+                                               request->state == DP_STATE_DOWNLOADING ||
+                                               request->state == DP_STATE_COMPLETED) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] now [%s]", client_cmd.id,
+                                                       dp_print_state(request->state));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_INVALID_STATE);
+                                               continue;
+                                       }
+                                       dp_state_type state = DP_STATE_QUEUED;
+                                       if (dp_db_set_column
+                                                       (request->id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                       &state) < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d][SQL] try [%s]->[%s]",
+                                                       client_cmd.id,
+                                                       dp_print_state(request->state),
+                                                       dp_print_state(state));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       group->queued_count++;
+                                       if (dp_db_update_date(request->id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_ACCESS_TIME) < 0)
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+                                       request->start_time = (int)time(NULL);
+                                       request->pause_time = 0;
+                                       request->stop_time = 0;
+                                       request->state = state;
+                                       request->error = DP_ERROR_NONE;
+                                       // need to check how long take to come here.
+                                       dp_ipc_send_errorcode
+                                               (group->cmd_socket, DP_ERROR_NONE);
+                                       //send signal to queue thread
+                                       dp_thread_queue_manager_wake_up();
+                               } else if (client_cmd.cmd == DP_CMD_PAUSE) {
+                                       if (request == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_ID_NOT_FOUND);
+                                               continue;
+                                       }
+                                       if (dp_db_update_date(request->id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_ACCESS_TIME) < 0)
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+
+                                       CLIENT_MUTEX_LOCK(&(request->mutex));
+                                       if (request->state > DP_STATE_DOWNLOADING) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] now [%s]", client_cmd.id,
+                                                       dp_print_state(request->state));
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_INVALID_STATE);
+                                               continue;
+                                       }
+                                       if (request->state <= DP_STATE_QUEUED) {
+                                               request->state = DP_STATE_PAUSED;
+                                               request->error = DP_ERROR_NONE;
+                                               if (dp_db_set_column
+                                                               (request->id, DP_DB_TABLE_LOG,
+                                                               DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                               &request->state) < 0) {
+                                                       TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
+                                                               client_cmd.id,
+                                                               dp_print_state(request->state));
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               } else {
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, DP_ERROR_NONE);
+                                               }
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               continue;
+                                       }
+                                       if (dp_pause_agent_download(request->agent_id)
+                                               < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d][AGENT][ID:%d] now [%s]",
+                                                       client_cmd.id, request->agent_id,
+                                                       dp_print_state(request->state));
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_INVALID_STATE);
+                                               continue;
+                                       }
+                                       request->pause_time = (int)time(NULL);
+                                       request->state = DP_STATE_PAUSE_REQUESTED;
+                                       request->error = DP_ERROR_NONE;
+                                       if (dp_db_set_column
+                                                       (request->id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                       &request->state) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
+                                                               client_cmd.id,
+                                                               dp_print_state(request->state));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                       } else {
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NONE);
+                                       }
+                                       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                               } else if (client_cmd.cmd == DP_CMD_CANCEL) {
+                                       if (request == NULL) {
+                                               // find id in DB.
+                                               dp_state_type state =
+                                                       dp_db_get_int_column(client_cmd.id,
+                                                               DP_DB_TABLE_LOG, DP_DB_COL_STATE);
+                                               if (state > DP_STATE_NONE) {
+                                                       // if exist & it is paused, change to canceled.
+                                                       if (state == DP_STATE_PAUSED ||
+                                                               state == DP_STATE_PAUSE_REQUESTED) {
+                                                               // change state to canceled.
+                                                               state = DP_STATE_CANCELED;
+                                                               if (dp_db_set_column
+                                                                               (client_cmd.id,
+                                                                               DP_DB_TABLE_LOG,
+                                                                               DP_DB_COL_STATE,
+                                                                               DP_DB_COL_TYPE_INT,
+                                                                               &state) < 0) {
+                                                                       TRACE_ERROR
+                                                                               ("[ERROR][%d][SQL] try [%s]",
+                                                                                       client_cmd.id,
+                                                                                       dp_print_state(state));
+                                                                       dp_ipc_send_errorcode
+                                                                               (group->cmd_socket,
+                                                                               DP_ERROR_IO_ERROR);
+                                                               } else {
+                                                                       dp_ipc_send_errorcode
+                                                                               (group->cmd_socket,
+                                                                               DP_ERROR_NONE);
+                                                               }
+                                                       } else {
+                                                               TRACE_ERROR("[ERROR][%d] now [%s]",
+                                                                               client_cmd.id,
+                                                                               dp_print_state(state));
+                                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                                       DP_ERROR_INVALID_STATE);
+                                                       }
+                                                       continue;
+                                               }
+                                               // if not match these conditions, invalied param
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_ID_NOT_FOUND);
+                                               continue;
+                                       }
+                                       CLIENT_MUTEX_LOCK(&(request->mutex));
+                                       if (request->state >= DP_STATE_COMPLETED) {
+                                               // already finished.
+                                               TRACE_ERROR("[ERROR][%d] now [%s]",
+                                                               client_cmd.id,
+                                                               dp_print_state(request->state));
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_INVALID_STATE);
+                                               continue;
+                                       }
+                                       if (request->state <= DP_STATE_QUEUED) {
+                                               request->state = DP_STATE_CANCELED;
+                                               request->error = DP_ERROR_NONE;
+                                               if (dp_db_set_column
+                                                               (request->id, DP_DB_TABLE_LOG,
+                                                               DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                               &request->state) < 0) {
+                                                       TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
+                                                               client_cmd.id,
+                                                               dp_print_state(request->state));
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               } else {
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, DP_ERROR_NONE);
+                                               }
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               continue;
+                                       }
+                                       if (dp_db_update_date(request->id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_ACCESS_TIME) < 0)
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+
+                                       if (dp_cancel_agent_download(request->agent_id)
+                                               < 0) {
+                                               TRACE_ERROR("[ERROR][%d][AGENT][ID:%d] now [%s]",
+                                                               client_cmd.id,
+                                                               request->agent_id,
+                                                               dp_print_state(request->state));
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_INVALID_STATE);
+                                               continue;
+                                       }
+                                       // need to check how long take to come here.
+                                       if (dp_db_set_column
+                                                       (request->id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                       &request->state) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL] try [%s]",
+                                                               client_cmd.id,
+                                                               dp_print_state(request->state));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                       } else {
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NONE);
+                                       }
+                                       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                               } else if (client_cmd.cmd == DP_CMD_SET_URL) {
+                                       char *url = dp_ipc_read_string(group->cmd_socket);
+                                       if (url == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] DP_ERROR_INVALID_URL",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_INVALID_URL);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_url(client_cmd.id, request, url);
+                                       TRACE_INFO("[SET_URL][%d][%s]", client_cmd.id, url);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       free(url);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_DESTINATION) {
+                                       char *dest = dp_ipc_read_string(group->cmd_socket);
+                                       if (dest == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] DP_ERROR_INVALID_DESTINATION",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_INVALID_DESTINATION);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_destination
+                                                       (client_cmd.id, request, dest);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO("[SET_DEST][%d][%s]", client_cmd.id, dest);
+                                       free(dest);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_FILENAME) {
+                                       char *fname = dp_ipc_read_string(group->cmd_socket);
+                                       if (fname == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] DP_ERROR_INVALID_PARAMETER",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_INVALID_PARAMETER);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_filename
+                                                       (client_cmd.id, request, fname);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO
+                                               ("[SET_FILE][%d][%s]", client_cmd.id, fname);
+                                       free(fname);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_NOTIFICATION) {
+                                       int value = 0;
+                                       if (dp_ipc_read_custom_type(group->cmd_socket,
+                                               &value, sizeof(int)) < 0) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                               client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_notification
+                                                       (client_cmd.id, request, value);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO
+                                               ("[SET_NOTI][%d] [%d]", client_cmd.id, value);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_STATE_CALLBACK) {
+                                       int value = 0;
+                                       if (dp_ipc_read_custom_type(group->cmd_socket,
+                                               &value, sizeof(int)) < 0) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_state_event
+                                                       (client_cmd.id, request, value);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO
+                                               ("[STATE-EVENT][%d][%d]", client_cmd.id, value);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_PROGRESS_CALLBACK) {
+                                       int value = 0;
+                                       if (dp_ipc_read_custom_type(group->cmd_socket,
+                                               &value, sizeof(int)) < 0) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_progress_event
+                                                       (client_cmd.id, request, value);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO
+                                               ("[PROG-EVENT][%d][%d]", client_cmd.id, value);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_AUTO_DOWNLOAD) {
+                                       int value = 0;
+                                       if (dp_ipc_read_custom_type(group->cmd_socket,
+                                               &value, sizeof(int)) < 0) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_auto_download
+                                                       (client_cmd.id, request, value);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO
+                                               ("[SET_AUTO][%d][%d]", client_cmd.id, value);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_NETWORK_TYPE) {
+                                       int value = 0;
+                                       if (dp_ipc_read_custom_type(group->cmd_socket,
+                                               &value, sizeof(int)) < 0) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       dp_error_type ret =
+                                               dp_request_set_network_type
+                                                       (client_cmd.id, request, value);
+                                       dp_ipc_send_errorcode(group->cmd_socket, ret);
+                                       TRACE_INFO
+                                               ("[SET_NETTYPE][%d][%d]", client_cmd.id, value);
+                                       if (ret != DP_ERROR_NONE)
+                                               TRACE_ERROR("[ERROR][%d][%s]",
+                                                       client_cmd.id, dp_print_errorcode(ret));
+                               } else if (client_cmd.cmd == DP_CMD_SET_EXTRA_PARAM) {
+                                       char *key = dp_ipc_read_string(group->cmd_socket);
+                                       if (key == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       char *value = dp_ipc_read_string(group->cmd_socket);
+                                       if (value == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               free(key);
+                                               continue;
+                                       }
+
+                                       TRACE_INFO("[EXTRA-PARAM][%d][%s][%s]",
+                                               client_cmd.id, key, value);
+
+                                       if (dp_db_replace_column
+                                                       (client_cmd.id, DP_DB_TABLE_NOTIFICATION,
+                                                       DP_DB_COL_EXTRA_KEY, DP_DB_COL_TYPE_TEXT,
+                                                       key) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               free(key);
+                                               free(value);
+                                               continue;
+                                       }
+                                       free(key);
+                                       if (dp_db_set_column
+                                                       (client_cmd.id, DP_DB_TABLE_NOTIFICATION,
+                                                       DP_DB_COL_EXTRA_VALUE, DP_DB_COL_TYPE_TEXT,
+                                                       value) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                       } else {
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NONE);
+                                       }
+                                       free(value);
+                               } else if (client_cmd.cmd == DP_CMD_SET_HTTP_HEADER) {
+                                       char *field = dp_ipc_read_string(group->cmd_socket);
+                                       if (field == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       char *value = dp_ipc_read_string(group->cmd_socket);
+                                       if (value == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               free(field);
+                                               continue;
+                                       }
+                                       char *check_field = dp_db_cond_get_text_column
+                                               (client_cmd.id, DP_DB_TABLE_HTTP_HEADERS,
+                                               DP_DB_COL_HEADER_FIELD, DP_DB_COL_HEADER_FIELD,
+                                               DP_DB_COL_TYPE_TEXT, field);
+                                       if (check_field == NULL) {
+                                               // INSERT New Field
+                                               if (dp_db_insert_column
+                                                               (client_cmd.id,
+                                                               DP_DB_TABLE_HTTP_HEADERS,
+                                                               DP_DB_COL_HEADER_FIELD,
+                                                               DP_DB_COL_TYPE_TEXT, field) < 0) {
+                                                       TRACE_ERROR
+                                                               ("[ERROR][%d][SQL]", client_cmd.id);
+                                                       free(field);
+                                                       free(value);
+                                                       dp_ipc_send_errorcode
+                                                               (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                                       continue;
+                                               }
+                                       } else {
+                                               free(check_field);
+                                       }
+                                       // UPDATE Value for Field
+                                       if (dp_db_cond_set_column(client_cmd.id,
+                                                       DP_DB_TABLE_HTTP_HEADERS,
+                                                       DP_DB_COL_HEADER_DATA,
+                                                       DP_DB_COL_TYPE_TEXT, value,
+                                                       DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT,
+                                                       field) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                       } else {
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NONE);
+                                       }
+                                       free(field);
+                                       free(value);
+                               } else if (client_cmd.cmd == DP_CMD_DEL_HTTP_HEADER) {
+                                       char *field = dp_ipc_read_string(group->cmd_socket);
+                                       if (field == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       char *check_field = dp_db_cond_get_text_column
+                                               (client_cmd.id, DP_DB_TABLE_HTTP_HEADERS,
+                                               DP_DB_COL_HEADER_FIELD, DP_DB_COL_HEADER_FIELD,
+                                               DP_DB_COL_TYPE_TEXT, field);
+                                       if (check_field == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NO_DATA);
+                                               free(field);
+                                               continue;
+                                       }
+                                       free(check_field);
+                                       if (dp_db_cond_remove(client_cmd.id,
+                                                       DP_DB_TABLE_HTTP_HEADERS,
+                                                       DP_DB_COL_HEADER_FIELD, DP_DB_COL_TYPE_TEXT,
+                                                       field) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL]", client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                       } else {
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NONE);
+                                       }
+                                       free(field);
+                               } else if (client_cmd.cmd == DP_CMD_GET_HTTP_HEADER) {
+                                       char *field = dp_ipc_read_string(group->cmd_socket);
+                                       if (field == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [DP_ERROR_IO_ERROR]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_IO_ERROR);
+                                               continue;
+                                       }
+                                       char *value = dp_db_cond_get_text_column
+                                               (client_cmd.id, DP_DB_TABLE_HTTP_HEADERS,
+                                               DP_DB_COL_HEADER_DATA, DP_DB_COL_HEADER_FIELD,
+                                               DP_DB_COL_TYPE_TEXT, field);
+                                       free(field);
+                                       if (value == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NO_DATA);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, value);
+                                               free(value);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_EXTRA_PARAM) {
+                                       char *key = dp_db_get_text_column
+                                                       (client_cmd.id, DP_DB_TABLE_NOTIFICATION,
+                                                       DP_DB_COL_EXTRA_KEY);
+                                       if (key == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NO_DATA);
+                                               continue;
+                                       }
+                                       char *value = dp_db_get_text_column
+                                                       (client_cmd.id, DP_DB_TABLE_NOTIFICATION,
+                                                       DP_DB_COL_EXTRA_VALUE);
+                                       if (value == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, DP_ERROR_NO_DATA);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, key);
+                                               dp_ipc_send_string(group->cmd_socket, value);
+                                               free(value);
+                                       }
+                                       free(key);
+                               } else if (client_cmd.cmd == DP_CMD_GET_URL) {
+                                       char *url = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       url = dp_request_get_url
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (url == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, url);
+                                               free(url);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_DESTINATION) {
+                                       char *dest = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       dest = dp_request_get_destination
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (dest == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, dest);
+                                               free(dest);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_FILENAME) {
+                                       char *filename = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       filename = dp_request_get_filename
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (filename == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, filename);
+                                               free(filename);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_NOTIFICATION) {
+                                       int enable = 0;
+                                       enable = dp_db_get_int_column(client_cmd.id,
+                                                                       DP_DB_TABLE_NOTIFICATION,
+                                                                       DP_DB_COL_NOTIFICATION_ENABLE);
+                                       if (enable < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_NO_DATA);
+                                       } else {
+                                               __send_return_custom_type
+                                                       (group->cmd_socket, DP_ERROR_NONE,
+                                                       &enable, sizeof(int));
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_AUTO_DOWNLOAD) {
+                                       int enable = 0;
+                                       enable = dp_db_get_int_column(client_cmd.id,
+                                                                       DP_DB_TABLE_REQUEST_INFO,
+                                                                       DP_DB_COL_AUTO_DOWNLOAD);
+                                       if (enable < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_NO_DATA);
+                                       } else {
+                                               __send_return_custom_type
+                                                       (group->cmd_socket, DP_ERROR_NONE,
+                                                       &enable, sizeof(int));
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_NETWORK_TYPE) {
+                                       int type = 0;
+                                       type = dp_db_get_int_column(client_cmd.id,
+                                                                       DP_DB_TABLE_REQUEST_INFO,
+                                                                       DP_DB_COL_NETWORK_TYPE);
+                                       if (type < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_NO_DATA);
+                                       } else {
+                                               __send_return_custom_type
+                                                       (group->cmd_socket, DP_ERROR_NONE,
+                                                       &type, sizeof(dp_network_type));
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_SAVED_PATH) {
+                                       char *savedpath = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       savedpath = dp_request_get_savedpath
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (savedpath == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, savedpath);
+                                               free(savedpath);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_TEMP_SAVED_PATH) {
+                                       char *tmppath = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       tmppath = dp_request_get_tmpsavedpath
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (tmppath == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, tmppath);
+                                               free(tmppath);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_MIME_TYPE) {
+                                       char *mimetype = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       mimetype = dp_request_get_mimetype
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (mimetype == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, mimetype);
+                                               free(mimetype);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_RECEIVED_SIZE) {
+                                       if (request == NULL) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_ID_NOT_FOUND);
+                                       } else {
+                                               __send_return_custom_type
+                                                       (group->cmd_socket, DP_ERROR_NONE,
+                                                       &request->received_size,
+                                                       sizeof(unsigned long long));
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_TOTAL_FILE_SIZE) {
+                                       if (request != NULL) {
+                                               __send_return_custom_type(group->cmd_socket,
+                                                       DP_ERROR_NONE, &request->file_size,
+                                                       sizeof(unsigned long long));
+                                               continue;
+                                       }
+                                       long long file_size =
+                                               dp_db_get_int64_column(client_cmd.id,
+                                                                       DP_DB_TABLE_DOWNLOAD_INFO,
+                                                                       DP_DB_COL_CONTENT_SIZE);
+                                       if (file_size < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_NO_DATA);
+                                       } else {
+                                               // casting
+                                               unsigned long long total_file_size = file_size;
+                                               __send_return_custom_type
+                                                       (group->cmd_socket, DP_ERROR_NONE,
+                                                       &total_file_size, sizeof(total_file_size));
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_CONTENT_NAME) {
+                                       char *content = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       content = dp_request_get_contentname
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (content == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, content);
+                                               free(content);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_HTTP_STATUS) {
+                                       int http_status = 0;
+                                       http_status = dp_db_get_int_column(client_cmd.id,
+                                                                       DP_DB_TABLE_DOWNLOAD_INFO,
+                                                                       DP_DB_COL_HTTP_STATUS);
+                                       if (http_status < 0) {
+                                               TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_NO_DATA]",
+                                                       client_cmd.id);
+                                               dp_ipc_send_errorcode(group->cmd_socket,
+                                                       DP_ERROR_NO_DATA);
+                                       } else {
+                                               __send_return_custom_type
+                                                       (group->cmd_socket, DP_ERROR_NONE,
+                                                       &http_status, sizeof(int));
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_ETAG) {
+                                       char *etag = NULL;
+                                       errorcode = DP_ERROR_NONE;
+                                       etag = dp_request_get_etag
+                                                       (client_cmd.id, request, &errorcode);
+                                       if (etag == NULL) {
+                                               TRACE_ERROR("[ERROR][%d] [%s]", client_cmd.id,
+                                                       dp_print_errorcode(errorcode));
+                                               dp_ipc_send_errorcode
+                                                       (group->cmd_socket, errorcode);
+                                       } else {
+                                               __send_return_string
+                                                       (group->cmd_socket, DP_ERROR_NONE, etag);
+                                               free(etag);
+                                       }
+                               } else if (client_cmd.cmd == DP_CMD_GET_STATE) {
+                                       dp_state_type download_state = DP_STATE_NONE;
+                                       if (request == NULL) {
+                                               download_state =
+                                                       dp_db_get_int_column(client_cmd.id,
+                                                                               DP_DB_TABLE_LOG,
+                                                                               DP_DB_COL_STATE);
+                                               if (download_state < 0) {
+                                                       TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
+                                                       client_cmd.id);
+                                                       dp_ipc_send_errorcode(group->cmd_socket,
+                                                               DP_ERROR_ID_NOT_FOUND);
+                                                       continue;
+                                               }
+                                       } else {
+                                               CLIENT_MUTEX_LOCK(&(request->mutex));
+                                               download_state = request->state;
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       }
+                                       __send_return_custom_type
+                                               (group->cmd_socket, DP_ERROR_NONE,
+                                               &download_state, sizeof(dp_state_type));
+                               } else if (client_cmd.cmd == DP_CMD_GET_ERROR) {
+                                       errorcode = DP_ERROR_NONE;
+                                       if (request == NULL) {
+                                               errorcode =
+                                                       dp_db_get_int_column(client_cmd.id,
+                                                                               DP_DB_TABLE_LOG,
+                                                                               DP_DB_COL_ERRORCODE);
+                                               if (errorcode < 0) {
+                                                       TRACE_ERROR
+                                                       ("[ERROR][%d] [DP_ERROR_ID_NOT_FOUND]",
+                                                       client_cmd.id);
+                                                       dp_ipc_send_errorcode(group->cmd_socket,
+                                                               DP_ERROR_ID_NOT_FOUND);
+                                                       continue;
+                                               }
+                                       } else {
+                                               CLIENT_MUTEX_LOCK(&(request->mutex));
+                                               errorcode = request->error;
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       }
+                                       dp_ipc_send_errorcode
+                                               (group->cmd_socket, DP_ERROR_NONE);
+                                       dp_ipc_send_errorcode
+                                               (group->cmd_socket, errorcode);
+                               } else {
+                                       TRACE_INFO
+                                               ("[UNKNOWN] I [%d] PID [%d]", i,
+                                               privates->groups[i].group->credential.pid);
+                                       dp_ipc_send_errorcode(group->cmd_socket,
+                                               DP_ERROR_INVALID_PARAMETER);
+                                       // disconnect this group, bad client
+                                       FD_CLR(group->cmd_socket, &listen_fdset);
+                                       dp_client_group_free(group);
+                                       privates->groups[i].group = NULL;
+                               }
+                       } // FD_ISSET
+               } // DP_MAX_GROUP
+
+               // timeout
+               if (is_timeout == 1) {
+                       int now_timeout = (int)time(NULL);
+                       TRACE_INFO("[TIMEOUT] prev %ld, now %ld, setted %ld sec",
+                               prev_timeout, now_timeout, flexible_timeout);
+                       if (prev_timeout == 0) {
+                               prev_timeout = now_timeout;
+                       } else {
+                               if ((now_timeout - prev_timeout) <
+                                       DP_CARE_CLIENT_MIN_INTERVAL) {
+                                       // this is error.
+                                       // terminate Process
+                                       TRACE_STRERROR
+                                       ("[CRITICAL] Sock exception prev[%ld]now[%ld][%ld]",
+                                       prev_timeout, now_timeout, flexible_timeout);
+                                       break;
+                               }
+                       }
+
+                       // get 48hour old request from log DB
+                       // clear old request
+                       dp_db_limit_rows(DP_LOG_DB_LIMIT_ROWS);
+                       int old_request_count = dp_db_get_count_by_limit_time();
+                       if (old_request_count > 0) {
+                               if (old_request_count > DP_LOG_DB_CLEAR_LIMIT_ONE_TIME)
+                                       old_request_count = DP_LOG_DB_CLEAR_LIMIT_ONE_TIME;
+
+                               TRACE_INFO
+                                       ("[CLEAR] [%d] old reqeusts", old_request_count);
+
+                               dp_request_slots *old_requests =
+                                       dp_request_slots_new(old_request_count);
+                               if (old_requests) {
+                                       int list_count = dp_db_get_list_by_limit_time
+                                                               (old_requests, old_request_count);
+                                       if (list_count > 0) {
+                                               for (i = 0; i < list_count; i++) {
+                                                       // search on slots by ID.
+                                                       int index =
+                                                               __get_same_request_index
+                                                                       (privates->requests,
+                                                                       old_requests[i].request->id);
+                                                       if (index >= 0) {
+                                                               dp_request *request =
+                                                                       privates->requests[index].request;
+                                                               // if downloading..remain it.
+                                                               CLIENT_MUTEX_LOCK(&(request->mutex));
+                                                               if (request->state ==
+                                                                       DP_STATE_CONNECTING ||
+                                                                       request->state ==
+                                                                       DP_STATE_DOWNLOADING) {
+                                                                       CLIENT_MUTEX_UNLOCK
+                                                                               (&(request->mutex));
+                                                                       continue;
+                                                               }
+                                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                                               // unload from slots ( memory )
+                                                               dp_request_free(request);
+                                                               privates->requests[index].request = NULL;
+                                                       }
+                                                       // remove tmp file
+                                                       char *tmp_path =
+                                                               dp_request_get_tmpsavedpath
+                                                                       (old_requests[i].request->id,
+                                                                       old_requests[i].request,
+                                                                       &errorcode);
+                                                       if ((tmp_path && strlen(tmp_path) > 0) &&
+                                                               dp_is_file_exist(tmp_path) == 0) {
+                                                               TRACE_INFO
+                                                                       ("[REMOVE][%d] TEMP FILE [%s]",
+                                                                       old_requests[i].request->id,
+                                                                       tmp_path);
+                                                               if (unlink(tmp_path) != 0)
+                                                                       TRACE_STRERROR
+                                                                               ("[ERROR][%d] remove file",
+                                                                               old_requests[i].request->id);
+                                                               free(tmp_path);
+                                                       }
+                                                       // remove from DB
+                                                       dp_db_remove_all(old_requests[i].request->id);
+                                               }
+                                       }
+                                       dp_request_slots_free(old_requests, old_request_count);
+                               }
+                       }
+
+                       // clean slots
+                       int ready_requests = 0;
+                       for (i = 0; i < DP_MAX_REQUEST; i++) {
+                               if (!privates->requests[i].request)
+                                       continue;
+                               dp_request *request = privates->requests[i].request;
+
+                               CLIENT_MUTEX_LOCK(&(request->mutex));
+
+                               // If downloading is too slow ? how to deal this request?
+                               // can limit too slot download using starttime.(48 hours)
+                               if (request->state == DP_STATE_CONNECTING ||
+                                       request->state == DP_STATE_DOWNLOADING) {
+                                       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       continue;
+                               }
+
+                               // paused & agent_id not exist.... unload from memory.
+                               if (request->state == DP_STATE_PAUSED &&
+                                       dp_is_alive_download(request->agent_id) == 0) {
+                                       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       TRACE_INFO
+                                       ("[FREE] [%d] unavailable agent ID [%d]",
+                                               request->id, request->agent_id);
+                                       dp_request_free(request);
+                                       privates->requests[i].request = NULL;
+                                       continue;
+                               }
+
+                               // client should call START command in 60 sec
+                               // unload from memory
+                               if (request->start_time <= 0 &&
+                                       (now_timeout - request->create_time) >
+                                               DP_CARE_CLIENT_MAX_INTERVAL) {
+                                       int download_id = request->id;
+                                       dp_state_type state = DP_STATE_FAILED;
+                                       errorcode = DP_ERROR_RESPONSE_TIMEOUT;
+                                       if (request->group
+                                               && request->group->event_socket >= 0
+                                               && request->state_cb)
+                                               dp_ipc_send_event
+                                                       (request->group->event_socket,
+                                                       download_id, state, errorcode, 0);
+                                       CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                       TRACE_INFO
+                                       ("[FREE] no response ID[%d] last access [%ld]",
+                                               request->id, request->start_time);
+                                       dp_request_free(request);
+                                       privates->requests[i].request = NULL;
+                                       // no problem although updating is failed.
+                                       if (dp_db_set_column
+                                                       (download_id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_STATE, DP_DB_COL_TYPE_INT,
+                                                       &state) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL]", request->id);
+                                       }
+                                       if (dp_db_set_column
+                                                       (download_id, DP_DB_TABLE_LOG,
+                                                       DP_DB_COL_ERRORCODE, DP_DB_COL_TYPE_INT,
+                                                       &errorcode) < 0) {
+                                               TRACE_ERROR("[ERROR][%d][SQL]", request->id);
+                                       }
+                                       continue;
+                               }
+
+                               // client should call DESTROY command in 60 sec after finished
+                               if (request->stop_time > 0 &&
+                                       (now_timeout - request->stop_time) >
+                                       DP_CARE_CLIENT_MAX_INTERVAL) {
+                                       // check state again. stop_time means it's stopped
+                                       if (request->state == DP_STATE_COMPLETED ||
+                                               request->state == DP_STATE_FAILED ||
+                                               request->state == DP_STATE_CANCELED) {
+                                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                                               TRACE_INFO("[FREE] by timeout cleaner ID[%d]",
+                                                       request->id);
+                                               dp_request_free(request);
+                                               privates->requests[i].request = NULL;
+                                               continue;
+                                       }
+                               }
+
+                               // check after clear
+                               if (request->state == DP_STATE_QUEUED)
+                                       ready_requests++;
+
+                               CLIENT_MUTEX_UNLOCK(&(request->mutex));
+                       }
+
+                       if (ready_requests > 0) {
+                               //send signal to queue thread will check queue.
+                               dp_thread_queue_manager_wake_up();
+                       } else {
+#ifdef DP_SUPPORT_DBUS_ACTIVATION
+                               // if no request & timeout is bigger than 60 sec
+                               // terminate by self.
+                               if ((now_timeout - prev_timeout) >= flexible_timeout &&
+                                       dp_get_request_count(privates->requests) <= 0) {
+                                       TRACE_INFO("No Request. Terminate Daemon");
+                                       break;
+                               }
+#endif
+                       }
+                       prev_timeout = now_timeout;
+               } // timeout
+       }
+       TRACE_INFO("terminate main thread ...");
+       dp_terminate(SIGTERM);
+       pthread_exit(NULL);
+       return 0;
+}
diff --git a/src/include/download-provider-config.h b/src/include/download-provider-config.h
new file mode 100755 (executable)
index 0000000..a0ba61d
--- /dev/null
@@ -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_PROVIDER2_CONFIG_H
+#define DOWNLOAD_PROVIDER2_CONFIG_H
+
+#include <download-provider.h>
+#include <download-provider-slots.h>
+
+#include <net_connection.h>
+
+#define DP_LOCK_PID "/tmp/download-provider.lock"
+
+#define DP_CARE_CLIENT_MIN_INTERVAL 5
+#define DP_CARE_CLIENT_MAX_INTERVAL 60
+
+// check this value should be lower than DP_MAX_REQUEST
+#define DP_MAX_DOWNLOAD_AT_ONCE 50
+
+#define DP_LOG_DB_LIMIT_ROWS 1000
+#define DP_LOG_DB_CLEAR_LIMIT_ONE_TIME 100
+
+// Share the structure for all threads
+typedef struct {
+       int listen_fd;
+       connection_h connection;
+       dp_network_type network_status;
+       dp_group_slots *groups;
+       dp_request_slots *requests;
+} dp_privates;
+
+#endif
diff --git a/src/include/download-provider-da-interface.h b/src/include/download-provider-da-interface.h
new file mode 100755 (executable)
index 0000000..dcafc1a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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_DA_INTERFACE_H
+#define DOWNLOAD_PROVIDER2_DA_INTERFACE_H
+
+int dp_is_file_exist(const char *file_path);
+int dp_init_agent();
+void dp_deinit_agent();
+dp_error_type dp_start_agent_download(dp_request *request);
+dp_error_type dp_resume_agent_download(int req_id);
+dp_error_type dp_pause_agent_download(int req_id);
+dp_error_type dp_cancel_agent_download(int req_id);
+int dp_is_alive_download(int req_id);
+
+#endif
diff --git a/src/include/download-provider-db.h b/src/include/download-provider-db.h
new file mode 100755 (executable)
index 0000000..1618e67
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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_DB_H
+#define DOWNLOAD_PROVIDER2_DB_H
+
+#include "download-provider-config.h"
+#include "download-provider-slots.h"
+
+/*
+ * Memory ( sync with logging ) : id, state, errorcode, startcount, packagename
+ * DB TABLES
+ *                             logging                 : id, state, errorcode, startcount, createtime, accesstime, packagename
+ *                             requestinfo             : id, auto_download, network_type, filename, destination, url
+ *                             downloadinfo    : id, http_status, content_size, mimetype, contentname, saved_path, tmp_saved_path, etag
+ *                             httpheaders             : id, header_field, header_data
+ *                             notification    : id, noti_enable, extra_key, extra_data
+ */
+/*
+CREATE TABLE logging
+(
+        id              INTEGER UNIQUE PRIMARY KEY,
+        state           INTEGER DEFAULT 0,
+        errorcode       INTEGER DEFAULT 0,
+        startcount      INTEGER DEFAULT 0,
+        packagename     TEXT DEFAULT NULL,
+        createtime      DATE,
+        accesstime      DATE
+);
+
+CREATE TABLE requestinfo
+(
+        id              INTEGER UNIQUE PRIMARY KEY,
+        auto_download   BOOLEAN DEFAULT 0,
+        state_event     BOOLEAN DEFAULT 0,
+        progress_event  BOOLEAN DEFAULT 0,
+        network_type    TINYINT DEFAULT 0,
+        filename        TEXT DEFAULT NULL,
+        destination     TEXT DEFAULT NULL,
+        url             TEXT DEFAULT NULL,
+        FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE
+);
+
+CREATE TABLE downloadinfo
+(
+        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
+);
+
+CREATE TABLE httpheaders
+(
+        id              INTEGER NOT NULL,
+        header_field    TEXT DEFAULT NULL,
+        header_data     TEXT DEFAULT NULL,
+        FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE
+);
+
+CREATE TABLE notification
+(
+        id              INTEGER UNIQUE PRIMARY KEY,
+        noti_enable     BOOLEAN DEFAULT 0,
+        extra_key       TEXT DEFAULT NULL,
+        extra_data      TEXT DEFAULT NULL,
+        FOREIGN KEY(id) REFERENCES logging(id) ON DELETE CASCADE
+);
+
+CREATE UNIQUE INDEX requests_index ON logging (id, state, errorcode, packagename, createtime, accesstime);
+*/
+
+#define DP_DB_TABLE_LOG "logging"
+#define DP_DB_TABLE_REQUEST_INFO "requestinfo"
+#define DP_DB_TABLE_DOWNLOAD_INFO "downloadinfo"
+#define DP_DB_TABLE_HTTP_HEADERS "httpheaders"
+#define DP_DB_TABLE_NOTIFICATION "notification"
+
+#define DP_DB_COL_ID "id"
+#define DP_DB_COL_STATE "state"
+#define DP_DB_COL_ERRORCODE "errorcode"
+#define DP_DB_COL_NETWORK_TYPE "network_type"
+#define DP_DB_COL_HTTP_STATUS "http_status"
+#define DP_DB_COL_AUTO_DOWNLOAD "auto_download"
+#define DP_DB_COL_STATE_EVENT "state_event"
+#define DP_DB_COL_PROGRESS_EVENT "progress_event"
+#define DP_DB_COL_CONTENT_SIZE "content_size"
+#define DP_DB_COL_CREATE_TIME "createtime"
+#define DP_DB_COL_ACCESS_TIME "accesstime"
+#define DP_DB_COL_STARTCOUNT "startcount"
+#define DP_DB_COL_PACKAGENAME "packagename"
+#define DP_DB_COL_DESTINATION "destination"
+#define DP_DB_COL_FILENAME "filename"
+#define DP_DB_COL_CONTENT_NAME "content_name"
+#define DP_DB_COL_MIMETYPE "mimetype"
+#define DP_DB_COL_ETAG "etag"
+#define DP_DB_COL_SAVED_PATH "saved_path"
+#define DP_DB_COL_TMP_SAVED_PATH "tmp_saved_path"
+#define DP_DB_COL_URL "url"
+#define DP_DB_COL_HEADER_FIELD "header_field"
+#define DP_DB_COL_HEADER_DATA "header_data"
+#define DP_DB_COL_NOTIFICATION_ENABLE "noti_enable"
+#define DP_DB_COL_EXTRA_KEY "extra_key"
+#define DP_DB_COL_EXTRA_VALUE "extra_data"
+
+typedef enum {
+       DP_DB_COL_TYPE_NONE = 0,
+       DP_DB_COL_TYPE_INT = 10,
+       DP_DB_COL_TYPE_INT64 = 20,
+       DP_DB_COL_TYPE_TEXT = 30
+} db_column_data_type;
+
+int dp_db_open();
+void dp_db_close();
+
+int dp_db_remove_all(int id);
+int dp_db_remove(int id, char *table);
+int dp_db_insert_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value);
+int dp_db_set_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value);
+int dp_db_replace_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value);
+char *dp_db_get_text_column(int id, char *table, char *column);
+int dp_db_get_int_column(int id, char *table, char *column);
+long long dp_db_get_int64_column(int id, char *table, char *column);
+int dp_db_update_date(int id, char *table, char *column);
+
+// cond : id & cond
+int dp_db_cond_set_column(int id, char *table, char *column,
+                                               db_column_data_type datatype, void *value,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue);
+char *dp_db_cond_get_text_column(int id, char *table, char *column,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue);
+int dp_db_cond_remove(int id, char *table,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue);
+int dp_db_get_cond_rows_count(int id, char *table,
+                                               char *condcolumn, db_column_data_type condtype,
+                                               void *condvalue);
+
+// Special API for http headers
+int dp_db_get_http_headers_list(int id, char **headers);
+
+// For auto-download in booting time
+int dp_db_crashed_list(dp_request_slots *requests, int limit);
+
+// For loading to memory when no in memory
+dp_request *dp_db_load_logging_request(int id);
+
+// For limitation by 48 hours & 1000 rows
+int dp_db_limit_rows(int limit);
+int dp_db_get_count_by_limit_time();
+int dp_db_get_list_by_limit_time(dp_request_slots *requests, int limit);
+#endif
diff --git a/src/include/download-provider-log.h b/src/include/download-provider-log.h
new file mode 100755 (executable)
index 0000000..d07d63b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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
+
+#include <string.h>
+#include <errno.h>
+
+#define DEBUG_MSG
+//#define DEBUG_PRINTF
+
+#ifdef DEBUG_MSG
+#ifdef DEBUG_PRINTF
+#include <stdio.h>
+#define TRACE_ERROR(format, ARG...)  \
+{ \
+fprintf(stderr,"[PROVIDER][%s:%d] "format"\n", __FUNCTION__, __LINE__, ##ARG); \
+}
+#define TRACE_STRERROR(format, ARG...)  \
+{ \
+fprintf(stderr,"[PROVIDER][%s:%d] "format" [%s]\n", __FUNCTION__, __LINE__, ##ARG, strerror(errno)); \
+}
+#define TRACE_INFO(format, ARG...)  \
+{ \
+fprintf(stderr,"[PROVIDER][%s:%d] "format"\n", __FUNCTION__, __LINE__, ##ARG); \
+}
+#else
+#include <dlog.h>
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "DOWNLOAD_PROVIDER"
+#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); \
+}
+#endif
+#else
+#define TRACE_DEBUG_MSG(format, ARG...) ;
+#endif
+#endif
diff --git a/src/include/download-provider-network.h b/src/include/download-provider-network.h
new file mode 100755 (executable)
index 0000000..a4d5b7f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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_NETWORK_H
+#define DOWNLOAD_PROVIDER2_NETWORK_H
+
+#include "download-provider.h"
+
+dp_network_type dp_get_network_connection_status(connection_h connection, connection_type_e type);
+void dp_network_connection_type_changed_cb(connection_type_e type, void *data);
+int dp_network_connection_init(dp_privates *privates);
+void dp_network_connection_destroy(connection_h connection);
+dp_network_type dp_get_network_connection_instant_status();
+
+#endif
diff --git a/src/include/download-provider-notification.h b/src/include/download-provider-notification.h
new file mode 100755 (executable)
index 0000000..5a9f5b9
--- /dev/null
@@ -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_PROVIDER2_NOTIFICATION_H
+#define DOWNLOAD_PROVIDER2_NOTIFICATION_H
+
+#include "download-provider-config.h"
+
+int dp_set_downloadinginfo_notification(int id, char *packagename);
+int dp_set_downloadedinfo_notification(int priv_id, int id, char *packagename, dp_state_type state);
+void dp_update_downloadinginfo_notification(int priv_id, double received_size, double file_size);
+void dp_clear_downloadinginfo_notification(void);
+
+#endif
diff --git a/src/include/download-provider-pthread.h b/src/include/download-provider-pthread.h
new file mode 100755 (executable)
index 0000000..8c02c59
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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_PTHREAD_H
+#define DOWNLOAD_PROVIDER2_PTHREAD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <unistd.h>
+#include <pthread.h>
+#include <errno.h>
+
+// download-provider use default style mutex.
+
+#define CLIENT_MUTEX_LOCK(mutex_add) {\
+       int ret = 0;\
+       ret = pthread_mutex_lock(mutex_add);\
+       if (EINVAL == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_lock FAIL with EINVAL.");\
+       } else if (EDEADLK == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_lock FAIL with EDEADLK.");\
+       } else if (ret != 0) {\
+               TRACE_STRERROR("ERR:pthread_mutex_lock FAIL with %d.", ret);\
+       } \
+}
+
+#define CLIENT_MUTEX_UNLOCK(mutex_add) {\
+       int ret = 0;\
+       ret = pthread_mutex_unlock(mutex_add);\
+       if (EINVAL == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_unlock FAIL with EINVAL.");\
+       } else if (EDEADLK == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_unlock FAIL with EDEADLK.");\
+       } else if (ret != 0) {\
+               TRACE_STRERROR("ERR:pthread_mutex_unlock FAIL with %d.", ret);\
+       } \
+}
+
+#define CLIENT_MUTEX_DESTROY(mutex_add) { \
+       int ret = 0; \
+       ret = pthread_mutex_destroy(mutex_add); \
+       if(EINVAL == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with EINVAL."); \
+       } else if(ENOMEM == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with ENOMEM."); \
+       } else if(EBUSY == ret) {\
+               TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with EBUSY."); \
+               if (pthread_mutex_unlock(mutex_add) == 0) \
+                       pthread_mutex_destroy(mutex_add); \
+       } else if (ret != 0) {\
+               TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with %d.", ret); \
+       } \
+}
+
+#define CLIENT_MUTEX_INIT(mutex_add, attr) { \
+       int ret = 0; \
+       unsigned retry = 3; \
+       while (retry > 0) { \
+               ret = pthread_mutex_init(mutex_add, attr); \
+               if (0 == ret) { \
+                       break; \
+               } else if(EINVAL == ret) { \
+                       TRACE_STRERROR("ERR:pthread_mutex_init FAIL with EINVAL."); \
+               } else if(ENOMEM == ret) { \
+                       TRACE_STRERROR("ERR:pthread_mutex_init FAIL with ENOMEM."); \
+                       usleep(1000); \
+               } else if(EBUSY == ret) {\
+                       TRACE_STRERROR("ERR:pthread_mutex_destroy FAIL with EBUSY."); \
+                       if (pthread_mutex_unlock(mutex_add) == 0) \
+                               pthread_mutex_destroy(mutex_add); \
+               } else if (ret != 0) { \
+                       TRACE_STRERROR("ERR:pthread_mutex_init FAIL with %d.", ret); \
+               } \
+               retry--; \
+       } \
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/include/download-provider-queue.h b/src/include/download-provider-queue.h
new file mode 100755 (executable)
index 0000000..4a7d877
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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_QUEUE_H
+#define DOWNLOAD_PROVIDER2_QUEUE_H
+
+void dp_thread_queue_manager_wake_up();
+void *dp_thread_queue_manager(void *arg);
+
+#endif
diff --git a/src/include/download-provider-request.h b/src/include/download-provider-request.h
new file mode 100755 (executable)
index 0000000..63aee32
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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_REQUEST_H
+#define DOWNLOAD_PROVIDER2_REQUEST_H
+
+#include "download-provider.h"
+
+// for Debugging
+char *dp_print_state(dp_state_type state);
+char *dp_print_errorcode(dp_error_type errorcode);
+
+char *dp_strdup(char *src);
+
+dp_error_type dp_request_create(int id, dp_client_group *group, dp_request** empty_slot);
+dp_error_type dp_request_set_url(int id, dp_request *request, char *url);
+dp_error_type dp_request_set_destination(int id, dp_request *request, char *dest);
+dp_error_type dp_request_set_filename(int id, dp_request *request, char *filename);
+dp_error_type dp_request_set_notification(int id, dp_request *request, unsigned enable);
+dp_error_type dp_request_set_auto_download(int id, dp_request *request, unsigned enable);
+dp_error_type dp_request_set_state_event(int id, dp_request *request, unsigned enable);
+dp_error_type dp_request_set_progress_event(int id, dp_request *request, unsigned enable);
+dp_error_type dp_request_set_network_type(int id, dp_request *request, int type);
+char *dp_request_get_url(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_destination(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_filename(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_contentname(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_etag(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_savedpath(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_tmpsavedpath(int id, dp_request *request, dp_error_type *errorcode);
+char *dp_request_get_mimetype(int id, dp_request *request, dp_error_type *errorcode);
+dp_request *dp_request_load_from_log(int id, dp_error_type *errorcode);
+#endif
diff --git a/src/include/download-provider-slots.h b/src/include/download-provider-slots.h
new file mode 100755 (executable)
index 0000000..cccbddf
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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_SLOTS_H
+#define DOWNLOAD_PROVIDER2_SLOTS_H
+
+#include "download-provider.h"
+#include "download-provider-pthread.h"
+
+// Backgound Daemon should has the limitation of resource.
+#define DP_MAX_GROUP 15
+#define DP_MAX_REQUEST 64
+
+typedef struct {
+       pid_t pid;
+       uid_t uid;
+       gid_t gid;
+} dp_credential;
+
+typedef struct {
+       // send command * get return value.
+       int cmd_socket;
+       // send event to client
+       int event_socket;
+       unsigned queued_count; // start ++, finish or failed -- ( queue & active )
+       // fill by app-manager
+       char *pkgname;
+       dp_credential credential;
+} dp_client_group;
+
+typedef struct {
+       int id; // ID created in create request in requests thread.
+       int agent_id;
+       int create_time;
+       int start_time; // setted by START command
+       int pause_time; // setted by PAUSE command
+       int stop_time; // time setted by finished_cb
+       int noti_priv_id;
+       unsigned state_cb; // set : 1 unset : 0
+       unsigned progress_cb; // set : 1 unset : 0
+       unsigned startcount;
+       unsigned auto_notification;
+       dp_state_type state; // downloading state
+       dp_error_type error;
+       dp_network_type network_type;
+       size_t progress_lasttime;
+       unsigned long long received_size; // progress
+       unsigned long long file_size;
+       char *packagename;
+       dp_credential credential;
+       dp_client_group *group; // indicate dp_client_group included this request
+       pthread_mutex_t mutex;
+} dp_request;
+
+typedef struct {
+       dp_client_group *group;
+} dp_group_slots;
+
+typedef struct {
+       dp_request *request;
+} dp_request_slots;
+
+
+// functions
+dp_group_slots *dp_client_group_slots_new(int size);
+dp_request_slots *dp_request_slots_new(int size);
+int dp_client_group_free(dp_client_group *group);
+int dp_client_group_slots_free(dp_group_slots *slots, int size);
+dp_request *dp_request_new();
+void dp_request_init(dp_request *request);
+int dp_request_free(dp_request *request);
+int dp_request_slots_free(dp_request_slots *slots, int size);
+int dp_get_request_count(dp_request_slots *slots);
+
+#endif
diff --git a/src/include/download-provider-socket.h b/src/include/download-provider-socket.h
new file mode 100755 (executable)
index 0000000..7ec708a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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_SOCKET_H
+#define DOWNLOAD_PROVIDER2_SOCKET_H
+
+#include "download-provider.h"
+#include "download-provider-slots.h"
+
+int dp_ipc_send_errorcode(int fd, dp_error_type errorcode);
+int dp_ipc_send_event(int fd, int id, dp_state_type state,
+       dp_error_type errorcode, unsigned long long received_size);
+#if 0
+int dp_ipc_send_progressinfo(int fd, int id,
+       unsigned long long received_size, unsigned long long file_size,
+       unsigned int chunk_size);
+int dp_ipc_send_stateinfo(int fd, int id, dp_state_type state,
+       dp_error_type errorcode);
+#endif
+char *dp_ipc_read_string(int fd);
+int dp_ipc_send_string(int fd, const char *str);
+int dp_ipc_send_custom_type(int fd, void *value, size_t type_size);
+int dp_ipc_read_custom_type(int fd, void *value, size_t type_size);
+int dp_accept_socket_new();
+int dp_socket_free(int sockfd);
+
+#endif
diff --git a/src/include/download-provider.h b/src/include/download-provider.h
new file mode 100755 (executable)
index 0000000..5083ecd
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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_H
+#define DOWNLOAD_PROVIDER2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DP_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
+
+#ifdef DP_SUPPORT_DBUS_ACTIVATION
+#define DP_DBUS_ACTIVATION
+#define DP_DBUS_SERVICE_DBUS           "org.download-provider"
+#endif
+
+#define DP_ECHO_TEST
+
+       typedef enum {
+               DP_CMD_NONE = 0,
+               DP_CMD_CREATE = DP_CMD_NONE + 1,
+               DP_CMD_START = DP_CMD_NONE + 2,
+               DP_CMD_PAUSE = DP_CMD_NONE + 3,
+               DP_CMD_CANCEL = DP_CMD_NONE + 4,
+               DP_CMD_DESTROY = DP_CMD_NONE + 9,
+               DP_CMD_FREE = DP_CMD_NONE + 10,
+               DP_CMD_ECHO = DP_CMD_NONE + 15,
+               DP_CMD_SET_URL = DP_CMD_NONE + 21,
+               DP_CMD_SET_DESTINATION = DP_CMD_NONE + 22,
+               DP_CMD_SET_FILENAME = DP_CMD_NONE + 23,
+               DP_CMD_SET_NOTIFICATION = DP_CMD_NONE + 24,
+               DP_CMD_SET_STATE_CALLBACK = DP_CMD_NONE + 25,
+               DP_CMD_SET_PROGRESS_CALLBACK = DP_CMD_NONE + 26,
+               DP_CMD_SET_AUTO_DOWNLOAD = DP_CMD_NONE + 28,
+               DP_CMD_SET_NETWORK_TYPE = DP_CMD_NONE + 29,
+               DP_CMD_SET_HTTP_HEADER = DP_CMD_NONE + 30,
+               DP_CMD_SET_EXTRA_PARAM = DP_CMD_NONE + 31,
+               DP_CMD_DEL_HTTP_HEADER = DP_CMD_NONE + 35,
+               DP_CMD_GET_URL = DP_CMD_NONE + 41,
+               DP_CMD_GET_DESTINATION = DP_CMD_NONE + 42,
+               DP_CMD_GET_FILENAME = DP_CMD_NONE + 43,
+               DP_CMD_GET_NOTIFICATION = DP_CMD_NONE + 44,
+               DP_CMD_GET_STATE_CALLBACK = DP_CMD_NONE + 45,
+               DP_CMD_GET_PROGRESS_CALLBACK = DP_CMD_NONE + 46,
+               DP_CMD_GET_HTTP_HEADERS = DP_CMD_NONE + 47,
+               DP_CMD_GET_AUTO_DOWNLOAD = DP_CMD_NONE + 48,
+               DP_CMD_GET_NETWORK_TYPE = DP_CMD_NONE + 49,
+               DP_CMD_GET_SAVED_PATH = DP_CMD_NONE + 50,
+               DP_CMD_GET_TEMP_SAVED_PATH = DP_CMD_NONE + 51,
+               DP_CMD_GET_MIME_TYPE = DP_CMD_NONE + 52,
+               DP_CMD_GET_HTTP_HEADER = DP_CMD_NONE + 53,
+               DP_CMD_GET_EXTRA_PARAM = DP_CMD_NONE + 54,
+               DP_CMD_GET_RECEIVED_SIZE = DP_CMD_NONE + 71,
+               DP_CMD_GET_TOTAL_FILE_SIZE = DP_CMD_NONE + 72,
+               DP_CMD_GET_CONTENT_NAME = DP_CMD_NONE + 73,
+               DP_CMD_GET_HTTP_STATUS = DP_CMD_NONE + 74,
+               DP_CMD_GET_ETAG = DP_CMD_NONE + 75,
+               DP_CMD_GET_STATE = DP_CMD_NONE + 81,
+               DP_CMD_GET_ERROR = DP_CMD_NONE + 91,
+               DP_CMD_SET_COMMAND_SOCKET = DP_CMD_NONE + 100,
+               DP_CMD_SET_EVENT_SOCKET = DP_CMD_NONE + 101
+       } dp_command_type;
+
+       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_PAUSE_REQUESTED = DP_STATE_NONE + 25,
+               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 = 0,
+               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_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_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_ID_NOT_FOUND = DP_ERROR_NONE + 90,
+               DP_ERROR_UNKNOWN = DP_ERROR_NONE + 100
+       } dp_error_type;
+
+       typedef enum {
+               DP_NETWORK_TYPE_OFF = -1,
+               DP_NETWORK_TYPE_ALL = 0,
+               DP_NETWORK_TYPE_WIFI = 1,
+               DP_NETWORK_TYPE_DATA_NETWORK = 2,
+               DP_NETWORK_TYPE_ETHERNET = 3,
+       } dp_network_type;
+
+       typedef struct {
+               unsigned int length;
+               char *str;
+       } dp_string;
+
+       typedef struct {
+               int id;
+               dp_state_type state;
+               dp_error_type err;
+               unsigned long long received_size;
+       } dp_event_info;
+
+       typedef struct {
+               dp_command_type cmd;
+               int id;
+       } dp_command;
+
+       // Usage IPC : send(dp_command);send(dp_string);
+
+#ifdef __cplusplus
+}
+#endif
+#endif