diff --git a/include/netutils/curl4nx.h b/include/netutils/curl4nx.h new file mode 100644 index 000000000..d0e9f2798 --- /dev/null +++ b/include/netutils/curl4nx.h @@ -0,0 +1,323 @@ +/**************************************************************************** + * apps/include/netutils/curl4nx.h + * + * This file is part of the NuttX RTOS: + * + * Copyright (C) 2019 Sebastien Lorquet. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_NETUTILS_CURL4NX_H +#define __APPS_INCLUDE_NETUTILS_CURL4NX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Defines + ****************************************************************************/ + +enum curl4nxerrors_e +{ + CURL4NXE_OK, + CURL4NXE_UNSUPPORTED_PROTOCOL, + CURL4NXE_FAILED_INIT, + CURL4NXE_URL_MALFORMAT, + CURL4NXE_NOT_BUILT_IN, + CURL4NXE_COULDNT_RESOLVE_HOST, + CURL4NXE_COULDNT_CONNECT, + CURL4NXE_HTTP2, + CURL4NXE_PARTIAL_FILE, + CURL4NXE_HTTP_RETURNED_ERROR, + CURL4NXE_WRITE_ERROR, + CURL4NXE_UPLOAD_FAILED, + CURL4NXE_READ_ERROR, + CURL4NXE_OUT_OF_MEMORY, + CURL4NXE_OPERATION_TIMEDOUT, + CURL4NXE_RANGE_ERROR, + CURL4NXE_HTTP_POST_ERROR, + CURL4NXE_SSL_CONNECT_ERROR, + CURL4NXE_BAD_DOWNLOAD_RESUME, + CURL4NXE_FUNCTION_NOT_FOUND, + CURL4NXE_ABORTED_BY_CALLBACK, + CURL4NXE_BAD_FUNCTION_ARGUMENT, + CURL4NXE_TOO_MANY_REDIRECTS, + CURL4NXE_UNKNOWN_OPTION, + CURL4NXE_GOT_NOTHING, + CURL4NXE_SEND_ERROR, + CURL4NXE_RECV_ERROR, + CURL4NXE_SSL_CERTPROBLEM, + CURL4NXE_SSL_CIPHER, + CURL4NXE_PEER_FAILED_VERIFICATION, + CURL4NXE_BAD_CONTENT_ENCODING, + CURL4NXE_LOGIN_DENIED, + CURL4NXE_REMOTE_DISK_FULL, + CURL4NXE_REMOTE_FILE_EXISTS, + CURL4NXE_SSL_CACERT_BADFILE, + CURL4NXE_REMOTE_FILE_NOT_FOUND, + CURL4NXE_AGAIN, + CURL4NXE_SSL_ISSUER_ERROR, + CURL4NXE_CHUNK_FAILED, + CURL4NXE_SSL_PINNEDPUBKEYNOTMATCH, + CURL4NXE_SSL_INVALIDCERTSTATUS, + CURL4NXE_HTTP2_STREAM, + CURL4NXE_RECURSIVE_API_CALL, +}; + +enum curl4nxopt_e +{ + /* Options that are currently implemented */ + + CURL4NXOPT_URL, + CURL4NXOPT_PORT, + CURL4NXOPT_BUFFERSIZE, + CURL4NXOPT_HEADERFUNCTION, + CURL4NXOPT_HEADERDATA, + CURL4NXOPT_FAILONERROR, + CURL4NXOPT_FOLLOWLOCATION, + CURL4NXOPT_MAXREDIRS, + CURL4NXOPT_VERBOSE, + + /* Options that will be implemented */ + + CURL4NXOPT_HEADER, + CURL4NXOPT_NOPROGRESS, + CURL4NXOPT_WRITEFUNCTION, + CURL4NXOPT_WRITEDATA, + CURL4NXOPT_READFUNCTION, + CURL4NXOPT_READDATA, + CURL4NXOPT_XFERINFOFUNCTION, + CURL4NXOPT_XFERINFODATA, + CURL4NXOPT_KEEP_SENDING_ON_ERROR, + CURL4NXOPT_PATH_AS_IS, + CURL4NXOPT_TCP_KEEPALIVE, + CURL4NXOPT_TCP_KEEPIDLE, + CURL4NXOPT_TCP_KEEPINTVL, + CURL4NXOPT_PUT, + CURL4NXOPT_POST, + CURL4NXOPT_POSTFIELDS, + CURL4NXOPT_POSTFIELDSIZE, + CURL4NXOPT_COPYPOSTFIELDS, + CURL4NXOPT_HTTPPOST, + CURL4NXOPT_REFERER, + CURL4NXOPT_USERAGENT, + CURL4NXOPT_HTTPHEADER, + CURL4NXOPT_HEADEROPT, + CURL4NXOPT_HTTPGET, + CURL4NXOPT_HTTP_VERSION, + + /* Options that will be implemented later */ + + CURL4NXOPT_SSL_CTX_FUNCTION, + CURL4NXOPT_SSL_CTX_DATA, + CURL4NXOPT_USERNAME, + CURL4NXOPT_PASSWORD, + CURL4NXOPT_HTTPAUTH, + CURL4NXOPT_POSTREDIR, + CURL4NXOPT_COOKIE, + CURL4NXOPT_COOKIEFILE, + CURL4NXOPT_COOKIEJAR, + CURL4NXOPT_COOKIESESSION, + CURL4NXOPT_COOKIELIST, + CURL4NXOPT_IGNORE_CONTENT_LENGTH, + CURL4NXOPT_RANGE, + CURL4NXOPT_RESUME_FROM, + CURL4NXOPT_CUSTOMREQUEST, + CURL4NXOPT_UPLOAD, + CURL4NXOPT_UPLOAD_BUFFERSIZE, + CURL4NXOPT_TIMEOUT, + CURL4NXOPT_TIMEOUT_MS, + CURL4NXOPT_FRESH_CONNECT, + CURL4NXOPT_CONNECTTIMEOUT, + CURL4NXOPT_CONNECTTIMEOUT_MS, + CURL4NXOPT_USE_SSL, + CURL4NXOPT_SSLCERT, + CURL4NXOPT_SSLKEY, + CURL4NXOPT_KEYPASSWD, + CURL4NXOPT_SSLVERSION, + CURL4NXOPT_SSL_VERIFYHOST, + CURL4NXOPT_SSL_VERIFYPEER, + CURL4NXOPT_SSL_VERIFYSTATUS, + CURL4NXOPT_CAPATH, + CURL4NXOPT_PINNEDPUBLICKEY, + CURL4NXOPT_RANDOM_FILE, + CURL4NXOPT_SSL_CIPHER_LIST, + CURL4NXOPT_TLS13_CIPHERS, + CURL4NXOPT_SSL_OPTIONS, +}; + +/* For CURL4NXOPT_HTTP_VERSION */ + +#define CURL4NX_HTTP_VERSION_1_0 0x10 +#define CURL4NX_HTTP_VERSION_1_1 0x11 +#define CURL4NX_HTTP_VERSION_2_0 0x20 /* Unsupported! */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_iofunction_f + * + * Description: Type of the callback function used with + * CURL4NXOPT_WRITEFUNCTION and CURL4NXOPT_READFUNCTION. + * + ****************************************************************************/ + +typedef size_t (*curl4nx_iofunc_f)(FAR char *ptr, size_t size, + size_t nmemb, FAR void *userdata); + +/**************************************************************************** + * Name: curl4nx_easy_strerror() + * + * Description: Return a textual description for an error code. + * + ****************************************************************************/ + +typedef int (*curl4nx_xferinfofunc_f)(FAR void *clientp, + uint64_t dltotal, uint64_t dlnow, + uint64_t ultotal, uint64_t ulnow); + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_strerror() + * + * Description: Return a textual description for an error code. + * + ****************************************************************************/ + +FAR const char *curl4nx_easy_strerror(int errornum); + +/**************************************************************************** + * Name: curl4nx_easy_init() + * + * Description: Initialize a context for curl4nx operations. + * + ****************************************************************************/ + +FAR struct curl4nx_s *curl4nx_easy_init(void); + +/**************************************************************************** + * Name: curl4nx_easy_escape() + * + * Description: Escape an URL to remove any forbidden character. Returned + * string MUST be released using free(). + * + ****************************************************************************/ + +FAR char *curl4nx_easy_escape(FAR struct curl4nx_s *handle, + FAR const char *string, int length); + +/**************************************************************************** + * Name: curl4nx_easy_unescape() + * + * Description: Unescape an escaped URL to replace all escaped characters. + * Returned string MUST be released using free(). + * + ****************************************************************************/ + +FAR char *curl4nx_easy_unescape(FAR struct curl4nx_s *handle, + FAR const char *url, int inlength, + FAR int *outlength); + +/**************************************************************************** + * Name: curl4nx_easy_setopt() + * + * Description: Define an option in the given curl4nx context. + * + ****************************************************************************/ + +int curl4nx_easy_setopt(FAR struct curl4nx_s *handle, int option, + FAR void *optionptr); + +/**************************************************************************** + * Name: curl4nx_easy_reset() + * + * Description: Reset all operations that were set using curl4nx_easy_setopt() + * to their default values. + * + ****************************************************************************/ + +void curl4nx_easy_reset(FAR struct curl4nx_s *handle); + +/**************************************************************************** + * Name: curl4nx_easy_duphandle() + * + * Description: Clone the current state of a handle. + * + ****************************************************************************/ + +FAR struct curl4nx_s *curl4nx_easy_duphandle(FAR struct curl4nx_s *handle); + +/**************************************************************************** + * Name: curl4nx_easy_perform() + * + * Description: Perform the http operation that was set up in this curl4nx + * context. + * + ****************************************************************************/ + +int curl4nx_easy_perform(FAR struct curl4nx_s *handle); + +/**************************************************************************** + * Name: curl4nx_easy_getinfo() + * + * Description: Get information about the current transfer. + * + ****************************************************************************/ + +int curl4nx_easy_getinfo(FAR struct curl4nx_s *handle, int info, + FAR void *infoptr); + +/**************************************************************************** + * Name: curl4nx_easy_cleanup() + * + * Description: Cleanup any resource allocated within a curl4nx context. + * + ****************************************************************************/ + +void curl4nx_easy_cleanup(FAR struct curl4nx_s *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_NETUTILS_BASE64_H */ + diff --git a/netutils/libcurl4nx/.gitignore b/netutils/libcurl4nx/.gitignore new file mode 100644 index 000000000..f21c854d1 --- /dev/null +++ b/netutils/libcurl4nx/.gitignore @@ -0,0 +1,6 @@ +/.built +/.depend +/Make.dep +/*.src +/*.obj +/*.lst diff --git a/netutils/libcurl4nx/Kconfig b/netutils/libcurl4nx/Kconfig new file mode 100644 index 000000000..bbdf99110 --- /dev/null +++ b/netutils/libcurl4nx/Kconfig @@ -0,0 +1,49 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config NETUTILS_LIBCURL4NX + tristate "cURL4nx HTTP client library" + default n + depends on NET_TCP + select LIBC_NETDB + select NETUTILS_NETLIB_GENERICURLPARSER + ---help--- + Enable the NuttX cURL like library. + +if NETUTILS_LIBCURL4NX + +config LIBCURL4NX_MAXHOST + int "Maximum URL host length" + default 128 + +config LIBCURL4NX_MAXPATH + int "Maximum URL path length" + default 128 + +config LIBCURL4NX_MAXMETHOD + int "Maximum HTTP method length" + default 16 + +config LIBCURL4NX_MAXUSERAGENT + int "Maximum HTTP user agent length" + default 64 + +config LIBCURL4NX_MAXHEADERLINE + int "Maximum receivable header line" + default 128 + +config LIBCURL4NX_RXBUFLEN + int "Initial RX buffer size" + default 512 + +config LIBCURL4NX_MINRXBUFLEN + int "Minimum RX buffer size for CURL4NXOPT_BUFFERSIZE" + default 16 + +config LIBCURL4NX_MAXRXBUFLEN + int "Maximum RX buffer size for CURL4NXOPT_BUFFERSIZE" + default 2048 + +endif diff --git a/netutils/libcurl4nx/Make.defs b/netutils/libcurl4nx/Make.defs new file mode 100644 index 000000000..eb294373c --- /dev/null +++ b/netutils/libcurl4nx/Make.defs @@ -0,0 +1,39 @@ +# apps/netutils/libcurl4nx/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2019 Gregory Nutt. All rights reserved. +# Author: Sebastien Lorquet +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_NETUTILS_LIBCURL4NX),y) +CONFIGURED_APPS += netutils/libcurl4nx +endif + diff --git a/netutils/libcurl4nx/Makefile b/netutils/libcurl4nx/Makefile new file mode 100644 index 000000000..363d38f46 --- /dev/null +++ b/netutils/libcurl4nx/Makefile @@ -0,0 +1,46 @@ +############################################################################ +# apps/netutils/libcurl4nx/Makefile +# +# Copyright (C) 2019 Gregory Nutt. All rights reserved. +# Author: Sebastien Lorquet +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +# Web client library + +CSRCS = curl4nx_easy_init.c curl4nx_easy_cleanup.c \ + curl4nx_easy_reset.c curl4nx_easy_duphandle.c \ + curl4nx_easy_escape.c curl4nx_easy_unescape.c \ + curl4nx_easy_setopt.c curl4nx_easy_perform.c \ + curl4nx_easy_getinfo.c + +include $(APPDIR)/Application.mk diff --git a/netutils/libcurl4nx/curl4nx_easy_cleanup.c b/netutils/libcurl4nx/curl4nx_easy_cleanup.c new file mode 100644 index 000000000..aaeadf99c --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_cleanup.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_cleanup.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_cleanup() + ****************************************************************************/ + +void curl4nx_easy_cleanup(FAR struct curl4nx_s *handle) +{ + curl4nx_info("handle=%p\n", handle); + + /* Reset custom options in the context, effectively freeing the headers */ + + curl4nx_easy_reset(handle); + + /* And release allocated memory */ + + if (handle->rxbuf != NULL) + { + free(handle->rxbuf); + handle->rxbufsize = 0; + } + + free(handle); +} diff --git a/netutils/libcurl4nx/curl4nx_easy_duphandle.c b/netutils/libcurl4nx/curl4nx_easy_duphandle.c new file mode 100644 index 000000000..dbe8b416a --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_duphandle.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_duphandle.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_duphandle() + ****************************************************************************/ + +FAR struct curl4nx_s *curl4nx_easy_duphandle(FAR struct curl4nx_s *handle) +{ +#warning TODO, this requires duplicating header entries + return NULL; +} + diff --git a/netutils/libcurl4nx/curl4nx_easy_escape.c b/netutils/libcurl4nx/curl4nx_easy_escape.c new file mode 100644 index 000000000..0232a2bec --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_escape.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_escape.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_escape() + ****************************************************************************/ + +FAR char *curl4nx_easy_escape(FAR struct curl4nx_s *curl, + FAR const char *string, int length) +{ + return NULL; +} + diff --git a/netutils/libcurl4nx/curl4nx_easy_getinfo.c b/netutils/libcurl4nx/curl4nx_easy_getinfo.c new file mode 100644 index 000000000..3a1650048 --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_getinfo.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_getinfo.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_getinfo() + ****************************************************************************/ + +int curl4nx_easy_getinfo(FAR struct curl4nx_s *curl, int info, + FAR void *value) +{ + return 0; +} + diff --git a/netutils/libcurl4nx/curl4nx_easy_init.c b/netutils/libcurl4nx/curl4nx_easy_init.c new file mode 100644 index 000000000..05019253c --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_init.c @@ -0,0 +1,77 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_init.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_init() + ****************************************************************************/ + +FAR struct curl4nx_s * curl4nx_easy_init(void) +{ + FAR struct curl4nx_s *handle = malloc(sizeof(struct curl4nx_s)); + + if (!handle) + { + curl4nx_err("Unable to allocate memory\n"); + return NULL; + } + + curl4nx_info("handle=%p\n", handle); + + memset(handle, 0, sizeof(struct curl4nx_s)); + + curl4nx_easy_reset(handle); + + return handle; +} diff --git a/netutils/libcurl4nx/curl4nx_easy_perform.c b/netutils/libcurl4nx/curl4nx_easy_perform.c new file mode 100644 index 000000000..cf77d250c --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_perform.c @@ -0,0 +1,642 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_perform.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +#if defined(CONFIG_NETUTILS_CODECS) +# if defined(CONFIG_CODECS_URLCODE) +# define WGET_USE_URLENCODE 1 +# include "netutils/urldecode.h" +# endif +# if defined(CONFIG_CODECS_BASE64) +# include "netutils/base64.h" +# endif +#else +# undef CONFIG_CODECS_URLCODE +# undef CONFIG_CODECS_BASE64 +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CURL4NX_STATE_STATUSLINE 0 +#define CURL4NX_STATE_STATUSCODE 1 +#define CURL4NX_STATE_STATUSREASON 2 +#define CURL4NX_STATE_HEADERS 3 +#define CURL4NX_STATE_DATA_NORMAL 4 +#define CURL4NX_STATE_DATA_CHUNKED 5 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_perform() + * + * Description: + * Resolve the hostname to an IP address. There are 3 cases: + * - direct IP: inet_aton is used + * - using internal curl4nx resolution + * - DNS resolution, if available + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_resolve + * Description: + * Translate a host name to an IP addres (V4 only for the moment) + * - either the host is a string with an IP + * - either the known hosts were defined by CURL4NXOPT_ + ****************************************************************************/ + +static int curl4nx_resolve(FAR struct curl4nx_s *handle, FAR char *hostname, + FAR struct in_addr *ip) +{ + int ret = inet_aton(hostname, ip); + if (ret != 0) + { + return CURL4NXE_OK; /* IP address is valid */ + } + + curl4nx_warn("Not a valid IP address, trying hostname resolution\n"); + return CURL4NXE_COULDNT_RESOLVE_HOST; +} + +/**************************************************************************** + * Name: curl4nx_is_header + * Description: + * Return TRUE if buf contains header, then update off to point at the + * beginning of header value + ****************************************************************************/ + +static int curl4nx_is_header(FAR char *buf, int len, + FAR const char *header, FAR int *off) +{ + if (strncasecmp(buf, header, strlen(header))) + { + return false; + } + + *off = strlen(header); + while ((*off) < len && buf[*off] == ' ') + { + (*off)++; + } + + return true; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_perform() + ****************************************************************************/ + +int curl4nx_easy_perform(FAR struct curl4nx_s *handle) +{ + struct sockaddr_in server; + FILE * stream; /* IOSTREAM used to printf in the socket TODO avoid */ + int rxoff; /* Current offset within RX buffer */ + char tmpbuf[16]; /* Buffer to hold small strings */ + int tmplen; /* Number of bytes used in tmpbuffer */ + int state; /* Current state of the parser */ + int ret; /* Return value from internal calls */ + char * headerbuf; + int headerlen; + char * end; + int cret = CURL4NXE_OK; /* Public return value */ + bool redirected = false; /* Boolean to manage HTTP redirections */ + bool chunked = false; + unsigned long long done = 0; + int redircount = 0; + + curl4nx_info("started\n"); + + stream = NULL; + headerbuf = malloc(CONFIG_LIBCURL4NX_MAXHEADERLINE); + if (!headerbuf) + { + cret = CURL4NXE_OUT_OF_MEMORY; + goto abort; + } + + if (handle->host[0] == 0 || handle->port == 0) + { + /* URL has not been set */ + + cret = CURL4NXE_URL_MALFORMAT; + goto freebuf; + } + + /* TODO: check that host and port have changed or are the same, so we can + * recycle the socket for the next request. + */ + + do + { + handle->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (handle->sockfd < 0) + { + /* socket failed. It will set the errno appropriately */ + + curl4nx_err("ERROR: socket failed: %d\n", errno); + cret = CURL4NXE_COULDNT_CONNECT; + goto freebuf; + } + + /* TODO: timeouts */ + + server.sin_family = AF_INET; + server.sin_port = htons(handle->port); + cret = curl4nx_resolve(handle, handle->host, &server.sin_addr); + if (cret != CURL4NXE_OK) + { + /* Could not resolve host (or malformed IP address) */ + + curl4nx_err("ERROR: Failed to resolve hostname\n"); + cret = CURL4NXE_COULDNT_RESOLVE_HOST; + goto freebuf; + } + + /* Connect to server. First we have to set some fields in the + * 'server' address structure. The system will assign me an arbitrary + * local port that is not in use. + */ + + ret = connect(handle->sockfd, + (struct sockaddr *)&server, sizeof(struct sockaddr_in)); + if (ret < 0) + { + curl4nx_err("ERROR: connect failed: %d\n", errno); + cret = CURL4NXE_COULDNT_CONNECT; + goto close; + } + + curl4nx_info("Connected...\n"); + + stream = fdopen(handle->sockfd, "wb"); + + /* Send request */ + + fprintf(stream, "%s %s HTTP/%d.%d\r\n", + handle->method, + handle->path, + handle->version >> 4, + handle->version & 0x0f); + + /* Send headers */ + + fprintf(stream, "Host: %s\r\n", handle->host); + + /* For the moment we do not support compression */ + + fprintf(stream, "Content-encoding: identity\r\n"); + + /* Send more headers */ + + /* End of headers */ + + fprintf(stream, "\r\n"); + + /* TODO send data */ + + fflush(stream); + curl4nx_info("Request sent\n"); + + /* Now wait for the result */ + + redirected = false; /* for now */ + state = CURL4NX_STATE_STATUSLINE; + tmplen = 0; + + while (1) + { + ret = recv(handle->sockfd, handle->rxbuf, handle->rxbufsize, 0); + if (ret < 0) + { + curl4nx_err("RECV failed, errno=%d\n", errno); + cret = CURL4NXE_RECV_ERROR; + goto close; + } + else if (ret == 0) + { + curl4nx_err("Connection lost\n"); + cret = CURL4NXE_GOT_NOTHING; + goto close; + } + + curl4nx_info("Received %d bytes\n", ret); + rxoff = 0; + + if (state == CURL4NX_STATE_STATUSLINE) + { + /* Accumulate HTTP/x.y until space */ + + while ((tmplen < sizeof(tmpbuf)) && (rxoff < ret)) + { + if (handle->rxbuf[rxoff] == ' ') + { + /* found space after http version */ + + tmpbuf[tmplen] = 0; /* Finish pending string */ + rxoff++; + curl4nx_info("received version: [%s]\n", tmpbuf); + tmplen = 0; /* reset buffer to look at code */ + state = CURL4NX_STATE_STATUSCODE; + break; + } + + /* Not a space: accumulate chars */ + + tmpbuf[tmplen] = handle->rxbuf[rxoff]; + tmplen++; + rxoff++; + } + + /* Check for overflow, version code should not fill the tmpbuf */ + + if (tmplen == sizeof(tmpbuf)) + { + /* extremely long http version -> invalid response */ + + curl4nx_err("Buffer overflow while reading version\n"); + cret = CURL4NXE_RECV_ERROR; + goto close; + } + + /* No overflow and no space found: wait for next buffer */ + } + + /* NO ELSE HERE, state may have changed and require new management + * for the same rx buffer. + */ + + if (state == CURL4NX_STATE_STATUSCODE) + { + /* Accumulate response code until space */ + + while ((tmplen < sizeof(tmpbuf)) && (rxoff < ret)) + { + if (handle->rxbuf[rxoff] == ' ') + { + /* Found space after http version */ + + tmpbuf[tmplen] = 0; /* Finish pending string */ + rxoff++; + curl4nx_info("received code: [%s]\n", tmpbuf); + handle->status = strtol(tmpbuf, &end, 10); + + if (*end != 0) + { + curl4nx_err("Bad status code [%s]\n", tmpbuf); + cret = CURL4NXE_RECV_ERROR; + goto close; + } + + tmplen = 0; /* reset buffer to look at code */ + state = CURL4NX_STATE_STATUSREASON; + break; + } + + /* Not a space: accumulate chars */ + + tmpbuf[tmplen] = handle->rxbuf[rxoff]; + tmplen++; + rxoff++; + } + + /* Check for overflow, version code should not fill the tmpbuf */ + + if (tmplen == sizeof(tmpbuf)) + { + /* Extremely long http code -> invalid response */ + + curl4nx_err("Buffer overflow while reading code\n"); + cret = CURL4NXE_RECV_ERROR; + goto close; + } + + /* No overflow and no space found: wait for next buffer */ + } + + if (state == CURL4NX_STATE_STATUSREASON) + { + /* Accumulate response code until CRLF */ + + while (rxoff < ret) + { + if (handle->rxbuf[rxoff] == 0x0d || + handle->rxbuf[rxoff] == 0x0a) + { + /* Accumulate all contiguous CR and LF in any order */ + + tmpbuf[tmplen] = handle->rxbuf[rxoff]; + tmplen++; + if (tmplen == 2) + { + if (tmpbuf[0] == 0x0d && tmpbuf[1] == 0x0a) + { + headerlen = 0; + handle->content_length = 0; + state = CURL4NX_STATE_HEADERS; + break; + } + else + { + tmplen = 0; /* Reset search for CRLF */ + } + } + } + else + { + /* This char is not interesting: reset storage */ + + tmplen = 0; + + /* curl4nx_info("-> %c\n", handle->rxbuf[rxoff]); */ + } + + rxoff++; + } + } + + if (state == CURL4NX_STATE_HEADERS) + { + while (rxoff < ret) + { + if (handle->rxbuf[rxoff] == 0x0d || + handle->rxbuf[rxoff] == 0x0a) + { + /* Accumulate all contiguous CR and LF in any order */ + + tmpbuf[tmplen] = handle->rxbuf[rxoff]; + tmplen++; + if (tmplen == 2) + { + if (tmpbuf[0] == 0x0d && tmpbuf[1] == 0x0a) + { + if (headerlen == 0) /* Found an empty header */ + { + curl4nx_info("\n"); + rxoff++; /* Skip this char */ + state = chunked ? + CURL4NX_STATE_DATA_CHUNKED : + CURL4NX_STATE_DATA_NORMAL; + break; + } + else + { + int off; + curl4nx_iofunc_f func; + headerbuf[headerlen] = 0; + func = handle->headerfunc; + if (func == NULL) + { + func = handle->writefunc; + } + + func(headerbuf, headerlen, 1, + handle->headerdata); + + /* Find the content-length */ + + if (curl4nx_is_header(headerbuf, headerlen, + "content-length:", + &off)) + { + handle->content_length = + strtoull(headerbuf + off, &end, 10); + if (*end != 0) + { + curl4nx_err("Stray chars after " + "content length!\n"); + cret = CURL4NXE_RECV_ERROR; + goto close; + } + + curl4nx_info("Found content length: " + "%llu\n", + handle->content_length); + } + + /* Find the transfer encoding */ + + if (curl4nx_is_header(headerbuf, headerlen, + "transfer-encoding:", + &off)) + { + chunked = !strncasecmp(headerbuf + off, + "chunked", 7); + if (chunked) + { + curl4nx_info("Transfer using " + "chunked format\n"); + } + } + + /* Find the location */ + + if (curl4nx_is_header(headerbuf, headerlen, + "location:", + &off)) + { + /* Parse the new URL if we get a + * redirection code. + */ + + if (handle->status >= 300 && + handle->status < 400) + { + if (handle->flags & + CURL4NX_FLAGS_FOLLOWLOCATION) + { + if ((handle->max_redirs > 0) && + (redircount >= + handle->max_redirs)) + { + curl4nx_info( + "Too many redirections\n"); + cret = CURL4NXE_TOO_MANY_REDIRECTS; + goto close; + } + + cret = + curl4nx_easy_setopt(handle, + CURL4NXOPT_URL, + headerbuf + off); + if (cret != CURL4NXE_OK) + { + goto close; + } + + redirected = true; + redircount += 1; + curl4nx_info("REDIRECTION (%d) -> %s\n", + redircount, + headerbuf + off); + } + } + } + + /* Prepare for next header */ + + headerlen = 0; + tmplen = 0; /* Reset search for CRLF */ + } + } + else + { + tmplen = 0; /* Reset search for CRLF */ + } + } + } + else + { + tmplen = 0; /* Reset CRLF detection */ + + /* Plus one for final zero */ + + if (headerlen < (CONFIG_LIBCURL4NX_MAXHEADERLINE - 1)) + { + headerbuf[headerlen] = handle->rxbuf[rxoff]; + headerlen++; + } + else + { + curl4nx_warn("prevented header overload\n"); + } + } + + rxoff++; + } + } + + if (state == CURL4NX_STATE_DATA_NORMAL) + { + if ((handle->flags & CURL4NX_FLAGS_FAILONERROR) && + handle->status >= 400) + { + cret = CURL4NXE_HTTP_RETURNED_ERROR; + goto close; + } + + curl4nx_info("now in normal data state, rxoff=%d rxlen=%d\n", + rxoff, ret); + done += (ret - rxoff); + + handle->writefunc(handle->rxbuf + rxoff, ret - rxoff, 1, + handle->writedata); + if (handle->content_length != 0) + { + curl4nx_info("Done %llu of %llu\n", + done, handle->content_length); + + if (handle->progressfunc) + { + handle->progressfunc(handle->progressdata, + handle->content_length, + done, 0, 0); + } + + if (handle->content_length == done) + { + /* Transfer is complete */ + + goto close; + } + } + } + + if (state == CURL4NX_STATE_DATA_CHUNKED) + { + if ((handle->flags & CURL4NX_FLAGS_FAILONERROR) && + handle->status >= 400) + { + cret = CURL4NXE_HTTP_RETURNED_ERROR; + goto close; + } + + curl4nx_info("now in chunked data state, rxoff=%d rxlen=%d\n", + rxoff, ret); + curl4nx_err("Not supported yet.\n"); + goto close; + } + } + + /* Done with this connection - this will also close the socket */ + +close: + curl4nx_info("Closing\n"); + if (stream) + { + fclose(stream); + } + } + while (redirected); + +freebuf: + free(headerbuf); + +abort: + curl4nx_info("done\n"); + return cret; +} diff --git a/netutils/libcurl4nx/curl4nx_easy_reset.c b/netutils/libcurl4nx/curl4nx_easy_reset.c new file mode 100644 index 000000000..330a4fa92 --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_reset.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_reset.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_LIBCURL4NX_USERAGENT +# if CONFIG_VERSION_MAJOR != 0 || CONFIG_VERSION_MINOR != 0 +# define CONFIG_LIBCURL4NX_USERAGENT \ + "NuttX/" CONFIG_VERSION_STRING " (; http://www.nuttx.org/)" +# else +# define CONFIG_LIBCURL4NX_USERAGENT \ + "NuttX/7.x (; http://www.nuttx.org/)" +# endif +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static size_t curl4nx_default_writefunc(FAR char *ptr, size_t size, + size_t nmemb, FAR void *data) +{ + fwrite(ptr, size, nmemb, stdout); + fflush(stdout); + return size * nmemb; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_reset() + ****************************************************************************/ + +void curl4nx_easy_reset(FAR struct curl4nx_s *handle) +{ + curl4nx_info("handle=%p\n", handle); + + /* Setup default options */ + + handle->port = 80; + strncpy(handle->useragent, CONFIG_LIBCURL4NX_USERAGENT, + sizeof(handle->useragent)); + strncpy(handle->method, "GET", sizeof(handle->method)); + handle->version = CURL4NX_HTTP_VERSION_1_1; + handle->writefunc = curl4nx_default_writefunc; + + if (handle->rxbufsize == 0) + { + /* RX buffer not initialized */ + + handle->rxbufsize = CONFIG_LIBCURL4NX_RXBUFLEN; + } + + if (handle->rxbuf != NULL) + { + free(handle->rxbuf); + handle->rxbuf = NULL; + } + + handle->rxbuf = malloc(handle->rxbufsize); + curl4nx_info("Allocated a %d bytes RX buffer\n", handle->rxbufsize); + + /* Delete all custom headers */ +} + diff --git a/netutils/libcurl4nx/curl4nx_easy_setopt.c b/netutils/libcurl4nx/curl4nx_easy_setopt.c new file mode 100644 index 000000000..0f6ec8acf --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_setopt.c @@ -0,0 +1,235 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_setopt.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_setopt() + ****************************************************************************/ + +int curl4nx_easy_setopt(FAR struct curl4nx_s *handle, int option, + FAR void *param) +{ + int ret; + int cret = CURL4NXE_OK; + char scheme[16]; + + switch (option) + { + case CURL4NXOPT_URL: + { + struct url_s url; + memset(&url, 0, sizeof(struct url_s)); + url.scheme = scheme; + url.schemelen = sizeof(scheme); + url.host = handle->host; + url.hostlen = CONFIG_LIBCURL4NX_MAXHOST; + url.path = handle->path; + url.pathlen = CONFIG_LIBCURL4NX_MAXPATH; + + ret = netlib_parseurl(param, &url); + + if (ret == -E2BIG) + { + cret = CURL4NXE_OUT_OF_MEMORY; + break; + } + else if (ret != 0) /* includes -EINVAL */ + { + curl4nx_warn("Malformed URL: %s\n", param); + cret = CURL4NXE_URL_MALFORMAT; + break; + } + + if (url.port == 0) + { + curl4nx_err("Invalid port 0\n"); + cret = CURL4NXE_URL_MALFORMAT; /* User passed invalid port */ + break; + } + + if (url.host[0] == 0) + { + curl4nx_err("Empty host\n"); + cret = CURL4NXE_URL_MALFORMAT; /* User passed empty host */ + break; + } + + if (strncmp(scheme, "http", strlen(scheme))) + { + curl4nx_err("Unsupported protocol '%s'\n", scheme); + cret = CURL4NXE_UNSUPPORTED_PROTOCOL; + break; + } + + handle->port = url.port; + curl4nx_info("found scheme: %s\n", scheme); + curl4nx_info("found host : %s\n", handle->host); + curl4nx_info("found port : %d\n", handle->port); + curl4nx_info("found path : %s\n", handle->path); + break; + } + + case CURL4NXOPT_PORT: + { + long port = (long)param; + if (port == 0) + { + cret = CURL4NXE_BAD_FUNCTION_ARGUMENT; + break; + } + handle->port = (uint16_t)(port & 0xffff); + break; + } + + case CURL4NXOPT_BUFFERSIZE: + { + long len = (long)param; + if (len < CONFIG_LIBCURL4NX_MINRXBUFLEN || + len > CONFIG_LIBCURL4NX_MAXRXBUFLEN) + { + cret = CURL4NXE_BAD_FUNCTION_ARGUMENT; + break; + } + + if (handle->rxbuf) + { + curl4nx_info("Freeing previous buffer\n"); + free(handle->rxbuf); + } + + handle->rxbuf = malloc(len); + if (!handle->rxbuf) + { + cret = CURL4NXE_OUT_OF_MEMORY; + break; + } + + handle->rxbufsize = len; + break; + } + + case CURL4NXOPT_HEADERFUNCTION: + if (param == NULL) + { + cret = CURL4NXE_BAD_FUNCTION_ARGUMENT; + break; + } + + handle->headerfunc = param; + break; + + case CURL4NXOPT_HEADERDATA: + handle->headerdata = param; + break; + + case CURL4NXOPT_FAILONERROR: + if ((long)param) + { + handle->flags |= CURL4NX_FLAGS_FAILONERROR; + } + else + { + handle->flags &= ~CURL4NX_FLAGS_FAILONERROR; + } + break; + + case CURL4NXOPT_FOLLOWLOCATION: + if ((long)param) + { + handle->flags |= CURL4NX_FLAGS_FOLLOWLOCATION; + } + else + { + handle->flags &= ~CURL4NX_FLAGS_FOLLOWLOCATION; + } + break; + + case CURL4NXOPT_MAXREDIRS: + { + long redirs = (long)param; + if (redirs < -1 || + redirs > CONFIG_LIBCURL4NX_MAXREDIRS) + { + cret = CURL4NXE_BAD_FUNCTION_ARGUMENT; + break; + } + handle->max_redirs = redirs; + break; + } + + case CURL4NXOPT_VERBOSE: + if ((long)param) + { + handle->flags |= CURL4NX_FLAGS_VERBOSE; + } + else + { + handle->flags &= ~CURL4NX_FLAGS_VERBOSE; + } + break; + + default: + cret = CURL4NXE_UNKNOWN_OPTION; + break; + } + + return cret; +} + diff --git a/netutils/libcurl4nx/curl4nx_easy_unescape.c b/netutils/libcurl4nx/curl4nx_easy_unescape.c new file mode 100644 index 000000000..d8700ad52 --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_easy_unescape.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * apps/netutils/libcurl4nx/curl4nx_easy_unescape.c + * Implementation of the HTTP client, cURL like interface. + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" +#include "netutils/curl4nx.h" +#include "curl4nx_private.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: curl4nx_easy_unescape() + ****************************************************************************/ + +FAR char *curl4nx_easy_unescape(FAR struct curl4nx_s *curl, + FAR const char *url, + int inlength, int *outlength) +{ + return NULL; +} + diff --git a/netutils/libcurl4nx/curl4nx_private.h b/netutils/libcurl4nx/curl4nx_private.h new file mode 100644 index 000000000..3ea706f1a --- /dev/null +++ b/netutils/libcurl4nx/curl4nx_private.h @@ -0,0 +1,188 @@ +/**************************************************************************** + * apps/netutils/curl4nx/curl4nx_private.h + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __APPS_NETUTILS_CURL4NX_CURL4NX_PRIVATE_H +#define __APPS_NETUTILS_CURL4NX_CURL4NX_PRIVATE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_LIBCURL4NX_MAXHOST +#define CONFIG_LIBCURL4NX_MAXHOST 128 +#endif + +#ifndef CONFIG_LIBCURL4NX_MAXPATH +#define CONFIG_LIBCURL4NX_MAXPATH 128 +#endif + +#ifndef CONFIG_LIBCURL4NX_MAXMETHOD +#define CONFIG_LIBCURL4NX_MAXMETHOD 10 +#endif + +#ifndef CONFIG_LIBCURL4NX_MAXUSERAGENT +#define CONFIG_LIBCURL4NX_MAXUSERAGENT 64 +#endif + +#ifndef CONFIG_LIBCURL4NX_RXBUFLEN +#define CONFIG_LIBCURL4NX_RXBUFLEN 512 +#endif + +#ifndef CONFIG_LIBCURL4NX_MAXHEADERLINE +#define CONFIG_LIBCURL4NX_MAXHEADERLINE 128 +#endif + +#ifndef CONFIG_LIBCURL4NX_MAXREDIRS +#define CONFIG_LIBCURL4NX_MAXREDIRS -1 /* Means unlimited */ +#endif + +#define CURL4NX_FLAGS_FAILONERROR 0x00000001 +#define CURL4NX_FLAGS_FOLLOWLOCATION 0x00000002 +#define CURL4NX_FLAGS_VERBOSE 0x00000004 + +#define curl4nx_err(fmt, ...) \ + do \ + { \ + if(handle->flags & CURL4NX_FLAGS_VERBOSE) \ + _err(fmt, ##__VA_ARGS__); \ + } \ + while(0) + +#define curl4nx_warn(fmt, ...) \ + do \ + { \ + if(handle->flags & CURL4NX_FLAGS_VERBOSE) \ + _warn(fmt, ##__VA_ARGS__); \ + } \ + while(0) + +#define curl4nx_info(fmt, ...) \ + do \ + { \ + if(handle->flags & CURL4NX_FLAGS_VERBOSE) \ + _info(fmt, ##__VA_ARGS__); \ + } \ + while(0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Name: struct curl4nx_header_s + * + * Description: Holds data for an individual http header added in a request. + * + ****************************************************************************/ + +struct curl4nx_header_s +{ + struct curl4nx_header_s *next; + FAR const char *value; +}; + +/**************************************************************************** + * Name: struct curl4nx_s + * + * Description: Holds the integrity of all informations required for a curl4nx + * transfer. + * + ****************************************************************************/ + +struct curl4nx_s +{ + /* Network stuff */ + + int sockfd; + + /* General stuff */ + + uint32_t flags; + bool verbose; + curl4nx_xferinfofunc_f progressfunc; /* Called when data chunks are received */ + FAR void * progressdata; + + /* Request side */ + + char host[CONFIG_LIBCURL4NX_MAXHOST]; + char path[CONFIG_LIBCURL4NX_MAXPATH]; + uint16_t port; + int version; + char method[CONFIG_LIBCURL4NX_MAXMETHOD]; + char useragent[CONFIG_LIBCURL4NX_MAXUSERAGENT]; + FAR struct curl4nx_header_s *headers; + int max_redirs; + + curl4nx_iofunc_f writefunc; /* Called when data has to be uploaded */ + FAR void * writedata; + + /* Response side */ + + int rxbufsize; + FAR char * rxbuf; + + int status; + unsigned long long content_length; + + curl4nx_iofunc_f readfunc; /* Called when data has to be downloaded */ + FAR void * readdata; + + curl4nx_iofunc_f headerfunc; /* Called when a complete HTTP header has been received */ + FAR void * headerdata; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __APPS_NETLIB_CURL4NX_CURL4NX_PRIVATE_H */