/*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate$
* $Revision$
* $LastChangedBy$
* $URL$
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _LIBVENTRILO3_H
#define _LIBVENTRILO3_H
#ifndef NO_AUTOMAKE
#include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#ifndef _WIN32
#include
#include
#include
#include
#include
#include
#include
#else
#include
#include
#include
#define SHUT_WR SD_SEND
#endif
#define true 1
#define false 0
char *_v3_errors[] = {
"Success",
"Operation can not be performed on your self.",
"Specified object no longer exists.",
"Invalid password.",
"You do not have server admin rights.",
"You do not have channel admin rights.",
"Bad name specified.",
"Insufficient resources to complete operation.",
"Specified name is already taken.",
"You are banned from the specified channel.",
"The channel is full.",
"You do not have admin permission.",
"You do not have root channel admin permission.",
"State change does not apply in this instance.",
"Max channel width exceeded.",
"Max channel depth exceeded.",
"Ban failed. Might already be banned by subnet.",
"Unable to update the USR file.",
"The server requires that you enable the 'Show login name in remote status request' of your server definition for this server.",
"Maximum number of allowed guest logins has been reached. Try again later.",
"Connection time limit (GUEST or INI) has been exceeded.",
"You are not allowed to switch channels manually.",
"You do not have sufficient rights to ban another user.",
"You do not have sufficient rights to kick another user.",
"You do not have sufficient rights to move another user to a different channel.",
"You already have Server Admin rights.",
"You do not have sufficient rights to issue RCon commands.",
"You are not allowed to edit the regular MOTD.",
"You are not allowed to edit the guest MOTD.",
"You do not have sufficient rights to receive complaints.",
"You do not have sufficient rights to send complaints.",
"Another client is currently using the User Editor. See name: ",
"You have not been given access rights to enter a User Authorization mode channel.",
"Another client is currently editing the Rank list. See name: ",
"Account locked. Reason: ",
"Guest accounts are currently locked. Reason: ",
"You do not have the 'Add user' right.",
"You have been kicked off the server. Reason: ",
"You have been kicked from the server for spamming.",
"You have been kicked from the server. Duplicate names are not allowed.",
"You have been kicked from the server. Duplicate IP's are not allowed for your account.",
"You have been kicked from the server. Duplicate IP limit for your account has been reached.",
"You have been kicked for inactivity.",
"You have been kicked by the console.",
"You have been kicked because your account on this server has been deleted.",
"You have been kicked because you provided a bad Server Admin password. You will be automatically banned if you fail several more times, so be sure that you are entering the correct password before you try again. Be advised that your attempts to use the Server Admin password are being logged. If you are not authorized to be a Server Admin you may be subject to legal action.",
"You have been banned from the server. Reason: ",
"You have been banned from the server for spamming.",
"You are temporarily banned.",
"You are on the banned list.",
"Guest accounts are not allowed to join the specified channel."
};
char *_v3_page_errors[] = {
"User does not exist.",
"User is not accepting pages.",
"Users current channel does not allow for paging.",
"Insufficient access rights."
};
char *_v3_move_errors[] = {
"Admin rights.",
"Invalid source object.",
"Invalid target object.",
"Not support in given mode.",
"Target channel is full.",
"Target channel does not allow phantoms, or source does not have proper access rights."
};
char *_v3_server_disabled_errors[] = {
"This server has not been authenticated yet. Please try connecting again in a few minutes.",
"This server has not been configured properly. Please contact your hosting company.",
"This server has been remotely disabled.",
"This server has been disabled by order of the Department of Homeland Security.",
"This server has been disabled by order of the Federal Bureau of Investigation.",
"This server has been disabled by order of the United States Government.",
"This server has been disabled by order of the United States Secret Service.",
"This server has been disabled by order of the goverment in which the server is hosted.",
"This server has been disabled by order of the United States Military."
};
char *_v3_phantom_errors[] = {
"Channel does not allow phantoms.",
"Phantoms are restricted to USR file.",
"Duplicate.",
"Unknown channel.",
"Not found.",
"Not authenticated for specified channel.",
"No slots available.",
"Channel is full.",
"Insufficient resources.",
"Banned from channel.",
"Insufficient access rights.",
};
char *_v3_permissions_errors[] = {
"Specified ID is no longer valid.",
"Duplicate name.",
"Server reported an error.",
"All user accounts must have a valid password.",
"Missing required fields.",
"Not allowed to delete Guest account.",
"The specified login name is not allowed.",
"The specified login name contains characters that are not allowed.",
"Insufficient access rights to complete the request.",
NULL,
"Specified alternate ID is not valid.",
"Specified new owner does not have 'Add Users' rights.",
"The user account database is full. You must delete an existing account before you can add a new one.",
"The Guest account can not be locked without having at least one other account defined and is not locked it self. Otherwise, you would be locking everyone out of the server.",
};
char *_v3_ranks_errors[] = {
"Invalid ID specified.",
"Duplicate Abbreviation.",
"Duplicate Description.",
"Insufficient access rights.",
NULL,
"Maximum number of allowed Ranks has been reached.",
"Missing abbreviation or description.",
};
char *_v3_bitmasks[] = {
"0.0.0.0",
"128.0.0.0",
"192.0.0.0",
"224.0.0.0",
"240.0.0.0",
"248.0.0.0",
"252.0.0.0",
"254.0.0.0",
"255.0.0.0",
"255.128.0.0",
"255.192.0.0",
"255.224.0.0",
"255.240.0.0",
"255.248.0.0",
"255.252.0.0",
"255.254.0.0",
"255.255.0.0",
"255.255.128.0",
"255.255.192.0",
"255.255.224.0",
"255.255.240.0",
"255.255.248.0",
"255.255.252.0",
"255.255.254.0",
"255.255.255.0",
"255.255.255.128",
"255.255.255.192",
"255.255.255.224",
"255.255.255.240",
"255.255.255.248",
"255.255.255.252",
"255.255.255.254",
"255.255.255.255",
NULL
};
#define V3_OK 0
#define V3_MALFORMED 1
#define V3_NOTIMPL 2
#define V3_FAILURE 3
#define V3_NOT_WAITING 0
#define V3_EVENT_WAITING 1
#define V3_MSG_WAITING 2
#define V3_BOTH_WAITING 3
/*
* This structure defines the bit number of each permission setting, the
* internal name, and a name suitable for display to a user.
*/
struct _v3_perm_info v3_perm_info[] = {
{ 1, "V3_PERM_LOCK_ACCT", "Lock Account" },
{ 2, "V3_PERM_DFL_CHAN", "Access Default Channel" },
{ 3, "V3_PERM_DUPE_IP", "DUPE_IP" },
{ 4, "V3_PERM_SWITCH_CHAN", "Switch Channels" },
{ 5, "V3_PERM_IN_RESERVE_LIST", "IN_RESERVE_LIST" },
{ 6, "V3_PERM_RECV_BCAST", "Receive Broadcasts" },
{ 7, "V3_PERM_ADD_PHANTOM", "ADD_PHANTOM" },
{ 8, "V3_PERM_RECORD", "Record Audio" },
{ 9, "V3_PERM_RECV_COMPLAINT", "Receive Complaint" },
{ 10, "V3_PERM_SEND_COMPLAINT", "Send Complaint" },
{ 11, "V3_PERM_INACTIVE_EXEMPT", "Exempt from Inactivity Timer" },
{ 12, "V3_PERM_SRV_ADMIN", "Server Admin" },
{ 13, "V3_PERM_ADD_USER", "Add Users" },
{ 14, "V3_PERM_DEL_USER", "Delete Users" },
{ 15, "V3_PERM_BAN_USER", "Ban a User" },
{ 16, "V3_PERM_KICK_USER", "Kick a User" },
{ 17, "V3_PERM_MOVE_USER", "Move a User's Channel" },
{ 18, "V3_PERM_ASSIGN_CHAN_ADMIN", "Assign Channel Admins" },
{ 19, "V3_PERM_EDIT_RANK", "Edit User Ranks" },
{ 20, "V3_PERM_EDIT_MOTD", "Edit the MOTD" },
{ 21, "V3_PERM_EDIT_GUEST_MOTD", "Edit the Guest MOTD" },
{ 22, "V3_PERM_ISSUE_RCON_CMD", "ISSUE_RCON_CMD" },
{ 23, "V3_PERM_EDIT_VOICE_TARGET", "EDIT_VOICE_TARGET" },
{ 24, "V3_PERM_EDIT_COMMAND_TARGET", "EDIT_COMMAND_TARGET" },
{ 25, "V3_PERM_ASSIGN_RANK", "Assign a Rank" },
{ 26, "V3_PERM_ASSIGN_RESERVED", "ASSIGN_RESERVED" },
{ 27, "V3_PERM_BCAST", "Send Broadcasts" },
{ 28, "V3_PERM_BCAST_LOBBY", "Send Broadcast to Lobby" },
{ 29, "V3_PERM_BCAST_USER", "Send Broadcast to User" },
{ 30, "V3_PERM_BCAST_X_CHAN", "Send Cross Channel Broadcasts" },
{ 31, "V3_PERM_SEND_TTS_BIND", "SEND_TTS_BIND" },
{ 32, "V3_PERM_SEND_WAV_BIND", "SEND_WAV_BIND" },
{ 33, "V3_PERM_SEND_PAGE", "Send Pages" },
{ 34, "V3_PERM_SEND_COMMENT", "Send Comments" },
{ 35, "V3_PERM_SET_PHON_NAME", "Set Phonetic Name" },
{ 36, "V3_PERM_GEN_COMMENT_SNDS", "GEN_COMMENT_SNDS" },
{ 37, "V3_PERM_EVENT_SNDS", "EVENT_SNDS" },
{ 38, "V3_PERM_MUTE_GLBL", "MUTE_GLBL" },
{ 39, "V3_PERM_MUTE_OTHER", "MUTE_OTHER" },
{ 40, "V3_PERM_GLBL_CHAT", "GLBL_CHAT" },
{ 41, "V3_PERM_START_PRIV_CHAT", "START_PRIV_CHAT" },
{ 42, "V3_PERM_EQ_OUT", "EQ_OUT" },
{ 43, "V3_PERM_SEE_GUEST", "See Guests" },
{ 44, "V3_PERM_SEE_NONGUEST", "See Registered Useres" },
{ 45, "V3_PERM_SEE_MOTD", "See Message of the Day" },
{ 46, "V3_PERM_SEE_SRV_COMMENT", "See Server Comment" },
{ 47, "V3_PERM_SEE_CHAN_LIST", "See Channel List" },
{ 48, "V3_PERM_SEE_CHAN_COMMENT", "See Channel Comments" },
{ 49, "V3_PERM_SEE_USER_COMMENT", "See User Comments" }
};
uint32_t _v3_hash_table[] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/*
* Global Variables
*/
_v3_server v3_server = { 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1, { 0, 0 }, 0, 0, { "", 0, 0 }, { "", 0, 0 }, NULL, NULL, {0, 0}, 0, 0, 0, 0, false, false, false};
_v3_luser v3_luser = { -1, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, { } };
v3_channel *v3_channel_list = NULL;
int _v3_channel_count;
v3_user *v3_user_list = NULL;
int _v3_user_count;
v3_rank *v3_rank_list = NULL;
int _v3_rank_count;
v3_account *v3_account_list = NULL;
int _v3_account_count;
v3_server_prop _v3_server_prop = { 0 };
uint16_t _v3_server_prop_tid = 0;
char _v3_error_text[256];
char _v3_status_text[256];
int _v3_sockd = -1;
uint32_t _v3_debuglevel = V3_DEBUG_NONE;
uint32_t _v3_user_loggedin = 0;
pthread_mutex_t *userlist_mutex = NULL;
pthread_mutex_t *channellist_mutex = NULL;
pthread_mutex_t *ranklist_mutex = NULL;
pthread_mutex_t *accountlist_mutex = NULL;
pthread_mutex_t *server_mutex = NULL;
pthread_mutex_t *luser_mutex = NULL;
pthread_mutex_t *sendq_mutex = NULL;
pthread_mutex_t *eventq_mutex = NULL;
pthread_cond_t *eventq_cond = NULL;
v3_event *_v3_eventq = NULL;
#if HAVE_SPEEX_DSP
pthread_mutex_t *audioq_mutex = NULL;
void *_v3_resampler = NULL;
uint32_t _v3_in_rate = 0;
uint32_t _v3_out_rate = 0;
uint8_t _v3_channels = 0;
int _v3_pcm_pipe[2] = { -1, -1 };
uint32_t _v3_pcm_write = 0;
#endif
v3_codec v3_codecs[] = {
#if HAVE_GSM
{ 0, 0, 640, 8000, -1, "GSM 6.10 8kHz" },
{ 0, 1, 640, 11025, -1, "GSM 6.10 11kHz" },
{ 0, 2, 640, 22050, -1, "GSM 6.10 22kHz" },
{ 0, 3, 640, 44100, -1, "GSM 6.10 44kHz" },
#endif
#if HAVE_CELT
{ 1, 0, 640, 44100, -1, "CELT 0.7 44kHz" },
{ 2, 0, 640, 22050, -1, "CELT 0.7 22kHz" },
#endif
#if HAVE_SPEEX
{ 3, 0, 320, 8000, 0, "Speex 8kHz Quality 0" },
{ 3, 1, 320, 8000, 1, "Speex 8kHz Quality 1" },
{ 3, 2, 320, 8000, 2, "Speex 8kHz Quality 2" },
{ 3, 3, 320, 8000, 3, "Speex 8kHz Quality 3" },
{ 3, 4, 320, 8000, 4, "Speex 8kHz Quality 4" },
{ 3, 5, 320, 8000, 5, "Speex 8kHz Quality 5" },
{ 3, 6, 320, 8000, 6, "Speex 8kHz Quality 6" },
{ 3, 7, 320, 8000, 7, "Speex 8kHz Quality 7" },
{ 3, 8, 320, 8000, 8, "Speex 8kHz Quality 8" },
{ 3, 9, 320, 8000, 9, "Speex 8kHz Quality 9" },
{ 3, 10, 320, 8000, 10, "Speex 8kHz Quality 10" },
{ 3, 11, 640, 16000, 0, "Speex 16kHz Quality 0" },
{ 3, 12, 640, 16000, 1, "Speex 16kHz Quality 1" },
{ 3, 13, 640, 16000, 2, "Speex 16kHz Quality 2" },
{ 3, 14, 640, 16000, 3, "Speex 16kHz Quality 3" },
{ 3, 15, 640, 16000, 4, "Speex 16kHz Quality 4" },
{ 3, 16, 640, 16000, 5, "Speex 16kHz Quality 5" },
{ 3, 17, 640, 16000, 6, "Speex 16kHz Quality 6" },
{ 3, 18, 640, 16000, 7, "Speex 16kHz Quality 7" },
{ 3, 19, 640, 16000, 8, "Speex 16kHz Quality 8" },
{ 3, 20, 640, 16000, 9, "Speex 16kHz Quality 9" },
{ 3, 21, 640, 16000, 10, "Speex 16kHz Quality 10" },
{ 3, 22, 1280, 32000, 0, "Speex 32kHz Quality 0" },
{ 3, 23, 1280, 32000, 1, "Speex 32kHz Quality 1" },
{ 3, 24, 1280, 32000, 2, "Speex 32kHz Quality 2" },
{ 3, 25, 1280, 32000, 3, "Speex 32kHz Quality 3" },
{ 3, 26, 1280, 32000, 4, "Speex 32kHz Quality 4" },
{ 3, 27, 1280, 32000, 5, "Speex 32kHz Quality 5" },
{ 3, 28, 1280, 32000, 6, "Speex 32kHz Quality 6" },
{ 3, 29, 1280, 32000, 7, "Speex 32kHz Quality 7" },
{ 3, 30, 1280, 32000, 8, "Speex 32kHz Quality 8" },
{ 3, 31, 1280, 32000, 9, "Speex 32kHz Quality 9" },
{ 3, 32, 1280, 32000, 10, "Speex 32kHz Quality 10" },
#endif
{ -1, -1, 0, 0, -1, "Unsupported Codec" },
};
typedef struct __v3_decoders {
#if HAVE_GSM
void *gsm;
#endif
uint32_t speexrate;
void *speex;
#if HAVE_CELT
uint8_t celtchans;
void *celtmode;
void *celt;
#endif
} _v3_decoders;
_v3_decoders v3_decoders[65535];
uint8_t _v3_user_volumes[65535];
uint8_t _v3_master_volume = 79;
uint8_t _v3_xmit_volume = 79;
// TODO: it's too messy to have this here. move into new lv3 repo.
/*{{{*/
#define V3_VRF_HEADID "VENTRECD"
#define V3_VRF_TEMPID "TEMPRECD"
#define V3_VRF_VERSION 0x01
#define V3_VRF_HEADLEN 0x28
#define V3_VRF_INFOLEN 0x2910
#define V3_VRF_TEXTLEN 0x100
#define V3_VRF_TYPE_AUDIO 0x01
#define V3_VRF_TYPE_TEXT 0x02
#define V3_VRF_TYPE_EXT 0x03
#define V3_VRF_MAX_FRAGLEN 1 << 11 // 1105
enum _v3_vrf_events {
V3_VRF_EVENT_DATA_FLUSH = 1,
V3_VRF_EVENT_AUDIO_DATA,
V3_VRF_EVENT_AUDIO_STOP,
V3_VRF_EVENT_TEXT_DATA
};
typedef struct _v3_vrf_header _v3_vrf_header;
typedef struct _v3_vrf_segment _v3_vrf_segment;
typedef struct _v3_vrf_audio _v3_vrf_audio;
typedef struct _v3_vrf_fragment _v3_vrf_fragment;
typedef struct _v3_vrf_rec _v3_vrf_rec;
typedef struct _v3_vrf _v3_vrf;
struct _v3_vrf_header { // 10552
char headid[8]; // 0 - header id (VENTRECD)
uint32_t size; // 8 - file size
uint32_t headlen; // 12 - header length (0x28 / 40)
uint32_t unknown1; // 16 - unused
uint32_t segtable; // 20 - segment table offset
uint32_t segcount; // 24 - segment count
uint32_t vrfversion; // 28 - vrf version
uint32_t unknown2; // 32 - unused
uint32_t unknown3; // 36 - unused
uint32_t infolen; // 40 - info length (0x2910 / 10512)
uint32_t codec; // 44 - codec
uint32_t codecformat; // 48 - codec format
uint32_t unknown4; // 52 - unused
char platform[64]; // 56 - platform
char version[64]; // 120 - client version
char username[128]; // 184 - user name
char comment[8192]; // 312 - info comment
char url[1024]; // 8504 - info url
char copyright[1024]; // 9528 - info copyright
} __attribute__ ((__packed__));
struct _v3_vrf_segment { // 64
uint32_t headlen; // 0 - header length (0x40 / 64)
uint32_t type; // 4 - audio type (0x01: v2.x audio | 0x02: text bind | 0x03: v3.x extended audio)
uint32_t valid; // 8 - valid
uint32_t offset; // 12 - audio offset
uint32_t time; // 16 - audio time
uint32_t duration; // 20 - audio duration
uint32_t unknown1; // 24 - unused
uint32_t unknown2; // 28 - unused
char username[32]; // 32 - user name
} __attribute__ ((__packed__));
struct _v3_vrf_audio { // 32
uint32_t headlen; // 0 - header length (0x20 / 32)
uint32_t type; // 4 - audio type (0x01: v2.x audio | 0x02: text bind | 0x03: v3.x extended audio)
uint32_t unknown1; // 8 - unused
uint32_t index; // 12 - segment index
uint32_t fragcount; // 16 - fragment count
uint32_t unknown2; // 20 - unused
uint32_t unknown3; // 24 - unused
uint32_t offset; // 28 - unused
} __attribute__ ((__packed__));
struct _v3_vrf_fragment { // 24
uint32_t headlen; // 0 - header length (0x01: 0x10 / 16 | 0x02: variable length | 0x03: 0x18 / 24)
uint32_t fraglen; // 4 - fragment length
struct {
uint32_t pcmlen; // 8 - pcm buffer length
uint32_t unknown1; // 12 - unused
struct {
uint16_t codec; // 16 - codec
uint16_t codecformat; // 18 - codec format
uint32_t unknown2; // 20 - unused
} __attribute__ ((__packed__)) ext;
} __attribute__ ((__packed__)) audio;
} __attribute__ ((__packed__));
struct _v3_vrf_rec {
uint32_t user_id;
_v3_vrf_audio audio;
_v3_vrf_segment segment;
void *data;
uint32_t datalen;
uint8_t stopped;
_v3_vrf_rec *next;
};
struct _v3_vrf {
int file;
char *filename;
uint32_t filelen;
pthread_mutex_t mutex;
_v3_vrf_header header;
_v3_vrf_segment *table;
uint32_t tablesize;
struct timeval start;
_v3_vrf_rec queue;
uint8_t stopped;
};
void _v3_vrf_lock(_v3_vrf *vrfh);
void _v3_vrf_unlock(_v3_vrf *vrfh);
void _v3_vrf_print_header(const _v3_vrf_header *header);
void _v3_vrf_print_info(const _v3_vrf_header *header);
void _v3_vrf_print_segment(uint32_t id, const _v3_vrf_segment *segment);
void _v3_vrf_print_audio(const _v3_vrf_audio *audio);
void _v3_vrf_print_fragment(uint32_t type, const _v3_vrf_fragment *fragment);
int _v3_vrf_get_header(_v3_vrf *vrfh);
int _v3_vrf_get_table(_v3_vrf *vrfh);
int _v3_vrf_check_table(_v3_vrf *vrfh);
int _v3_vrf_get_segment(_v3_vrf *vrfh, uint32_t id, _v3_vrf_segment **segment);
int _v3_vrf_get_audio(_v3_vrf *vrfh, uint32_t offset, _v3_vrf_audio *audio);
int _v3_vrf_get_fragment(_v3_vrf *vrfh, uint32_t type, uint32_t *offset, _v3_vrf_fragment *fragment, uint32_t *fraglen, void **fragdata);
int _v3_vrf_put_header(_v3_vrf *vrfh);
uint32_t _v3_vrf_put_segment(uint32_t id, const _v3_vrf_segment *segment, void *offset);
uint32_t _v3_vrf_put_audio(const _v3_vrf_audio *audio, void *offset);
uint32_t _v3_vrf_put_fragment(uint32_t type, const _v3_vrf_fragment *fragment, void *offset);
void _v3_vrf_put_record(uint32_t user_id, uint32_t index, uint32_t type, const char *username, _v3_vrf_rec *rec);
void _v3_vrf_record_event(
int type,
uint16_t user_id,
uint16_t codec,
uint16_t codecformat,
uint32_t pcmlen,
uint32_t datalen,
const void *data);
void _v3_vrf_record_finish(_v3_vrf *vrfh, uint32_t segtable);
int _v3_vrf_recover(_v3_vrf *vrfh);
/*}}}*/
_v3_vrf *v3_vrfh = NULL;
pthread_mutex_t *vrfh_mutex = NULL;
/*
* Functions in ventrilo3_algo.c
*/
int ventrilo_read_keys(ventrilo_key_ctx *client, ventrilo_key_ctx *server, uint8_t *data, int size
#ifdef VENTRILO_ALGO_PROTOCOL
, int protocol
#endif
);
void ventrilo_first_dec(uint8_t *data, int size);
void ventrilo_first_enc(uint8_t *data, int size);
void ventrilo_dec(ventrilo_key_ctx *ctx, uint8_t *data, int size);
void ventrilo_enc(ventrilo_key_ctx *ctx, uint8_t *data, int size);
int ventrilo3_handshake(uint32_t ip, uint16_t port, uint8_t *handshake, uint32_t *handshake_num, uint8_t *handshake_key);
void ventrilo3_algo_scramble(ventrilo_key_ctx *ctx, uint8_t *v3key);
int _v3_logout(void);
/*
* Internal functions
*/
void _v3_debug(uint32_t level, const char *format, ...);
char * _v3_status(uint8_t percent, const char *format, ...);
void _v3_hexdump(int level, const char *data, int len);
void _v3_net_message_dump_raw(const char *data, int len);
void _v3_net_message_dump(_v3_net_message *msg);
int _v3_login_connect(struct in_addr *srvip, uint16_t srvport);
int _v3_server_auth(struct in_addr *srvip, uint16_t srvport);
int _v3_evpipe_write(int fd, v3_event *ev);
int _v3_send(_v3_net_message *);
_v3_net_message * _v3_recv(int block);
_v3_net_message * _v3_create_message(_v3_net_message *msg, uint16_t type, uint16_t len, char *data);
int _v3_server_key_exchange(void);
int _v3_send_enc_msg(char *data, int len);
int _v3_recv_enc_msg(char *data);
int _v3_process_message(_v3_net_message *msg);
void _v3_destroy_packet(_v3_net_message *msg);
int _v3_update_channel(v3_channel *channel);
void _v3_copy_channel(v3_channel *dest, v3_channel *src);
int _v3_update_user(v3_user *user);
void _v3_copy_user(v3_user *dest, v3_user *src);
v3_user * _v3_get_user(uint16_t id);
int _v3_update_rank(v3_rank *rank);
void _v3_copy_rank(v3_rank *dest, v3_rank *src);
int _v3_update_account(v3_account *account);
int _v3_remove_account(uint16_t id);
void _v3_copy_account(v3_account *dest, v3_account *src);
void _v3_destroy_userlist(void);
void _v3_destroy_channellist(void);
void _v3_destroy_ranklist(void);
void _v3_destroy_accountlist(void);
void _v3_lock_userlist(void);
void _v3_unlock_userlist(void);
void _v3_lock_channellist(void);
void _v3_unlock_channellist(void);
void _v3_lock_ranklist(void);
void _v3_unlock_ranklist(void);
void _v3_lock_accountlist(void);
void _v3_unlock_accountlist(void);
void _v3_lock_luser(void);
void _v3_unlock_luser(void);
void _v3_lock_sendq(void);
void _v3_unlock_sendq(void);
void _v3_lock_server(void);
void _v3_unlock_server(void);
int v3_queue_event(v3_event *ev);
v3_event *_v3_get_last_event(int *len);
v3_event *_v3_create_event(uint16_t event);
#ifdef _WIN32
// TODO: May want to move these function definitions to a windows specific header file.
int mingw_inet_aton(const char *cp, struct in_addr *addr);
#endif
#if HAVE_SPEEX_DSP
void _v3_lock_audioq(void);
void _v3_unlock_audioq(void);
int _v3_nonblock(int pipefd[2]);
#endif
void _v3_init_decoders(void);
void _v3_destroy_decoder(_v3_decoders *decoder);
void _v3_destroy_decoders(void);
uint8_t *_v3_audio_encode(
/* pcm input */
uint8_t *sample,
uint32_t pcmlen,
/* encoded output */
const v3_codec *codec,
uint16_t *datalen,
/* optional args */
uint8_t channels,
uint16_t *framecount,
uint8_t *celtfragsize);
int _v3_audio_decode(
/* encoded input */
const v3_codec *codec,
_v3_decoders *decoder,
uint8_t *data,
uint16_t datalen,
/* pcm output */
uint8_t *sample,
uint32_t *pcmlen,
/* optional args */
uint8_t channels);
#endif // _LIBVENTRILO3_H