#5432 fix the non responding connection request issue.

Signed-off-by: MOHAMED Kallel <mohamed.kallel@pivasoftware.com>
This commit is contained in:
MOHAMED Kallel 2014-10-01 11:03:44 +01:00 committed by Simon Kers
parent ee0df8c63c
commit 20a54a20cc
4 changed files with 160 additions and 162 deletions

13
cwmp.c
View file

@ -505,6 +505,12 @@ void *thread_uloop_run (void *v)
return NULL;
}
void *thread_http_cr_server_init (void *v)
{
http_server_init();
return NULL;
}
void *thread_exit_program (void *v)
{
CWMP_LOG(INFO,"EXIT CWMP");
@ -521,6 +527,7 @@ int main(int argc, char **argv)
pthread_t scheduleInform_thread;
pthread_t download_thread;
pthread_t ubus_thread;
pthread_t http_cr_server_thread;
if (error = cwmp_init(argc, argv, cwmp))
{
@ -559,11 +566,17 @@ int main(int argc, char **argv)
{
CWMP_LOG(ERROR,"Error when creating the download thread!");
}
error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_init, NULL);
if (error<0)
{
CWMP_LOG(ERROR,"Error when creating the http connection request server thread!");
}
cwmp_schedule_session (cwmp);
pthread_join(ubus_thread, NULL);
pthread_join(periodic_event_thread, NULL);
pthread_join(scheduleInform_thread, NULL);
pthread_join(download_thread, NULL);
pthread_join(http_cr_server_thread, NULL);
CWMP_LOG(INFO,"EXIT CWMP");
return CWMP_OK;

291
http.c
View file

@ -17,6 +17,9 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include "cwmp.h"
#include "log.h"
@ -40,7 +43,6 @@
#define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"
static struct http_client http_c;
static struct http_server http_s;
#ifdef HTTP_CURL
static CURL *curl;
@ -263,150 +265,151 @@ error:
return -1;
}
static void
http_success_cr()
{
struct event_container *event_container;
CWMP_LOG(INFO,"Connection Request thread: add connection request event in the queue");
pthread_mutex_lock (&(cwmp_main.mutex_session_queue));
event_container = cwmp_add_event_container (&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, "");
pthread_mutex_unlock (&(cwmp_main.mutex_session_queue));
pthread_cond_signal(&(cwmp_main.threshold_session_send));
}
static void http_cr_new_client(int client, bool service_available)
{
FILE *fp;
char buffer[BUFSIZ];
int8_t auth_status = 0;
fp = fdopen(client, "r+");
while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncasecmp(buffer, "Authorization: Digest ", strlen("Authorization: Digest "))) {
char *username = cwmp_main.conf.cpe_userid;
char *password = cwmp_main.conf.cpe_passwd;
if (!username || !password) {
// if we dont have username or password configured proceed with connecting to ACS
service_available = false;
goto http_end;
}
if (http_digest_auth_check("GET", "/", buffer + strlen("Authorization: Digest "), REALM, username, password, 300) == MHD_YES)
auth_status = 1;
else
auth_status = 0;
}
if (buffer[0] == '\r' || buffer[0] == '\n') {
/* end of http request (empty line) */
goto http_end;
}
}
if(!service_available) {
goto http_end;
}
goto http_done;
http_end:
if (!service_available) {
CWMP_LOG (INFO,"Receive Connection Request: Return 503 Service Unavailable");
fputs("HTTP/1.1 503 Service Unavailable\r\n", fp);
fputs("Connection: close\r\n", fp);
fputs("Content-Length: 0\r\n", fp);
} else if (auth_status) {
CWMP_LOG (INFO,"Receive Connection Request: success authentication");
fputs("HTTP/1.1 200 OK\r\n", fp);
fputs("Connection: close\r\n", fp);
fputs("Content-Length: 0\r\n", fp);
http_success_cr();
} else {
CWMP_LOG (INFO,"Receive Connection Request: Return 401 Unauthorized");
fputs("HTTP/1.1 401 Unauthorized\r\n", fp);
fputs("Connection: close\r\n", fp);
http_digest_auth_fail_response(fp, "GET", "/", REALM, OPAQUE);
fputs("\r\n", fp);
}
fputs("\r\n", fp);
http_done:
fclose(fp);
}
void http_server_init(void)
{
char port[16];
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
static int cr_request = 0;
static time_t restrict_start_time = 0;
time_t current_time;
bool service_available;
sprintf(port,"%d",cwmp_main.conf.connection_request_port);
http_s.http_event.cb = http_new_client;
http_s.http_event.fd = usock(USOCK_TCP | USOCK_SERVER, "0.0.0.0", port);
uloop_fd_add(&http_s.http_event, ULOOP_READ | ULOOP_EDGE_TRIGGER);
}
static void http_new_client(struct uloop_fd *ufd, unsigned events)
{
int status;
struct timeval t;
static int cr_request = 0;
static time_t restrict_start_time = 0;
time_t current_time;
bool service_available;
t.tv_sec = 60;
t.tv_usec = 0;
for (;;) {
int client = accept(ufd->fd, NULL, NULL);
/* set one minute timeout */
if (setsockopt(ufd->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&t, sizeof t)) {
CWMP_LOG(ERROR,"setsockopt() failed");
}
if (client == -1)
break;
current_time = time(NULL);
service_available = true;
if ((restrict_start_time==0) ||
((current_time-restrict_start_time) > CONNECTION_REQUEST_RESTRICT_PERIOD))
{
restrict_start_time = current_time;
cr_request = 1;
}
else
{
cr_request++;
if (cr_request>CONNECTION_REQUEST_RESTRICT_REQUEST)
{
restrict_start_time = current_time;
service_available = false;
}
}
struct uloop_process *uproc = calloc(1, sizeof(*uproc));
if (!uproc || (uproc->pid = fork()) == -1) {
free(uproc);
close(client);
}
if (uproc->pid != 0) {
/* parent */
/* register an event handler for when the child terminates */
uproc->cb = http_del_client;
uloop_process_add(uproc);
close(client);
} else {
/* child */
FILE *fp;
char buffer[BUFSIZ];
int8_t auth_status = 0;
fp = fdopen(client, "r+");
if(!service_available)
goto http_end_child;
while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncasecmp(buffer, "Authorization: Digest ", strlen("Authorization: Digest "))) {
char *username = cwmp_main.conf.cpe_userid;
char *password = cwmp_main.conf.cpe_passwd;
if (!username || !password) {
// if we dont have username or password configured proceed with connecting to ACS
service_available = false;
goto http_end_child;
}
if (http_digest_auth_check("GET", "/", buffer + strlen("Authorization: Digest "), REALM, username, password, 300) == MHD_YES)
auth_status = 1;
else
auth_status = 0;
}
if (buffer[0] == '\r' || buffer[0] == '\n') {
/* end of http request (empty line) */
goto http_end_child;
}
}
error_child:
/* here we are because of an error, e.g. timeout */
status = ETIMEDOUT|ENOMEM;
goto done_child;
http_end_child:
fflush(fp);
if (auth_status) {
CWMP_LOG (INFO,"Receive Connection Request: success authentication");
status = 0;
fputs("HTTP/1.1 200 OK\r\n", fp);
fputs("Content-Length: 0\r\n", fp);
} else if (!service_available) {
CWMP_LOG (INFO,"Receive Connection Request: Return 503 Service Unavailable");
status = EACCES;
fputs("HTTP/1.1 503 Service Unavailable\r\n", fp);
fputs("Connection: close\r\n", fp);
} else {
CWMP_LOG (INFO,"Receive Connection Request: Return 401 Unauthorized");
status = EACCES;
fputs("HTTP/1.1 401 Unauthorized\r\n", fp);
fputs("Connection: close\r\n", fp);
http_digest_auth_fail_response(fp, "GET", "/", REALM, OPAQUE);
fputs("\r\n", fp);
}
fputs("\r\n", fp);
goto done_child;
done_child:
fclose(fp);
free(uproc);
exit(status);
}
}
}
static void
http_del_client(struct uloop_process *uproc, int ret)
{
free(uproc);
struct event_container *event_container;
/* child terminated ; check return code */
if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) {
CWMP_LOG(INFO,"Connection Request thread: add connection request event in the queue");
pthread_mutex_lock (&(cwmp_main.mutex_session_queue));
event_container = cwmp_add_event_container (&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, "");
pthread_mutex_unlock (&(cwmp_main.mutex_session_queue));
pthread_cond_signal(&(cwmp_main.threshold_session_send));
}
for(;;) {
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
CWMP_LOG (ERROR,"Could not open server socket for Connection Requests");
sleep(1);
continue;
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(cwmp_main.conf.connection_request_port);
/* enable SO_REUSEADDR */
int reusaddr = 1;
if (setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) {
CWMP_LOG (WARNING,"setsockopt(SO_REUSEADDR) failed");
}
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
CWMP_LOG (ERROR,"Could not bind server socket for Connection Requests");
sleep(1);
continue;
}
break;
}
CWMP_LOG (INFO,"Connection Request server initiated");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
c = sizeof(struct sockaddr_in);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
current_time = time(NULL);
service_available = true;
if ((restrict_start_time==0) ||
((current_time-restrict_start_time) > CONNECTION_REQUEST_RESTRICT_PERIOD))
{
restrict_start_time = current_time;
cr_request = 1;
}
else
{
cr_request++;
if (cr_request > CONNECTION_REQUEST_RESTRICT_REQUEST)
{
restrict_start_time = current_time;
service_available = false;
}
}
http_cr_new_client(client_sock, service_available);
close(client_sock);
}
if (client_sock < 0)
{
CWMP_LOG(ERROR,"Could not accept connections for Connection Requests!");
return;
}
}

View file

@ -41,11 +41,6 @@ struct http_client
char *url;
};
struct http_server
{
struct uloop_fd http_event;
};
#ifdef HTTP_CURL
static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in);
#endif /* HTTP_CURL */
@ -55,8 +50,6 @@ void http_client_exit(void);
int http_send_message(struct cwmp *cwmp, char *msg_out, char **msg_in);
void http_server_init(void);
static void http_new_client(struct uloop_fd *ufd, unsigned events);
static void http_del_client(struct uloop_process *uproc, int ret);
#endif

View file

@ -34,17 +34,8 @@
#include "log.h"
static void netlink_new_msg(struct uloop_fd *ufd, unsigned events);
static void freecwmp_kickoff(struct uloop_timeout *);
static struct uloop_timeout netlink_timer = { .cb = freecwmp_kickoff };
static struct uloop_fd netlink_event = { .cb = netlink_new_msg };
static void freecwmp_kickoff(struct uloop_timeout *timeout)
{
http_server_init();
}
static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
{
struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
@ -173,7 +164,5 @@ int netlink_init(void)
struct uloop_fd dummy_event = { .fd = sock[1] };
netlink_new_msg(&dummy_event, 0);
uloop_timeout_set(&netlink_timer, 2500);
return 0;
}