[UDP-HTTP] Big refactoring
Create owlps-udp-to-http.h, rename variables, refactor functions, etc.
This commit is contained in:
parent
177bd6284c
commit
c2aaa3af15
|
@ -29,7 +29,7 @@
|
|||
* UnknownRequest;NOK
|
||||
*/
|
||||
|
||||
#include <owlps-resultreader-udp.h>
|
||||
#include "owlps-udp-to-http.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <semaphore.h>
|
||||
|
@ -42,58 +42,25 @@
|
|||
#include <assert.h>
|
||||
|
||||
|
||||
#define TCP_PORT 8080
|
||||
#define NB_CONNECTIONS 1
|
||||
#define CLIENT_MESSAGE_STRLEN 2500
|
||||
|
||||
#define SIMPLE_RESULTS_ID 1
|
||||
#define SIMPLE_RESULTS_REQUEST "ReadSimpleResults"
|
||||
#define SIMPLE_RESULTS_ANSWER "SimpleResults"
|
||||
#define CLIENT_REQUEST_STRLEN 21
|
||||
|
||||
#ifndef OWLPS_VERSION
|
||||
# define OWLPS_VERSION "unknown version"
|
||||
#endif // OWLPS_VERSION
|
||||
|
||||
#define ANSWER_HEADER \
|
||||
"HTTP/1.1 200 OK\n" \
|
||||
"Date: Sat, 01 Jan 0001 00:00:01 GMT\n" \
|
||||
"Server: OwlPS UDP-to-HTTP ["OWLPS_VERSION"]\n" \
|
||||
"Access-Control-Allow-Origin: *\n" \
|
||||
"Connection: close\n" \
|
||||
"Content-Type: text/html\n" \
|
||||
"\n"
|
||||
|
||||
|
||||
typedef struct _results_list
|
||||
{
|
||||
owl_result *result ;
|
||||
struct _results_list *next ;
|
||||
} results_list ;
|
||||
|
||||
|
||||
void store_result(owl_result *result) ;
|
||||
void* tcp_server(void *NULL_value) ;
|
||||
int
|
||||
extract_request_from_message(char client_request[CLIENT_REQUEST_STRLEN],
|
||||
char *client_message) ;
|
||||
void free_results_list(void) ;
|
||||
|
||||
|
||||
char *program_name = NULL ;
|
||||
|
||||
results_list *results = NULL ;
|
||||
unsigned int nb_results = 0 ;
|
||||
sem_t lock_results ;
|
||||
|
||||
int udp_sockfd = -1 ;
|
||||
int tcp_sockfd = -1 ;
|
||||
|
||||
char *answer = NULL ; // Answer to send to the client
|
||||
size_t answer_strlen = 0 ; // Total size of the answer string
|
||||
size_t answer_buflen = 0 ; // Size of the answer allocated buffer
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct sigaction action ; // Signal handler structure
|
||||
int ret = 0 ; // Program return value
|
||||
pthread_t tcp_server_thread ;
|
||||
owl_result *result ;
|
||||
int udp_sockfd ;
|
||||
|
||||
program_name = argv[0] ;
|
||||
owl_run = owl_true ;
|
||||
|
@ -109,14 +76,6 @@ int main(int argc, char *argv[])
|
|||
/* Set up the semaphore */
|
||||
sem_init(&lock_results, 0, 1) ;
|
||||
|
||||
/* Open the UDP socket */
|
||||
udp_sockfd = owl_create_udp_listening_socket(OWL_DEFAULT_RESULT_PORT) ;
|
||||
if (udp_sockfd < 0)
|
||||
{
|
||||
ret = 1 ;
|
||||
goto exit ;
|
||||
}
|
||||
|
||||
/* Launch the TCP thread */
|
||||
ret = pthread_create(&tcp_server_thread, NULL,
|
||||
&tcp_server, NULL) ;
|
||||
|
@ -127,19 +86,8 @@ int main(int argc, char *argv[])
|
|||
goto exit ;
|
||||
}
|
||||
|
||||
/* UDP read loop */
|
||||
while (owl_run)
|
||||
{
|
||||
result = owl_receive_position(udp_sockfd) ;
|
||||
if (result == NULL)
|
||||
{
|
||||
ret = 1 ;
|
||||
goto exit ;
|
||||
}
|
||||
owl_print_result(result) ;
|
||||
store_result(result) ;
|
||||
printf("--------------\n") ;
|
||||
}
|
||||
/* Main loop */
|
||||
ret = receive_udp() ;
|
||||
|
||||
/* Stop the TCP thread */
|
||||
if (pthread_join(tcp_server_thread, NULL))
|
||||
|
@ -147,15 +95,54 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* Cleaning */
|
||||
exit:
|
||||
if (tcp_sockfd >= 0)
|
||||
if (close(tcp_sockfd))
|
||||
perror("Error closing the TCP socket") ;
|
||||
if (udp_sockfd >= 0)
|
||||
if (close(udp_sockfd))
|
||||
perror("Error closing the UDP socket") ;
|
||||
|
||||
free(answer) ;
|
||||
free_results_list() ;
|
||||
sem_destroy(&lock_results) ;
|
||||
close(udp_sockfd) ;
|
||||
|
||||
printf("%s: end.\n", program_name) ;
|
||||
return ret ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Opens the UDP socket and reads from it the results sent by OwlPS
|
||||
* Positioning.
|
||||
* Returns a non-zero value in case of error.
|
||||
*/
|
||||
int receive_udp()
|
||||
{
|
||||
owl_result *result ;
|
||||
|
||||
/* Open the UDP socket */
|
||||
udp_sockfd = owl_create_udp_listening_socket(OWL_DEFAULT_RESULT_PORT) ;
|
||||
if (udp_sockfd < 0)
|
||||
return 1 ;
|
||||
|
||||
/* UDP read loop */
|
||||
while (owl_run)
|
||||
{
|
||||
result = owl_receive_position(udp_sockfd) ;
|
||||
if (result == NULL)
|
||||
return 1 ;
|
||||
owl_print_result(result) ;
|
||||
store_result(result) ;
|
||||
printf("--------------\n") ;
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adds a new owl_result to the results' list.
|
||||
*/
|
||||
void store_result(owl_result *new_result)
|
||||
{
|
||||
sem_wait(&lock_results) ;
|
||||
|
@ -200,18 +187,18 @@ void store_result(owl_result *new_result)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Opens the TCP socket and wait for requests from HTTP clients.
|
||||
*/
|
||||
void* tcp_server(void *NULL_value)
|
||||
{
|
||||
int tcp_sockfd, newsockfd ;
|
||||
int newsockfd ;
|
||||
socklen_t client_len ;
|
||||
struct sockaddr_in server_addr, client_addr ;
|
||||
ssize_t nbytes ; // recv/send return value
|
||||
char client_message[CLIENT_MESSAGE_STRLEN] ;
|
||||
char client_request[CLIENT_REQUEST_STRLEN] ;
|
||||
int request_id ;
|
||||
char *answer ; // Answer to send to the client
|
||||
size_t answer_hdr_len = strlen(ANSWER_HEADER) ;
|
||||
size_t answer_len ; // Total size of the answer
|
||||
|
||||
tcp_sockfd = socket(AF_INET, SOCK_STREAM, 0) ;
|
||||
if (tcp_sockfd < 0)
|
||||
|
@ -219,7 +206,6 @@ void* tcp_server(void *NULL_value)
|
|||
perror("Error opening the TCP socket") ;
|
||||
exit(1) ;
|
||||
}
|
||||
pthread_cleanup_push(&owl_close_fd, &tcp_sockfd) ;
|
||||
|
||||
bzero((char *) &server_addr, sizeof(server_addr)) ;
|
||||
server_addr.sin_family = AF_INET ;
|
||||
|
@ -236,10 +222,11 @@ void* tcp_server(void *NULL_value)
|
|||
listen(tcp_sockfd, NB_CONNECTIONS) ;
|
||||
client_len = sizeof(client_addr) ;
|
||||
|
||||
// Prepare the answer, assuming there is only 1 result (an error
|
||||
// Prepare the answer, assuming there is only 1 full result (an error
|
||||
// message will also fit)
|
||||
answer = malloc(answer_hdr_len + OWL_CSV_RESULT_STRLEN) ;
|
||||
strncpy(answer, ANSWER_HEADER, answer_hdr_len) ;
|
||||
answer_buflen = ANSWER_HDR_STRLEN + OWL_CSV_RESULT_STRLEN ;
|
||||
answer = malloc(answer_buflen) ;
|
||||
strncpy(answer, ANSWER_HDR, ANSWER_HDR_STRLEN) ;
|
||||
|
||||
while (owl_run)
|
||||
{
|
||||
|
@ -259,7 +246,6 @@ void* tcp_server(void *NULL_value)
|
|||
close(newsockfd) ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
client_message[nbytes] = '\0' ;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -267,86 +253,22 @@ void* tcp_server(void *NULL_value)
|
|||
"\"%s\"\n", client_message) ;
|
||||
#endif // DEBUG
|
||||
|
||||
answer_len = answer_hdr_len ;
|
||||
request_id =
|
||||
extract_request_from_message(client_request, client_message) ;
|
||||
switch (request_id)
|
||||
{
|
||||
case SIMPLE_RESULTS_ID:
|
||||
strncpy(answer + answer_len, SIMPLE_RESULTS_ANSWER,
|
||||
strlen(SIMPLE_RESULTS_ANSWER)) ;
|
||||
answer_len += strlen(SIMPLE_RESULTS_ANSWER) ;
|
||||
prepare_answer(request_id) ;
|
||||
|
||||
sem_wait(&lock_results) ;
|
||||
|
||||
if (! results)
|
||||
{
|
||||
char answer_end[] = ";NOK;NoResult" ;
|
||||
strncpy(answer + answer_len, answer_end,
|
||||
strlen(answer_end)) ;
|
||||
answer_len += strlen(answer_end) ;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
results_list *result ;
|
||||
char answer_begin[10] ;
|
||||
size_t answer_begin_len, answer_buf_len ;
|
||||
|
||||
snprintf(answer_begin, 10, ";OK;%u", nb_results) ;
|
||||
answer_begin_len = strlen(answer_begin) ;
|
||||
strncpy(answer + answer_len, answer_begin,
|
||||
answer_begin_len) ;
|
||||
answer_len += answer_begin_len ;
|
||||
|
||||
answer_buf_len =
|
||||
answer_len +
|
||||
nb_results * OWL_CSV_RESULT_STRLEN ;
|
||||
answer = realloc(answer, answer_buf_len) ;
|
||||
|
||||
result = results ;
|
||||
while (result != NULL)
|
||||
{
|
||||
char result_str[OWL_CSV_RESULT_STRLEN] ;
|
||||
size_t result_len ;
|
||||
owl_result_to_csv_simple(result_str, result->result) ;
|
||||
result_len = strlen(result_str) ;
|
||||
answer[answer_len++] = ';' ;
|
||||
strncpy(answer + answer_len, result_str,
|
||||
result_len) ;
|
||||
answer_len += result_len ;
|
||||
result = result->next ;
|
||||
}
|
||||
}
|
||||
|
||||
sem_post(&lock_results) ;
|
||||
|
||||
break ;
|
||||
|
||||
default:
|
||||
{
|
||||
char answer_end[] = "UnknownRequest;NOK" ;
|
||||
strncpy(answer + answer_hdr_len, answer_end,
|
||||
strlen(answer_end)) ;
|
||||
answer_len += strlen(answer_end) ;
|
||||
}
|
||||
}
|
||||
|
||||
answer[answer_len] = '\0' ;
|
||||
#ifdef DEBUG
|
||||
printf("Answer to send:\n\"%s\"\n", answer) ;
|
||||
#endif // DEBUG
|
||||
|
||||
nbytes = send(newsockfd, answer, answer_len, 0) ;
|
||||
/* Send the answer */
|
||||
nbytes = send(newsockfd, answer, answer_strlen, 0) ;
|
||||
if (nbytes < 0)
|
||||
perror("Error sending answer to the TCP socket") ;
|
||||
|
||||
close(newsockfd) ;
|
||||
}
|
||||
|
||||
/* Cleaning */
|
||||
// Close tcp_sockfd
|
||||
pthread_cleanup_pop(1) ;
|
||||
free(answer) ;
|
||||
|
||||
pthread_exit(NULL_value) ;
|
||||
}
|
||||
|
||||
|
@ -375,6 +297,99 @@ extract_request_from_message(char client_request[CLIENT_REQUEST_STRLEN],
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare the answer string to send to the TCP client.
|
||||
*/
|
||||
void prepare_answer(int request_id)
|
||||
{
|
||||
// Reset the answer's length:
|
||||
answer_strlen = ANSWER_HDR_STRLEN ;
|
||||
|
||||
switch (request_id)
|
||||
{
|
||||
case SIMPLE_RESULTS_ID:
|
||||
strncpy(answer + answer_strlen, SIMPLE_RESULTS_ANSWER,
|
||||
strlen(SIMPLE_RESULTS_ANSWER)) ;
|
||||
answer_strlen += strlen(SIMPLE_RESULTS_ANSWER) ;
|
||||
|
||||
sem_wait(&lock_results) ;
|
||||
|
||||
if (! results)
|
||||
{
|
||||
char answer_end[] = ";NOK;NoResult" ;
|
||||
strncpy(answer + answer_strlen, answer_end,
|
||||
strlen(answer_end)) ;
|
||||
answer_strlen += strlen(answer_end) ;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
results_list *result ;
|
||||
char answer_begin[10] ;
|
||||
size_t answer_begin_len ;
|
||||
|
||||
snprintf(answer_begin, 10, ";OK;%u", nb_results) ;
|
||||
answer_begin_len = strlen(answer_begin) ;
|
||||
strncpy(answer + answer_strlen, answer_begin,
|
||||
answer_begin_len) ;
|
||||
answer_strlen += answer_begin_len ;
|
||||
|
||||
realloc_answer(answer_strlen +
|
||||
nb_results * OWL_CSV_RESULT_SIMPLE_STRLEN) ;
|
||||
|
||||
result = results ;
|
||||
while (result != NULL)
|
||||
{
|
||||
char result_str[OWL_CSV_RESULT_SIMPLE_STRLEN] ;
|
||||
size_t result_len ;
|
||||
owl_result_to_csv_simple(result_str, result->result) ;
|
||||
result_len = strlen(result_str) ;
|
||||
answer[answer_strlen++] = ';' ;
|
||||
strncpy(answer + answer_strlen, result_str,
|
||||
result_len) ;
|
||||
answer_strlen += result_len ;
|
||||
result = result->next ;
|
||||
}
|
||||
}
|
||||
|
||||
sem_post(&lock_results) ;
|
||||
|
||||
break ;
|
||||
|
||||
default:
|
||||
{
|
||||
char answer_end[] = "UnknownRequest;NOK" ;
|
||||
strncpy(answer + ANSWER_HDR_STRLEN, answer_end,
|
||||
strlen(answer_end)) ;
|
||||
answer_strlen += strlen(answer_end) ;
|
||||
}
|
||||
}
|
||||
|
||||
answer[answer_strlen] = '\0' ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Realloc the answer buffer to the if needed: grows it if new_size is
|
||||
* greater than the current size, shrink it if the current size is
|
||||
* greater than the double of new_size.
|
||||
*/
|
||||
void realloc_answer(size_t new_size)
|
||||
{
|
||||
if (new_size > answer_buflen)
|
||||
answer_buflen = new_size ;
|
||||
else if (answer_buflen / 2 >= new_size)
|
||||
answer_buflen /= 2 ;
|
||||
else
|
||||
return ;
|
||||
|
||||
answer = realloc(answer, answer_buflen) ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Frees the memory allocated for the results' list.
|
||||
*/
|
||||
void free_results_list()
|
||||
{
|
||||
results_list *ptr = results ;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef _OWLPS_UDP_TO_HTTP_H_
|
||||
#define _OWLPS_UDP_TO_HTTP_H_
|
||||
|
||||
#include <owlps-resultreader-udp.h>
|
||||
|
||||
#define TCP_PORT 8080
|
||||
#define NB_CONNECTIONS 1
|
||||
#define CLIENT_MESSAGE_STRLEN 2500
|
||||
|
||||
#define SIMPLE_RESULTS_ID 1
|
||||
#define SIMPLE_RESULTS_REQUEST "ReadSimpleResults"
|
||||
#define SIMPLE_RESULTS_ANSWER "SimpleResults"
|
||||
#define CLIENT_REQUEST_STRLEN 21
|
||||
|
||||
#ifndef OWLPS_VERSION
|
||||
# define OWLPS_VERSION "unknown version"
|
||||
#endif // OWLPS_VERSION
|
||||
|
||||
#define ANSWER_HDR \
|
||||
"HTTP/1.1 200 OK\n" \
|
||||
"Date: Sat, 01 Jan 0001 00:00:01 GMT\n" \
|
||||
"Server: OwlPS UDP-to-HTTP ["OWLPS_VERSION"]\n" \
|
||||
"Access-Control-Allow-Origin: *\n" \
|
||||
"Connection: close\n" \
|
||||
"Content-Type: text/html\n" \
|
||||
"\n"
|
||||
#define ANSWER_HDR_STRLEN strlen(ANSWER_HDR)
|
||||
|
||||
|
||||
typedef struct _results_list
|
||||
{
|
||||
owl_result *result ;
|
||||
struct _results_list *next ;
|
||||
} results_list ;
|
||||
|
||||
|
||||
int receive_udp(void) ;
|
||||
void store_result(owl_result *result) ;
|
||||
void* tcp_server(void *NULL_value) ;
|
||||
int
|
||||
extract_request_from_message(char client_request[CLIENT_REQUEST_STRLEN],
|
||||
char *client_message) ;
|
||||
void prepare_answer(int request_id) ;
|
||||
void realloc_answer(size_t new_size) ;
|
||||
void free_results_list(void) ;
|
||||
|
||||
|
||||
#endif // _OWLPS_UDP_TO_HTTP_H_
|
Loading…
Reference in New Issue