Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cellframe/cellframe-sdk
  • MIKA83/cellframe-sdk
2 results
Show changes
Commits on Source (1)
...@@ -2,7 +2,7 @@ project(cellframe-sdk C) ...@@ -2,7 +2,7 @@ project(cellframe-sdk C)
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CELLFRAME_SDK_NATIVE_VERSION "2.4-0") set(CELLFRAME_SDK_NATIVE_VERSION "2.4-1")
add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
set(DAPSDK_MODULES "") set(DAPSDK_MODULES "")
......
...@@ -133,12 +133,11 @@ dap_events_socket_t * dap_events_socket_create_type_event(dap_worker_t * a_w, da ...@@ -133,12 +133,11 @@ dap_events_socket_t * dap_events_socket_create_type_event(dap_worker_t * a_w, da
return NULL; return NULL;
}else }else
log_it(L_DEBUG, "Created one-way unnamed pipe %d->%d", l_pipe[0], l_pipe[1]); log_it(L_DEBUG, "Created one-way unnamed pipe %d->%d", l_pipe[0], l_pipe[1]);
l_es->fd = l_pipe[1]; l_es->fd = l_pipe[0];
l_es->fd2 = l_pipe[0]; l_es->fd2 = l_pipe[1];
#endif #endif
#if defined(DAP_EVENTS_CAPS_EPOLL) #if defined(DAP_EVENTS_CAPS_EPOLL)
struct epoll_event l_ev={0};
int l_event_fd = l_es->fd; int l_event_fd = l_es->fd;
//log_it( L_INFO, "Create event descriptor with queue %d (%p) and add it on epoll fd %d", l_event_fd, l_es, a_w->epoll_fd); //log_it( L_INFO, "Create event descriptor with queue %d (%p) and add it on epoll fd %d", l_event_fd, l_es, a_w->epoll_fd);
l_es->ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP; l_es->ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP;
...@@ -219,6 +218,7 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da ...@@ -219,6 +218,7 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da
ret->socket = a_sock; ret->socket = a_sock;
ret->events = a_events; ret->events = a_events;
ret->server = a_server;
memcpy(&ret->callbacks,a_callbacks, sizeof ( ret->callbacks) ); memcpy(&ret->callbacks,a_callbacks, sizeof ( ret->callbacks) );
ret->flags = DAP_SOCK_READY_TO_READ; ret->flags = DAP_SOCK_READY_TO_READ;
...@@ -229,9 +229,6 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da ...@@ -229,9 +229,6 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da
HASH_ADD_INT( a_events->sockets, socket, ret ); HASH_ADD_INT( a_events->sockets, socket, ret );
pthread_rwlock_unlock( &a_events->sockets_rwlock ); pthread_rwlock_unlock( &a_events->sockets_rwlock );
if( a_callbacks->new_callback )
a_callbacks->new_callback( ret, NULL ); // Init internal structure
return ret; return ret;
} }
......
/* /*
* Authors: * Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Ltd. https://demlabs.net * DeM Labs Ltd. https://demlabs.net
* Copyright (c) 2017 * Copyright (c) 2017
* All rights reserved. * All rights reserved.
This file is part of DAP SDK the open source project This file is part of DAP SDK the open source project
DAP SDK is free software: you can redistribute it and/or modify DAP SDK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
DAP SDK is distributed in the hope that it will be useful, DAP SDK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <netdb.h> #include <netdb.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <utlist.h> #include <utlist.h>
#if ! defined(_GNU_SOURCE) #if ! defined(_GNU_SOURCE)
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#if ! defined (__USE_GNU) #if ! defined (__USE_GNU)
#define __USE_GNU #define __USE_GNU
#endif #endif
#include <sched.h> #include <sched.h>
#include "dap_common.h" #include "dap_common.h"
#include "dap_config.h" #include "dap_config.h"
#include "dap_server.h" #include "dap_server.h"
#include "dap_worker.h" #include "dap_worker.h"
#include "dap_events.h" #include "dap_events.h"
#define LOG_TAG "dap_server" #define LOG_TAG "dap_server"
static void s_es_server_read(dap_events_socket_t *a_events, void * a_arg); static void s_es_server_accept(dap_events_socket_t *a_es, int a_remote_socket, struct sockaddr* a_remote_addr);
static void s_es_server_error(dap_events_socket_t *a_events, void * a_arg); static void s_es_server_error(dap_events_socket_t *a_es, void * a_arg);
static void s_es_server_new(dap_events_socket_t *a_es, void * a_arg);
static void s_server_delete(dap_server_t * a_server);
/** static void s_server_delete(dap_server_t * a_server);
* @brief dap_server_init /**
* @return * @brief dap_server_init
*/ * @return
int dap_server_init() */
{ int dap_server_init()
log_it(L_NOTICE,"Server module init"); {
return 0; log_it(L_NOTICE,"Server module init");
} return 0;
}
/**
* @brief dap_server_deinit /**
*/ * @brief dap_server_deinit
void dap_server_deinit() */
{ void dap_server_deinit()
} {
}
/**
* @brief dap_server_delete /**
* @param a_server * @brief dap_server_delete
*/ * @param a_server
void s_server_delete(dap_server_t * a_server) */
{ void s_server_delete(dap_server_t * a_server)
if(a_server->delete_callback) {
a_server->delete_callback(a_server,NULL); if(a_server->delete_callback)
if( a_server->address ) a_server->delete_callback(a_server,NULL);
DAP_DELETE(a_server->address ); if( a_server->address )
if( a_server->_inheritor ) DAP_DELETE(a_server->address );
DAP_DELETE( a_server->_inheritor ); if( a_server->_inheritor )
DAP_DELETE(a_server); DAP_DELETE( a_server->_inheritor );
} DAP_DELETE(a_server);
}
/**
* @brief dap_server_new /**
* @param a_events * @brief dap_server_new
* @param a_addr * @param a_events
* @param a_port * @param a_addr
* @param a_type * @param a_port
* @return * @param a_type
*/ * @return
dap_server_t* dap_server_new(dap_events_t *a_events, const char * a_addr, uint16_t a_port, dap_server_type_t a_type) */
{ dap_server_t* dap_server_new(dap_events_t *a_events, const char * a_addr, uint16_t a_port, dap_server_type_t a_type)
assert(a_events); {
dap_server_t *l_server = DAP_NEW_Z(dap_server_t); assert(a_events);
dap_server_t *l_server = DAP_NEW_Z(dap_server_t);
l_server->socket_listener=-1; // To diff it from 0 fd
l_server->address = a_addr? strdup( a_addr) : strdup("0.0.0.0"); // If NULL we listen everything l_server->socket_listener=-1; // To diff it from 0 fd
l_server->port = a_port; l_server->address = a_addr? strdup( a_addr) : strdup("0.0.0.0"); // If NULL we listen everything
l_server->type = a_type; l_server->port = a_port;
l_server->type = a_type;
if(l_server->type == DAP_SERVER_TCP)
l_server->socket_listener = socket(AF_INET, SOCK_STREAM, 0); if(l_server->type == DAP_SERVER_TCP)
l_server->socket_listener = socket(AF_INET, SOCK_STREAM, 0);
if (l_server->socket_listener < 0) {
int l_errno = errno; if (l_server->socket_listener < 0) {
log_it (L_ERROR,"Socket error %s (%d)",strerror(l_errno), l_errno); int l_errno = errno;
DAP_DELETE(l_server); log_it (L_ERROR,"Socket error %s (%d)",strerror(l_errno), l_errno);
return NULL; DAP_DELETE(l_server);
} return NULL;
}
log_it(L_NOTICE,"Listen socket created...");
int reuse=1; log_it(L_NOTICE,"Listen socket %d created...", l_server->socket_listener);
int reuse=1;
if (setsockopt(l_server->socket_listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket"); if (setsockopt(l_server->socket_listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
#ifdef SO_REUSEPORT log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket");
if (setsockopt(l_server->socket_listener, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0) #ifdef SO_REUSEPORT
log_it(L_WARNING, "Can't set up REUSEPORT flag to the socket"); if (setsockopt(l_server->socket_listener, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
#endif log_it(L_WARNING, "Can't set up REUSEPORT flag to the socket");
#endif
//create socket
l_server->listener_addr.sin_family = AF_INET; //create socket
l_server->listener_addr.sin_port = htons(l_server->port); l_server->listener_addr.sin_family = AF_INET;
inet_pton(AF_INET, l_server->address, &(l_server->listener_addr.sin_addr)); l_server->listener_addr.sin_port = htons(l_server->port);
inet_pton(AF_INET, l_server->address, &(l_server->listener_addr.sin_addr));
if(bind (l_server->socket_listener, (struct sockaddr *) &(l_server->listener_addr), sizeof(l_server->listener_addr)) < 0){
log_it(L_ERROR,"Bind error: %s",strerror(errno)); if(bind (l_server->socket_listener, (struct sockaddr *) &(l_server->listener_addr), sizeof(l_server->listener_addr)) < 0){
return NULL; log_it(L_ERROR,"Bind error: %s",strerror(errno));
}else{ close(l_server->socket_listener);
log_it(L_INFO,"Binded %s:%u",l_server->address,l_server->port); DAP_DELETE(l_server);
listen(l_server->socket_listener, SOMAXCONN); return NULL;
} }else{
log_it(L_INFO,"Binded %s:%u",l_server->address,l_server->port);
fcntl( l_server->socket_listener, F_SETFL, O_NONBLOCK); listen(l_server->socket_listener, SOMAXCONN);
}
dap_events_socket_callbacks_t l_callbacks = {{ 0 }};
l_callbacks.read_callback = s_es_server_read; fcntl( l_server->socket_listener, F_SETFL, O_NONBLOCK);
l_callbacks.error_callback = s_es_server_error; pthread_mutex_init(&l_server->started_mutex,NULL);
pthread_cond_init(&l_server->started_cond,NULL);
for(size_t l_worker_id = 0; l_worker_id < dap_events_worker_get_count() ; l_worker_id++){
dap_events_socket_t * l_es = dap_events_socket_wrap_no_add( a_events, l_server->socket_listener, &l_callbacks);
dap_worker_t *l_w = dap_events_worker_get(l_worker_id);
assert(l_w); dap_events_socket_callbacks_t l_callbacks;
memset(&l_callbacks,0,sizeof (l_callbacks));
if ( l_es){ l_callbacks.new_callback = s_es_server_new;
log_it(L_DEBUG, "Wrapped server socket %p on worker %u", l_es, l_worker_id); l_callbacks.accept_callback = s_es_server_accept;
l_es->_inheritor = l_server; l_callbacks.error_callback = s_es_server_error;
l_es->server = l_server;
l_es->type = DESCRIPTOR_TYPE_SOCKET_LISTENING; for(size_t l_worker_id = 0; l_worker_id < dap_events_worker_get_count() ; l_worker_id++){
#ifdef DAP_EVENTS_CAPS_EPOLL dap_worker_t *l_w = dap_events_worker_get(l_worker_id);
// Prepare for multi thread listening assert(l_w);
l_es->ev_base_flags = EPOLLET| EPOLLIN | EPOLLEXCLUSIVE; dap_events_socket_t * l_es = dap_events_socket_wrap2( l_server, a_events, l_server->socket_listener, &l_callbacks);
#endif
dap_worker_add_events_socket( l_es, l_w ); if ( l_es){
} else{ l_es->type = DESCRIPTOR_TYPE_SOCKET_LISTENING;
log_it(L_WARNING, "Can't wrap event socket for %s:%u server", a_addr, a_port); #ifdef DAP_EVENTS_CAPS_EPOLL
return NULL; // Prepare for multi thread listening
} l_es->ev_base_flags = EPOLLET| EPOLLIN | EPOLLEXCLUSIVE;
} #endif
return l_server; l_es->_inheritor = l_server;
} pthread_mutex_lock(&l_server->started_mutex);
dap_worker_add_events_socket( l_es, l_w );
pthread_cond_wait(&l_server->started_cond, &l_server->started_mutex);
/** pthread_mutex_unlock(&l_server->started_mutex);
* @brief s_es_server_error } else{
* @param a_es log_it(L_WARNING, "Can't wrap event socket for %s:%u server", a_addr, a_port);
* @param a_arg return NULL;
*/ }
static void s_es_server_error(dap_events_socket_t *a_es, void * a_arg) }
{ return l_server;
(void) a_arg; }
(void) a_es;
char l_buf[128]; /**
strerror_r(errno, l_buf, sizeof (l_buf)); * @brief s_es_server_new
log_it(L_WARNING, "Listening socket error: %s, ", l_buf); * @param a_es
} * @param a_arg
*/
/** static void s_es_server_new(dap_events_socket_t *a_es, void * a_arg)
* @brief s_es_server_read {
* @param a_es log_it(L_DEBUG, "Created server socket %p on worker %u", a_es, a_es->worker->id);
* @param a_arg dap_server_t *l_server = (dap_server_t*) a_es->_inheritor;
*/ pthread_cond_broadcast( &l_server->started_cond);
static void s_es_server_read(dap_events_socket_t *a_es,void * a_arg) }
{
(void) a_arg; /**
a_es->buf_in_size = 0; // It should be 1 so we reset it to 0 * @brief s_es_server_error
//log_it(L_DEBUG, "Server socket %d is active",i); * @param a_es
dap_server_t * l_server = (dap_server_t*) a_es->_inheritor; * @param a_arg
if( l_server ){ */
dap_events_socket_t * l_es_new = NULL; static void s_es_server_error(dap_events_socket_t *a_es, void * a_arg)
log_it(L_DEBUG, "Listening socket (binded on %s:%u) got new incomming connection",l_server->address,l_server->port); {
struct sockaddr client_addr = {0}; (void) a_arg;
socklen_t client_addr_size = sizeof(struct sockaddr); (void) a_es;
int l_es_new_socket; char l_buf[128];
while ( (l_es_new_socket = accept(a_es->socket ,&client_addr,&client_addr_size)) > 0){ strerror_r(errno, l_buf, sizeof (l_buf));
log_it(L_DEBUG, "Accepted new connection (sock %d from %d)", l_es_new_socket, a_es->socket); log_it(L_WARNING, "Listening socket error: %s, ", l_buf);
l_es_new = dap_server_events_socket_new(a_es->events,l_es_new_socket,&l_server->client_callbacks,l_server); }
getnameinfo(&client_addr,client_addr_size, l_es_new->hostaddr /**
, sizeof(l_es_new->hostaddr),l_es_new->service,sizeof(l_es_new->service), * @brief s_es_server_accept
NI_NUMERICHOST | NI_NUMERICSERV); * @param a_events
log_it(L_INFO,"Connection accepted from %s (%s)", l_es_new->hostaddr, l_es_new->service ); * @param a_remote_socket
dap_worker_add_events_socket_auto(l_es_new); * @param a_remote_addr
} */
if ( l_es_new_socket == -1 && errno == EAGAIN){ static void s_es_server_accept(dap_events_socket_t *a_es, int a_remote_socket, struct sockaddr *a_remote_addr)
// Everything is good, we'll receive ACCEPT on next poll {
return; socklen_t a_remote_addr_size = sizeof(*a_remote_addr);
}else{ a_es->buf_in_size = 0; // It should be 1 so we reset it to 0
log_it(L_WARNING,"accept() returned %d",l_es_new_socket); //log_it(L_DEBUG, "Server socket %d is active",i);
} dap_server_t * l_server = (dap_server_t*) a_es->_inheritor;
assert(l_server);
}else
log_it(L_ERROR, "No sap_server object related with socket %d in the select loop",a_es->socket); dap_events_socket_t * l_es_new = NULL;
} log_it(L_DEBUG, "Listening socket (binded on %s:%u) got new incomming connection",l_server->address,l_server->port);
log_it(L_DEBUG, "Accepted new connection (sock %d from %d)", a_remote_socket, a_es->socket);
l_es_new = dap_server_events_socket_new(a_es->events,a_remote_socket,&l_server->client_callbacks,l_server);
/**
* @brief dap_server_events_socket_new getnameinfo(a_remote_addr,a_remote_addr_size, l_es_new->hostaddr
* @param a_events , sizeof(l_es_new->hostaddr),l_es_new->service,sizeof(l_es_new->service),
* @param a_sock NI_NUMERICHOST | NI_NUMERICSERV);
* @param a_callbacks
* @param a_server log_it(L_INFO,"Connection accepted from %s (%s)", l_es_new->hostaddr, l_es_new->service );
* @return dap_worker_add_events_socket_auto(l_es_new);
*/ }
dap_events_socket_t * dap_server_events_socket_new(dap_events_t * a_events, int a_sock,
dap_events_socket_callbacks_t * a_callbacks, dap_server_t * a_server)
{ /**
dap_events_socket_t * ret = NULL; * @brief dap_server_events_socket_new
if (a_sock > 0) { * @param a_events
// set it nonblock * @param a_sock
//fcntl(a_sock, F_SETFL, O_NONBLOCK); * @param a_callbacks
* @param a_server
ret = dap_events_socket_wrap_no_add(a_events, a_sock, a_callbacks); * @return
ret->type = DESCRIPTOR_TYPE_SOCKET; */
ret->server = a_server; dap_events_socket_t * dap_server_events_socket_new(dap_events_t * a_events, int a_sock,
dap_events_socket_callbacks_t * a_callbacks, dap_server_t * a_server)
} else { {
log_it(L_CRITICAL,"Accept error: %s",strerror(errno)); dap_events_socket_t * ret = NULL;
} if (a_sock > 0) {
return ret; // set it nonblock
} //fcntl(a_sock, F_SETFL, O_NONBLOCK);
ret = dap_events_socket_wrap_no_add(a_events, a_sock, a_callbacks);
ret->type = DESCRIPTOR_TYPE_SOCKET;
ret->server = a_server;
} else {
log_it(L_CRITICAL,"Accept error: %s",strerror(errno));
}
return ret;
}
...@@ -138,7 +138,8 @@ void *dap_worker_thread(void *arg) ...@@ -138,7 +138,8 @@ void *dap_worker_thread(void *arg)
} }
l_cur->last_time_active = l_cur_time; l_cur->last_time_active = l_cur_time;
//log_it(L_DEBUG, "Worker=%d fd=%d socket=%d event=0x%x(%d)", w->number_thread, w->epoll_fd,cur->socket, events[n].events,events[n].events); log_it(L_DEBUG, "Worker=%d fd=%d socket=%d event=0x%x(%d)", l_worker->id,
l_worker->epoll_fd,l_cur->socket, l_epoll_events[n].events,l_epoll_events[n].events);
int l_sock_err = 0, l_sock_err_size = sizeof(l_sock_err); int l_sock_err = 0, l_sock_err_size = sizeof(l_sock_err);
//connection already closed (EPOLLHUP - shutdown has been made in both directions) //connection already closed (EPOLLHUP - shutdown has been made in both directions)
if(l_epoll_events[n].events & EPOLLHUP) { // && events[n].events & EPOLLERR) { if(l_epoll_events[n].events & EPOLLHUP) { // && events[n].events & EPOLLERR) {
...@@ -195,6 +196,24 @@ void *dap_worker_thread(void *arg) ...@@ -195,6 +196,24 @@ void *dap_worker_thread(void *arg)
break; break;
case DESCRIPTOR_TYPE_SOCKET_LISTENING: case DESCRIPTOR_TYPE_SOCKET_LISTENING:
// Accept connection // Accept connection
if ( l_cur->callbacks.accept_callback){
struct sockaddr l_remote_addr;
socklen_t l_remote_addr_size= sizeof (l_remote_addr);
int l_remote_socket= accept(l_cur->socket ,&l_remote_addr,&l_remote_addr_size);
int l_errno = errno;
if ( l_remote_socket == -1 ){
if( l_errno == EAGAIN || l_errno == EWOULDBLOCK){// Everything is good, we'll receive ACCEPT on next poll
continue;
}else{
char l_errbuf[128];
strerror_r(l_errno, l_errbuf, sizeof (l_errbuf));
log_it(L_WARNING,"accept() on socket %d error:\"%s\"(%d)",l_cur->socket, l_errbuf,l_errno);
}
}
l_cur->callbacks.accept_callback(l_cur,l_remote_socket,&l_remote_addr);
}else
log_it(L_ERROR,"No accept_callback on listening socket");
break; break;
case DESCRIPTOR_TYPE_TIMER:{ case DESCRIPTOR_TYPE_TIMER:{
uint64_t val; uint64_t val;
...@@ -224,7 +243,12 @@ void *dap_worker_thread(void *arg) ...@@ -224,7 +243,12 @@ void *dap_worker_thread(void *arg)
if(l_bytes_read > 0) { if(l_bytes_read > 0) {
l_cur->buf_in_size += l_bytes_read; l_cur->buf_in_size += l_bytes_read;
//log_it(DEBUG, "Received %d bytes", bytes_read); //log_it(DEBUG, "Received %d bytes", bytes_read);
l_cur->callbacks.read_callback(l_cur, NULL); // Call callback to process read event. At the end of callback buf_in_size should be zero if everything was read well if(l_cur->callbacks.read_callback)
l_cur->callbacks.read_callback(l_cur, NULL); // Call callback to process read event. At the end of callback buf_in_size should be zero if everything was read well
else{
log_it(L_WARNING, "We have incomming %u data but no read callback on socket %d, removing from read set", l_cur->socket);
dap_events_socket_set_readable_unsafe(l_cur,false);
}
} }
else if(l_bytes_read < 0) { else if(l_bytes_read < 0) {
if (l_errno != EAGAIN && l_errno != EWOULDBLOCK){ // Socket is blocked if (l_errno != EAGAIN && l_errno != EWOULDBLOCK){ // Socket is blocked
...@@ -287,19 +311,17 @@ void *dap_worker_thread(void *arg) ...@@ -287,19 +311,17 @@ void *dap_worker_thread(void *arg)
break; break;
} }
}else{ }else{
l_bytes_sent += l_bytes_sent; //log_it(L_DEBUG, "Output: %u from %u bytes are sent ", l_bytes_sent,l_cur->buf_out_size);
//log_it(L_DEBUG, "Output: %u from %u bytes are sent ", total_sent,sa_cur->buf_out_size);
//} //}
//log_it(L_DEBUG,"Output: sent %u bytes",total_sent); //log_it(L_DEBUG,"Output: sent %u bytes",total_sent);
if (l_bytes_sent) { if (l_bytes_sent) {
pthread_mutex_lock(&l_cur->mutex);
l_cur->buf_out_size -= l_bytes_sent; l_cur->buf_out_size -= l_bytes_sent;
//log_it(L_DEBUG,"Output: left %u bytes in buffer",l_cur->buf_out_size);
if (l_cur->buf_out_size) { if (l_cur->buf_out_size) {
memmove(l_cur->buf_out, &l_cur->buf_out[l_bytes_sent], l_cur->buf_out_size); memmove(l_cur->buf_out, &l_cur->buf_out[l_bytes_sent], l_cur->buf_out_size);
} else { } else {
l_cur->flags &= ~DAP_SOCK_READY_TO_WRITE; l_cur->flags &= ~DAP_SOCK_READY_TO_WRITE;
} }
pthread_mutex_unlock(&l_cur->mutex);
} }
} }
} }
...@@ -358,14 +380,14 @@ static void s_new_es_callback( dap_events_socket_t * a_es, void * a_arg) ...@@ -358,14 +380,14 @@ static void s_new_es_callback( dap_events_socket_t * a_es, void * a_arg)
pthread_rwlock_unlock(&w->events->sockets_rwlock); pthread_rwlock_unlock(&w->events->sockets_rwlock);
struct epoll_event l_ev={0}; struct epoll_event l_ev={0};
l_ev.events = l_es_new->flags ; l_es_new->ev.events = l_es_new->ev_base_flags ;
if(l_es_new->flags & DAP_SOCK_READY_TO_READ ) if(l_es_new->flags & DAP_SOCK_READY_TO_READ )
l_ev.events |= EPOLLIN; l_es_new->ev.events |= EPOLLIN;
if(l_es_new->flags & DAP_SOCK_READY_TO_WRITE ) if(l_es_new->flags & DAP_SOCK_READY_TO_WRITE )
l_ev.events |= EPOLLOUT; l_es_new->ev.events |= EPOLLOUT;
l_ev.data.ptr = l_es_new; l_es_new->ev.data.ptr = l_es_new;
if ( epoll_ctl(w->epoll_fd, EPOLL_CTL_ADD, l_es_new->socket, &l_ev) == 1 ) if ( epoll_ctl(w->epoll_fd, EPOLL_CTL_ADD, l_es_new->socket, &l_es_new->ev) == 1 )
log_it(L_CRITICAL,"Can't add event socket's handler to epoll_fd"); log_it(L_CRITICAL,"Can't add event socket's handler to epoll_fd");
else{ else{
log_it(L_DEBUG, "Added socket %d on worker %u", l_es_new->socket, w->id); log_it(L_DEBUG, "Added socket %d on worker %u", l_es_new->socket, w->id);
......
...@@ -59,11 +59,12 @@ typedef struct dap_worker dap_worker_t; ...@@ -59,11 +59,12 @@ typedef struct dap_worker dap_worker_t;
typedef struct dap_server dap_server_t; typedef struct dap_server dap_server_t;
typedef void (*dap_events_socket_callback_t) (dap_events_socket_t *,void * ); // Callback for specific client operations typedef void (*dap_events_socket_callback_t) (dap_events_socket_t *,void * ); // Callback for specific client operations
typedef void (*dap_events_socket_callback_timer_t) (dap_events_socket_t * ); // Callback for specific client operations typedef void (*dap_events_socket_callback_timer_t) (dap_events_socket_t * ); // Callback for specific client operations
typedef void (*dap_events_socket_callback_accept_t) (dap_events_socket_t * , int, struct sockaddr* ); // Callback for accept of new connection
typedef void (*dap_events_socket_worker_callback_t) (dap_events_socket_t *,dap_worker_t * ); // Callback for specific client operations typedef void (*dap_events_socket_worker_callback_t) (dap_events_socket_t *,dap_worker_t * ); // Callback for specific client operations
typedef struct dap_events_socket_callbacks { typedef struct dap_events_socket_callbacks {
union{ union{
dap_events_socket_callback_t accept_callback; // Accept callback for listening socket dap_events_socket_callback_accept_t accept_callback; // Accept callback for listening socket
dap_events_socket_callback_timer_t timer_callback; // Timer callback for listening socket dap_events_socket_callback_timer_t timer_callback; // Timer callback for listening socket
dap_events_socket_callback_t event_callback; // Timer callback for listening socket dap_events_socket_callback_t event_callback; // Timer callback for listening socket
dap_events_socket_callback_t action_callback; // Callback for action with socket dap_events_socket_callback_t action_callback; // Callback for action with socket
...@@ -160,6 +161,8 @@ dap_events_socket_t * dap_events_socket_create_type_event(dap_worker_t * a_w, da ...@@ -160,6 +161,8 @@ dap_events_socket_t * dap_events_socket_create_type_event(dap_worker_t * a_w, da
void dap_events_socket_send_event( dap_events_socket_t * a_es, void* a_arg); void dap_events_socket_send_event( dap_events_socket_t * a_es, void* a_arg);
dap_events_socket_t * dap_events_socket_wrap_no_add(struct dap_events * a_events, dap_events_socket_t * dap_events_socket_wrap_no_add(struct dap_events * a_events,
int s, dap_events_socket_callbacks_t * a_callbacks); // Create new client and add it to the list int s, dap_events_socket_callbacks_t * a_callbacks); // Create new client and add it to the list
dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct dap_events *a_events,
int a_sock, dap_events_socket_callbacks_t *a_callbacks );
dap_events_socket_t * dap_events_socket_find(int sock, struct dap_events * sh); // Find client by socket dap_events_socket_t * dap_events_socket_find(int sock, struct dap_events * sh); // Find client by socket
......
...@@ -75,6 +75,9 @@ typedef struct dap_server { ...@@ -75,6 +75,9 @@ typedef struct dap_server {
dap_server_callback_t delete_callback; dap_server_callback_t delete_callback;
dap_events_socket_callbacks_t client_callbacks; // Callbacks for the new clients dap_events_socket_callbacks_t client_callbacks; // Callbacks for the new clients
pthread_cond_t started_cond; // Condition for initialized socket
pthread_mutex_t started_mutex; // Mutex for shared operation between mirrored sockets
} dap_server_t; } dap_server_t;
int dap_server_init( ); // Init server module int dap_server_init( ); // Init server module
......
/* /*
* Authors: * Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Ltd. https://demlabs.net * DeM Labs Ltd. https://demlabs.net
* Copyright (c) 2017 * Copyright (c) 2017
* All rights reserved. * All rights reserved.
This file is part of DAP SDK the open source project This file is part of DAP SDK the open source project
DAP SDK is free software: you can redistribute it and/or modify DAP SDK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
DAP SDK is distributed in the hope that it will be useful, DAP SDK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#ifndef _WIN32 #ifndef _WIN32
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#else #else
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <mswsock.h> #include <mswsock.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <io.h> #include <io.h>
#endif #endif
#include <pthread.h> #include <pthread.h>
#include <magic.h> #include <magic.h>
#include "dap_common.h" #include "dap_common.h"
#include "dap_events_socket.h" #include "dap_events_socket.h"
#include "dap_http.h" #include "dap_http.h"
#include "dap_http_client.h" #include "dap_http_client.h"
#include "dap_http_folder.h" #include "dap_http_folder.h"
#include "http_status_code.h" #include "http_status_code.h"
typedef struct dap_http_url_proc_folder { typedef struct dap_http_url_proc_folder {
char local_path[4096]; char local_path[4096];
magic_t mime_detector; magic_t mime_detector;
} dap_http_url_proc_folder_t; } dap_http_url_proc_folder_t;
#define URL_PROC_FOLDER(a) ((dap_http_url_proc_folder_t*) (a)->_inhertior ) #define URL_PROC_FOLDER(a) ((dap_http_url_proc_folder_t*) (a)->_inhertior )
typedef struct dap_http_file{ typedef struct dap_http_file{
FILE * fd; FILE * fd;
size_t position; size_t position;
char local_path[4096+2048+1]; char local_path[4096+2048+1];
dap_http_client_t *client; dap_http_client_t *client;
} dap_http_file_t; } dap_http_file_t;
#define DAP_HTTP_FILE(a) ((dap_http_file_t*) (a)->_inheritor ) #define DAP_HTTP_FILE(a) ((dap_http_file_t*) (a)->_inheritor )
void dap_http_folder_headers_read( dap_http_client_t *cl_ht, void *arg ); void dap_http_folder_headers_read( dap_http_client_t *cl_ht, void *arg );
void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void *arg ); void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void *arg );
void dap_http_folder_data_read( dap_http_client_t *cl_ht, void *arg ); void dap_http_folder_data_read( dap_http_client_t *cl_ht, void *arg );
void dap_http_folder_data_write( dap_http_client_t *cl_ht, void *arg ); void dap_http_folder_data_write( dap_http_client_t *cl_ht, void *arg );
#define LOG_TAG "dap_http_folder" #define LOG_TAG "dap_http_folder"
int dap_http_folder_init( ) int dap_http_folder_init( )
{ {
return 0; return 0;
} }
void dap_http_folder_deinit( ) void dap_http_folder_deinit( )
{ {
} }
/** /**
* @brief dap_http_folder_add Add folder for reading to the HTTP server * @brief dap_http_folder_add Add folder for reading to the HTTP server
* @param sh Server instance * @param sh Server instance
* @param url_path Beginning part of the URL * @param url_path Beginning part of the URL
* @param local_path Local path that will be read for * @param local_path Local path that will be read for
*/ */
int dap_http_folder_add( dap_http_t *sh, const char *url_path, const char *local_path ) int dap_http_folder_add( dap_http_t *sh, const char *url_path, const char *local_path )
{ {
if ( !local_path ) { if ( !local_path ) {
log_it( L_ERROR, "Directory Path parameter is empty!" ); log_it( L_ERROR, "Directory Path parameter is empty!" );
return -11; return -11;
} }
log_it( L_DEBUG, "Checking url path %s", local_path ); log_it( L_DEBUG, "Checking url path %s", local_path );
#ifndef _WIN32 #ifndef _WIN32
DIR *dirptr = opendir( local_path ); DIR *dirptr = opendir( local_path );
if ( dirptr == NULL ) { if ( dirptr == NULL ) {
log_it( L_ERROR, "Directory Not Found!" ); log_it( L_ERROR, "Directory Not Found!" );
return -11; return -11;
} }
else { else {
closedir( dirptr ); closedir( dirptr );
} }
#else // WIN32 #else // WIN32
DWORD attr = GetFileAttributesA( local_path ); DWORD attr = GetFileAttributesA( local_path );
if ( attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) { if ( attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) {
log_it( L_ERROR, "Directory Not Found!" ); log_it( L_ERROR, "Directory Not Found!" );
return -11; return -11;
} }
#endif #endif
log_it( L_NOTICE, "File service for %s => %s ", url_path, local_path ); log_it( L_NOTICE, "File service for %s => %s ", url_path, local_path );
dap_http_url_proc_folder_t *up_folder = (dap_http_url_proc_folder_t *)calloc( 1, sizeof(dap_http_url_proc_folder_t) ); dap_http_url_proc_folder_t *up_folder = (dap_http_url_proc_folder_t *)calloc( 1, sizeof(dap_http_url_proc_folder_t) );
strncpy( up_folder->local_path, local_path, sizeof(up_folder->local_path)-1 ); strncpy( up_folder->local_path, local_path, sizeof(up_folder->local_path)-1 );
up_folder->mime_detector = magic_open( MAGIC_SYMLINK | MAGIC_MIME | MAGIC_PRESERVE_ATIME ); up_folder->mime_detector = magic_open( MAGIC_SYMLINK | MAGIC_MIME | MAGIC_PRESERVE_ATIME );
if ( up_folder->mime_detector == NULL) { if ( up_folder->mime_detector == NULL) {
log_it( L_CRITICAL,"Can't init MIME detection library" ); log_it( L_CRITICAL,"Can't init MIME detection library" );
free( up_folder ); free( up_folder );
return -1; return -1;
} }
#ifndef _WIN32 #ifndef _WIN32
if( 0 != magic_load( up_folder->mime_detector, NULL) ) { if( 0 != magic_load( up_folder->mime_detector, NULL) ) {
#else #else
if( 0 != magic_load( up_folder->mime_detector, "data.mag" ) ) { if( 0 != magic_load( up_folder->mime_detector, "data.mag" ) ) {
#endif #endif
log_it( L_CRITICAL, "Can't load MIME magic detection database" ); log_it( L_CRITICAL, "Can't load MIME magic detection database" );
magic_close( up_folder->mime_detector ); magic_close( up_folder->mime_detector );
free( up_folder ); free( up_folder );
return -2; return -2;
} }
dap_http_add_proc( sh, dap_http_add_proc( sh,
url_path, url_path,
up_folder, up_folder,
NULL, NULL,
NULL, NULL,
dap_http_folder_headers_read, dap_http_folder_headers_read,
dap_http_folder_headers_write, dap_http_folder_headers_write,
dap_http_folder_data_read, dap_http_folder_data_read,
dap_http_folder_data_write, dap_http_folder_data_write,
NULL ); NULL );
return 0; return 0;
} }
/** /**
* @brief dap_http_folder_headers_read Signal thats HTTP client is now going to output the data * @brief dap_http_folder_headers_read Signal thats HTTP client is now going to output the data
* @param cl_ht HTTP client instance * @param cl_ht HTTP client instance
* @param arg Not used * @param arg Not used
*/ */
void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg) void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg)
{ {
(void) arg; (void) arg;
cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START;
cl_ht->state_read=cl_ht->keep_alive?DAP_HTTP_CLIENT_STATE_START:DAP_HTTP_CLIENT_STATE_NONE; cl_ht->state_read=cl_ht->keep_alive?DAP_HTTP_CLIENT_STATE_START:DAP_HTTP_CLIENT_STATE_NONE;
dap_events_socket_set_writable_unsafe(cl_ht->esocket,true); dap_events_socket_set_writable_unsafe(cl_ht->esocket,true);
dap_events_socket_set_readable_unsafe(cl_ht->esocket, cl_ht->keep_alive); dap_events_socket_set_readable_unsafe(cl_ht->esocket, cl_ht->keep_alive);
} }
#ifdef _WIN32 #ifdef _WIN32
time_t FileTimeToUnixTime( FILETIME ft ) time_t FileTimeToUnixTime( FILETIME ft )
{ {
ULARGE_INTEGER ull; ULARGE_INTEGER ull;
ull.LowPart = ft.dwLowDateTime; ull.LowPart = ft.dwLowDateTime;
ull.HighPart = ft.dwHighDateTime; ull.HighPart = ft.dwHighDateTime;
return ull.QuadPart / 10000000ULL - 11644473600ULL; return ull.QuadPart / 10000000ULL - 11644473600ULL;
} }
#endif #endif
/** /**
* @brief dap_http_folder_headers Prepare response HTTP headers for file folder request * @brief dap_http_folder_headers Prepare response HTTP headers for file folder request
* @param cl_ht HTTP client instane * @param cl_ht HTTP client instane
* @param arg Not used * @param arg Not used
*/ */
void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void * arg) void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void * arg)
{ {
(void) arg; (void) arg;
// Get specific data for folder URL processor // Get specific data for folder URL processor
dap_http_url_proc_folder_t * up_folder=(dap_http_url_proc_folder_t*) cl_ht->proc->_inheritor; dap_http_url_proc_folder_t * up_folder=(dap_http_url_proc_folder_t*) cl_ht->proc->_inheritor;
// Init specific file response data for HTTP client instance // Init specific file response data for HTTP client instance
cl_ht->_inheritor=DAP_NEW_Z(dap_http_file_t); cl_ht->_inheritor=DAP_NEW_Z(dap_http_file_t);
dap_http_file_t* cl_ht_file=DAP_HTTP_FILE(cl_ht); dap_http_file_t* cl_ht_file=DAP_HTTP_FILE(cl_ht);
cl_ht_file->client=cl_ht; cl_ht_file->client=cl_ht;
// Produce local path for file to open // Produce local path for file to open
dap_snprintf(cl_ht_file->local_path,sizeof(cl_ht_file->local_path),"%s/%s", up_folder->local_path, cl_ht->url_path ); dap_snprintf(cl_ht_file->local_path,sizeof(cl_ht_file->local_path),"%s/%s", up_folder->local_path, cl_ht->url_path );
log_it(L_DEBUG, "Check %s file", cl_ht_file->local_path); log_it(L_DEBUG, "Check %s file", cl_ht_file->local_path);
#ifndef _WIN32 #ifndef _WIN32
struct stat file_stat; struct stat file_stat;
if ( stat(cl_ht_file->local_path, &file_stat) != 0 ) if ( stat(cl_ht_file->local_path, &file_stat) != 0 )
goto err; goto err;
cl_ht->out_last_modified = file_stat.st_mtime; cl_ht->out_last_modified = file_stat.st_mtime;
cl_ht->out_content_length = file_stat.st_size; cl_ht->out_content_length = file_stat.st_size;
#else #else
FILETIME CreationTime; FILETIME CreationTime;
FILETIME LastAccessTime; FILETIME LastAccessTime;
FILETIME LastWriteTime; FILETIME LastWriteTime;
HANDLE fileh = CreateFileA( cl_ht_file->local_path, HANDLE fileh = CreateFileA( cl_ht_file->local_path,
GENERIC_READ, GENERIC_READ,
FILE_SHARE_READ, FILE_SHARE_READ,
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE,
NULL NULL
); );
if ( fileh == INVALID_HANDLE_VALUE ) if ( fileh == INVALID_HANDLE_VALUE )
goto err; goto err;
GetFileTime( fileh, GetFileTime( fileh,
&CreationTime, &CreationTime,
&LastAccessTime, &LastAccessTime,
&LastWriteTime ); &LastWriteTime );
cl_ht->out_last_modified = FileTimeToUnixTime( LastWriteTime ); cl_ht->out_last_modified = FileTimeToUnixTime( LastWriteTime );
cl_ht->out_content_length = GetFileSize( fileh, NULL ); cl_ht->out_content_length = GetFileSize( fileh, NULL );
CloseHandle( fileh ); CloseHandle( fileh );
#endif #endif
cl_ht_file->fd = fopen( cl_ht_file->local_path, "rb" ); cl_ht_file->fd = fopen( cl_ht_file->local_path, "rb" );
if ( cl_ht_file->fd == NULL ) { if ( cl_ht_file->fd == NULL ) {
log_it(L_ERROR, "Can't open %s: %s",cl_ht_file->local_path,strerror(errno)); log_it(L_ERROR, "Can't open %s: %s",cl_ht_file->local_path,strerror(errno));
cl_ht->reply_status_code = Http_Status_NotFound; cl_ht->reply_status_code = Http_Status_NotFound;
strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 ); strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 );
} }
else { else {
cl_ht->reply_status_code = Http_Status_OK; cl_ht->reply_status_code = Http_Status_OK;
strncpy( cl_ht->reply_reason_phrase,"OK",sizeof(cl_ht->reply_reason_phrase)-1 ); strncpy( cl_ht->reply_reason_phrase,"OK",sizeof(cl_ht->reply_reason_phrase)-1 );
const char *mime_type = magic_file( up_folder->mime_detector, cl_ht_file->local_path ); const char *mime_type = magic_file( up_folder->mime_detector, cl_ht_file->local_path );
if( mime_type ) { if( mime_type ) {
strncpy(cl_ht->out_content_type,mime_type,sizeof(cl_ht->out_content_type)-1); strncpy(cl_ht->out_content_type,mime_type,sizeof(cl_ht->out_content_type)-1);
log_it( L_DEBUG, "MIME type detected: '%s'", mime_type ); log_it( L_DEBUG, "MIME type detected: '%s'", mime_type );
} }
else { else {
cl_ht->reply_status_code=Http_Status_NotFound; cl_ht->reply_status_code=Http_Status_NotFound;
cl_ht->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; cl_ht->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE;
log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector)); log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector));
} }
} }
return; return;
err: err:
log_it( L_WARNING, "Can't get file info: %s", strerror(errno) ); log_it( L_WARNING, "Can't get file info: %s", strerror(errno) );
cl_ht->reply_status_code = 404; cl_ht->reply_status_code = 404;
strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 ); strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 );
return; return;
} }
/** /**
* @brief dap_http_folder_read HTTP client callback for reading function for the folder processing * @brief dap_http_folder_read HTTP client callback for reading function for the folder processing
* @param cl_ht HTTP client instance * @param cl_ht HTTP client instance
* @param arg Pointer to int with return bytes number * @param arg Pointer to int with return bytes number
*/ */
void dap_http_folder_data_read(dap_http_client_t * cl_ht, void * arg) void dap_http_folder_data_read(dap_http_client_t * cl_ht, void * arg)
{ {
int * bytes_return = (int*) arg; // Return number of read bytes int * bytes_return = (int*) arg; // Return number of read bytes
//Do nothing //Do nothing
*bytes_return=cl_ht->esocket->buf_in_size; *bytes_return=cl_ht->esocket->buf_in_size;
} }
/** /**
* @brief dap_http_folder_write HTTP client callback for writting function for the folder processing * @brief dap_http_folder_write HTTP client callback for writting function for the folder processing
* @param cl_ht HTTP client instance * @param cl_ht HTTP client instance
* @param arg * @param arg
*/ */
void dap_http_folder_data_write(dap_http_client_t * cl_ht, void * arg) void dap_http_folder_data_write(dap_http_client_t * cl_ht, void * arg)
{ {
(void) arg; (void) arg;
dap_http_file_t * cl_ht_file= DAP_HTTP_FILE(cl_ht); dap_http_file_t * cl_ht_file= DAP_HTTP_FILE(cl_ht);
cl_ht->esocket->buf_out_size=fread(cl_ht->esocket->buf_out,1,sizeof(cl_ht->esocket->buf_out),cl_ht_file->fd); cl_ht->esocket->buf_out_size=fread(cl_ht->esocket->buf_out,1,sizeof(cl_ht->esocket->buf_out),cl_ht_file->fd);
cl_ht_file->position+=cl_ht->esocket->buf_out_size; cl_ht_file->position+=cl_ht->esocket->buf_out_size;
if(feof(cl_ht_file->fd)!=0){ if(feof(cl_ht_file->fd)!=0){
log_it(L_INFO, "All the file %s is sent out",cl_ht_file->local_path); log_it(L_INFO, "All the file %s is sent out",cl_ht_file->local_path);
//strncat(cl_ht->client->buf_out+cl_ht->client->buf_out_size,"\r\n",sizeof(cl_ht->client->buf_out)); //strncat(cl_ht->client->buf_out+cl_ht->client->buf_out_size,"\r\n",sizeof(cl_ht->client->buf_out));
fclose(cl_ht_file->fd); fclose(cl_ht_file->fd);
dap_events_socket_set_writable_unsafe(cl_ht->esocket,false); dap_events_socket_set_writable_unsafe(cl_ht->esocket,false);
if ( !cl_ht->keep_alive ) if ( !cl_ht->keep_alive )
cl_ht->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; cl_ht->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE;
cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE; cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE;
} }
} }