implemented UDP submit support
git-svn-id: http://repo.ham.fi/svn/aprsc/trunk@727 3ce903b1-3385-4e86-93cd-f9a4a239f7ac
This commit is contained in:
parent
e75669d684
commit
7bf0500a50
159
src/accept.c
159
src/accept.c
|
|
@ -36,6 +36,7 @@
|
|||
#include "dupecheck.h"
|
||||
#include "filter.h"
|
||||
#include "login.h"
|
||||
#include "http.h"
|
||||
#include "incoming.h" /* incoming_handler prototype */
|
||||
#include "uplink.h"
|
||||
|
||||
|
|
@ -65,6 +66,10 @@ static struct listen_t *listen_list;
|
|||
int accept_shutting_down;
|
||||
int accept_reconfiguring;
|
||||
|
||||
/* pseudoworker + pseudoclient for incoming UDP packets */
|
||||
struct worker_t *udp_worker = NULL;
|
||||
struct client_t *udp_pseudoclient = NULL;
|
||||
|
||||
|
||||
/* structure allocator/free */
|
||||
|
||||
|
|
@ -128,7 +133,7 @@ static int accept_sighandler(int signum)
|
|||
* Pass a new client to a worker thread
|
||||
*/
|
||||
|
||||
int accept_pass_client_to_worker(struct worker_t *wc, struct client_t *c)
|
||||
static int accept_pass_client_to_worker(struct worker_t *wc, struct client_t *c)
|
||||
{
|
||||
int pe;
|
||||
|
||||
|
|
@ -337,7 +342,7 @@ static void close_listeners(void)
|
|||
* Generate UDP peer "clients"
|
||||
*/
|
||||
|
||||
void peerip_clients_config(void)
|
||||
static void peerip_clients_config(void)
|
||||
{
|
||||
struct client_t *c;
|
||||
struct peerip_config_t *pe;
|
||||
|
|
@ -416,46 +421,114 @@ void peerip_clients_config(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an incoming UDP packet submission
|
||||
*/
|
||||
|
||||
static void accept_process_udpsubmit(struct listen_t *l, char *buf, int len, char *remote_host)
|
||||
{
|
||||
int packet_len;
|
||||
char *login_string = NULL;
|
||||
char *packet = NULL;
|
||||
char *username = NULL;
|
||||
char validated;
|
||||
int e;
|
||||
|
||||
//hlog(LOG_DEBUG, "got udp submit: %.*s", len, buf);
|
||||
|
||||
packet_len = loginpost_split(buf, len, &login_string, &packet);
|
||||
if (packet_len == -1) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: No newline (LF) found in data", remote_host);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!login_string) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: No login string in data", remote_host);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!packet) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: No packet data found in data", remote_host);
|
||||
return;
|
||||
}
|
||||
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: login string: %s", remote_host, login_string);
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: packet: %s", remote_host, packet);
|
||||
|
||||
/* process the login string */
|
||||
validated = http_udp_upload_login(remote_host, login_string, &username);
|
||||
if (validated < 0) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: Invalid login string", remote_host);
|
||||
return;
|
||||
}
|
||||
|
||||
if (validated != 1) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: Invalid passcode for user %s", remote_host, username);
|
||||
return;
|
||||
}
|
||||
|
||||
/* packet size limits */
|
||||
if (packet_len < PACKETLEN_MIN) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: Packet too short: %d bytes", remote_host, packet_len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_len > PACKETLEN_MAX-2) {
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: Packet too long: %d bytes", remote_host, packet_len);
|
||||
return;
|
||||
}
|
||||
|
||||
e = pseudoclient_push_packet(udp_worker, udp_pseudoclient, username, packet, packet_len);
|
||||
|
||||
if (e < 0)
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: Incoming packet parse failure code %d: %s", remote_host, e, packet);
|
||||
else
|
||||
hlog(LOG_DEBUG, "UDP submit [%s]: Incoming packet parsed, code %d: %s", remote_host, e, packet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive UDP packets from an UDP listener
|
||||
*/
|
||||
|
||||
static void accept_udp_recv(struct listen_t *l)
|
||||
{
|
||||
union sockaddr_u addr;
|
||||
socklen_t addrlen;
|
||||
char buf[2000];
|
||||
int i;
|
||||
char *addrs;
|
||||
|
||||
/* Receive as much as there is -- that is, LOOP... */
|
||||
addrlen = sizeof(addr);
|
||||
|
||||
while ((i = recvfrom( l->udp->fd, buf, sizeof(buf)-1, MSG_DONTWAIT|MSG_TRUNC, (struct sockaddr *)&addr, &addrlen )) >= 0) {
|
||||
if (!(l->clientflags & CLFLAGS_UDPSUBMIT)) {
|
||||
hlog(LOG_DEBUG, "accept thread discarded an UDP packet on a listening socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
addrs = strsockaddr(&addr.sa, addrlen);
|
||||
accept_process_udpsubmit(l, buf, i, addrs);
|
||||
hfree(addrs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a single connection
|
||||
*/
|
||||
|
||||
static struct client_t *do_accept(struct listen_t *l)
|
||||
static void do_accept(struct listen_t *l)
|
||||
{
|
||||
int fd, i;
|
||||
struct client_t *c;
|
||||
union sockaddr_u sa; /* large enough for also IPv6 address */
|
||||
socklen_t addr_len = sizeof(sa);
|
||||
char buf[2000];
|
||||
static int next_receiving_worker;
|
||||
struct worker_t *w;
|
||||
struct worker_t *wc;
|
||||
static time_t last_EMFILE_report;
|
||||
char *s;
|
||||
|
||||
while (l->udp) {
|
||||
/* This should not really happen any more, since accept_thread
|
||||
* does not poll() UDP sockets, that's left to worker 0.
|
||||
*/
|
||||
|
||||
/* Received data will be discarded, so receiving it */
|
||||
/* TRUNCATED is just fine. Sender isn't interesting either. */
|
||||
/* Receive as much as there is -- that is, LOOP... */
|
||||
|
||||
i = recv( l->udp->fd, buf, sizeof(buf), MSG_DONTWAIT|MSG_TRUNC );
|
||||
|
||||
if (i < 0)
|
||||
return 0; /* no more data */
|
||||
|
||||
if (!(l->clientflags & CLFLAGS_UDPSUBMIT)) {
|
||||
hlog(LOG_DEBUG, "accept thread discarded an UDP packet on a listening socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
hlog(LOG_DEBUG, "accept thread got an UDP packet on an udpsubmit socket");
|
||||
|
||||
}
|
||||
|
||||
if ((fd = accept(l->fd, (struct sockaddr*)&sa, &addr_len)) < 0) {
|
||||
int e = errno;
|
||||
switch (e) {
|
||||
|
|
@ -486,11 +559,11 @@ static struct client_t *do_accept(struct listen_t *l)
|
|||
last_EMFILE_report = tick;
|
||||
hlog(LOG_ERR, "accept() failed: %s (continuing)", strerror(e));
|
||||
}
|
||||
return NULL;
|
||||
return;
|
||||
/* Errors reporting system internal/external glitches */
|
||||
default:
|
||||
hlog(LOG_ERR, "accept() failed: %s (continuing)", strerror(e));
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +580,7 @@ static struct client_t *do_accept(struct listen_t *l)
|
|||
close(fd);
|
||||
hfree(s);
|
||||
inbound_connects_account(-1, l->portaccount); /* account rejected connection */
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* match against acl... could probably have an error message to the client */
|
||||
|
|
@ -517,7 +590,7 @@ static struct client_t *do_accept(struct listen_t *l)
|
|||
close(fd);
|
||||
hfree(s);
|
||||
inbound_connects_account(-1, l->portaccount); /* account rejected connection */
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -645,13 +718,13 @@ static struct client_t *do_accept(struct listen_t *l)
|
|||
if (accept_pass_client_to_worker(wc, c))
|
||||
goto err;
|
||||
|
||||
return c;
|
||||
return;
|
||||
|
||||
err:
|
||||
|
||||
inbound_connects_account(0, c->portaccount); /* something failed, remove this from accounts.. */
|
||||
client_free(c);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -683,6 +756,18 @@ void accept_thread(void *asdf)
|
|||
/* start the accept thread, which will start server threads */
|
||||
hlog(LOG_INFO, "Accept_thread starting...");
|
||||
|
||||
/* we allocate a worker structure to be used within the accept thread
|
||||
* for parsing incoming UDP packets and passing them on to the dupecheck
|
||||
* thread.
|
||||
*/
|
||||
udp_worker = worker_alloc();
|
||||
udp_worker->id = 81;
|
||||
|
||||
/* we also need a client structure to be used with incoming
|
||||
* HTTP position uploads
|
||||
*/
|
||||
udp_pseudoclient = pseudoclient_setup(81);
|
||||
|
||||
accept_reconfiguring = 1;
|
||||
while (!accept_shutting_down) {
|
||||
if (accept_reconfiguring) {
|
||||
|
|
@ -761,8 +846,12 @@ void accept_thread(void *asdf)
|
|||
hlog(LOG_CRIT, "accept_thread: polling list and listener list do mot match!");
|
||||
exit(1);
|
||||
}
|
||||
if (acceptpfd[n].revents)
|
||||
do_accept(l); /* accept a single connection */
|
||||
if (acceptpfd[n].revents) {
|
||||
if (l->udp)
|
||||
accept_udp_recv(l); /* receive UDP packets */
|
||||
else
|
||||
do_accept(l); /* accept a single connection */
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
extern int accept_reconfiguring;
|
||||
extern int accept_shutting_down;
|
||||
|
||||
extern struct worker_t *udp_worker;
|
||||
|
||||
extern void accept_thread(void *asdf);
|
||||
|
||||
extern int accept_listener_status(cJSON *listeners, cJSON *totals);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "filter.h"
|
||||
#include "historydb.h"
|
||||
#include "http.h"
|
||||
#include "accept.h"
|
||||
|
||||
int dupecheck_shutting_down;
|
||||
int dupecheck_running;
|
||||
|
|
@ -524,6 +525,13 @@ static void dupecheck_thread(void)
|
|||
&pb_out_count, &pb_out_dupe_count);
|
||||
}
|
||||
|
||||
if ((udp_worker) && udp_worker->pbuf_incoming) {
|
||||
n += dupecheck_drain_worker(udp_worker,
|
||||
&pb_out_prevp, &pb_out_last,
|
||||
&pb_out_dupe_prevp, &pb_out_dupe_last,
|
||||
&pb_out_count, &pb_out_dupe_count);
|
||||
}
|
||||
|
||||
// terminate those out-chains in every case..
|
||||
*pb_out_prevp = NULL;
|
||||
*pb_out_dupe_prevp = NULL;
|
||||
|
|
|
|||
170
src/http.c
170
src/http.c
|
|
@ -42,6 +42,7 @@
|
|||
#include "status.h"
|
||||
#include "passcode.h"
|
||||
#include "incoming.h"
|
||||
#include "login.h"
|
||||
#include "counterdata.h"
|
||||
|
||||
int http_shutting_down;
|
||||
|
|
@ -96,7 +97,7 @@ static struct http_static_t http_content_types[] = {
|
|||
* Find a content-type for a file name
|
||||
*/
|
||||
|
||||
char *http_content_type(char *fn)
|
||||
static char *http_content_type(const char *fn)
|
||||
{
|
||||
struct http_static_t *cmdp;
|
||||
static char default_ctype[] = "text/html";
|
||||
|
|
@ -120,7 +121,7 @@ char *http_content_type(char *fn)
|
|||
* HTTP date formatting
|
||||
*/
|
||||
|
||||
int http_date(char *buf, int len, time_t t)
|
||||
static int http_date(char *buf, int len, time_t t)
|
||||
{
|
||||
struct tm tb;
|
||||
char *wkday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", NULL };
|
||||
|
|
@ -134,7 +135,7 @@ int http_date(char *buf, int len, time_t t)
|
|||
tb.tm_hour, tb.tm_min, tb.tm_sec);
|
||||
}
|
||||
|
||||
void http_header_base(struct evkeyvalq *headers, int last_modified)
|
||||
static void http_header_base(struct evkeyvalq *headers, int last_modified)
|
||||
{
|
||||
char dbuf[80];
|
||||
|
||||
|
|
@ -149,64 +150,6 @@ void http_header_base(struct evkeyvalq *headers, int last_modified)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the login string in a POST
|
||||
* Argh, why are these not in standard POST parameters?
|
||||
*/
|
||||
|
||||
int http_upload_login(char *addr_rem, char *s, char **username)
|
||||
{
|
||||
int argc;
|
||||
char *argv[256];
|
||||
int i;
|
||||
|
||||
/* parse to arguments */
|
||||
if ((argc = parse_args_noshell(argv, s)) == 0)
|
||||
return -1;
|
||||
|
||||
if (argc < 2) {
|
||||
hlog(LOG_WARNING, "%s: HTTP POST: Invalid login string, too few arguments: '%s'", addr_rem, s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[0], "user") != 0) {
|
||||
hlog(LOG_WARNING, "%s: HTTP POST: Invalid login string, no 'user': '%s'", addr_rem, s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*username = argv[1];
|
||||
if (strlen(*username) > 9) /* limit length */
|
||||
*username[9] = 0;
|
||||
|
||||
int given_passcode = -1;
|
||||
int validated = 0;
|
||||
|
||||
for (i = 2; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "pass") == 0) {
|
||||
if (++i >= argc) {
|
||||
hlog(LOG_WARNING, "%s (%s): HTTP POST: No passcode after pass command", addr_rem, username);
|
||||
break;
|
||||
}
|
||||
|
||||
given_passcode = atoi(argv[i]);
|
||||
if (given_passcode >= 0)
|
||||
if (given_passcode == aprs_passcode(*username))
|
||||
validated = 1;
|
||||
} else if (strcasecmp(argv[i], "vers") == 0) {
|
||||
if (i+2 >= argc) {
|
||||
hlog(LOG_DEBUG, "%s (%s): HTTP POST: No application name and version after vers command", addr_rem, username);
|
||||
break;
|
||||
}
|
||||
|
||||
// skip app name and version
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return validated;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split a login + packet string. Terminates login string with 0,
|
||||
* returns length of packet.
|
||||
|
|
@ -254,6 +197,48 @@ int loginpost_split(char *post, int len, char **login_string, char **packet)
|
|||
return packet_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process an incoming HTTP or UDP packet by parsing it and pushing
|
||||
* it to the dupecheck thread through the pseudoworker
|
||||
*/
|
||||
|
||||
int pseudoclient_push_packet(struct worker_t *worker, struct client_t *pseudoclient, const char *username, char *packet, int packet_len)
|
||||
{
|
||||
int e;
|
||||
|
||||
/* fill the user's information in the pseudoclient's structure
|
||||
* for the q construct handler's viewing pleasure
|
||||
*/
|
||||
#ifdef FIXED_IOBUFS
|
||||
strncpy(pseudoclient->username, username, sizeof(pseudoclient->username));
|
||||
pseudoclient->username[sizeof(pseudoclient->username)-1] = 0;
|
||||
#else
|
||||
pseudoclient->username = username;
|
||||
#endif
|
||||
pseudoclient->username_len = strlen(pseudoclient->username);
|
||||
|
||||
/* ok, try to digest the packet */
|
||||
e = incoming_parse(worker, pseudoclient, packet, packet_len);
|
||||
|
||||
#ifdef FIXED_IOBUFS
|
||||
pseudoclient->username[0] = 0;
|
||||
#else
|
||||
pseudoclient->username = NULL;
|
||||
#endif
|
||||
pseudoclient->username_len = 0;
|
||||
|
||||
if (e < 0)
|
||||
return e;
|
||||
|
||||
/* if the packet parser managed to digest the packet and put it to
|
||||
* the thread-local incoming queue, flush it for dupecheck to
|
||||
* grab
|
||||
*/
|
||||
if (worker->pbuf_incoming_local)
|
||||
incoming_flush(worker);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a POST containing a position
|
||||
|
|
@ -261,7 +246,7 @@ int loginpost_split(char *post, int len, char **login_string, char **packet)
|
|||
|
||||
#define MAX_HTTP_POST_DATA 2048
|
||||
|
||||
void http_upload_position(struct evhttp_request *r, char *remote_host)
|
||||
static void http_upload_position(struct evhttp_request *r, const char *remote_host)
|
||||
{
|
||||
struct evbuffer *bufin, *bufout;
|
||||
struct evkeyvalq *req_headers;
|
||||
|
|
@ -271,6 +256,7 @@ void http_upload_position(struct evhttp_request *r, char *remote_host)
|
|||
ev_ssize_t l;
|
||||
char *login_string = NULL;
|
||||
char *packet = NULL;
|
||||
char *username = NULL;
|
||||
char validated;
|
||||
int e;
|
||||
int packet_len;
|
||||
|
|
@ -331,8 +317,7 @@ void http_upload_position(struct evhttp_request *r, char *remote_host)
|
|||
hlog(LOG_DEBUG, "packet: %s", packet);
|
||||
|
||||
/* process the login string */
|
||||
char *username;
|
||||
validated = http_upload_login(remote_host, login_string, &username);
|
||||
validated = http_udp_upload_login(remote_host, login_string, &username);
|
||||
if (validated < 0) {
|
||||
evhttp_send_error(r, HTTP_BADREQUEST, "Invalid login string");
|
||||
return;
|
||||
|
|
@ -354,39 +339,14 @@ void http_upload_position(struct evhttp_request *r, char *remote_host)
|
|||
return;
|
||||
}
|
||||
|
||||
/* fill the user's information in the pseudoclient's structure
|
||||
* for the q construct handler's viewing pleasure
|
||||
*/
|
||||
#ifdef FIXED_IOBUFS
|
||||
strncpy(http_pseudoclient->username, username, sizeof(http_pseudoclient->username));
|
||||
http_pseudoclient->username[sizeof(http_pseudoclient->username)-1] = 0;
|
||||
#else
|
||||
http_pseudoclient->username = username;
|
||||
#endif
|
||||
http_pseudoclient->username_len = strlen(http_pseudoclient->username);
|
||||
|
||||
/* ok, try to digest the packet */
|
||||
e = incoming_parse(http_worker, http_pseudoclient, packet, packet_len);
|
||||
e = pseudoclient_push_packet(http_worker, http_pseudoclient, username, packet, packet_len);
|
||||
|
||||
#ifdef FIXED_IOBUFS
|
||||
http_pseudoclient->username[0] = 0;
|
||||
#else
|
||||
http_pseudoclient->username = NULL;
|
||||
#endif
|
||||
|
||||
if (e < 0) {
|
||||
hlog(LOG_DEBUG, "http incoming packet parse failure code %d: %s", e, packet);
|
||||
evhttp_send_error(r, HTTP_BADREQUEST, "Packet parsing failure");
|
||||
return;
|
||||
}
|
||||
|
||||
/* if the packet parser managed to digest the packet and put it to
|
||||
* the thread-local incoming queue, flush it for dupecheck to
|
||||
* grab
|
||||
*/
|
||||
if (http_worker->pbuf_incoming_local)
|
||||
incoming_flush(http_worker);
|
||||
|
||||
bufout = evbuffer_new();
|
||||
evbuffer_add(bufout, "ok\n", 3);
|
||||
|
||||
|
|
@ -402,7 +362,7 @@ void http_upload_position(struct evhttp_request *r, char *remote_host)
|
|||
* Generate a status JSON response
|
||||
*/
|
||||
|
||||
void http_status(struct evhttp_request *r)
|
||||
static void http_status(struct evhttp_request *r)
|
||||
{
|
||||
char *json;
|
||||
struct evbuffer *buffer = evbuffer_new();
|
||||
|
|
@ -424,7 +384,7 @@ void http_status(struct evhttp_request *r)
|
|||
* Return counterdata in JSON
|
||||
*/
|
||||
|
||||
void http_counterdata(struct evhttp_request *r, const char *uri)
|
||||
static void http_counterdata(struct evhttp_request *r, const char *uri)
|
||||
{
|
||||
char *json;
|
||||
const char *query;
|
||||
|
|
@ -548,7 +508,7 @@ static void http_route_static(struct evhttp_request *r, const char *uri)
|
|||
* HTTP request router
|
||||
*/
|
||||
|
||||
void http_router(struct evhttp_request *r, void *which_server)
|
||||
static void http_router(struct evhttp_request *r, void *which_server)
|
||||
{
|
||||
char *remote_host;
|
||||
ev_uint16_t remote_port;
|
||||
|
|
@ -603,7 +563,7 @@ struct event_base *libbase = NULL;
|
|||
* HTTP timer event, mainly to catch the shutdown signal
|
||||
*/
|
||||
|
||||
void http_timer(evutil_socket_t fd, short events, void *arg)
|
||||
static void http_timer(evutil_socket_t fd, short events, void *arg)
|
||||
{
|
||||
struct timeval http_timer_tv;
|
||||
http_timer_tv.tv_sec = 0;
|
||||
|
|
@ -620,7 +580,7 @@ void http_timer(evutil_socket_t fd, short events, void *arg)
|
|||
event_add(ev_timer, &http_timer_tv);
|
||||
}
|
||||
|
||||
void http_srvr_defaults(struct evhttp *srvr)
|
||||
static void http_srvr_defaults(struct evhttp *srvr)
|
||||
{
|
||||
// limit what the clients can do a bit
|
||||
evhttp_set_allowed_methods(srvr, EVHTTP_REQ_GET);
|
||||
|
|
@ -631,24 +591,6 @@ void http_srvr_defaults(struct evhttp *srvr)
|
|||
// TODO: How to limit the amount of concurrent HTTP connections?
|
||||
}
|
||||
|
||||
struct client_t *http_pseudoclient_setup(void)
|
||||
{
|
||||
struct client_t *c;
|
||||
|
||||
c = http_pseudoclient = client_alloc();
|
||||
c->fd = -1;
|
||||
c->portnum = 80;
|
||||
c->state = CSTATE_CONNECTED;
|
||||
c->flags = CLFLAGS_INPORT|CLFLAGS_CLIENTONLY;
|
||||
c->validated = 1; // we will validate on every packet
|
||||
//c->portaccount = l->portaccount;
|
||||
c->keepalive = tick;
|
||||
c->connect_time = tick;
|
||||
c->last_read = tick;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTP server thread
|
||||
*/
|
||||
|
|
@ -689,7 +631,7 @@ void http_thread(void *asdf)
|
|||
/* we also need a client structure to be used with incoming
|
||||
* HTTP position uploads
|
||||
*/
|
||||
http_pseudoclient_setup();
|
||||
http_pseudoclient = pseudoclient_setup(80);
|
||||
|
||||
http_reconfiguring = 1;
|
||||
while (!http_shutting_down) {
|
||||
|
|
|
|||
|
|
@ -11,11 +11,16 @@
|
|||
#ifndef HTTP_H
|
||||
#define HTTP_H
|
||||
|
||||
#include "worker.h"
|
||||
|
||||
extern struct worker_t *http_worker;
|
||||
|
||||
extern int http_reconfiguring;
|
||||
extern int http_shutting_down;
|
||||
|
||||
extern int loginpost_split(char *post, int len, char **login_string, char **packet);
|
||||
extern int pseudoclient_push_packet(struct worker_t *worker, struct client_t *pseudoclient, const char *username, char *packet, int packet_len);
|
||||
|
||||
extern void http_thread(void *asdf);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
58
src/login.c
58
src/login.c
|
|
@ -22,6 +22,64 @@
|
|||
#include "clientlist.h"
|
||||
#include "parse_qc.h"
|
||||
|
||||
/*
|
||||
* Parse the login string in a HTTP POST or UDP submit packet
|
||||
* Argh, why are these not in standard POST parameters in HTTP?
|
||||
*/
|
||||
|
||||
int http_udp_upload_login(const char *addr_rem, char *s, char **username)
|
||||
{
|
||||
int argc;
|
||||
char *argv[256];
|
||||
int i;
|
||||
|
||||
/* parse to arguments */
|
||||
if ((argc = parse_args_noshell(argv, s)) == 0)
|
||||
return -1;
|
||||
|
||||
if (argc < 2) {
|
||||
hlog(LOG_WARNING, "%s: HTTP POST: Invalid login string, too few arguments: '%s'", addr_rem, s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[0], "user") != 0) {
|
||||
hlog(LOG_WARNING, "%s: HTTP POST: Invalid login string, no 'user': '%s'", addr_rem, s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*username = argv[1];
|
||||
if (strlen(*username) > 9) /* limit length */
|
||||
*username[9] = 0;
|
||||
|
||||
int given_passcode = -1;
|
||||
int validated = 0;
|
||||
|
||||
for (i = 2; i < argc; i++) {
|
||||
if (strcasecmp(argv[i], "pass") == 0) {
|
||||
if (++i >= argc) {
|
||||
hlog(LOG_WARNING, "%s (%s): HTTP POST: No passcode after pass command", addr_rem, username);
|
||||
break;
|
||||
}
|
||||
|
||||
given_passcode = atoi(argv[i]);
|
||||
if (given_passcode >= 0)
|
||||
if (given_passcode == aprs_passcode(*username))
|
||||
validated = 1;
|
||||
} else if (strcasecmp(argv[i], "vers") == 0) {
|
||||
if (i+2 >= argc) {
|
||||
hlog(LOG_DEBUG, "%s (%s): HTTP POST: No application name and version after vers command", addr_rem, username);
|
||||
break;
|
||||
}
|
||||
|
||||
// skip app name and version
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return validated;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* login.c: works in the context of the worker thread
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "worker.h"
|
||||
|
||||
extern int http_udp_upload_login(const char *addr_rem, char *s, char **username);
|
||||
extern int login_handler(struct worker_t *self, struct client_t *c, int l4proto, char *s, int len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
21
src/worker.c
21
src/worker.c
|
|
@ -350,6 +350,27 @@ void client_free(struct client_t *c)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a pseudoclient for UDP and HTTP submitted packets
|
||||
*/
|
||||
|
||||
struct client_t *pseudoclient_setup(int portnum)
|
||||
{
|
||||
struct client_t *c;
|
||||
|
||||
c = client_alloc();
|
||||
c->fd = -1;
|
||||
c->portnum = portnum;
|
||||
c->state = CSTATE_CONNECTED;
|
||||
c->flags = CLFLAGS_INPORT|CLFLAGS_CLIENTONLY;
|
||||
c->validated = 1; // we will validate on every packet
|
||||
//c->portaccount = l->portaccount;
|
||||
c->keepalive = tick;
|
||||
c->connect_time = tick;
|
||||
c->last_read = tick;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
char *strsockaddr(const struct sockaddr *sa, const int addr_len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ struct client_t {
|
|||
|
||||
extern struct client_t *client_alloc(void);
|
||||
extern void client_free(struct client_t *c);
|
||||
extern struct client_t *pseudoclient_setup(int portnum);
|
||||
|
||||
|
||||
/* worker thread structure */
|
||||
|
|
|
|||
Loading…
Reference in New Issue