Reorganized sources slightly.
This commit is contained in:
142
src/adc/adcconst.h
Normal file
142
src/adc/adcconst.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_ADC_CONSTANTS_H
|
||||
#define HAVE_UHUB_ADC_CONSTANTS_H
|
||||
|
||||
typedef uint32_t sid_t;
|
||||
typedef uint32_t fourcc_t;
|
||||
|
||||
/* Internal uhub limit */
|
||||
#define MAX_ADC_CMD_LEN 4096
|
||||
|
||||
#define FOURCC(a,b,c,d) (fourcc_t) ((a << 24) | (b << 16) | (c << 8) | d)
|
||||
|
||||
/* default welcome protocol support message, as sent by this server */
|
||||
#define ADC_PROTO_SUPPORT "ADBASE ADTIGR ADPING"
|
||||
|
||||
/* Server sent commands */
|
||||
#define ADC_CMD_ISID FOURCC('I','S','I','D')
|
||||
#define ADC_CMD_ISUP FOURCC('I','S','U','P')
|
||||
#define ADC_CMD_IGPA FOURCC('I','G','P','A')
|
||||
#define ADC_CMD_ISTA FOURCC('I','S','T','A')
|
||||
#define ADC_CMD_IINF FOURCC('I','I','N','F')
|
||||
#define ADC_CMD_IMSG FOURCC('I','M','S','G')
|
||||
#define ADC_CMD_IQUI FOURCC('I','Q','U','I')
|
||||
|
||||
/* Handshake and login/passwordstuff */
|
||||
#define ADC_CMD_HSUP FOURCC('H','S','U','P')
|
||||
#define ADC_CMD_HPAS FOURCC('H','P','A','S')
|
||||
#define ADC_CMD_HINF FOURCC('H','I','N','F')
|
||||
#define ADC_CMD_BINF FOURCC('B','I','N','F')
|
||||
|
||||
/* This is a Admin extension */
|
||||
#define ADC_CMD_HDSC FOURCC('H','D','S','C')
|
||||
|
||||
/* Status/error messages */
|
||||
#define ADC_CMD_HSTA FOURCC('H','S','T','A')
|
||||
#define ADC_CMD_DSTA FOURCC('D','S','T','A')
|
||||
|
||||
/* searches */
|
||||
#define ADC_CMD_BSCH FOURCC('B','S','C','H')
|
||||
#define ADC_CMD_DSCH FOURCC('D','S','C','H')
|
||||
#define ADC_CMD_ESCH FOURCC('E','S','C','H')
|
||||
#define ADC_CMD_FSCH FOURCC('F','S','C','H')
|
||||
#define ADC_CMD_DRES FOURCC('D','R','E','S')
|
||||
|
||||
/* connection setup */
|
||||
#define ADC_CMD_DCTM FOURCC('D','C','T','M')
|
||||
#define ADC_CMD_DRCM FOURCC('D','R','C','M')
|
||||
#define ADC_CMD_ECTM FOURCC('E','C','T','M')
|
||||
#define ADC_CMD_ERCM FOURCC('E','R','C','M')
|
||||
|
||||
/* chat messages */
|
||||
#define ADC_CMD_BMSG FOURCC('B','M','S','G')
|
||||
#define ADC_CMD_DMSG FOURCC('D','M','S','G')
|
||||
#define ADC_CMD_EMSG FOURCC('E','M','S','G')
|
||||
#define ADC_CMD_FMSG FOURCC('F','M','S','G')
|
||||
|
||||
/* disallowed messages */
|
||||
#define ADC_CMD_DINF FOURCC('D','I','N','F')
|
||||
#define ADC_CMD_EINF FOURCC('E','I','N','F')
|
||||
#define ADC_CMD_FINF FOURCC('F','I','N','F')
|
||||
|
||||
/* Extension messages */
|
||||
#define ADC_CMD_HCHK FOURCC('H','C','H','K')
|
||||
|
||||
#define ADC_INF_FLAG_IPV4_ADDR "I4" /* ipv4 address */
|
||||
#define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */
|
||||
#define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */
|
||||
#define ADC_INF_FLAG_IPV6_UDP_PORT "U6" /* port number */
|
||||
#define ADC_INF_FLAG_CLIENT_TYPE "CT" /* client type */
|
||||
#define ADC_INF_FLAG_PRIVATE_ID "PD" /* private id, aka PID */
|
||||
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
|
||||
#define ADC_INF_FLAG_NICK "NI" /* nick name */
|
||||
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
|
||||
#define ADC_INF_FLAG_USER_AGENT "VE" /* software version */
|
||||
#define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */
|
||||
#define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */
|
||||
#define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */
|
||||
#define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed acheived in bytes/sec */
|
||||
#define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download speed acheived in bytes/sec */
|
||||
#define ADC_INF_FLAG_UPLOAD_SLOTS "SL" /* maximum upload slots (concurrent uploads) */
|
||||
#define ADC_INF_FLAG_AUTO_SLOTS "AS" /* automatic slot if upload speed is less than this in bytes/sec */
|
||||
#define ADC_INF_FLAG_AUTO_SLOTS_MAX "AM" /* maximum number of automatic slots */
|
||||
#define ADC_INF_FLAG_COUNT_HUB_NORMAL "HN" /* user is logged into this amount of hubs as a normal user (guest) */
|
||||
#define ADC_INF_FLAG_COUNT_HUB_REGISTER "HR" /* user is logged into this amount of hubs as a registered user (password) */
|
||||
#define ADC_INF_FLAG_COUNT_HUB_OPERATOR "HO" /* user is logged into this amount of hubs as an operator */
|
||||
#define ADC_INF_FLAG_AWAY "AW" /* away flag, 1=away, 2=extended away */
|
||||
#define ADC_INF_FLAG_REFERER "RF" /* URL to referer in case of hub redirect */
|
||||
#define ADC_INF_FLAG_EMAIL "EM" /* E-mail address */
|
||||
|
||||
#define ADC_MSG_FLAG_ACTION "ME" /* message is an *action* message */
|
||||
#define ADC_MSG_FLAG_PRIVATE "PM" /* message is a private message */
|
||||
|
||||
#define ADC_SCH_FLAG_INCLUDE "AN" /* include given search term */
|
||||
#define ADC_SCH_FLAG_EXCLUDE "NO" /* exclude given serach term */
|
||||
#define ADC_SCH_FLAG_FILE_EXTENSION "EX" /* search only for files with the given file extension */
|
||||
#define ADC_SCH_FLAG_FILE_TYPE "TY" /* search only for files with this file type (separate type) */
|
||||
#define ADC_SCH_FLAG_LESS_THAN "LE" /* search for files with this size or less */
|
||||
#define ADC_SCH_FLAG_GREATER_THAN "GE" /* search for files with this size or greater */
|
||||
#define ADC_SCH_FLAG_EQUAL "EQ" /* search only for files with this exact size */
|
||||
#define ADC_SCH_FLAG_TOKEN "TO" /* use this token for search replies */
|
||||
|
||||
#define ADC_RES_FLAG_FILE_NAME "FN" /* file name */
|
||||
#define ADC_RES_FLAG_FILE_SIZE "SI" /* file size */
|
||||
#define ADC_RES_FLAG_UPLOAD_SLOTS "SL" /* number of upload slots available (if > 0, download is possible) */
|
||||
#define ADC_RES_FLAG_TOKEN "TO" /* token, same as the token in the search request */
|
||||
|
||||
#define ADC_QUI_FLAG_TIME_LEFT "TL" /* time in seconds before reconnect is allowed, or -1 forever */
|
||||
#define ADC_QUI_FLAG_MESSAGE "MS" /* kick/leave message */
|
||||
#define ADC_QUI_FLAG_DISCONNECT "DI" /* all further transfers with this user should be disconnected */
|
||||
#define ADC_QUI_FLAG_REDIRECT "RD" /* redirect to URL */
|
||||
#define ADC_QUI_FLAG_KICK_OPERATOR "ID" /* SID of operator who disconnected the user */
|
||||
|
||||
#define ADC_SUP_FLAG_ADD "AD"
|
||||
#define ADC_SUP_FLAG_REMOVE "RM"
|
||||
|
||||
#define ADC_CLIENT_TYPE_BOT "1"
|
||||
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
|
||||
#define ADC_CLIENT_TYPE_OPERATOR "4"
|
||||
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
|
||||
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
|
||||
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_ADC_CONSTANTS_H */
|
||||
845
src/adc/message.c
Normal file
845
src/adc/message.c
Normal file
@@ -0,0 +1,845 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ADC_MSG_ASSERT(X) \
|
||||
uhub_assert(X); \
|
||||
uhub_assert(X->cache); \
|
||||
uhub_assert(X->capacity); \
|
||||
uhub_assert(X->length); \
|
||||
uhub_assert(X->length <= X->capacity); \
|
||||
uhub_assert(X->length == strlen(X->cache)); \
|
||||
uhub_assert(X->references >= 0);
|
||||
#else
|
||||
#define ADC_MSG_ASSERT(X) do { } while(0)
|
||||
#endif
|
||||
|
||||
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||
{
|
||||
if (!msg) return 0;
|
||||
#ifndef ADC_MESSAGE_INCREF
|
||||
msg->references++;
|
||||
return msg;
|
||||
#else
|
||||
struct adc_message* copy = adc_msg_copy(msg);
|
||||
return copy;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void adc_msg_set_length(struct adc_message* msg, size_t len)
|
||||
{
|
||||
msg->length = len;
|
||||
}
|
||||
|
||||
static int adc_msg_grow(struct adc_message* msg, size_t size)
|
||||
{
|
||||
char* buf;
|
||||
size_t newsize = 0;
|
||||
|
||||
if (msg->capacity > size)
|
||||
return 1;
|
||||
|
||||
/* Make sure we align our data */
|
||||
newsize = size;
|
||||
newsize += 2; /* termination */
|
||||
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
||||
|
||||
buf = hub_malloc_zero(newsize);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
if (msg->cache)
|
||||
{
|
||||
memcpy(buf, msg->cache, msg->length);
|
||||
hub_free(msg->cache);
|
||||
}
|
||||
|
||||
msg->cache = buf;
|
||||
msg->capacity = newsize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* NOTE: msg must be unterminated here */
|
||||
static int adc_msg_cache_append(struct adc_message* msg, const char* string, size_t len)
|
||||
{
|
||||
if (!adc_msg_grow(msg, msg->length + len))
|
||||
{
|
||||
/* FIXME: OOM! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&msg->cache[msg->length], string, len);
|
||||
adc_msg_set_length(msg, msg->length + len);
|
||||
|
||||
assert(msg->capacity > msg->length);
|
||||
msg->cache[msg->length] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns position of the first argument of the message.
|
||||
* Excludes mandatory arguments for the given type of message
|
||||
* like source and target.
|
||||
*/
|
||||
int adc_msg_get_arg_offset(struct adc_message* msg)
|
||||
{
|
||||
if (!msg || !msg->cache)
|
||||
return -1;
|
||||
|
||||
switch (msg->cache[0])
|
||||
{
|
||||
/* These *SHOULD* never be seen on a hub */
|
||||
case 'U':
|
||||
case 'C':
|
||||
return 4; /* Actually: 4 + strlen(cid). */
|
||||
|
||||
case 'I':
|
||||
case 'H':
|
||||
return 4;
|
||||
|
||||
case 'B':
|
||||
return 9;
|
||||
|
||||
case 'F':
|
||||
return (10 + (list_size(msg->feature_cast_include)*5) + (list_size(msg->feature_cast_exclude)*5));
|
||||
|
||||
case 'D':
|
||||
case 'E':
|
||||
return 14;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int adc_msg_is_empty(struct adc_message* msg)
|
||||
{
|
||||
int offset = adc_msg_get_arg_offset(msg);
|
||||
|
||||
if (offset == -1)
|
||||
return -1;
|
||||
|
||||
if ((msg->length - 1) == (size_t) offset)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void adc_msg_free(struct adc_message* msg)
|
||||
{
|
||||
if (!msg) return;
|
||||
|
||||
ADC_MSG_ASSERT(msg);
|
||||
|
||||
if (msg->references > 0)
|
||||
{
|
||||
msg->references--;
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_free(msg->cache);
|
||||
|
||||
if (msg->feature_cast_include)
|
||||
{
|
||||
list_clear(msg->feature_cast_include, &hub_free);
|
||||
list_destroy(msg->feature_cast_include);
|
||||
msg->feature_cast_include = 0;
|
||||
}
|
||||
|
||||
if (msg->feature_cast_exclude)
|
||||
{
|
||||
list_clear(msg->feature_cast_exclude, &hub_free);
|
||||
list_destroy(msg->feature_cast_exclude);
|
||||
msg->feature_cast_exclude = 0;
|
||||
}
|
||||
|
||||
hub_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
{
|
||||
char* tmp = 0;
|
||||
struct adc_message* copy = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||
if (!copy) return NULL; /* OOM */
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
/* deep copy */
|
||||
copy->cmd = cmd->cmd;
|
||||
copy->source = cmd->source;
|
||||
copy->target = cmd->target;
|
||||
copy->cache = 0;
|
||||
copy->length = cmd->length;
|
||||
copy->capacity = 0;
|
||||
copy->priority = cmd->priority;
|
||||
copy->references = 0;
|
||||
copy->feature_cast_include = 0;
|
||||
copy->feature_cast_exclude = 0;
|
||||
|
||||
if (cmd->cache)
|
||||
{
|
||||
if (!adc_msg_grow(copy, copy->length))
|
||||
{
|
||||
adc_msg_free(copy);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
memcpy(copy->cache, cmd->cache, cmd->length);
|
||||
copy->cache[copy->length] = 0;
|
||||
}
|
||||
|
||||
if (cmd->feature_cast_include)
|
||||
{
|
||||
copy->feature_cast_include = list_create();
|
||||
tmp = list_get_first(cmd->feature_cast_include);
|
||||
while (tmp)
|
||||
{
|
||||
list_append(copy->feature_cast_include, hub_strdup(tmp));
|
||||
tmp = list_get_next(cmd->feature_cast_include);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->feature_cast_exclude)
|
||||
{
|
||||
copy->feature_cast_exclude = list_create();
|
||||
tmp = list_get_first(cmd->feature_cast_exclude);
|
||||
while (tmp)
|
||||
{
|
||||
list_append(copy->feature_cast_exclude, hub_strdup(tmp));
|
||||
tmp = list_get_next(cmd->feature_cast_exclude);
|
||||
}
|
||||
}
|
||||
|
||||
ADC_MSG_ASSERT(copy);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_t length)
|
||||
{
|
||||
struct adc_message* command = adc_msg_parse(line, length);
|
||||
|
||||
if (!command)
|
||||
return 0;
|
||||
|
||||
if (command->source && (!u || command->source != u->id.sid))
|
||||
{
|
||||
hub_log(log_debug, "Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
|
||||
adc_msg_free(command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
{
|
||||
struct adc_message* command = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||
char prefix = line[0];
|
||||
size_t n = 0;
|
||||
char temp_sid[5];
|
||||
int ok = 1;
|
||||
int need_terminate = 0;
|
||||
struct linked_list* feature_cast_list;
|
||||
|
||||
if (command == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
if (!is_printable_utf8(line, length))
|
||||
{
|
||||
hub_log(log_debug, "Dropped message with non-printable UTF-8 characters.");
|
||||
hub_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (line[length-1] != '\n')
|
||||
{
|
||||
need_terminate = 1;
|
||||
}
|
||||
|
||||
if (!adc_msg_grow(command, length + need_terminate))
|
||||
{
|
||||
hub_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
adc_msg_set_length(command, length + need_terminate);
|
||||
memcpy(command->cache, line, length);
|
||||
|
||||
/* Ensure we are zero terminated */
|
||||
command->cache[length] = 0;
|
||||
command->cache[length+need_terminate] = 0;
|
||||
|
||||
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
||||
command->priority = 0;
|
||||
|
||||
switch (prefix)
|
||||
{
|
||||
case 'U':
|
||||
case 'C':
|
||||
/* these should never be seen on a hub */
|
||||
ok = 0;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
case 'H':
|
||||
ok = (length > 3);
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
ok = (length > 8 &&
|
||||
is_space(line[4]) &&
|
||||
is_valid_base32_char(line[5]) &&
|
||||
is_valid_base32_char(line[6]) &&
|
||||
is_valid_base32_char(line[7]) &&
|
||||
is_valid_base32_char(line[8]));
|
||||
|
||||
if (!ok) break;
|
||||
|
||||
temp_sid[0] = line[5];
|
||||
temp_sid[1] = line[6];
|
||||
temp_sid[2] = line[7];
|
||||
temp_sid[3] = line[8];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
command->source = string_to_sid(temp_sid);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
ok = (length > 8 &&
|
||||
is_space(line[4]) &&
|
||||
is_valid_base32_char(line[5]) &&
|
||||
is_valid_base32_char(line[6]) &&
|
||||
is_valid_base32_char(line[7]) &&
|
||||
is_valid_base32_char(line[8]));
|
||||
|
||||
if (!ok) break;
|
||||
|
||||
temp_sid[0] = line[5];
|
||||
temp_sid[1] = line[6];
|
||||
temp_sid[2] = line[7];
|
||||
temp_sid[3] = line[8];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
command->source = string_to_sid(temp_sid);
|
||||
|
||||
/* Create feature cast lists */
|
||||
command->feature_cast_include = list_create();
|
||||
command->feature_cast_exclude = list_create();
|
||||
|
||||
if (!command->feature_cast_include || !command->feature_cast_exclude)
|
||||
{
|
||||
list_destroy(command->feature_cast_include);
|
||||
list_destroy(command->feature_cast_exclude);
|
||||
hub_free(command->cache);
|
||||
hub_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
n = 10;
|
||||
while (line[n] == '+' || line[n] == '-')
|
||||
{
|
||||
if (line[n++] == '+')
|
||||
feature_cast_list = command->feature_cast_include;
|
||||
else
|
||||
feature_cast_list = command->feature_cast_exclude;
|
||||
|
||||
temp_sid[0] = line[n++];
|
||||
temp_sid[1] = line[n++];
|
||||
temp_sid[2] = line[n++];
|
||||
temp_sid[3] = line[n++];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
list_append(feature_cast_list, hub_strdup(temp_sid));
|
||||
}
|
||||
|
||||
if (n == 10)
|
||||
ok = 0;
|
||||
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
case 'E':
|
||||
ok = (length > 13 &&
|
||||
is_space(line[4]) &&
|
||||
is_valid_base32_char(line[5]) &&
|
||||
is_valid_base32_char(line[6]) &&
|
||||
is_valid_base32_char(line[7]) &&
|
||||
is_valid_base32_char(line[8]) &&
|
||||
is_space(line[9]) &&
|
||||
is_valid_base32_char(line[10]) &&
|
||||
is_valid_base32_char(line[11]) &&
|
||||
is_valid_base32_char(line[12]) &&
|
||||
is_valid_base32_char(line[13]));
|
||||
|
||||
if (!ok) break;
|
||||
|
||||
temp_sid[0] = line[5];
|
||||
temp_sid[1] = line[6];
|
||||
temp_sid[2] = line[7];
|
||||
temp_sid[3] = line[8];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
command->source = string_to_sid(temp_sid);
|
||||
|
||||
temp_sid[0] = line[10];
|
||||
temp_sid[1] = line[11];
|
||||
temp_sid[2] = line[12];
|
||||
temp_sid[3] = line[13];
|
||||
temp_sid[4] = '\0';
|
||||
|
||||
command->target = string_to_sid(temp_sid);
|
||||
break;
|
||||
|
||||
default:
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (need_terminate)
|
||||
{
|
||||
command->cache[length] = '\n';
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
adc_msg_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* At this point the arg_offset should point to a space, or the end of message */
|
||||
n = adc_msg_get_arg_offset(command);
|
||||
if (command->cache[n] == ' ')
|
||||
{
|
||||
if (command->cache[n+1] == ' ') ok = 0;
|
||||
}
|
||||
else if (command->cache[n] == '\n') ok = 1;
|
||||
else ok = 0;
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
adc_msg_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ADC_MSG_ASSERT(command);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_create(const char* line)
|
||||
{
|
||||
return adc_msg_parse_verify(NULL, line, strlen(line));
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
{
|
||||
struct adc_message* msg = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||
|
||||
if (!msg)
|
||||
return NULL; /* OOM */
|
||||
|
||||
if (size < sizeof(fourcc)) size = sizeof(fourcc);
|
||||
|
||||
if (!adc_msg_grow(msg, size+1))
|
||||
{
|
||||
hub_free(msg);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
if (fourcc)
|
||||
{
|
||||
msg->cache[0] = (char) ((fourcc >> 24) & 0xff);
|
||||
msg->cache[1] = (char) ((fourcc >> 16) & 0xff);
|
||||
msg->cache[2] = (char) ((fourcc >> 8) & 0xff);
|
||||
msg->cache[3] = (char) ((fourcc ) & 0xff);
|
||||
msg->cache[4] = '\n';
|
||||
|
||||
/* Ensure we are zero terminated */
|
||||
adc_msg_set_length(msg, 5);
|
||||
msg->cache[msg->length] = 0;
|
||||
}
|
||||
|
||||
msg->cmd = fourcc;
|
||||
msg->priority = 0;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
{
|
||||
char* start;
|
||||
char* end;
|
||||
char* endInfo;
|
||||
size_t endlen;
|
||||
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
|
||||
int found = 0;
|
||||
int arg_offset = adc_msg_get_arg_offset(cmd);
|
||||
size_t temp_len = 0;
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
|
||||
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
|
||||
while (start)
|
||||
{
|
||||
endInfo = &cmd->cache[cmd->length];
|
||||
|
||||
if (&start[0] < &endInfo[0])
|
||||
{
|
||||
end = memchr(&start[1], ' ', &endInfo[0]-&start[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
end = NULL;
|
||||
}
|
||||
|
||||
if (end)
|
||||
{
|
||||
|
||||
temp_len = &end[0] - &start[0]; // strlen(start);
|
||||
/* hub_log(log_trace, " length=%d", (int) (temp_len)); */
|
||||
endlen = strlen(end);
|
||||
|
||||
memmove(start, end, endlen);
|
||||
start[endlen] = '\0';
|
||||
found++;
|
||||
adc_msg_set_length(cmd, cmd->length - temp_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
found++;
|
||||
adc_msg_set_length(cmd, cmd->length - strlen(start));
|
||||
start[0] = '\0';
|
||||
break;
|
||||
}
|
||||
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
|
||||
}
|
||||
|
||||
adc_msg_terminate(cmd);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
{
|
||||
int count = 0;
|
||||
char* start;
|
||||
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
|
||||
int arg_offset = adc_msg_get_arg_offset(cmd);
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
|
||||
while (start)
|
||||
{
|
||||
count++;
|
||||
if ((&start[0] - &cmd->cache[0]) < 1+cmd->length)
|
||||
start = memmem(&start[1], (&cmd->cache[cmd->length] - &start[0]), prefix, 3);
|
||||
else
|
||||
start = NULL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
{
|
||||
char* start;
|
||||
char* end;
|
||||
char* argument;
|
||||
size_t length;
|
||||
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
|
||||
int arg_offset = adc_msg_get_arg_offset(cmd);
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
start = memmem(&cmd->cache[arg_offset], cmd->length - arg_offset, prefix, 3);
|
||||
if (!start)
|
||||
return NULL;
|
||||
|
||||
start = &start[3];
|
||||
end = strchr(start, ' ');
|
||||
if (!end) end = &cmd->cache[cmd->length];
|
||||
length = &end[0] - &start[0];
|
||||
|
||||
argument = hub_strndup(start, length);
|
||||
|
||||
if (length > 0 && argument[length-1] == '\n')
|
||||
{
|
||||
argument[length-1] = 0;
|
||||
}
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
|
||||
int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string)
|
||||
{
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
while (adc_msg_has_named_argument(cmd, prefix))
|
||||
{
|
||||
adc_msg_remove_named_argument(cmd, prefix);
|
||||
}
|
||||
|
||||
if (adc_msg_add_named_argument(cmd, prefix, string) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void adc_msg_terminate(struct adc_message* cmd)
|
||||
{
|
||||
if (cmd->cache[cmd->length - 1] != '\n')
|
||||
{
|
||||
adc_msg_cache_append(cmd, "\n", 1);
|
||||
}
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
}
|
||||
|
||||
/* FIXME: this looks bogus */
|
||||
void adc_msg_unterminate(struct adc_message* cmd)
|
||||
{
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
||||
{
|
||||
cmd->length--;
|
||||
cmd->cache[cmd->length] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!string)
|
||||
return -1;
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
adc_msg_cache_append(cmd, " ", 1);
|
||||
adc_msg_cache_append(cmd, prefix, 2);
|
||||
adc_msg_cache_append(cmd, string, strlen(string));
|
||||
adc_msg_terminate(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
||||
{
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
adc_msg_cache_append(cmd, " ", 1);
|
||||
adc_msg_cache_append(cmd, string, strlen(string));
|
||||
adc_msg_terminate(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
||||
{
|
||||
char* start;
|
||||
char* end;
|
||||
char* argument;
|
||||
int count = 0;
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
|
||||
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
|
||||
while (start)
|
||||
{
|
||||
end = strchr(&start[1], ' ');
|
||||
|
||||
if (count == offset)
|
||||
{
|
||||
if (end)
|
||||
{
|
||||
argument = hub_strndup(&start[1], (&end[0] - &start[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
argument = hub_strdup(&start[1]);
|
||||
if (argument[strlen(argument)-1] == '\n')
|
||||
argument[strlen(argument)-1] = 0;
|
||||
}
|
||||
|
||||
if (*argument)
|
||||
{
|
||||
adc_msg_terminate(cmd);
|
||||
return argument;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
start = end;
|
||||
}
|
||||
|
||||
adc_msg_terminate(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: Untested code.
|
||||
*/
|
||||
int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
|
||||
{
|
||||
char* start;
|
||||
char* end;
|
||||
int count = 0;
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
|
||||
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
|
||||
while (start)
|
||||
{
|
||||
end = strchr(&start[1], ' ');
|
||||
if (((&end[0] - &start[1]) > 2) && ((start[1] == prefix[0]) && (start[2] == prefix[1])))
|
||||
{
|
||||
adc_msg_terminate(cmd);
|
||||
return count;
|
||||
}
|
||||
count++;
|
||||
start = end;
|
||||
}
|
||||
adc_msg_terminate(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int adc_msg_escape_length(const char* str)
|
||||
{
|
||||
int add = 0;
|
||||
int n = 0;
|
||||
for (; str[n]; n++)
|
||||
if (str[n] == ' ' || str[n] == '\n' || str[n] == '\\') add++;
|
||||
return n + add;
|
||||
}
|
||||
|
||||
|
||||
int adc_msg_unescape_length(const char* str)
|
||||
{
|
||||
int add = 0;
|
||||
int n = 0;
|
||||
int escape = 0;
|
||||
for (; str[n]; n++)
|
||||
{
|
||||
if (escape)
|
||||
{
|
||||
escape = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (str[n] == '\\')
|
||||
{
|
||||
escape = 1;
|
||||
add++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n - add;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char* adc_msg_unescape(const char* string)
|
||||
{
|
||||
char* new_string = hub_malloc(adc_msg_unescape_length(string)+1);
|
||||
char* ptr = (char*) new_string;
|
||||
char* str = (char*) string;
|
||||
int escaped = 0;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (escaped) {
|
||||
if (*str == 's')
|
||||
*ptr++ = ' ';
|
||||
else if (*str == '\\')
|
||||
*ptr++ = '\\';
|
||||
else if (*str == 'n')
|
||||
*ptr++ = '\n';
|
||||
else
|
||||
*ptr++ = *str;
|
||||
|
||||
escaped = 0;
|
||||
} else {
|
||||
if (*str == '\\')
|
||||
escaped = 1;
|
||||
else
|
||||
*ptr++ = *str;
|
||||
|
||||
}
|
||||
str++;
|
||||
}
|
||||
*ptr = 0;
|
||||
return new_string;
|
||||
}
|
||||
|
||||
|
||||
char* adc_msg_escape(const char* string)
|
||||
{
|
||||
char* str = hub_malloc(adc_msg_escape_length(string)+1);
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
{
|
||||
switch (string[i]) {
|
||||
case '\\': /* fall through */
|
||||
str[n++] = '\\';
|
||||
str[n++] = '\\';
|
||||
break;
|
||||
case '\n':
|
||||
str[n++] = '\\';
|
||||
str[n++] = 'n';
|
||||
break;
|
||||
case ' ':
|
||||
str[n++] = '\\';
|
||||
str[n++] = 's';
|
||||
break;
|
||||
default:
|
||||
str[n++] = string[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
str[n] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
206
src/adc/message.h
Normal file
206
src/adc/message.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_COMMAND_H
|
||||
#define HAVE_UHUB_COMMAND_H
|
||||
|
||||
struct user;
|
||||
|
||||
struct adc_message
|
||||
{
|
||||
fourcc_t cmd;
|
||||
sid_t source;
|
||||
sid_t target;
|
||||
char* cache;
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
size_t priority;
|
||||
size_t references;
|
||||
struct linked_list* feature_cast_include;
|
||||
struct linked_list* feature_cast_exclude;
|
||||
};
|
||||
|
||||
enum msg_status_level
|
||||
{
|
||||
status_level_info = 0, /* Success/informative status message */
|
||||
status_level_error = 1, /* Recoverable error */
|
||||
status_level_fatal = 2, /* Fatal error (disconnect) */
|
||||
};
|
||||
|
||||
/**
|
||||
* Increase the reference counter for an ADC message struct.
|
||||
* NOTE: Always use the returned value, and not the passed value, as
|
||||
* it ensures we can actually copy the value if needed.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_incref(struct adc_message* msg);
|
||||
|
||||
/**
|
||||
* Decrease the reference counter, and free the memory when apropriate.
|
||||
*/
|
||||
extern void adc_msg_free(struct adc_message* msg);
|
||||
|
||||
/**
|
||||
* Perform deep copy a command.
|
||||
* NOTE: 'references' will be zero for the copied command.
|
||||
* @return a copy of cmd or NULL if not able to allocate memory.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_copy(const struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* This will parse 'string' and return it as a adc_message struct, or
|
||||
* NULL if not able to allocate memory or 'string' does not contain
|
||||
* a valid ADC command.
|
||||
*
|
||||
* The message is only considered valid if the user who sent it
|
||||
* is the rightful origin of the message.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_parse_verify(struct user* u, const char* string, size_t length);
|
||||
|
||||
/**
|
||||
* This will parse 'string' and return it as a adc_message struct, or
|
||||
* NULL if not able to allocate memory or 'string' does not contain
|
||||
* a valid ADC command.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_parse(const char* string, size_t length);
|
||||
|
||||
/**
|
||||
* This will construct a adc_message based on 'string'.
|
||||
* Only to be used for server generated commands.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_create(const char* string);
|
||||
|
||||
/**
|
||||
* Construct a message with the given 'fourcc' and allocate
|
||||
* 'size' bytes for later use.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
|
||||
|
||||
/**
|
||||
* Remove a named argument from the command.
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @return the number of named arguments removed.
|
||||
*/
|
||||
extern int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix[2]);
|
||||
|
||||
/**
|
||||
* Count the number of arguments matching the given 2 character prefix.
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @return the number of matching arguments
|
||||
*/
|
||||
extern int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix[2]);
|
||||
|
||||
/**
|
||||
* Returns a named arguments based on the 2 character prefix.
|
||||
* If multiple matching arguments exists, only the first one will be returned
|
||||
* by this function.
|
||||
*
|
||||
* NOTE: Returned memory must be free'd with hub_free().
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @return the argument or NULL if OOM/not found.
|
||||
*/
|
||||
extern char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix[2]);
|
||||
|
||||
/**
|
||||
* Returns a offset of an argument based on the 2 character prefix.
|
||||
* If multiple matching arguments exists, only the first one will be returned
|
||||
* by this function.
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @return the offset or -1 if the argument is not found.
|
||||
*/
|
||||
extern int adc_msg_get_named_argument_index(struct adc_message* cmd, const char prefix[2]);
|
||||
|
||||
/**
|
||||
* @param cmd command to be checked
|
||||
* @return 1 if the command does not have any arguments (parameters), 0 otherwise, -1 if cmd is invalid.
|
||||
*/
|
||||
extern int adc_msg_is_empty(struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Returns the argument on the offset position in the command.
|
||||
* If offset is invalid NULL is returned.
|
||||
*
|
||||
* NOTE: Returned memory must be free'd with hub_free().
|
||||
*
|
||||
* @return the argument or NULL if OOM/not found.
|
||||
*/
|
||||
extern char* adc_msg_get_argument(struct adc_message* cmd, int offset);
|
||||
|
||||
/**
|
||||
* Replace a named argument in the command.
|
||||
* This will remove any matching arguments (multiple, or none),
|
||||
* then add 'string' as an argument using the given prefix.
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @arg string must be escaped (see adc_msg_escape).
|
||||
* @return 0 if successful, or -1 if an error occured.
|
||||
*/
|
||||
extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||
|
||||
/**
|
||||
* Append an argument
|
||||
*
|
||||
* @arg string must be escaped (see adc_msg_escape).
|
||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
||||
*/
|
||||
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
||||
|
||||
/**
|
||||
* Append a named argument
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @arg string must be escaped (see adc_msg_escape).
|
||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
||||
*/
|
||||
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||
|
||||
/**
|
||||
* Convert a ADC command escaped string to a regular string.
|
||||
* @return string or NULL if out of memory
|
||||
*/
|
||||
extern char* adc_msg_unescape(const char* string);
|
||||
|
||||
/**
|
||||
* Convert a string to a ADC command escaped string.
|
||||
* @return adc command escaped string or NULL if out of memory.
|
||||
*/
|
||||
extern char* adc_msg_escape(const char* string);
|
||||
|
||||
/**
|
||||
* This will ensure a newline is at the end of the command.
|
||||
*/
|
||||
void adc_msg_terminate(struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* This will remove any newline from the end of the command
|
||||
*/
|
||||
void adc_msg_unterminate(struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* @return the offset for the first command argument in msg->cache.
|
||||
* or -1 if the command is not understood.
|
||||
* NOTE: for 'U' and 'C' commands (normally not seen by hubs),
|
||||
* this returns 4. Should be 4 + lengthOf(cid).
|
||||
*/
|
||||
int adc_msg_get_arg_offset(struct adc_message* msg);
|
||||
|
||||
#endif /* HAVE_UHUB_COMMAND_H */
|
||||
61
src/adc/sid.c
Normal file
61
src/adc/sid.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
char* sid_to_string(sid_t sid_)
|
||||
{
|
||||
static char t_sid[5];
|
||||
sid_t sid = (sid_ & 0xFFFFF); /* 20 bits only */
|
||||
sid_t A, B, C, D = 0;
|
||||
D = (sid % 32);
|
||||
sid = (sid - D) / 32;
|
||||
C = (sid % 32);
|
||||
sid = (sid - C) / 32;
|
||||
B = (sid % 32);
|
||||
sid = (sid - B) / 32;
|
||||
A = (sid % 32);
|
||||
t_sid[0] = BASE32_ALPHABET[A];
|
||||
t_sid[1] = BASE32_ALPHABET[B];
|
||||
t_sid[2] = BASE32_ALPHABET[C];
|
||||
t_sid[3] = BASE32_ALPHABET[D];
|
||||
t_sid[4] = 0;
|
||||
return t_sid;
|
||||
}
|
||||
|
||||
|
||||
sid_t string_to_sid(const char* sid)
|
||||
{
|
||||
sid_t nsid = 0;
|
||||
sid_t n, x;
|
||||
sid_t factors[] = { 32768, 1024, 32, 1};
|
||||
|
||||
if (!sid || strlen(sid) != 4) return 0;
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
for (x = 0; x < strlen(BASE32_ALPHABET); x++)
|
||||
if (sid[n] == BASE32_ALPHABET[x]) break;
|
||||
if (x == 32) return 0;
|
||||
nsid += x * factors[n];
|
||||
}
|
||||
return nsid;
|
||||
}
|
||||
|
||||
67
src/adc/sid.h
Normal file
67
src/adc/sid.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_SID_H
|
||||
#define HAVE_UHUB_SID_H
|
||||
|
||||
#define SID_MAX 1048576
|
||||
|
||||
extern const char* BASE32_ALPHABET;
|
||||
extern char* sid_to_string(sid_t sid_);
|
||||
extern sid_t string_to_sid(const char* sid);
|
||||
|
||||
struct sid_map
|
||||
{
|
||||
struct user* ptr;
|
||||
struct sid_map* next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Session IDs are heavily reused, since they are a fairly scarce
|
||||
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
|
||||
* value and 'AAAA' (0) is reserved for the hub.
|
||||
*
|
||||
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
|
||||
*
|
||||
* When allocating a session ID:
|
||||
* - If 'count' is less than the pool size (max-min), then allocate within the pool
|
||||
* - Increase the pool size (see below)
|
||||
* - If unable to do that, hub is really full - don't let anyone in!
|
||||
*
|
||||
* When freeing a session ID:
|
||||
* - If the session ID being freed is 'max', then decrease the pool size by one.
|
||||
*
|
||||
*/
|
||||
struct sid_pool
|
||||
{
|
||||
sid_t min;
|
||||
sid_t max;
|
||||
sid_t count;
|
||||
struct sid_map* map;
|
||||
};
|
||||
|
||||
|
||||
extern void sid_initialize(struct sid_pool*);
|
||||
extern sid_t sid_alloc(struct sid_pool*, struct user*);
|
||||
extern void sid_free(struct sid_pool*, sid_t);
|
||||
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_SID_H */
|
||||
|
||||
Reference in New Issue
Block a user