* tpool.h
// https://nachtimwald.com/2019/04/12/thread-pool-in-c/
#ifndef ARP_TEST_TPOOL_H
#define ARP_TEST_TPOOL_H
#ifndef size_t
typedef unsigned long size_t;
#endif
#ifndef bool
typedef int bool;
#endif
struct tpool;
typedef struct tpool tpool_t;
typedef void (*thread_func_t)(void *arg);
tpool_t *tpool_create(size_t num);
void tpool_destroy(tpool_t *tm);
bool tpool_add_work(tpool_t *tm, thread_func_t func, void *arg);
void tpool_wait(tpool_t *tm);
#endif //ARP_TEST_TPOOL_H
* tpool.c
#include <pthread.h>
#include <stdlib.h> /* malloc, free */
#include "tpool.h"
struct tpool_work {
thread_func_t func;
void *arg;
struct tpool_work *next;
};
typedef struct tpool_work tpool_work_t;
struct tpool {
tpool_work_t *work_first;
tpool_work_t *work_last;
pthread_mutex_t work_mutex;
pthread_cond_t work_cond;
pthread_cond_t working_cond;
size_t working_cnt;
size_t thread_cnt;
bool stop;
};
static tpool_work_t *tpool_work_create(thread_func_t func, void *arg) {
tpool_work_t *work;
if (func == NULL)
return NULL;
work = malloc(sizeof(*work));
work->func = func;
work->arg = arg;
work->next = NULL;
return work;
}
static void tpool_work_destroy(tpool_work_t *work) {
if (work == NULL)
return;
free(work);
}
static tpool_work_t *tpool_work_get(tpool_t *tm) {
tpool_work_t *work;
if (tm == NULL)
return NULL;
work = tm->work_first;
if (work == NULL)
return NULL;
if (work->next == NULL) {
tm->work_first = NULL;
tm->work_last = NULL;
} else {
tm->work_first = work->next;
}
return work;
}
static void *tpool_worker(void *arg) {
tpool_t *tm = arg;
tpool_work_t *work;
while (1) {
pthread_mutex_lock(&tm->work_mutex);
while (tm->work_first == NULL && !tm->stop) {
pthread_cond_wait(&tm->work_cond, &tm->work_mutex);
}
if (tm->stop) {
break;
}
work = tpool_work_get(tm);
tm->working_cnt++;
pthread_mutex_unlock(&tm->work_mutex);
if (work != NULL) {
work->func(work->arg);
tpool_work_destroy(work);
}
pthread_mutex_lock(&tm->work_mutex);
tm->working_cnt--;
if (!tm->stop && tm->working_cnt == 0 && tm->work_first == NULL) {
pthread_cond_signal(&tm->working_cond);
}
pthread_mutex_unlock(&tm->work_mutex);
}
tm->thread_cnt--;
pthread_cond_signal(&tm->working_cond);
pthread_mutex_unlock(&tm->work_mutex);
return NULL;
}
tpool_t *tpool_create(size_t num) {
tpool_t *tm;
pthread_t thread;
size_t i;
if (num == 0)
num = 2;
tm = calloc(1, sizeof(*tm));
tm->thread_cnt = num;
pthread_mutex_init(&tm->work_mutex, NULL);
pthread_cond_init(&tm->work_cond, NULL);
pthread_cond_init(&tm->working_cond, NULL);
tm->work_first = NULL;
tm->work_last = NULL;
for (i=0; i<num; i++) {
pthread_create(&thread, NULL, tpool_worker, tm);
pthread_detach(thread);
}
return tm;
}
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
void tpool_destroy(tpool_t *tm)
{
tpool_work_t *work;
tpool_work_t *work2;
if (tm == NULL)
return;
pthread_mutex_lock(&tm->work_mutex);
work = tm->work_first;
while (work != NULL) {
work2 = work->next;
tpool_work_destroy(work);
work = work2;
}
tm->stop = true;
pthread_cond_broadcast(&tm->work_cond);
pthread_mutex_unlock(&tm->work_mutex);
tpool_wait(tm);
pthread_mutex_destroy(&tm->work_mutex);
pthread_cond_destroy(&tm->work_cond);
pthread_cond_destroy(&tm->working_cond);
free(tm);
}
bool tpool_add_work(tpool_t *tm, thread_func_t func, void *arg)
{
tpool_work_t *work;
if (tm == NULL) {
return false;
}
work = tpool_work_create(func, arg);
if (work == NULL) {
return false;
}
pthread_mutex_lock(&tm->work_mutex);
if (tm->work_first == NULL) {
tm->work_first = work;
tm->work_last = tm->work_first;
} else {
tm->work_last->next = work;
tm->work_last = work;
}
pthread_cond_broadcast(&tm->work_cond);
pthread_mutex_unlock(&tm->work_mutex);
return true;
}
void tpool_wait(tpool_t *tm)
{
if (tm == NULL)
return;
pthread_mutex_lock(&tm->work_mutex);
while ((!tm->stop && tm->working_cnt != 0) || (tm->stop && tm->thread_cnt != 0)) {
pthread_cond_wait(&tm->working_cond, &tm->work_mutex);
}
pthread_mutex_unlock(&tm->work_mutex);
}
Usage:
typedef struct {
char path_dst[256];
char path_src[256];
char ip[16];
} save_response_t;
void https_worker(void *param) {
save_response_t *args = (save_response_t *)param;
https_get_body(args->ip, args->path_src, args->path_dst);
}
int main(int argc, char *argv[]) {
tpool_t *tm;
int i;
save_response_t thread_args;
/* ... */
strcpy(thread_args.path_dst, path_dst);
strcpy(thread_args.path_src, path_src);
strcpy(thread_args.ip, ip);
/* @ref: https://nachtimwald.com/2019/04/12/thread-pool-in-c/ */
tm = tpool_create(4);
for (i = 0; i < 1048576; i++) {
tpool_add_work(tm, https_worker, &thread_args);
}
tpool_wait(tm);
tpool_destroy(tm);
return 0;
}
* https.h
#ifndef ARP_TEST_HTTPS_H
#define ARP_TEST_HTTPS_H
int https_get_body(char *ip, char *in_path, char *out_path);
#endif //ARP_TEST_HTTPS_H
* https.c
/*
* @ref: https://aticleworld.com/ssl-server-client-using-openssl-in-c/
* sudo apt-get install libssl–dev
* -L/path/to/ssl_dir -lssl -lcrypto
*/
#include <string.h> /* memset */
#include "arclog.h" /* bclerreg, E_FAIL */
#include "bcl_socket.h"
#include "https.h"
#include <openssl/ssl.h> /* SSL_Library_init() */
#include <openssl/err.h>
extern unsigned int ip2int(const char *ip);
static SSL_CTX *InitCTX(void) {
SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */
method = TLSv1_2_client_method(); /* Create new client-method instance */
ctx = SSL_CTX_new(method); /* Create new context */
if ( ctx == NULL ) {
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}
ssize_t send_from_file_ssl(SSL *ssl, char *path) {
byte_t *buf = NULL;
size_t isz = 0;
ssize_t outBytes;
buf = file_get_contents(path, &isz);
/* bcl_xxd(buf, isz); */
outBytes = SSL_write(ssl, buf, isz);
/* bcl_xxd(buf, isz); */
free(buf);
return outBytes;
}
int https_get_body(char *ip, char *in_path, char *out_path) {
SSL_CTX *ctx = NULL;
SSL *ssl;
int bytes;
#define HTTPS_BUFF_SIZE 4096
char buf[HTTPS_BUFF_SIZE];
int sockfd = -1;
FILE *out = NULL;
char *body = NULL;
SSL_library_init();
ctx = InitCTX();
ssl = SSL_new(ctx); /* create new SSL connection state */
sockfd = bcl_tcp_connector(ip2int(ip), 443);
SSL_set_fd(ssl, sockfd); /* attach the socket descriptor */
if ( SSL_connect(ssl) < 0 ) { /* perform the connection */
ERR_print_errors_fp(stderr);
return E_FAIL;
}
send_from_file_ssl(ssl, in_path);
bytes = SSL_read(ssl, buf, HTTPS_BUFF_SIZE);
/* Dump HTTP header */
bcl_xxd(buf, bytes);
out = fopen(out_path, "w");
if (NULL == out) {
bclerreg(E_OSCALL, _FL_, "fopen(%s)", out_path);
return E_FAIL;
}
if (NULL != (body = strstr(buf, "\r\n\r\n"))) {
body += 4;
fwrite(body, 1, strlen(body), out);
}
while (0<(bytes = SSL_read(ssl, buf, HTTPS_BUFF_SIZE))) {
fwrite(buf, 1, bytes, out);
memset(buf, 0, bytes);
}
fclose(out);
bcl_closesock(sockfd);
SSL_free(ssl);
SSL_CTX_free(ctx);
return E_OK;
}
/mnt/e/CLionProjects/arp/fap30/print/sms.txt
POST /index.php/api/sendCode?phone=131****9242&type=1 HTTP/1.1
Host: enjoysoft.021city.cn
Accept: application/json
Connection: Closed
X-Forwared-For: 121.5.101.32
C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "export ESWTDIR=/mnt/e/CLionProjects/arp && export FAPWORKDIR=/mnt/e/CLionProjects/arp/fap30 && cd /mnt/e/CLionProjects/arp/fap30 && /mnt/e/CLionProjects/arp/cmake-build-debug/arp_test ./input/banner.txt banner_3.jpg"
ip=121.5.101.32
path_dst=/mnt/e/CLionProjects/arp/fap30/print/sms.txt
00000000: 4854 5450 2f31 2e31 2032 3030 204f 4b0d HTTP/1.1 200 OK.
00000010: 0a53 6572 7665 723a 206e 6769 6e78 0d0a .Server: nginx..
00000020: 436f 6e74 656e 742d 5479 7065 3a20 6170 Content-Type: ap
00000030: 706c 6963 6174 696f 6e2f 6a73 6f6e 0d0a plication/json..
00000040: 5472 616e 7366 6572 2d45 6e63 6f64 696e Transfer-Encodin
00000050: 673a 2063 6875 6e6b 6564 0d0a 436f 6e6e g: chunked..Conn
00000060: 6563 7469 6f6e 3a20 636c 6f73 650d 0a43 ection: close..C
00000070: 6163 6865 2d43 6f6e 7472 6f6c 3a20 6e6f ache-Control: no
00000080: 2d63 6163 6865 2c20 7072 6976 6174 650d -cache, private.
00000090: 0a44 6174 653a 204d 6f6e 2c20 3330 204f .Date: Mon, 30 O
000000a0: 6374 2032 3032 3320 3032 3a30 313a 3437 ct 2023 02:01:47
000000b0: 2047 4d54 0d0a 582d 5261 7465 4c69 6d69 GMT..X-RateLimi
000000c0: 742d 4c69 6d69 743a 2036 300d 0a58 2d52 t-Limit: 60..X-R
000000d0: 6174 654c 696d 6974 2d52 656d 6169 6e69 ateLimit-Remaini
000000e0: 6e67 3a20 3536 0d0a 4163 6365 7373 2d43 ng: 56..Access-C
000000f0: 6f6e 7472 6f6c 2d41 6c6c 6f77 2d4f 7269 ontrol-Allow-Ori
00000100: 6769 6e3a 202a 0d0a 5374 7269 6374 2d54 gin: *..Strict-T
00000110: 7261 6e73 706f 7274 2d53 6563 7572 6974 ransport-Securit
00000120: 793a 206d 6178 2d61 6765 3d33 3135 3336 y: max-age=31536
00000130: 3030 300d 0a0d 0a61 380d 0a7b 226d 6573 000....a8..{"mes
00000140: 7361 6765 223a 2266 6169 6c65 6422 2c22 sage":"failed","
00000150: 636f 6465 223a 3130 3031 2c22 7265 7375 code":1001,"resu
00000160: 6c74 223a 7b22 6d73 6722 3a22 7468 6520 lt":{"msg":"the
00000170: 6e75 6d62 6572 206f 6620 736d 7320 6d65 number of sms me
00000180: 7373 6167 6573 2073 656e 7420 6672 6f6d ssages sent from
00000190: 2061 2073 696e 676c 6520 6d6f 6269 6c65 a single mobile
000001a0: 206e 756d 6265 7220 6576 6572 7920 6461 number every da
000001b0: 7920 6578 6365 6564 7320 7468 6520 7570 y exceeds the up
000001c0: 7065 7220 6c69 6d69 7422 7d2c 2274 696d per limit"},"tim
000001d0: 6573 7461 6d70 223a 3136 3938 3633 3133 estamp":16986313
000001e0: 3037 7d0d 0a30 0d0a 0d0a 07}..0....