mirror of
https://github.com/lxsang/ant-http
synced 2025-07-13 13:04:23 +02:00
add support to reverse proxy (alpha)
This commit is contained in:
@ -24,35 +24,37 @@ THE SOFTWARE.
|
||||
#ifndef DICTIONARY_H
|
||||
#define DICTIONARY_H
|
||||
|
||||
#define DHASHSIZE 16
|
||||
#define for_each_assoc(assoc, dic) \
|
||||
for(unsigned int i = 0; i < dic->cap; i++) \
|
||||
for(assoc = dic->map[i];assoc!= NULL; assoc = assoc->next)
|
||||
#define DHASHSIZE 16
|
||||
#define for_each_assoc(assoc, dic) \
|
||||
for (unsigned int i = 0; i < dic->cap; i++) \
|
||||
for (assoc = dic->map[i]; assoc != NULL; assoc = assoc->next)
|
||||
|
||||
/**
|
||||
* Dictionary for header
|
||||
*/
|
||||
typedef struct __assoc{
|
||||
struct __assoc *next;
|
||||
char *key;
|
||||
void* value;
|
||||
typedef struct __assoc
|
||||
{
|
||||
struct __assoc *next;
|
||||
char *key;
|
||||
void *value;
|
||||
//char *value;
|
||||
} * chain_t;
|
||||
|
||||
typedef chain_t* map_t;
|
||||
typedef chain_t *map_t;
|
||||
|
||||
typedef struct __dict{
|
||||
typedef struct __dict
|
||||
{
|
||||
unsigned int cap;
|
||||
map_t map;
|
||||
unsigned int size;
|
||||
}* dictionary_t;
|
||||
} * dictionary_t;
|
||||
|
||||
dictionary_t dict();
|
||||
dictionary_t dict_n(unsigned int n);
|
||||
chain_t dlookup(dictionary_t,const char*);
|
||||
void* dvalue(dictionary_t, const char*);
|
||||
chain_t dput(dictionary_t,const char*, void*);
|
||||
chain_t dremove(dictionary_t, const char*);
|
||||
chain_t dlookup(dictionary_t, const char *);
|
||||
void *dvalue(dictionary_t, const char *);
|
||||
chain_t dput(dictionary_t, const char *, void *);
|
||||
chain_t dremove(dictionary_t, const char *);
|
||||
void freedict(dictionary_t);
|
||||
|
||||
#endif
|
79
lib/handle.c
79
lib/handle.c
@ -107,8 +107,8 @@ int compressable(char *ctype)
|
||||
|
||||
void htdocs(antd_request_t *rq, char *dest)
|
||||
{
|
||||
dictionary_t xheader = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
|
||||
char *www = (char *)dvalue(xheader, "SERVER_WWW_ROOT");
|
||||
//dictionary_t xheader = (dictionary_t)dvalue(rq->request, "REQUEST_HEADER");
|
||||
char *www = (char *)dvalue(rq->request, "SERVER_WWW_ROOT");
|
||||
if (www)
|
||||
{
|
||||
strcpy(dest, www);
|
||||
@ -527,7 +527,7 @@ int antd_send(void *src, const void *data_in, int len_in)
|
||||
writelen = (len - written) > BUFFLEN ? BUFFLEN : (len - written);
|
||||
time(&source->last_io);
|
||||
}
|
||||
else if (difftime(time(NULL), source->last_io) > MAX_IO_WAIT_TIME || (count == -1 && errno != EAGAIN && errno != EWOULDBLOCK))
|
||||
else if ((difftime(time(NULL), source->last_io) > MAX_IO_WAIT_TIME) || (count == -1 && errno != EAGAIN && errno != EWOULDBLOCK))
|
||||
{
|
||||
if (written == 0)
|
||||
written = count;
|
||||
@ -542,6 +542,76 @@ int antd_send(void *src, const void *data_in, int len_in)
|
||||
|
||||
return written;
|
||||
}
|
||||
/**
|
||||
* Read up to n bytes, not guaranty to have exactly nbytes
|
||||
* - return -1 if false
|
||||
* */
|
||||
int antd_recv_upto(void *src, void *data, int len)
|
||||
{
|
||||
if (!src)
|
||||
return -1;
|
||||
int received = 0;
|
||||
antd_client_t *source = (antd_client_t *)src;
|
||||
#ifdef USE_OPENSSL
|
||||
if (source->ssl)
|
||||
{
|
||||
ERR_clear_error();
|
||||
received = SSL_read(source->ssl, data, len);
|
||||
int err = SSL_get_error(source->ssl, received);
|
||||
if (received > 0)
|
||||
{
|
||||
time(&source->last_io);
|
||||
return received;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
{
|
||||
// peer disconnected...
|
||||
return -1;
|
||||
}
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
received = recv(((int)source->sock), data, len, 0);
|
||||
//LOG("Read : %c\n", *ptr);
|
||||
if (received > 0)
|
||||
{
|
||||
time(&source->last_io);
|
||||
return received;
|
||||
}
|
||||
if (received == 0 || (errno != EAGAIN && errno != EWOULDBLOCK))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#ifdef USE_OPENSSL
|
||||
}
|
||||
#endif
|
||||
}
|
||||
int antd_recv(void *src, void *data, int len)
|
||||
{
|
||||
if (!src)
|
||||
@ -688,7 +758,8 @@ int antd_recv(void *src, void *data, int len)
|
||||
time(&source->last_io);
|
||||
//LOG("Read len is %d\n", readlen);
|
||||
}
|
||||
else if (difftime(time(NULL), source->last_io) > MAX_IO_WAIT_TIME || (errno != EAGAIN && errno != EWOULDBLOCK))
|
||||
else if ((read == 0) ||
|
||||
difftime(time(NULL), source->last_io) > MAX_IO_WAIT_TIME || (errno != EAGAIN && errno != EWOULDBLOCK))
|
||||
{
|
||||
//ERROR("Error while reading: %s", strerror(errno));
|
||||
if (read == 0)
|
||||
|
@ -132,6 +132,7 @@ int ws_enable(dictionary_t);
|
||||
int read_buf(void *sock, char *buf, int i);
|
||||
int antd_send(void *source, const void *data, int len);
|
||||
int antd_recv(void *source, void *data, int len);
|
||||
int antd_recv_upto(void* src, void* data, int len);
|
||||
int antd_close(void *source);
|
||||
void destroy_request(void *data);
|
||||
#endif
|
||||
|
@ -694,7 +694,7 @@ void *antd_scheduler_wait(void *ptr)
|
||||
antd_queue_item_t it = NULL;
|
||||
antd_queue_item_t curr = NULL;
|
||||
antd_task_evt_item_t *eit = NULL;
|
||||
bst_node_t* node = NULL;
|
||||
bst_node_t* node, *task_node = NULL;
|
||||
struct pollfd *pfds = NULL;
|
||||
antd_scheduler_t *scheduler = (antd_scheduler_t *)ptr;
|
||||
|
||||
@ -745,6 +745,7 @@ void *antd_scheduler_wait(void *ptr)
|
||||
for (int i = 0; i < pollsize; i++)
|
||||
{
|
||||
// find the event
|
||||
task_node = NULL;
|
||||
node = bst_find(poll_list,i);
|
||||
if(node)
|
||||
eit = (antd_task_evt_item_t *)node->data;
|
||||
@ -755,9 +756,12 @@ void *antd_scheduler_wait(void *ptr)
|
||||
) {
|
||||
// event triggered schedule the task
|
||||
pthread_mutex_lock(&scheduler->scheduler_lock);
|
||||
scheduler->task_queue = bst_delete(scheduler->task_queue, eit->task->id);
|
||||
task_node = bst_find(scheduler->task_queue, eit->task->id);
|
||||
if(task_node)
|
||||
scheduler->task_queue = bst_delete(scheduler->task_queue, eit->task->id);
|
||||
pthread_mutex_unlock(&scheduler->scheduler_lock);
|
||||
antd_task_schedule(scheduler, eit->task);
|
||||
if(task_node)
|
||||
antd_task_schedule(scheduler, eit->task);
|
||||
}
|
||||
else if( (pfds[i].revents & POLLERR) || (pfds[i].revents & POLLHUP) ) {
|
||||
// task is no longer available
|
||||
@ -782,6 +786,8 @@ void *antd_scheduler_wait(void *ptr)
|
||||
|
||||
if (!scheduler->task_queue)
|
||||
{
|
||||
// reset id allocator
|
||||
//scheduler->id_allocator=0;
|
||||
// no task found, go to idle state
|
||||
sem_wait(scheduler->scheduler_sem);
|
||||
}
|
||||
@ -805,6 +811,7 @@ int antd_scheduler_next_id(antd_scheduler_t *sched, int input)
|
||||
|
||||
while (bst_find(sched->task_queue, id) != NULL)
|
||||
{
|
||||
sched->id_allocator++;
|
||||
id = sched->id_allocator;
|
||||
}
|
||||
pthread_mutex_unlock(&sched->scheduler_lock);
|
||||
|
58
lib/utils.c
58
lib/utils.c
@ -34,6 +34,8 @@ THE SOFTWARE.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h> //hostent
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/sha.h>
|
||||
@ -594,4 +596,60 @@ int guard_write(int fd, void* buffer, size_t size)
|
||||
n += st;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
send a request
|
||||
*/
|
||||
int request_socket(const char *ip, int port)
|
||||
{
|
||||
int sockfd;
|
||||
struct sockaddr_in dest;
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
ERROR("Socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/*struct linger lingerStruct;
|
||||
lingerStruct.l_onoff = 0; // turn lingering off for sockets
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct));*/
|
||||
|
||||
bzero(&dest, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(port);
|
||||
if (inet_aton(ip, &dest.sin_addr) == 0)
|
||||
{
|
||||
perror(ip);
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
if (connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) != 0)
|
||||
{
|
||||
close(sockfd);
|
||||
ERROR("Connect:%s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
char* ip_from_hostname(const char *hostname)
|
||||
{
|
||||
struct hostent *he;
|
||||
struct in_addr **addr_list;
|
||||
int i;
|
||||
if ((he = gethostbyname(hostname)) == NULL)
|
||||
{
|
||||
// get the host info
|
||||
ERROR("gethostbyname:%s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
addr_list = (struct in_addr **)he->h_addr_list;
|
||||
|
||||
for (i = 0; addr_list[i] != NULL; i++)
|
||||
{
|
||||
//Return the first one;
|
||||
return inet_ntoa(*addr_list[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
@ -96,4 +96,6 @@ void digest_to_hex(const uint8_t *, char *);
|
||||
void verify_header(char* k);
|
||||
int guard_read(int fd, void* buffer, size_t size);
|
||||
int guard_write(int fd, void* buffer, size_t size);
|
||||
int request_socket(const char *ip, int port);
|
||||
char* ip_from_hostname(const char *hostname);
|
||||
#endif
|
||||
|
81
lib/ws.c
81
lib/ws.c
@ -3,7 +3,6 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h> //hostent
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
@ -348,71 +347,6 @@ int ws_send_close(void *client, unsigned int status, int mask)
|
||||
//_send_header(client, header);
|
||||
//send(client,bytes,2,0);
|
||||
}
|
||||
int ip_from_hostname(const char *hostname, char *ip)
|
||||
{
|
||||
struct hostent *he;
|
||||
struct in_addr **addr_list;
|
||||
int i;
|
||||
if ((he = gethostbyname(hostname)) == NULL)
|
||||
{
|
||||
// get the host info
|
||||
ERROR("gethostbyname:%s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
addr_list = (struct in_addr **)he->h_addr_list;
|
||||
|
||||
for (i = 0; addr_list[i] != NULL; i++)
|
||||
{
|
||||
//Return the first one;
|
||||
strcpy(ip, inet_ntoa(*addr_list[i]));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
send a request
|
||||
*/
|
||||
int request_socket(const char *ip, int port)
|
||||
{
|
||||
int sockfd;
|
||||
struct sockaddr_in dest;
|
||||
|
||||
// time out setting
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = CONN_TIME_OUT_S;
|
||||
timeout.tv_usec = 0; //3 s
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
ERROR("Socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
|
||||
ERROR("setsockopt failed:%s", strerror(errno));
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
|
||||
ERROR("setsockopt failed:%s", strerror(errno));
|
||||
/*struct linger lingerStruct;
|
||||
lingerStruct.l_onoff = 0; // turn lingering off for sockets
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct));*/
|
||||
|
||||
bzero(&dest, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(port);
|
||||
if (inet_aton(ip, &dest.sin_addr) == 0)
|
||||
{
|
||||
perror(ip);
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
if (connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) != 0)
|
||||
{
|
||||
close(sockfd);
|
||||
ERROR("Connect:%s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void ws_client_close(ws_client_t *wsclient)
|
||||
{
|
||||
@ -437,9 +371,8 @@ void ws_client_close(ws_client_t *wsclient)
|
||||
//this is for the client side, not use for now
|
||||
int ws_client_connect(ws_client_t *wsclient, port_config_t pcnf)
|
||||
{
|
||||
char ip[100];
|
||||
int stat = ip_from_hostname(wsclient->host, ip);
|
||||
if (stat == -1)
|
||||
char* ip = ip_from_hostname(wsclient->host);
|
||||
if (ip == NULL)
|
||||
return -1;
|
||||
int sock = request_socket(ip, pcnf.port);
|
||||
if (sock <= 0)
|
||||
@ -447,6 +380,16 @@ int ws_client_connect(ws_client_t *wsclient, port_config_t pcnf)
|
||||
ERROR("Cannot request socket");
|
||||
return -1;
|
||||
}
|
||||
// time out setting
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = CONN_TIME_OUT_S;
|
||||
timeout.tv_usec = 0; //3 s
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
|
||||
ERROR("setsockopt failed:%s", strerror(errno));
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
|
||||
ERROR("setsockopt failed:%s", strerror(errno));
|
||||
|
||||
// will be free
|
||||
wsclient->antdsock->sock = sock;
|
||||
wsclient->antdsock->z_status = 0;
|
||||
|
2
lib/ws.h
2
lib/ws.h
@ -57,8 +57,6 @@ int ws_send_file(void *client, const char *file, int mask);
|
||||
int ws_send_binary(void *client, uint8_t *data, int l, int mask);
|
||||
|
||||
int ws_read_data(void *, ws_msg_header_t *, int, uint8_t *);
|
||||
int request_socket(const char *ip, int port);
|
||||
int ip_from_hostname(const char *hostname, char *ip);
|
||||
//int ws_open_hand_shake(const char* host, int port, const char* resource);
|
||||
char *get_ip_address();
|
||||
|
||||
|
Reference in New Issue
Block a user