2009-05-19 20:57:50 +00:00
|
|
|
/*
|
|
|
|
* uhub - A tiny ADC p2p connection hub
|
|
|
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "uhub.h"
|
|
|
|
#include "hubio.h"
|
|
|
|
|
2009-06-21 12:21:34 +00:00
|
|
|
// #define SEND_CHUNKS 1
|
2009-05-27 23:47:48 +00:00
|
|
|
|
|
|
|
/* FIXME: This should not be needed! */
|
|
|
|
extern struct hub_info* g_hub;
|
2009-05-19 20:57:50 +00:00
|
|
|
|
2009-07-25 01:23:06 +00:00
|
|
|
#ifdef DEBUG_SENDQ
|
|
|
|
static void debug_msg(const char* prefix, struct adc_message* msg)
|
|
|
|
{
|
|
|
|
size_t n;
|
|
|
|
char* buf = strdup(msg->cache);
|
|
|
|
for (n = 0; n < msg->length; n++)
|
|
|
|
{
|
|
|
|
if (buf[n] == '\r' || buf[n] == '\n')
|
|
|
|
buf[n] = '_';
|
|
|
|
}
|
|
|
|
hub_log(log_trace, "%s: [%s] (%d bytes)", prefix, buf, (int) msg->length);
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
struct hub_recvq* hub_recvq_create()
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hub_recvq_destroy(struct hub_recvq* q)
|
|
|
|
{
|
|
|
|
if (q)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
hub_free(q->buf);
|
|
|
|
hub_free(q);
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
assert(bufsize >= q->size);
|
|
|
|
if (q->size)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
size_t n = q->size;
|
|
|
|
memcpy(buf, q->buf, n);
|
|
|
|
hub_free(q->buf);
|
|
|
|
q->buf = 0;
|
|
|
|
q->size = 0;
|
|
|
|
return n;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
2009-05-26 17:46:51 +00:00
|
|
|
return 0;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
if (q->buf)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
hub_free(q->buf);
|
|
|
|
q->buf = 0;
|
|
|
|
q->size = 0;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
2009-05-26 19:05:06 +00:00
|
|
|
|
|
|
|
if (!bufsize)
|
2009-05-31 23:52:57 +00:00
|
|
|
{
|
2009-05-26 19:05:06 +00:00
|
|
|
return 0;
|
2009-05-31 23:52:57 +00:00
|
|
|
}
|
2009-05-26 17:46:51 +00:00
|
|
|
|
|
|
|
q->buf = hub_malloc(bufsize);
|
|
|
|
if (!q->buf)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
q->size = bufsize;
|
|
|
|
memcpy(q->buf, buf, bufsize);
|
|
|
|
return bufsize;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
|
|
|
|
struct hub_sendq* hub_sendq_create()
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
|
|
|
|
if (!q)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
q->queue = list_create();
|
|
|
|
if (!q->queue)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
hub_free(q);
|
|
|
|
return 0;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
2009-05-26 17:46:51 +00:00
|
|
|
|
|
|
|
return q;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
static void clear_send_queue_callback(void* ptr)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
adc_msg_free((struct adc_message*) ptr);
|
|
|
|
}
|
2009-05-19 20:57:50 +00:00
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
void hub_sendq_destroy(struct hub_sendq* q)
|
|
|
|
{
|
|
|
|
if (q)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
list_clear(q->queue, &clear_send_queue_callback);
|
|
|
|
list_destroy(q->queue);
|
|
|
|
hub_free(q);
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
2009-05-19 20:57:50 +00:00
|
|
|
{
|
2009-05-26 17:46:51 +00:00
|
|
|
struct adc_message* msg = adc_msg_incref(msg_);
|
2009-07-25 01:23:06 +00:00
|
|
|
#ifdef DEBUG_SENDQ
|
|
|
|
debug_msg("hub_sendq_add", msg);
|
|
|
|
#endif
|
2009-05-26 17:46:51 +00:00
|
|
|
list_append(q->queue, msg);
|
|
|
|
q->size += msg->length;
|
|
|
|
}
|
2009-05-19 20:57:50 +00:00
|
|
|
|
2009-05-26 17:46:51 +00:00
|
|
|
void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
|
|
|
{
|
2009-07-25 01:23:06 +00:00
|
|
|
#ifdef DEBUG_SENDQ
|
|
|
|
debug_msg("hub_sendq_remove", msg);
|
|
|
|
#endif
|
2009-05-26 17:46:51 +00:00
|
|
|
list_remove(q->queue, msg);
|
|
|
|
q->size -= msg->length;
|
2009-05-27 23:47:48 +00:00
|
|
|
adc_msg_free(msg);
|
2009-05-26 17:46:51 +00:00
|
|
|
q->offset = 0;
|
|
|
|
}
|
2009-05-19 20:57:50 +00:00
|
|
|
|
2009-06-22 23:56:37 +00:00
|
|
|
int hub_sendq_send(struct hub_sendq* q, hub_recvq_write w, void* data)
|
2009-05-26 17:46:51 +00:00
|
|
|
{
|
2009-05-27 23:47:48 +00:00
|
|
|
int ret = 0;
|
|
|
|
size_t bytes = 0;
|
|
|
|
size_t offset = q->offset; // offset into first message.
|
2009-06-21 12:21:34 +00:00
|
|
|
size_t remain = 0;
|
2009-05-27 23:47:48 +00:00
|
|
|
size_t length = 0;
|
|
|
|
char* sbuf = g_hub->sendbuf;
|
2009-06-21 12:21:34 +00:00
|
|
|
size_t max_send_buf = 4096;
|
2009-05-27 23:47:48 +00:00
|
|
|
|
|
|
|
/* Copy as many messages possible into global send queue */
|
|
|
|
struct adc_message* msg = list_get_first(q->queue);
|
|
|
|
while (msg)
|
|
|
|
{
|
|
|
|
length = MIN(msg->length - offset, (max_send_buf-1) - bytes);
|
|
|
|
memcpy(sbuf + bytes, msg->cache + offset, length);
|
|
|
|
bytes += length;
|
|
|
|
|
2009-06-21 12:21:34 +00:00
|
|
|
if (length < (msg->length - offset))
|
2009-05-27 23:47:48 +00:00
|
|
|
break;
|
|
|
|
offset = 0;
|
|
|
|
msg = list_get_next(q->queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
msg = list_get_first(q->queue);
|
2009-06-22 23:56:37 +00:00
|
|
|
|
2009-05-27 23:47:48 +00:00
|
|
|
/* Send as much as possible */
|
|
|
|
ret = w(data, sbuf, bytes);
|
2009-06-22 23:56:37 +00:00
|
|
|
|
2009-05-27 23:47:48 +00:00
|
|
|
if (ret > 0)
|
|
|
|
{
|
2009-06-22 23:56:37 +00:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
q->last_write_n = ret;
|
|
|
|
#endif
|
|
|
|
|
2009-05-27 23:47:48 +00:00
|
|
|
/* Remove messages sent */
|
|
|
|
offset = q->offset;
|
2009-06-21 12:21:34 +00:00
|
|
|
remain = ret;
|
|
|
|
|
2009-05-27 23:47:48 +00:00
|
|
|
while (msg)
|
|
|
|
{
|
2009-06-21 12:21:34 +00:00
|
|
|
length = msg->length - offset;
|
|
|
|
if (length >= remain)
|
|
|
|
{
|
|
|
|
q->offset += remain;
|
2009-05-27 23:47:48 +00:00
|
|
|
break;
|
2009-06-21 12:21:34 +00:00
|
|
|
}
|
|
|
|
remain -= length;
|
2009-05-27 23:47:48 +00:00
|
|
|
hub_sendq_remove(q, msg);
|
|
|
|
msg = list_get_next(q->queue);
|
2009-06-21 12:21:34 +00:00
|
|
|
offset = 0;
|
2009-05-27 23:47:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
2009-05-26 17:46:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int hub_sendq_is_empty(struct hub_sendq* q)
|
|
|
|
{
|
2009-07-25 01:23:06 +00:00
|
|
|
return (q->size - q->offset) == 0;
|
2009-05-26 17:46:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t hub_sendq_get_bytes(struct hub_sendq* q)
|
|
|
|
{
|
|
|
|
return q->size - q->offset;
|
2009-05-19 20:57:50 +00:00
|
|
|
}
|