Add:Servers module.

This commit is contained in:
Fancy code 2024-02-28 03:20:00 -08:00
parent 8b85c03e8d
commit c679ced96c
15 changed files with 1522 additions and 1 deletions

View File

@ -13,4 +13,5 @@ add_subdirectory(ModBusCRC16)
add_subdirectory(LedControl)
add_subdirectory(KeyControl)
add_subdirectory(MediaAdapter)
add_subdirectory(FxHttpServer)
add_subdirectory(FxHttpServer)
add_subdirectory(Servers)

136
utils/Servers/CMakeLists.txt Executable file
View File

@ -0,0 +1,136 @@
include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake)
set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH})
set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH})
include_directories(
./src
./include
${UTILS_SOURCE_PATH}/StatusCode/include
${UTILS_SOURCE_PATH}/Log/include
${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/include
)
#do not rely on any other library
# link_directories(
# ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/build/lib
# )
aux_source_directory(./src SRC_FILES)
set(TARGET_NAME Servers)
add_library(${TARGET_NAME} STATIC ${SRC_FILES})
target_link_libraries(${TARGET_NAME} Log)
if(${CURL_OPENSSL_LIB_SHARED_ENABLE} MATCHES "false")
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.a)
else()
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.so)
endif()
# ------------------ openssl ------------------ start
execute_process(COMMAND sh build_openssl.sh WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/openssl/)
if(${CURL_OPENSSL_LIB_SHARED_ENABLE} MATCHES "false")
# set(OPENSSL_TAILOR no-asm no-async no-md2 no-mdc2 no-poly1305 no-blake2
# no-siphash no-sm3 no-rc2 no-rc4 no-rc5 no-idea no-aria no-bf no-cast
# no-camellia no-chacha no-ec no-sm2 no-dso
# no-err no-comp no-cms no-ts no-cmac no-ct
# no-hw-padlock no-nextprotoneg no-psk no-rfc3779 no-srtp
# no-dgram no-dynamic-engine no-ec2m no-filenames no-gost
# no-afalgeng no-async no-autoalginit no-autoerrinit no-capieng
# no-tests
# no-ssl-trace no-static-engine no-stdio no-threads no-deprecated no-makedepend
# no-multiblock)
else()
# set(OPENSSL_TAILOR no-asm no-tests)
endif()
if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX})
set(OPENSSL_OS_PLATFORM "linux-x86_64")
else()
set(OPENSSL_OS_PLATFORM "linux-armv4")
# set(LINK_FLAGS "${LINK_FLAGS} -Wl,-rpath,${CURL_SHARED_LIBS_PATH}")
# set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_FLAGS}")
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_FLAGS}")
endif()
add_custom_target(
openssl
COMMAND echo "Build openssl."
COMMAND rm -rf ${EXTERNAL_SOURCE_PATH}/openssl/build
COMMAND ./Configure ${OPENSSL_TAILOR} ${OPENSSL_OS_PLATFORM} --prefix=${EXTERNAL_SOURCE_PATH}/openssl/build --openssldir=${EXTERNAL_SOURCE_PATH}/openssl/build --cross-compile-prefix=${CROSS_COMPILE_PREFIX} CC=gcc AR=ar
COMMAND make
COMMAND make install
WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/openssl/openssl-1.1.1s/
)
# ------------------ openssl ------------------ end
# ------------------ curl ------------------ start
execute_process(COMMAND sh build_curl.sh WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/curl/)
set(CURL_TAILOR --disable-dict --disable-file --disable-gopher
--disable-imap --disable-ldap --disable-pop3 --disable-rtmp
--disable-rtsp --disable-scp --disable-sftp --disable-smb
--disable-telnet --disable-tftp --disable-ipv6)
if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX})
set(CURL_HOST "")
else()
set(CURL_HOST "--host=arm-linux")
endif()
add_custom_target(
curl
DEPENDS openssl
COMMAND echo "Build curl. openssl path = ${EXTERNAL_SOURCE_PATH}"
COMMAND ./configure --without-zlib --prefix=${EXTERNAL_SOURCE_PATH}/curl --with-ssl=${EXTERNAL_SOURCE_PATH}/openssl/build ${CURL_HOST} CC=${CMAKE_C_COMPILER}
COMMAND make
COMMAND cp ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/lib*.a ${LIBS_OUTPUT_PATH}
COMMAND cp ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/lib*.a ${LIBS_OUTPUT_PATH}
# COMMAND cp ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/lib*.so* ${LIBS_OUTPUT_PATH}
# COMMAND cp ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/lib*.so* ${LIBS_OUTPUT_PATH}
WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/
)
# ------------------ curl ------------------ end
add_custom_command(
OUTPUT ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.a
COMMAND make curl
WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/cmake-shell/
)
add_custom_target(
compile_curl
DEPENDS ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.a
WORKING_DIRECTORY ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/
)
add_custom_command(
TARGET ${TARGET_NAME}
PRE_BUILD
COMMAND make compile_curl
WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/cmake-shell/
)
if ("${CLANG_TIDY_SUPPORT}" MATCHES "true")
add_custom_target(
Servers_code_check
COMMAND ${CLANG_TIDY_EXE}
-checks='${CLANG_TIDY_CHECKS}'
--header-filter=.*
--system-headers=false
${SRC_FILES}
${CLANG_TIDY_CONFIG}
-p ${PLATFORM_PATH}/cmake-shell
WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/Servers
)
file(GLOB_RECURSE HEADER_FILES *.h)
add_custom_target(
Servers_code_format
COMMAND ${CLANG_FORMAT_EXE}
-style=file
-i ${SRC_FILES} ${HEADER_FILES}
WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/Servers
)
add_custom_command(
TARGET ${TARGET_NAME}
PRE_BUILD
COMMAND make Servers_code_check
COMMAND make Servers_code_format
WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/
)
endif()
define_file_name(${TARGET_NAME})

109
utils/Servers/README.md Normal file
View File

@ -0,0 +1,109 @@
# 1. 服务器协议接口
## 1.1. 概述
   提供HTTP/FTP/SMTP协议的接口数据使用**curl+openssl开源库**二次封装。
## 1.2. 开发过程记录
1. 先编译openssl再编译curlcurl的构建配置需要指定openssl的输出文件目录否则curl将会构建失败
2. http协议指定url指定post数据curl即可按照POST发送请求
3. ftp/ftps协议对应不同的服务器IP必须一一对应
4. curl配置了忽略证书校验未知有什么实际影响
5. 分别对openssl和curl进行了裁剪
## 1.3. 关于MQTT
   curl源码包里并未提供MQTT相关的example网上搜索编码示例未找到。
## 1.4. Servers协议栈模块构建
   使用SifarSDK的构建体系进行编译编译curl时自动关联openssl进行编译。
* 配置文件(此处以/build/cmake/toolchain/linux.toolchain.cmake为示例
```
# ------------ build curl + openssl ------------ start
# 工具链前缀
set(CROSS_COMPILE_PREFIX "")
# 是否启动动态库(预留,暂未支持)
set(CURL_OPENSSL_LIB_SHARED_ENABLE "false")
# ------------ build curl + openssl ------------ end
```
* 项目根目录编译
```
make cmake
cd cmake-shell-linux/
make curl // 由于curl属于三方构建的开源库首次需要先编译curl + openssl
make Servers
```
## 1.5. Example
头文件servser.h
链接库libServers.a,libLog.a
三方依赖库(依次按序) libcurl.a,libssl.a,libcrypto.a
下述以FTP为例子
```
TEST(ServersTest, FtpsUpload)
{
const char *url = "ftp://150.109.112.64/ServersTest";test/bin/ServersTest";
const char *uploadFile = "./ServersTest";
const char *user_password = "ftp_user:Sifar%123456";
SERVERS_INIT init = {
.logFlag = LOG_FLAG_ENABLE, // 开启curl日志
.sslVerifyFlag = SSL_VERIFY_DISABLE, //关闭ssl的证书校验功能
};
InitLog(LOG_EASYLOGGING, nullptr); // 初始化自研log库
servers_init(init); // 初始化Servers模块
LogInfo("servers test start.\n");
SERVERS_FTP *ftp = new_servers_ftp(url, FTPS_FLAG_ENABLE); // 创建ftp的参数“句柄”
if (ftp)
{
ftp->user_password = (char *)user_password;
ftp->filePath = (char *)uploadFile;
ftp_upload(ftp); // 使用FTP上传文件
if (SERVERS_CODE_OK == ftp->code)
{
LogInfo("ftp succeed.\n");
}
else
{
LogError("ftp failed, code = %d.\n", static_cast<int>(ftp->code));
}
delete_servers_ftp(ftp); // 释放ftp“句柄”
}
UnInitLog();
}
```
**注意:**
* 必须调用servers_init()函数初始化Servers协议栈库
* 必须使用模块接口创建对应的协议参数“句柄”示例为new_servers_ftp();
* 必须释放协议参数“句柄”;
更多示例详见:/test/component/Servers/src/ServersTest.cpp
## 1.6. 测试
&emsp;&emsp; libServers.a自研代码通过asan测试未存在内存安全相关漏洞。
测试用例详见:/test/component/Servers/src/ServersTest.cpp
* 测试用例编译
```
make cmake
cd cmake-shell-linux/
make ServersTest
```
## 1.7. 总结
* 实现http/https/ftp/ftps/smtp/smtps接口
* 交叉编译测试ftp/ftps上传下载速率大概为1M/s333DE芯片平台
* 裁剪openssl和curl后编译的demo大小 < 1.2M
## 1.8. S530项目配置
* 工具链
```
set(CMAKE_C_COMPILER /opt/arm-ca9-linux-uclibcgnueabihf-8.4.01/usr/bin/arm-linux-gcc)
set(CMAKE_CXX_COMPILER /opt/arm-ca9-linux-uclibcgnueabihf-8.4.01/usr/bin/arm-linux-g++)
```
* curl + openssl
```
# ------------ build curl + openssl ------------ start
set(CROSS_COMPILE_PREFIX "/opt/arm-ca9-linux-uclibcgnueabihf-8.4.01/usr/bin/arm-linux-")
set(CURL_OPENSSL_LIB_SHARED_ENABLE "false")
set(CURL_SHARED_LIBS_PATH "/mnt/mmc")
# ------------ build curl + openssl ------------ end
```

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 SERVERS_H
#define SERVERS_H
#ifdef __cplusplus
extern "C" {
#endif
#define SERVERS_PARAM_NULL_MEANS_END NULL
#define SERVERS_NEVER_TIMEOUT 0
typedef enum
{
SERVERS_CODE_DEFAULT = -1,
SERVERS_CODE_OK = 0,
SERVERS_CODE_END
} ServersCode;
typedef enum
{
FTPS_FLAG_ENABLE = 0,
FTPS_FLAG_DISABLE,
FTPS_FLAG_END
} FtpsFlag;
typedef enum
{
LOG_FLAG_ENABLE = 0,
LOG_FLAG_DISABLE,
LOG_FLAG_END
} LogFlag;
typedef enum
{
SSL_VERIFY_ENABLE = 0,
SSL_VERIFY_DISABLE,
SSL_VERIFY_END
} SslFlag;
typedef struct servers_init
{
LogFlag logFlag;
SslFlag sslVerifyFlag;
} SERVERS_INIT;
typedef struct servers_http
{
const char *url;
char *postData;
char *filePath;
char **header;
char *reply;
unsigned int replyLength;
int code;
} SERVERS_HTTP;
typedef struct servers_ftp
{
const char *url;
const FtpsFlag ftpsFlag;
char *user_password;
char *filePath;
unsigned int timeOutMs;
int code;
} SERVERS_FTP;
typedef struct servers_smtp
{
const char *url;
const char *subject;
const char *from;
const char *to;
const char *userName;
const char *password;
const char *date;
char *inlineText;
char **toList;
unsigned int toListLength;
// char *text;
// unsigned int textLength;
char **attachment;
int code;
} SERVERS_SMTP;
void servers_init(SERVERS_INIT init);
void servers_unit(void);
// HTTP API
SERVERS_HTTP *new_servers_http(const char *url);
void delete_servers_http(SERVERS_HTTP *ptr);
void http_get(SERVERS_HTTP *param);
void http_post(SERVERS_HTTP *param);
void http_put(SERVERS_HTTP *param);
// FTP API
SERVERS_FTP *new_servers_ftp(const char *url, const FtpsFlag ftpsFlag);
void delete_servers_ftp(SERVERS_FTP *ptr);
void ftp_servers_check(SERVERS_FTP *param);
void ftp_download(SERVERS_FTP *param);
void ftp_upload(SERVERS_FTP *param);
// SMTP API
SERVERS_SMTP *new_servers_smtp(const char *url, const char *subject, const char *from, const char *to,
const char *userName, const char *password, const char *date);
void delete_servers_smtp(SERVERS_SMTP *ptr);
void smtp_send_email(SERVERS_SMTP *param);
#ifdef __cplusplus
}
#endif
#endif // !SERVERS_H

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 "curl_serve.h"
static SERVERS_INIT gCurlServe;
void set_verbose_log(LogFlag flag) { gCurlServe.logFlag = flag; }
void set_ssl_verify(SslFlag flag) { gCurlServe.sslVerifyFlag = flag; }
CURL *curl_easy_make(void)
{
CURL *curl;
curl = curl_easy_init();
if (!curl) {
return curl;
}
if (SSL_VERIFY_DISABLE == gCurlServe.sslVerifyFlag) {
/*
* If you want to connect to a site who is not using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
/*
* If the site you are connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
}
if (LOG_FLAG_ENABLE == gCurlServe.logFlag) {
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
}
return curl;
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 CURL_SERVE_H
#define CURL_SERVE_H
#include "servers.h"
#include <curl/curl.h>
#ifdef __cplusplus
extern "C" {
#endif
void set_verbose_log(LogFlag flag);
void set_ssl_verify(SslFlag flag);
CURL *curl_easy_make(void);
#ifdef __cplusplus
}
#endif
#endif // !CURL_SERVE_H

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 "ftp_servers.h"
#include "ILog.h"
#include "curl_serve.h"
#include <curl/curl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
struct FtpFile
{
const char *filename;
FILE *stream;
};
static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct FtpFile *out = (struct FtpFile *)stream;
if (!out->stream) {
/* open file for writing */
out->stream = fopen(out->filename, "wb");
if (!out->stream)
return -1; /* failure, cannot open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
static CURL *ftp_curl_easy_make(SERVERS_FTP *param)
{
CURL *curl = NULL;
curl = curl_easy_make();
if (curl) {
/*
* You better replace the URL with one that works!
*/
curl_easy_setopt(curl, CURLOPT_URL, param->url);
/* User and password for the FTP login */
if (param->user_password) {
curl_easy_setopt(curl, CURLOPT_USERPWD, param->user_password);
}
/* We activate SSL and we require it for both control and data */
if (FTPS_FLAG_ENABLE == param->ftpsFlag) {
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
}
if (SERVERS_NEVER_TIMEOUT < param->timeOutMs) {
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, param->timeOutMs);
}
}
return curl;
}
void ftp_servers_check_connect(SERVERS_FTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = ftp_curl_easy_make(param);
if (curl) {
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
res = curl_easy_perform(curl);
param->code = res;
/* always cleanup */
curl_easy_cleanup(curl);
if (CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
curl_global_cleanup();
}
void ftp_servers_download(SERVERS_FTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
CURL *curl;
CURLcode res;
struct FtpFile ftpfile = {param->filePath, /* name to store the file as if successful */
NULL};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = ftp_curl_easy_make(param);
if (curl) {
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
res = curl_easy_perform(curl);
param->code = res;
/* always cleanup */
curl_easy_cleanup(curl);
if (CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
if (ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
curl_global_cleanup();
}
/* NOTE: if you want this example to work on Windows with libcurl as a
DLL, you MUST also provide a read callback with CURLOPT_READFUNCTION.
Failing to do so will give you a crash since a DLL may not use the
variable's memory when passed in to it from an app like this. */
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
unsigned long nread;
/* in real-world cases, this would probably get this data differently
as this fread() stuff is exactly what the library already would do
by default internally */
size_t retcode = fread(ptr, size, nmemb, stream);
if (retcode > 0) {
nread = (unsigned long)retcode;
fprintf(stderr, "*** We read %lu bytes from file\n", nread);
}
return retcode;
}
void ftp_servers_upload(SERVERS_FTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
CURL *curl;
CURLcode res;
FILE *hd_src;
struct stat file_info;
unsigned long fsize;
struct curl_slist *headerlist = NULL;
// static const char buf_1[] = "RNFR " UPLOAD_FILE_AS; // TODO:
// static const char buf_2[] = "RNTO " RENAME_FILE_TO;
/* get the file size of the local file */
if (stat(param->filePath, &file_info)) {
LogInfo("Couldn't open '%s'\n", param->filePath);
return;
}
fsize = (unsigned long)file_info.st_size;
LogInfo("Local file size: %lu bytes.\n", fsize);
/* get a FILE * of the same file */
hd_src = fopen(param->filePath, "rb");
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = ftp_curl_easy_make(param);
if (curl) {
/* build a list of commands to pass to libcurl */
// headerlist = curl_slist_append(headerlist, buf_1); // TODO:
// headerlist = curl_slist_append(headerlist, buf_2);
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* pass in that last of FTP commands to run after the transfer */
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
/* Set the size of the file to upload (optional). If you give a *_LARGE
option you MUST make sure that the type of the passed-in argument is a
curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
make sure that to pass in a type 'long' argument. */
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);
/* Now run off and do what you have been told! */
res = curl_easy_perform(curl);
param->code = res;
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* clean up the FTP commands list */
curl_slist_free_all(headerlist);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 FTP_SERVERS_H
#define FTP_SERVERS_H
#include "servers.h"
#ifdef __cplusplus
extern "C" {
#endif
void ftp_servers_check_connect(SERVERS_FTP *param);
void ftp_servers_download(SERVERS_FTP *param);
void ftp_servers_upload(SERVERS_FTP *param);
#ifdef __cplusplus
}
#endif
#endif // !FTP_SERVERS_H

View File

@ -0,0 +1,224 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 "http_servers.h"
#include "ILog.h"
#include "curl_serve.h"
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static size_t write_cb(char *data, size_t n, size_t l, void *userp)
{
/* take care of the data here, ignored in this example */
(void)data;
(void)userp;
SERVERS_HTTP *p = (SERVERS_HTTP *)userp;
const int LENGTH = n * l;
// p->reply = (char *)realloc(p->reply, LENGTH);
char *newData = (char *)malloc(p->replyLength + LENGTH);
if (newData) {
if (p->reply) {
memcpy(newData, p->reply, p->replyLength);
free(p->reply);
p->reply = NULL;
}
memcpy(newData + p->replyLength, data, LENGTH);
p->replyLength += LENGTH;
p->reply = newData;
}
return n * l;
}
void http_servers_get(SERVERS_HTTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
CURL *curl;
CURLcode res;
curl = curl_easy_make();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, param->url);
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
//
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, param);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
param->code = res;
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
}
void http_servers_post(SERVERS_HTTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_make();
if (curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be an https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, param->url);
struct curl_slist *headers = NULL;
/* default type with postfields is application/x-www-form-urlencoded,
change it if you want */
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
/* Now specify the POST data */
if (param->postData) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param->postData);
}
else {
const char *NULL_POST_DATA = "{}";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL_POST_DATA);
}
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, param);
// curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);
// curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000L);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
/* free headers */
curl_slist_free_all(headers);
}
curl_global_cleanup();
}
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
size_t retcode;
unsigned long nread;
/* in real-world cases, this would probably get this data differently
as this fread() stuff is exactly what the library already would do
by default internally */
retcode = fread(ptr, size, nmemb, stream);
if (retcode > 0) {
nread = (unsigned long)retcode;
fprintf(stderr, "*** We read %lu bytes from file\n", nread);
}
return retcode;
}
void http_servers_put(SERVERS_HTTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
CURL *curl;
CURLcode res;
FILE *hd_src;
struct stat file_info;
struct curl_slist *headers = NULL;
char *file;
if (!param->filePath) {
LogError("file path is needed.\n");
return;
}
file = param->filePath;
/* get the file size of the local file */
stat(file, &file_info);
/* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just
an example! */
hd_src = fopen(file, "rb");
if (!hd_src) {
LogError("fopen files failed.\n");
return;
}
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_make();
if (curl) {
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* enable uploading (implies PUT over HTTP) */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* specify target URL, and note that this URL should include a file
name, not only a directory */
curl_easy_setopt(curl, CURLOPT_URL, param->url);
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
/* provide the size of the upload, we typecast the value to curl_off_t
since we must be sure to use the correct data size */
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, param);
// Add header
char **cpp = NULL;
for (cpp = param->header; *cpp; cpp++) {
headers = curl_slist_append(headers, *cpp);
}
if (headers) {
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
}
/* Now run off and do what you have been told! */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
/* free headers */
if (headers) {
curl_slist_free_all(headers);
}
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 HTTP_SERVERS_H
#define HTTP_SERVERS_H
#include "servers.h"
#ifdef __cplusplus
extern "C" {
#endif
void http_servers_get(SERVERS_HTTP *param);
void http_servers_post(SERVERS_HTTP *param);
void http_servers_put(SERVERS_HTTP *param);
#ifdef __cplusplus
}
#endif
#endif // !HTTP_SERVERS_H

146
utils/Servers/src/servers.c Normal file
View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 "servers.h"
#include "ILog.h"
#include "curl_serve.h"
#include "ftp_servers.h"
#include "http_servers.h"
#include "smtp_servers.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
void servers_init(SERVERS_INIT init)
{
set_verbose_log(init.logFlag);
set_ssl_verify(init.sslVerifyFlag);
}
void servers_unit(void) {}
void http_get(SERVERS_HTTP *param)
{
LogInfo("http_get\n");
http_servers_get(param);
}
void http_post(SERVERS_HTTP *param)
{
LogInfo("http_post\n");
http_servers_post(param);
}
void http_put(SERVERS_HTTP *param)
{
LogInfo("http_put\n");
http_servers_put(param);
}
void smtp_send_email(SERVERS_SMTP *param)
{
LogInfo("smtp_send_email\n");
smtp_servers_send_email(param);
// smtp_servers_send_email_only_text(param);
}
SERVERS_HTTP *new_servers_http(const char *url)
{
if (!url) {
LogError("new_servers_http failed.\n");
return NULL;
}
SERVERS_HTTP result = {
.url = url, .postData = NULL, .filePath = NULL, .header = NULL, .reply = NULL, .replyLength = 0, .code = 0};
const int LENGTH = sizeof(SERVERS_HTTP);
SERVERS_HTTP *p = (SERVERS_HTTP *)malloc(LENGTH);
if (p) {
LogInfo("malloc succeed.\n");
memcpy(p, &result, LENGTH);
}
return p;
}
void delete_servers_http(SERVERS_HTTP *ptr)
{
if (ptr) {
if (ptr->reply) {
free(ptr->reply);
ptr->reply = NULL;
}
free(ptr);
}
}
SERVERS_FTP *new_servers_ftp(const char *url, const FtpsFlag ftpsFlag)
{
if (!url) {
LogError("new_servers_ftp failed.\n");
return NULL;
}
SERVERS_FTP result = {.url = url,
.ftpsFlag = ftpsFlag,
.user_password = NULL,
.filePath = NULL,
.timeOutMs = SERVERS_NEVER_TIMEOUT,
.code = -1};
const int LENGTH = sizeof(SERVERS_FTP);
SERVERS_FTP *p = (SERVERS_FTP *)malloc(LENGTH);
if (p) {
LogInfo("malloc succeed.\n");
memcpy(p, &result, LENGTH);
}
return p;
}
void delete_servers_ftp(SERVERS_FTP *ptr)
{
if (ptr) {
free(ptr);
}
}
void ftp_servers_check(SERVERS_FTP *param) { ftp_servers_check_connect(param); }
void ftp_download(SERVERS_FTP *param)
{
LogInfo("ftp_download\n");
ftp_servers_download(param);
}
void ftp_upload(SERVERS_FTP *param)
{
LogInfo("ftp_upload\n");
ftp_servers_upload(param);
}
SERVERS_SMTP *new_servers_smtp(const char *url, const char *subject, const char *from, const char *to,
const char *userName, const char *password, const char *date)
{
if (!url || !from || !to || !userName || !password || !subject || !date) {
LogError("new_servers_smtp failed.\n");
return NULL;
}
SERVERS_SMTP result = {.url = url,
.subject = subject,
.from = from,
.to = to,
.userName = userName,
.password = password,
.date = date,
.inlineText = NULL,
// .text = NULL,
// .textLength = 0,
.attachment = NULL,
.code = -1};
const int LENGTH = sizeof(SERVERS_SMTP);
SERVERS_SMTP *p = (SERVERS_SMTP *)malloc(LENGTH);
if (p) {
LogInfo("malloc succeed.\n");
memcpy(p, &result, LENGTH);
}
return p;
}
void delete_servers_smtp(SERVERS_SMTP *ptr)
{
if (ptr) {
free(ptr);
}
}

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 "smtp_servers.h"
#include "ILog.h"
#include "curl_serve.h"
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct upload_status
{
char *payload_text;
size_t bytes_read;
};
// static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
// {
// struct upload_status *upload_ctx = (struct upload_status *)userp;
// const char *data;
// size_t room = size * nmemb;
// if ((size == 0) || (nmemb == 0) || ((size * nmemb) < 1))
// {
// return 0;
// }
// data = &upload_ctx->payload_text[upload_ctx->bytes_read];
// if (data)
// {
// size_t len = strlen(data);
// if (room < len)
// len = room;
// memcpy(ptr, data, len);
// upload_ctx->bytes_read += len;
// return len;
// }
// return 0;
// }
// static const char inline_html[] =
// "<html><body>\r\n"
// "<p>This is the inline <b>HTML</b> message of the email.</p>"
// "<br />\r\n"
// "<p>It could be a lot of HTML data that would be displayed by "
// "email viewers able to handle HTML.</p>"
// "</body></html>\r\n";
#define SEND_EMAIL_HEADERS_ARRAY_LENGTH 5
#define SEND_EMAIL_HEADERS_TEXT_LENGTH 1024
#define DATE "Date: "
#define TO "To: "
#define FROM "From: "
#define SUBJECT "Subject: "
#define HEADER_END "\r\n"
enum HEADERS_NAME
{
HEADERS_NAME_DATE = 0,
HEADERS_NAME_TO,
HEADERS_NAME_FROM,
HEADERS_NAME_SUBJECT,
HEADERS_NAME_END
};
static void headers_make(char **headers, SERVERS_SMTP *param)
{
int textLength = strlen(DATE) + strlen(param->date) + 1;
char *text = (char *)malloc(textLength);
if (text) {
memset(text, 0, textLength);
snprintf(text, textLength, "%s%s", DATE, param->date);
headers[HEADERS_NAME_DATE] = text;
LogInfo("HEADERS_NAME_DATE:%s\n", text);
}
textLength = strlen(TO) + strlen(param->to) + 1;
text = (char *)malloc(textLength);
if (text) {
memset(text, 0, textLength);
snprintf(text, textLength, "%s%s", TO, param->to);
headers[HEADERS_NAME_TO] = text;
LogInfo("HEADERS_NAME_TO:%s\n", text);
}
textLength = strlen(FROM) + strlen(param->from) + strlen(param->userName) + strlen("()") + 1;
text = (char *)malloc(textLength);
if (text) {
memset(text, 0, textLength);
snprintf(text, textLength, "%s%s(%s)", FROM, param->from, param->userName);
headers[HEADERS_NAME_FROM] = text;
LogInfo("HEADERS_NAME_FROM:%s\n", text);
}
textLength = strlen(SUBJECT) + strlen(param->subject) + 1;
text = (char *)malloc(textLength);
if (text) {
memset(text, 0, textLength);
snprintf(text, textLength, "%s%s", SUBJECT, param->subject);
headers[HEADERS_NAME_SUBJECT] = text;
LogInfo("HEADERS_NAME_SUBJECT:%s\n", text);
}
}
static void headers_free(char **headers)
{
char **cpp = headers;
for (int i = 0; i < SEND_EMAIL_HEADERS_ARRAY_LENGTH; i++) {
if (*cpp) {
free(*cpp);
headers[i] = NULL;
}
cpp++;
}
}
void smtp_servers_send_email(SERVERS_SMTP *param)
{
if (!param) {
LogError("null pointer.\n");
return;
}
char *headers_text[SEND_EMAIL_HEADERS_ARRAY_LENGTH] = {NULL};
headers_make(headers_text, param);
CURL *curl;
CURLcode res = CURLE_OK;
curl = curl_easy_make();
if (curl) {
struct curl_slist *headers = NULL;
struct curl_slist *recipients = NULL;
struct curl_slist *slist = NULL;
curl_mime *mime;
curl_mime *alt;
curl_mimepart *part;
const char **cpp;
const char **attachment;
/* This is the URL for your mailserver */
curl_easy_setopt(curl, CURLOPT_URL, param->url);
/* Set the username and password */
curl_easy_setopt(curl, CURLOPT_USERNAME, param->userName);
curl_easy_setopt(curl, CURLOPT_PASSWORD, param->password);
/* Note that this option is not strictly required, omitting it will result
* in libcurl sending the MAIL FROM command with empty sender data. All
* autoresponses should have an empty reverse-path, and should be directed
* to the address in the reverse-path which triggered them. Otherwise,
* they could cause an endless loop. See RFC 5321 Section 4.5.5 for more
* details.
*/
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, param->from);
/* Add two recipients, in this particular case they correspond to the
* To: and Cc: addressees in the header, but they could be any kind of
* recipient. */
recipients = curl_slist_append(recipients, param->to);
// recipients = curl_slist_append(recipients, CC);
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
/* Build and set the message header list. */
for (cpp = (const char **)headers_text; *cpp; cpp++) {
headers = curl_slist_append(headers, *cpp);
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
/* Build the mime message. */
mime = curl_mime_init(curl);
/* The inline part is an alternative proposing the html and the text
versions of the email. */
alt = curl_mime_init(curl);
/* HTML message. */
// part = curl_mime_addpart(alt);
// curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED);
// curl_mime_type(part, "text/html");
/* Text message. */
if (param->inlineText) {
part = curl_mime_addpart(alt);
curl_mime_data(part, param->inlineText, CURL_ZERO_TERMINATED);
curl_mime_type(part, "text/plain");
}
/* Create the inline part. */
part = curl_mime_addpart(mime);
curl_mime_subparts(part, alt);
curl_mime_type(part, "multipart/alternative");
slist = curl_slist_append(NULL, "Content-Disposition: inline");
curl_mime_headers(part, slist, 1);
/* Add the attachment. */
if (param->attachment) {
for (attachment = (const char **)param->attachment; *attachment; attachment++) {
part = curl_mime_addpart(mime);
curl_mime_filedata(part, *attachment);
}
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
}
/* Send the message */
res = curl_easy_perform(curl);
param->code = res;
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* Free lists. */
curl_slist_free_all(recipients);
if (headers)
curl_slist_free_all(headers);
/* curl will not send the QUIT command until you call cleanup, so you
* should be able to re-use this connection for additional messages
* (setting CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and
* calling curl_easy_perform() again. It may not be a good idea to keep
* the connection open for a very long time though (more than a few
* minutes may result in the server timing out the connection), and you do
* want to clean up in the end.
*/
curl_easy_cleanup(curl);
/* Free multipart message. */
curl_mime_free(mime);
headers_free(headers_text);
}
}
void smtp_servers_send_email_only_text(SERVERS_SMTP *param)
{
#if 0 // only for test.
if (!param)
{
LogError("null pointer.\n");
return;
}
int payloadTextLength =
strlen(DATE HEADER_END) + strlen(TO HEADER_END) + strlen(FROM HEADER_END) + strlen(SUBJECT HEADER_END) +
strlen(param->date) + strlen(param->to) + strlen(param->from) + strlen(param->subject);
if (param->inlineText)
{
payloadTextLength += strlen(param->inlineText);
}
char *payload_text = (char *)malloc(payloadTextLength);
if (!payload_text)
{
LogError("null pointer.\n");
return;
}
snprintf(payload_text, payloadTextLength, "%s%s%s"
"%s%s%s"
"%s%s%s"
"%s%s%s"
"%s",
DATE, param->date, HEADER_END,
TO, param->to, HEADER_END,
FROM, param->from, HEADER_END,
SUBJECT, param->subject, HEADER_END HEADER_END,
param->inlineText);
// LogInfo("payload_text =\n%s\n", payload_text);
CURL *curl;
CURLcode res = CURLE_OK;
struct curl_slist *recipients = NULL;
struct upload_status upload_ctx = {0};
upload_ctx.payload_text = payload_text;
curl = curl_easy_make();
if (curl)
{
curl_mime *mime;
curl_mime *alt;
curl_mimepart *part;
struct curl_slist *slist = NULL;
/* This is the URL for your mailserver */
curl_easy_setopt(curl, CURLOPT_URL, param->url);
/* Set the username and password */
curl_easy_setopt(curl, CURLOPT_USERNAME, param->userName);
curl_easy_setopt(curl, CURLOPT_PASSWORD, param->password);
/* Note that this option is not strictly required, omitting it will result
* in libcurl sending the MAIL FROM command with empty sender data. All
* autoresponses should have an empty reverse-path, and should be directed
* to the address in the reverse-path which triggered them. Otherwise,
* they could cause an endless loop. See RFC 5321 Section 4.5.5 for more
* details.
*/
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, param->from);
/* Add two recipients, in this particular case they correspond to the
* To: and Cc: addressees in the header, but they could be any kind of
* recipient. */
recipients = curl_slist_append(recipients, param->to);
// recipients = curl_slist_append(recipients, CC_ADDR);
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
/* We are using a callback function to specify the payload (the headers and
* body of the message). You could just use the CURLOPT_READDATA option to
* specify a FILE pointer to read from. */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// /* Build the mime message. */
// mime = curl_mime_init(curl);
// /* Create the inline part. */
// part = curl_mime_addpart(mime);
// curl_mime_subparts(part, alt);
// curl_mime_type(part, "multipart/alternative");
// slist = curl_slist_append(NULL, "Content-Disposition: inline");
// curl_mime_headers(part, slist, 1);
// curl_mime_filedata(part, "./Makefile");
// curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
/* Send the message */
res = curl_easy_perform(curl);
param->code = res;
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* Free the list of recipients */
curl_slist_free_all(recipients);
/* curl will not send the QUIT command until you call cleanup, so you
* should be able to re-use this connection for additional messages
* (setting CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and
* calling curl_easy_perform() again. It may not be a good idea to keep
* the connection open for a very long time though (more than a few
* minutes may result in the server timing out the connection), and you do
* want to clean up in the end.
*/
curl_easy_cleanup(curl);
/* Free multipart message. */
curl_mime_free(mime);
free(payload_text);
}
#endif
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2023 Fancy Code.
* 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 SMTP_SERVERS_H
#define SMTP_SERVERS_H
#include "servers.h"
#ifdef __cplusplus
extern "C" {
#endif
void smtp_servers_send_email(SERVERS_SMTP *param);
void smtp_servers_send_email_only_text(SERVERS_SMTP *param);
#ifdef __cplusplus
}
#endif
#endif // !SMTP_SERVERS_H

View File

@ -0,0 +1,35 @@
include(${CMAKE_SOURCE_DIR_SIFARSDK}/build/global_config.cmake)
set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH})
set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH})
include_directories(
${COMPONENT_SOURCE_PATH}/Log/include
${COMPONENT_SOURCE_PATH}/Servers/include
)
#do not rely on any other library
# link_directories(
# ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/build/lib
# )
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(./ SRC_FILES1)
set(TARGET_NAME ServersMainTest)
add_executable(${TARGET_NAME} ${SRC_FILES1})
target_link_libraries(${TARGET_NAME} Servers)
if(${CURL_OPENSSL_LIB_SHARED_ENABLE} MATCHES "false")
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.a)
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libssl.a)
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libcrypto.a)
else()
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/curl/curl-8.1.2/lib/.libs/libcurl.so)
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libssl.so)
target_link_libraries(${TARGET_NAME} ${EXTERNAL_SOURCE_PATH}/openssl/build/lib/libcrypto.so)
endif()
target_link_libraries(${TARGET_NAME} pthread dl)
if(${COVERAGE_ON} MATCHES "true")
target_link_libraries(${TARGET_NAME} gcov)
endif()

View File

@ -0,0 +1,38 @@
#include <unistd.h>
#include "servers.h"
void test0()
{
// InitLog(LOG_EASYLOGGING, NULL);
// LogInfo("servers test start.\n");
SERVERS_HTTP *http = new_servers_http("http://example.com");
if (http)
{
http_get(http);
if (http->reply)
{
// LogInfo("HttpGet ========\n %s\n", http->reply);
}
delete_servers_http(http);
}
// UnInitLog();
}
void test1()
{
// InitLog(LOG_EASYLOGGING, NULL);
// LogInfo("servers test start.\n");
// SERVERS_HTTP *http = new_servers_http("https://example.com");
// if (http)
// {
// http_get(http);
// if (http->reply)
// {
// LogInfo("HttpGet ========\n %s\n", http->reply);
// }
// delete_servers_http(http);
// }
// UnInitLog();
}
int main(int argc, char *argv[])
{
return 0;
}