ant-http/libs/handle.c

659 lines
16 KiB
C
Raw Normal View History

#include "handle.h"
2018-02-10 11:22:41 +01:00
#ifdef USE_OPENSSL
int usessl()
{
return 0;
}
#endif
2017-07-29 22:00:34 +02:00
2018-02-10 11:22:41 +01:00
void set_status(void* client,int code,const char* msg)
2017-07-29 22:00:34 +02:00
{
2018-03-02 19:04:00 +01:00
char *s = __s("HTTP/1.1 %d %s", code, msg);
response(client, s);
free(s);
s = __s("Server: %s ", SERVER_NAME);
response(client, s);
free(s);
2017-07-29 22:00:34 +02:00
}
2018-02-10 11:22:41 +01:00
void redirect(void* client,const char*path)
2017-07-29 22:00:34 +02:00
{
__t(client,"<html><head><meta http-equiv=\"refresh\" content=\"0; url=%s\"></head><body></body></html>",path);
}
2018-02-10 11:22:41 +01:00
void html(void* client)
2017-07-29 22:00:34 +02:00
{
ctype(client,"text/html; charset=utf-8");
}
2018-02-10 11:22:41 +01:00
void text(void* client)
2017-07-29 22:00:34 +02:00
{
ctype(client,"text/plain; charset=utf-8");
}
2018-02-10 11:22:41 +01:00
void json(void* client)
2017-07-29 22:00:34 +02:00
{
ctype(client,"application/json");
}
2018-02-10 11:22:41 +01:00
void textstream(void* client)
2017-07-29 22:00:34 +02:00
{
ctype(client, "text/event-stream");
}
2018-02-10 11:22:41 +01:00
void octstream(void* client, char* name)
2017-07-29 22:00:34 +02:00
{
set_status(client,200,"OK");
__t(client,"Content-Type: application/octet-stream");
__t(client,"Content-Disposition: attachment; filename=\"%s\"", name);
response(client,"");
//Content-Disposition: attachment; filename="fname.ext"
}
2018-02-10 11:22:41 +01:00
void jpeg(void* client)
2017-07-29 22:00:34 +02:00
{
ctype(client,"image/jpeg");
}
2018-02-10 11:22:41 +01:00
void ctype(void* client, const char* type)
2017-07-29 22:00:34 +02:00
{
set_status(client,200,"OK");
__t(client,"Content-Type: %s",type);
response(client,"");
}
2018-02-10 11:22:41 +01:00
int response(void* client, const char* data)
2017-07-29 22:00:34 +02:00
{
char buf[BUFFLEN+3];
strcpy(buf, data);
int nbytes;
int size = strlen(data);
buf[size] = '\r';
buf[size+1] = '\n';
2018-02-10 11:22:41 +01:00
buf[size+2] = '\0';
2018-02-10 13:44:25 +01:00
nbytes = antd_send(client, buf, strlen(buf));
2017-07-29 22:00:34 +02:00
return (nbytes ==-1?0:1);
}
2018-05-03 15:12:10 +02:00
int antd_send(void *src, const void* data, int len)
2018-02-10 11:22:41 +01:00
{
2018-03-02 19:04:00 +01:00
if(!src || !data) return -1;
2018-10-09 17:24:00 +02:00
int written;
2018-02-10 11:22:41 +01:00
antd_client_t * source = (antd_client_t *) src;
2018-10-27 12:58:12 +02:00
char* ptr;
int writelen;
int count;
2018-02-10 11:22:41 +01:00
#ifdef USE_OPENSSL
2018-02-10 13:44:25 +01:00
if(usessl())
2018-02-10 11:22:41 +01:00
{
2018-02-10 12:24:01 +01:00
//LOG("SSL WRITE\n");
2018-10-09 17:24:00 +02:00
//ret = SSL_write((SSL*) source->ssl, data, len);
2018-10-27 12:58:12 +02:00
ptr = (char* )data;
writelen = len > BUFFLEN?BUFFLEN:len;
2018-10-09 17:24:00 +02:00
written = 0;
fd_set fds;
struct timeval timeout;
2018-10-15 12:28:04 +02:00
while (writelen > 0) //source->attempt < MAX_ATTEMPT
2018-10-09 17:24:00 +02:00
{
count = SSL_write (source->ssl, ptr+written, writelen);
if (count > 0)
{
written += count;
writelen = (len - written) > BUFFLEN?BUFFLEN:(len-written);
}
else
{
//printf(" received equal to or less than 0\n")
int err = SSL_get_error(source->ssl, count);
switch (err)
{
case SSL_ERROR_NONE:
{
// no real error, just try again...
//LOG("SSL_ERROR_NONE \n");
2018-10-15 12:28:04 +02:00
//source->attempt++;
2018-10-09 17:24:00 +02:00
continue;
}
case SSL_ERROR_ZERO_RETURN:
{
// peer disconnected...
//printf("SSL_ERROR_ZERO_RETURN \n");
break;
}
case SSL_ERROR_WANT_READ:
{
// no data available right now, wait a few seconds in case new data arrives...
//printf("SSL_ERROR_WANT_READ\n");
int sock = SSL_get_rfd(source->ssl);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 0;
timeout.tv_usec = 500;
err = select(sock+1, &fds, NULL, NULL, &timeout);
if (err == 0 || (err > 0 && FD_ISSET(sock, &fds)))
2018-10-14 10:57:09 +02:00
{
2018-10-15 12:28:04 +02:00
//source->attempt++;
2018-10-09 17:24:00 +02:00
continue; // more data to read...
2018-10-14 10:57:09 +02:00
}
break;
2018-10-09 17:24:00 +02:00
}
case SSL_ERROR_WANT_WRITE:
{
// socket not writable right now, wait a few seconds and try again...
//printf("SSL_ERROR_WANT_WRITE \n");
int sock = SSL_get_wfd(source->ssl);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 0;
timeout.tv_usec = 500;
err = select(sock+1, NULL, &fds, NULL, &timeout);
if (err == 0 || (err > 0 && FD_ISSET(sock, &fds)))
2018-10-14 10:57:09 +02:00
{
2018-10-15 12:28:04 +02:00
//source->attempt++;
2018-10-09 17:24:00 +02:00
continue; // can write more data now...
2018-10-14 10:57:09 +02:00
}
break;
2018-10-09 17:24:00 +02:00
}
default:
{
// other error
break;
}
}
break;
}
}
2018-10-15 21:35:57 +02:00
//source->attempt = 0;
2018-02-10 11:22:41 +01:00
}
else
{
#endif
2018-10-27 16:15:25 +02:00
ptr = (char* )data;
2018-10-27 12:58:12 +02:00
writelen = len > BUFFLEN?BUFFLEN:len;
written = 0;
while (writelen > 0)
{
2018-10-27 16:15:25 +02:00
count = send(source->sock, ptr+written, writelen, 0);
2018-10-27 12:58:12 +02:00
if (count > 0)
{
written += count;
writelen = (len - written) > BUFFLEN?BUFFLEN:(len-written);
}
2018-10-27 16:15:25 +02:00
else if(count == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
2018-10-27 12:58:12 +02:00
{
2018-10-27 16:15:25 +02:00
return written;
2018-10-27 12:58:12 +02:00
}
}
2018-02-10 11:22:41 +01:00
#ifdef USE_OPENSSL
}
#endif
2018-06-26 13:40:53 +02:00
/*if(ret <= 0)
2018-05-03 15:10:44 +02:00
{
antd_close(src);
2018-06-26 13:40:53 +02:00
}*/
2018-10-09 17:24:00 +02:00
return written;
2018-02-10 11:22:41 +01:00
}
2018-05-03 15:12:10 +02:00
int antd_recv(void *src, void* data, int len)
2018-02-10 11:22:41 +01:00
{
2018-02-10 12:24:01 +01:00
if(!src) return -1;
2018-10-27 16:15:25 +02:00
int read=0;
char* ptr = NULL;
int received=0;
int readlen=0;
2018-02-10 11:22:41 +01:00
antd_client_t * source = (antd_client_t *) src;
#ifdef USE_OPENSSL
2018-02-10 13:44:25 +01:00
if(usessl())
2018-02-10 11:22:41 +01:00
{
2018-10-27 12:58:12 +02:00
ptr = (char* )data;
readlen = len > BUFFLEN?BUFFLEN:len;
2018-10-07 13:57:52 +02:00
read = 0;
fd_set fds;
struct timeval timeout;
2018-10-15 12:28:04 +02:00
while (readlen > 0 )//&& source->attempt < MAX_ATTEMPT
2018-10-07 13:57:52 +02:00
{
received = SSL_read (source->ssl, ptr+read, readlen);
if (received > 0)
{
read += received;
readlen = (len - read) > BUFFLEN?BUFFLEN:(len-read);
}
else
{
//printf(" received equal to or less than 0\n")
int err = SSL_get_error(source->ssl, received);
switch (err)
{
case SSL_ERROR_NONE:
{
// no real error, just try again...
//LOG("SSL_ERROR_NONE \n");
2018-10-15 12:28:04 +02:00
//source->attempt++;
2018-10-07 13:57:52 +02:00
continue;
}
case SSL_ERROR_ZERO_RETURN:
{
// peer disconnected...
//printf("SSL_ERROR_ZERO_RETURN \n");
break;
}
case SSL_ERROR_WANT_READ:
{
// no data available right now, wait a few seconds in case new data arrives...
//printf("SSL_ERROR_WANT_READ\n");
int sock = SSL_get_rfd(source->ssl);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 0;
timeout.tv_usec = 500;
err = select(sock+1, &fds, NULL, NULL, &timeout);
if (err == 0 || (err > 0 && FD_ISSET(sock, &fds)))
2018-10-14 10:57:09 +02:00
{
2018-10-15 12:28:04 +02:00
//source->attempt++;
2018-10-07 13:57:52 +02:00
continue; // more data to read...
2018-10-14 10:57:09 +02:00
}
break;
2018-10-07 13:57:52 +02:00
}
case SSL_ERROR_WANT_WRITE:
{
// socket not writable right now, wait a few seconds and try again...
//printf("SSL_ERROR_WANT_WRITE \n");
int sock = SSL_get_wfd(source->ssl);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 0;
timeout.tv_usec = 500;
err = select(sock+1, NULL, &fds, NULL, &timeout);
if (err == 0 || (err > 0 && FD_ISSET(sock, &fds)))
2018-10-14 10:57:09 +02:00
{
2018-10-15 12:28:04 +02:00
//source->attempt++;
2018-10-07 13:57:52 +02:00
continue; // can write more data now...
2018-10-14 10:57:09 +02:00
}
break;
2018-10-07 13:57:52 +02:00
}
default:
{
// other error
break;
}
}
break;
}
}
2018-10-15 21:35:57 +02:00
//source->attempt = 0;
2018-10-07 01:03:05 +02:00
/*
int stat, r, st;
do{
ret = SSL_read((SSL*) source->ssl, data, len);
stat = SSL_get_error((SSL*)source->ssl, r);
} while(ret == -1 &&
(
stat == SSL_ERROR_WANT_READ ||
stat == SSL_ERROR_WANT_WRITE ||
stat == SSL_ERROR_NONE ||
(stat == SSL_ERROR_SYSCALL && r== 0 && !ERR_get_error())
));
if(ret == -1)
{
LOG("Problem reading %d %d %d\n", ret, stat, r);
}
//set_nonblock(source->sock);
*/
2018-02-10 11:22:41 +01:00
}
else
{
#endif
2018-10-27 12:58:12 +02:00
ptr = (char* )data;
readlen = len > BUFFLEN?BUFFLEN:len;
read = 0;
while (readlen > 0 )//&& source->attempt < MAX_ATTEMPT
{
2018-10-27 16:15:25 +02:00
received = recv(((int) source->sock), ptr+read, readlen, 0);
2018-10-27 16:21:12 +02:00
//LOG("Read : %c\n", *ptr);
2018-10-27 12:58:12 +02:00
if (received > 0)
{
read += received;
readlen = (len - read) > BUFFLEN?BUFFLEN:(len-read);
2018-10-27 16:21:12 +02:00
//LOG("Read len is %d\n", readlen);
2018-10-27 12:58:12 +02:00
}
else if(errno != EAGAIN && errno != EWOULDBLOCK)
{
2018-10-27 16:15:25 +02:00
break;
2018-10-27 12:58:12 +02:00
}
}
2018-10-27 16:15:25 +02:00
//read = recv(((int) source->sock), data, len, 0);
2018-02-10 11:22:41 +01:00
#ifdef USE_OPENSSL
}
#endif
2018-10-27 16:15:25 +02:00
//LOG("Received %d bytes\n", read);
2018-06-26 13:40:53 +02:00
/*if(ret == 0)
2018-05-03 15:10:44 +02:00
{
antd_close(src);
2018-06-26 13:40:53 +02:00
}*/
2018-10-07 13:57:52 +02:00
return read;
2018-02-10 11:22:41 +01:00
}
2018-10-07 01:03:05 +02:00
void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
//assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
2018-10-07 14:20:36 +02:00
/*void set_block()
2018-10-07 01:03:05 +02:00
{
int flags;
flags = fcntl(socket,F_GETFL,0);
//assert(flags != -1);
fcntl(socket, F_SETFL, flags & (~O_NONBLOCK));
2018-10-07 14:20:36 +02:00
}*/
2018-02-10 11:22:41 +01:00
int antd_close(void* src)
{
2018-02-10 12:24:01 +01:00
if(!src) return -1;
2018-02-10 11:22:41 +01:00
antd_client_t * source = (antd_client_t *) src;
#ifdef USE_OPENSSL
if(source->ssl && usessl()){
2018-02-10 16:57:21 +01:00
//printf("SSL:Shutdown ssl\n");
//SSL_shutdown((SSL*) source->ssl);
SSL_set_shutdown((SSL*) source->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
//printf("SSL:Free ssl\n");
2018-02-10 11:22:41 +01:00
SSL_free((SSL*) source->ssl);
2018-10-09 12:15:48 +02:00
//EVP_cleanup();
//ENGINE_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);
ERR_free_strings();
source->ssl = NULL;
2018-02-10 12:24:01 +01:00
//LOG("Freeing SSL\n");
2018-02-10 11:22:41 +01:00
}
#endif
2018-02-10 12:24:01 +01:00
//printf("Close sock %d\n", source->sock);
int ret = close(source->sock);
if(source->ip) free(source->ip);
2018-02-10 12:24:01 +01:00
free(src);
2018-06-26 13:40:53 +02:00
src = NULL;
2018-02-10 12:24:01 +01:00
return ret;
2018-02-10 11:22:41 +01:00
}
int __ti(void* client,int data)
2017-07-29 22:00:34 +02:00
{
char str[15];
sprintf(str, "%d", data);
return response(client,str);
}
2018-02-10 11:22:41 +01:00
int __t(void* client, const char* fstring,...)
2017-07-29 22:00:34 +02:00
{
int nbytes;
int dlen;
int sent = 0;
int buflen = 0;
va_list arguments;
char * data;
char* chunk;
va_start( arguments, fstring);
dlen = vsnprintf(0,0,fstring,arguments) + 1;
va_end(arguments);
if ((data = (char*)malloc(dlen*sizeof(char))) != 0)
{
va_start(arguments, fstring);
vsnprintf(data, dlen, fstring, arguments);
va_end(arguments);
if(dlen < BUFFLEN)
2018-03-02 19:04:00 +01:00
{
int ret = response(client,data);
free(data);
return ret;
}
2017-07-29 22:00:34 +02:00
else
{
while(sent < dlen - 1)
{
if(dlen - sent > BUFFLEN)
buflen = BUFFLEN;
else
buflen = dlen - sent - 1;
//LOG("BUFFLEN %d\n",buflen);
chunk = (char*) malloc((buflen)*sizeof(char));
memcpy(chunk,data+sent,buflen);
//chunk[buflen-1] = '\0';
//response(client,chunk);
sent += buflen;
2018-02-10 13:44:25 +01:00
nbytes = antd_send(client, chunk, buflen);
2017-07-29 22:00:34 +02:00
free(chunk);
2018-03-02 19:04:00 +01:00
if(nbytes == -1)
{
//free(data);
//return 0;
break;
}
2017-07-29 22:00:34 +02:00
}
chunk = "\r\n";
2018-02-10 13:44:25 +01:00
antd_send(client, chunk, strlen(chunk));
2017-07-29 22:00:34 +02:00
}
free(data);
}
return 1;
//
}
2018-02-10 11:22:41 +01:00
int __b(void* client, const unsigned char* data, int size)
2017-07-29 22:00:34 +02:00
{
char buf[BUFFLEN];
int sent = 0;
int buflen = 0;
int nbytes;
2018-02-10 13:44:25 +01:00
2017-07-29 22:00:34 +02:00
if(size <= BUFFLEN)
{
2018-02-10 13:44:25 +01:00
nbytes = antd_send(client,data,size);
2017-07-29 22:00:34 +02:00
return (nbytes==-1?0:1);
}
else
{
while(sent < size)
{
if(size - sent > BUFFLEN)
buflen = BUFFLEN;
else
buflen = size - sent;
memcpy(buf,data+sent,buflen);
2018-02-10 13:44:25 +01:00
nbytes = antd_send(client,buf,buflen);
2017-07-29 22:00:34 +02:00
sent += buflen;
if(nbytes == -1) return 0;
}
}
return 1;
}
2018-02-10 11:22:41 +01:00
int __fb(void* client, const char* file)
2017-07-29 22:00:34 +02:00
{
printf("Open file %s\n",file );
unsigned char buffer[BUFFLEN];
FILE *ptr;
ptr = fopen(file,"rb");
if(!ptr)
{
LOG("Cannot read : %s\n", file);
return 0;
}
size_t size;
while(!feof(ptr))
{
size = fread(buffer,1,BUFFLEN,ptr);
if(!__b(client,buffer,size)) return 0;
}
fclose(ptr);
return 1;
}
2018-02-10 11:22:41 +01:00
int __f(void* client, const char* file)
2017-07-29 22:00:34 +02:00
{
2018-10-07 15:09:46 +02:00
char buf[BUFFLEN];
2017-07-29 22:00:34 +02:00
FILE *ptr;
int nbytes;
ptr = fopen(file,"r");
if(!ptr)
{
LOG("Cannot read : %s\n", file);
return 0;
}
while(fgets(buf, sizeof(buf), ptr) != NULL)
{
2018-02-10 13:44:25 +01:00
nbytes = antd_send(client, buf, strlen(buf));
2017-07-29 22:00:34 +02:00
if(nbytes == -1) return 0;
//LOG("READ : %s\n", buf);
//fgets(buf, sizeof(buf), ptr);
}
fclose(ptr);
return 1;
}
int upload(const char* tmp, const char* path)
{
return !rename(tmp, path);
}
// __plugin__.name
2018-02-10 11:22:41 +01:00
void set_cookie(void* client,const char* type, dictionary dic, const char* name)
2017-07-29 22:00:34 +02:00
{
set_status(client,200,"OK");
__t(client,"Content-Type: %s",type);
association assoc;
for_each_assoc(assoc,dic){
__t(client,"Set-Cookie: %s=%s; Path=/%s",assoc->key, (char*)assoc->value, name);
}
response(client,"");
}
2018-02-10 11:22:41 +01:00
void clear_cookie(void* client, dictionary dic)
2017-07-29 22:00:34 +02:00
{
set_status(client,200,"OK");
__t(client,"Content-Type: text/html; charset=utf-8");
association assoc;
for_each_assoc(assoc,dic){
__t(client,"Set-Cookie: %s=%s;expires=",assoc->key, (char*)assoc->value, server_time());
}
response(client,"");
}
2018-02-10 11:22:41 +01:00
void unknow(void* client)
2017-07-29 22:00:34 +02:00
{
2018-10-04 19:47:31 +02:00
set_status(client,520,"Unknown Error");
__t(client,"Content-Type: text/html; charset=utf-8");
response(client,"");
__t(client,"520 Unknow request");
}
void notfound(void* client)
{
set_status(client,404,"Not found");
__t(client,"Content-Type: text/html; charset=utf-8");
response(client,"");
__t(client,"Resource not found");
}
void badrequest(void* client)
{
set_status(client,400,"Bad request");
__t(client,"Content-Type: text/html; charset=utf-8");
response(client,"");
__t(client,"400 Bad request");
}
void unimplemented(void* client)
{
set_status(client,501,"Method Not Implemented");
__t(client,"Content-Type: text/html");
response(client,"");
__t(client, "<HTML><HEAD><TITLE>Method Not Implemented");
__t(client, "</TITLE></HEAD>");
__t(client, "<BODY><P>HTTP request method not supported.");
__t(client, "</BODY></HTML>");
}
void cannot_execute(void* client)
{
set_status(client,500,"Internal Server Error");
__t(client,"Content-Type: text/html");
response(client,"");
__t(client, "<P>Error prohibited CGI execution.");
2017-07-29 22:00:34 +02:00
}
int ws_enable(dictionary dic)
{
2018-09-18 10:33:42 +02:00
if(!dic) return 0;
char*v = (char*)dvalue(dic, "__web_socket__");
if(!v) return 0;
return atoi(v) == 1;
2017-07-29 23:54:43 +02:00
}
/**
* read the request as a string line format
* @param sock socket
* @return a request string
*/
2018-02-10 11:22:41 +01:00
char* read_line(void* sock)
2017-07-29 23:54:43 +02:00
{
char buf[BUFFLEN];
read_buf(sock,buf,sizeof(buf));
return strdup(buf);
}
/**
* Read the socket request in to a buffer or size
* The data is read until the buffer is full or
* there are a carrier return character
* @param sock socket
* @param buf buffer
* @param size size of buffer
* @return number of bytes read
*/
2018-02-10 11:22:41 +01:00
int read_buf(void* sock, char*buf,int size)
2017-07-29 23:54:43 +02:00
{
int i = 0;
char c = '\0';
int n;
while ((i < size - 1) && (c != '\n'))
{
2018-02-10 13:44:25 +01:00
n = antd_recv(sock, &c, 1);
2017-07-29 23:54:43 +02:00
if (n > 0)
{
2018-10-27 16:15:25 +02:00
//LOG("Data : %c\n", c);
2017-07-29 23:54:43 +02:00
buf[i] = c;
i++;
}
else
c = '\n';
}
buf[i] = '\0';
return i;
}
/*
We put it here since we want the plugin is able
to destroy the request if it want to
in this case, the plugin should return an empty
with no data
*/
void destroy_request(void *data)
{
if (!data)
return;
LOG("Close request\n");
antd_request_t *rq = (antd_request_t *)data;
// free all other thing
if (rq->request)
{
dictionary tmp = dvalue(rq->request, "COOKIE");
if (tmp)
freedict(tmp);
tmp = dvalue(rq->request, "REQUEST_HEADER");
if (tmp)
freedict(tmp);
tmp = dvalue(rq->request, "REQUEST_DATA");
if (tmp)
freedict(tmp);
dput(rq->request, "REQUEST_HEADER", NULL);
dput(rq->request, "REQUEST_DATA", NULL);
dput(rq->request, "COOKIE", NULL);
freedict(rq->request);
}
antd_close(rq->client);
free(rq);
2017-07-29 22:00:34 +02:00
}