首次推送

This commit is contained in:
sansen
2026-07-20 19:01:03 +08:00
parent ea01b9cf99
commit ef1bf61f9f
4484 changed files with 937163 additions and 1 deletions
@@ -0,0 +1,996 @@
/*
* TeamSpeak SDK server sample
*
* Copyright (c) TeamSpeak-Systems
*/
#ifdef _WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#else
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <stdio.h>
#include <teamspeak/public_definitions.h>
#include <teamspeak/public_errors.h>
#include <teamspeak/serverlib_publicdefinitions.h>
#include <teamspeak/serverlib.h>
#include "id_io.h"
#define DEFAULT_VIRTUAL_SERVER_ID 1
/* Maximum number of clients allowed per virtual server */
#define MAX_CLIENTS 8
#ifdef _WINDOWS
#define SLEEP(x) Sleep(x)
#else
#define SLEEP(x) usleep(x*1000)
#endif
/* Enable to use server-side voice recording */
/* #define USE_VOICEDATAEVENT */
/* Enable to use custom encryption */
/* #define USE_CUSTOM_ENCRYPTION
#define CUSTOM_CRYPT_KEY 123 */
/* Uncomment "#define CUSTOM_PASSWORDS" to try custom passwords.
* Please note that you have to do the same on the client demo too */
/* #define CUSTOM_PASSWORDS */
#ifdef USE_VOICEDATAEVENT
#ifdef _WINDOWS
#include <io.h>
#else /* Unix compatibility */
#include <unistd.h>
#define _open open
#define _write write
#define _close close
#define _O_CREAT O_CREAT
#define _O_WRONLY O_WRONLY
#define _S_IREAD S_IREAD
#define _S_IWRITE S_IWRITE
#define _O_APPEND O_APPEND
#define _O_BINARY 0
#endif
#include <fcntl.h>
#include <sys/stat.h>
#endif
#define CHECK_ERROR(x) if((error = x) != ERROR_ok) { goto on_error; }
/*
* Callback when client has connected.
*
* Parameter:
* serverID - Virtual server ID
* clientID - ID of connected client
* channelID - ID of channel the client joined
*/
void onClientConnected(uint64 serverID, anyID clientID, uint64 channelID, unsigned int* removeClientError) {
char* clientName;
unsigned int error;
/* Query client nickname */
if((error = ts3server_getClientVariableAsString(serverID, clientID, CLIENT_NICKNAME, &clientName)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error querying client nickname: %s\n", errormsg);
ts3server_freeMemory(errormsg);
}
return;
}
printf("Client '%s' joined channel %llu on virtual server %llu\n", clientName, (unsigned long long) channelID, (unsigned long long)serverID);
/* Example: Kick clients with nickname "BlockMe from server */
if(!strcmp(clientName, "BlockMe")) {
printf("Blocking bad client!\n");
*removeClientError = ERROR_client_not_logged_in; /* Give a reason */
}
}
/*
* Callback when client has disconnected.
*
* Parameter:
* serverID - Virtual server ID
* clientID - ID of disconnected client
* channelID - ID of channel the client left
*/
void onClientDisconnected(uint64 serverID, anyID clientID, uint64 channelID) {
printf("Client %u left channel %llu on virtual server %llu\n", clientID, (unsigned long long)channelID, (unsigned long long)serverID);
}
/*
* Callback when client has moved.
*
* Parameter:
* serverID - Virtual server ID
* clientID - ID of moved client
* oldChannelID - ID of old channel the client left
* newChannelID - ID of new channel the client joined
*/
void onClientMoved(uint64 serverID, anyID clientID, uint64 oldChannelID, uint64 newChannelID) {
printf("Client %u moved from channel %llu to channel %llu on virtual server %llu\n", clientID, (unsigned long long)oldChannelID, (unsigned long long)newChannelID, (unsigned long long)serverID);
}
/*
* Callback when channel has been created.
*
* Parameter:
* serverID - Virtual server ID
* invokerClientID - ID of the client who created the channel
* channelID - ID of the created channel
*/
void onChannelCreated(uint64 serverID, anyID invokerClientID, uint64 channelID) {
printf("Channel %llu created by %u on virtual server %llu\n", (unsigned long long)channelID, invokerClientID, (unsigned long long)serverID);
}
/*
* Callback when channel has been edited.
*
* Parameter:
* serverID - Virtual server ID
* invokerClientID - ID of the client who edited the channel
* channelID - ID of the edited channel
*/
void onChannelEdited(uint64 serverID, anyID invokerClientID, uint64 channelID) {
printf("Channel %llu edited by %u on virtual server %llu\n", (unsigned long long)channelID, invokerClientID, (unsigned long long)serverID);
}
/*
* Callback when channel has been deleted.
*
* Parameter:
* serverID - Virtual server ID
* invokerClientID - ID of the client who deleted the channel
* channelID - ID of the deleted channel
*/
void onChannelDeleted(uint64 serverID, anyID invokerClientID, uint64 channelID) {
printf("Channel %llu deleted by %u on virtual server %llu\n", (unsigned long long)channelID, invokerClientID, (unsigned long long)serverID);
}
/*
* Callback when a server text message has been received.
* Note that only server and channel chats are received, private client messages are not caught due to privacy reasons.
*
* Parameter:
* serverID - Virtual server ID
* invokerClientID - ID of the client who sent the text message
* textMessage - Message text
*/
void onServerTextMessageEvent(uint64 serverID, anyID invokerClientID, const char* textMessage) {
char* invokerNickname;
unsigned int error;
/* Get invoker nickname */
if((error = ts3server_getClientVariableAsString(serverID, invokerClientID, CLIENT_NICKNAME, &invokerNickname)) != ERROR_ok) {
printf("Error getting client nickname: %d\n", error);
return;
}
printf("Text message in server chat by %s: %s\n", invokerNickname, textMessage);
ts3server_freeMemory(invokerNickname); /* Release previously allocated memory */
}
/*
* Callback when a channel text message has been received.
* Note that only server and channel chats are received, private client messages are not caught due to privacy reasons.
*
* Parameter:
* serverID - Virtual server ID
* invokerClientID - ID of the client who sent the text message
* targetChannelID - ID of the channel in which the chat was sent
* textMessage - Message text
*/
void onChannelTextMessageEvent(uint64 serverID, anyID invokerClientID, uint64 targetChannelID, const char* textMessage) {
char* invokerNickname;
char* channelName;
unsigned int error;
/* Get invoker nickname */
if((error = ts3server_getClientVariableAsString(serverID, invokerClientID, CLIENT_NICKNAME, &invokerNickname)) != ERROR_ok) {
printf("Error getting client nickname: %d\n", error);
return;
}
/* Get channel name */
if((error = ts3server_getChannelVariableAsString(serverID, targetChannelID, CHANNEL_NAME, &channelName)) != ERROR_ok) {
printf("Error getting channel name: %d\n", error);
ts3server_freeMemory(invokerNickname);
return;
}
printf("Text message in channel '%s' by %s: %s\n", channelName, invokerNickname, textMessage);
ts3server_freeMemory(invokerNickname);
ts3server_freeMemory(channelName);
}
/*
* Callback for user-defined logging.
*
* Parameter:
* logMessage - Log message text
* logLevel - Severity of log message
* logChannel - Custom text to categorize the message channel
* logID - Virtual server ID giving the virtual server source of the log event
* logTime - String with the date and time the log entry occured
* completeLogString - Verbose log message including all previous parameters for convinience
*/
void onUserLoggingMessageEvent(const char* logMessage, int logLevel, const char* logChannel, uint64 logID, const char* logTime, const char* completeLogString) {
/* Your custom error display here... */
/* printf("LOG: %s\n", completeLogString); */
if(logLevel == LogLevel_CRITICAL) {
exit(1); /* Your custom handling of critical errors */
}
}
#ifdef USE_VOICEDATAEVENT
/*
* Callback triggered by the specified client sending voice data.
*
* Parameters:
* serverID - ID of the server sending the callback
* clientID - ID of the client sending the voice data
* voiceData - Voice data buffer. Format is 16 bit mono. Do not free this buffer.
* voiceDataSize - Size of the voiceData buffer
* frequency - Voice frequency
*/
void onVoiceDataEvent(uint64 serverID, anyID clientID, unsigned char* voiceData, unsigned int voiceDataSize, unsigned int frequency) {
int fd;
unsigned int error;
char* name;
/* Query client nickname as string */
if((error = ts3server_getClientVariableAsString(serverID, clientID, CLIENT_NICKNAME, &name)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error querying client nickname: %s\n", errormsg);
ts3server_freeMemory(errormsg);
}
return;
}
/* Open file with client nickname as filename and write voice data */
fd =_open(name, _O_CREAT | _O_APPEND | _O_BINARY | _O_WRONLY , _S_IREAD | _S_IWRITE);
if(fd == -1) {
printf("failed to open file\n");
ts3server_freeMemory(name);
exit(-1);
}
_write(fd, voiceData, voiceDataSize);
_close(fd);
/* Release string dynamically allocated in getClientVariableAsString */
ts3server_freeMemory(name);
}
#endif
#ifdef CUSTOM_PASSWORDS
/*
* Called to encrypt channel and server passwords
*
* In this example, we do not do any encryption. That way we have clear
* text passwords on the server.
*
* Parameters:
* serverID - Server ID
* plaintext - the clear text password
* encryptedText - pointer to a buffer to store the encrypted password
* encryptedTextByteSize - the size of the encryptedText buffer
*/
void onClientPasswordEncrypt(uint64 serverID, const char* plaintext, char* encryptedText, int encryptedTextByteSize){
int pt_len;
printf("onClientPasswordEncrypt called\n");
pt_len = strlen(plaintext);
if (encryptedTextByteSize < pt_len-1) pt_len = encryptedTextByteSize-1;
memcpy(encryptedText, plaintext, pt_len);
encryptedText[pt_len]=0;
}
/*
* Callback triggered for server password.
*
* Parameters:
* serverID - ID of the virtual server to which the client is connecting.
* client - Struct of client parameters like ident, nickname etc. who is connecting to the server. Please view public_definitions.h.
* password - Password provided by the client.
*
* Return ERROR_ok to indicate the password is correct. Return ERROR_server_invalid_password for incorrect.
*/
unsigned int onCustomServerPasswordCheck(uint64 serverID, const struct ClientMiniExport* client, const char* password){
if (strcmp(password, "secret") == 0) return ERROR_ok;
return ERROR_server_invalid_password;
}
/*
* Callback triggered for channel password.
*
* Parameters:
* serverID - ID of the virtual server on which the client is moving itself or other clients to a new channel.
* client - Struct of client parameters like ident, nickname etc. who is moving itself or other clients to the channel. Please view public_definitions.h.
* channelID - Channel ID of the channel being switched/moved to
* password - Password provided by client.
*
* Return ERROR_ok to indicate the password is correct. Return ERROR_channel_invalid_password for incorrect.
*/
unsigned int onCustomChannelPasswordCheck(uint64 serverID, const struct ClientMiniExport* client, uint64 channelID, const char* password){
if (strcmp(password, "channelpw") == 0) return ERROR_ok;
return ERROR_channel_invalid_password;
}
#endif
/*
* Callback triggered when the specified client starts talking.
*
* Parameters:
* serverID - ID of the server sending the callback
* clientID - ID of the client which started talking
*/
void onClientStartTalkingEvent(uint64 serverID, anyID clientID) {
printf("onClientStartTalkingEvent serverID=%llu, clientID=%u\n", (unsigned long long)serverID, clientID);
}
/*
* Callback triggered when the specified client stops talking.
*
* Parameters:
* serverID - ID of the server sending the callback
* clientID - ID of the client which stopped talking
*/
void onClientStopTalkingEvent(uint64 serverID, anyID clientID) {
printf("onClientStopTalkingEvent serverID=%llu, clientID=%u\n", (unsigned long long)serverID, clientID);
}
/*
* Callback triggered when a license error occurs.
*
* Parameters:
* serverID - ID of the virtual server on which the license error occured. This virtual server will be automatically
* shutdown. If the parameter is zero, all virtual servers are affected and have been shutdown.
* errorCode - Code of the occured error. Use ts3server_getGlobalErrorMessage() to convert to a message string
*/
void onAccountingErrorEvent(uint64 serverID, unsigned int errorCode) {
char* errorMessage;
if(ts3server_getGlobalErrorMessage(errorCode, &errorMessage) == ERROR_ok) {
printf("onAccountingErrorEvent serverID=%llu, errorCode=%u: %s\n", (unsigned long long)serverID, errorCode, errorMessage);
ts3server_freeMemory(errorMessage);
}
/* Your custom handling here. In a real application, you wouldn't stop the whole process because the TS3 server part went down.
* The whole idea of this callback is to let you gracefully handle the TS3 server failing to start and to continue your application. */
exit(1);
}
/*
* Callback allowing to apply custom encryption to outgoing packets.
* Using this function is optional. Do not implement if you want to handle the TeamSpeak SDK encryption.
*
* Parameters:
* dataToSend - Pointer to an array with the outgoing data to be encrypted
* sizeOfData - Pointer to an integer value containing the size of the data array
*
* Apply your custom encryption to the data array. If the encrypted data is smaller than sizeOfData, write
* your encrypted data into the existing memory of dataToSend. If your encrypted data is larger, you need
* to allocate memory and redirect the pointer dataToSend. You need to take care of freeing your own allocated
* memory yourself. The memory allocated by the SDK, to which dataToSend is originally pointing to, must not
* be freed.
*
*/
void onCustomPacketEncryptEvent(char** dataToSend, unsigned int* sizeOfData) {
#ifdef USE_CUSTOM_ENCRYPTION
unsigned int i;
for(i = 0; i < *sizeOfData; i++) {
(*dataToSend)[i] ^= CUSTOM_CRYPT_KEY;
}
#endif
}
/*
* Callback allowing to apply custom encryption to incoming packets
* Using this function is optional. Do not implement if you want to handle the TeamSpeak SDK encryption.
*
* Parameters:
* dataToSend - Pointer to an array with the received data to be decrypted
* sizeOfData - Pointer to an integer value containing the size of the data array
*
* Apply your custom decryption to the data array. If the decrypted data is smaller than dataReceivedSize, write
* your decrypted data into the existing memory of dataReceived. If your decrypted data is larger, you need
* to allocate memory and redirect the pointer dataReceived. You need to take care of freeing your own allocated
* memory yourself. The memory allocated by the SDK, to which dataReceived is originally pointing to, must not
* be freed.
*/
void onCustomPacketDecryptEvent(char** dataReceived, unsigned int* dataReceivedSize) {
#ifdef USE_CUSTOM_ENCRYPTION
unsigned int i;
for(i = 0; i < *dataReceivedSize; i++) {
(*dataReceived)[i] ^= CUSTOM_CRYPT_KEY;
}
#endif
}
void showHelp() {
printf("\n[q] - Quit\n[h] - Show this help\n[v] - List virtual servers\n[c] - Show channels of virtual server %d\n", DEFAULT_VIRTUAL_SERVER_ID);
printf("[l] - Show clients of virtual server %d\n[n] - Create new channel on virtual server %d with generated name\n[N] - Create new channel on virtual server %d with custom name\n", DEFAULT_VIRTUAL_SERVER_ID, DEFAULT_VIRTUAL_SERVER_ID, DEFAULT_VIRTUAL_SERVER_ID);
printf("[d] - Delete channel on virtual server %d\n[r] - Rename channel on virtual server %d\n[m] - Move client on virtual server %d\n", DEFAULT_VIRTUAL_SERVER_ID, DEFAULT_VIRTUAL_SERVER_ID, DEFAULT_VIRTUAL_SERVER_ID);
printf("[C] - Create new virtual server\n[E] - Edit virtual server\n[S] - Stop virtual server\n\n");
}
void emptyInputBuffer() {
int c;
while((c = getchar()) != '\n' && c != EOF);
}
void showVirtualServers() {
uint64* ids;
int i;
unsigned int error;
printf("\nList of virtual servers:\n");
if((error = ts3server_getVirtualServerList(&ids)) != ERROR_ok) { /* Get array of virtual server IDs */
printf("Error getting virtual server list: %d\n", error);
return;
}
if(!ids[0]) {
printf("No virtual servers\n\n");
ts3server_freeMemory(ids);
return;
}
for(i=0; ids[i]; i++) {
char* name;
int slotCount;
char* virtualServerUniqueIdentifier;
if((error = ts3server_getVirtualServerVariableAsString(ids[i], VIRTUALSERVER_NAME, &name)) != ERROR_ok) { /* Query server name */
printf("Error getting virtual server nickname: %d\n", error);
break;
}
if((error = ts3server_getVirtualServerVariableAsInt(ids[i], VIRTUALSERVER_MAXCLIENTS, &slotCount)) != ERROR_ok) {
printf("Error getting virtual server slot count: %d\n", error);
break;
}
if((error = ts3server_getVirtualServerVariableAsString(ids[i], VIRTUALSERVER_UNIQUE_IDENTIFIER, &virtualServerUniqueIdentifier)) != ERROR_ok) {
printf("Error getting virtual server unique identifier: %d\n", error);
break;
}
printf("ID=%llu NAME=\"%s\" CAPACITY=%d Unique Identifier=\"%s\"\n", (unsigned long long)ids[i], name, slotCount, virtualServerUniqueIdentifier);
ts3server_freeMemory(name); /* Do not free memory if above function returned an error */
ts3server_freeMemory(virtualServerUniqueIdentifier);
}
printf("\n");
ts3server_freeMemory(ids); /* Release array */
}
void showChannels(uint64 serverID) {
uint64* ids;
int i;
unsigned int error;
printf("\nList of channels on virtual server %llu:\n", (unsigned long long)serverID);
if((error = ts3server_getChannelList(serverID, &ids)) != ERROR_ok) { /* Get array of channel IDs */
printf("Error getting channel list: %d\n", error);
return;
}
if(!ids[0]) {
printf("No channels\n\n");
ts3server_freeMemory(ids);
return;
}
for(i=0; ids[i]; i++) {
char* name;
if((error = ts3server_getChannelVariableAsString(serverID, ids[i], CHANNEL_NAME, &name)) != ERROR_ok) { /* Query channel name */
printf("Error querying channel name: %d\n", error);
break;
}
printf("%llu - %s\n", (unsigned long long)ids[i], name);
ts3server_freeMemory(name); /* Do not free memory if above function returned an error */
}
printf("\n");
ts3server_freeMemory(ids); /* Release array */
}
void showClients(uint64 serverID) {
anyID* ids;
int i;
unsigned int error;
printf("\nList of clients on virtual server %llu:\n", (unsigned long long)serverID);
if((error = ts3server_getClientList(serverID, &ids)) != ERROR_ok) { /* Get array of client IDs */
printf("Error getting client list: %d\n", error);
return;
}
if(!ids[0]) {
printf("No clients\n\n");
ts3server_freeMemory(ids);
return;
}
for(i=0; ids[i]; i++) {
char* name;
if((error = ts3server_getClientVariableAsString(serverID, ids[i], CLIENT_NICKNAME, &name)) != ERROR_ok) { /* Query client nickname */
printf("Error querying client nickname: %d\n", error);
break;
}
printf("%u - %s\n", ids[i], name);
ts3server_freeMemory(name); /* Do not free memory if above function returned an error */
}
printf("\n");
ts3server_freeMemory(ids); /* Release array */
}
void createDefaultChannelName(char *name) {
static int i = 1;
sprintf(name, "Channel_%d", i++);
}
void enterName(char *name) {
char *s;
printf("\nEnter name: ");
fgets(name, BUFSIZ, stdin);
s = strrchr(name, '\n');
if(s) {
*s = '\0';
}
}
void createChannel(uint64 serverID, const char *name) {
unsigned int error;
uint64 newChannelID;
/* Set data of new channel. Use channelID of 0 for creating channels. */
CHECK_ERROR(ts3server_setChannelVariableAsString(serverID, 0, CHANNEL_NAME, name));
CHECK_ERROR(ts3server_setChannelVariableAsString(serverID, 0, CHANNEL_TOPIC, "Test channel topic"));
CHECK_ERROR(ts3server_setChannelVariableAsString(serverID, 0, CHANNEL_DESCRIPTION, "Test channel description"));
CHECK_ERROR(ts3server_setChannelVariableAsInt (serverID, 0, CHANNEL_FLAG_PERMANENT, 1));
CHECK_ERROR(ts3server_setChannelVariableAsInt (serverID, 0, CHANNEL_FLAG_SEMI_PERMANENT, 0));
CHECK_ERROR(ts3server_setChannelVariableAsInt (serverID, 0, CHANNEL_CODEC_QUALITY, 10));
/* Flush changes to server */
CHECK_ERROR(ts3server_flushChannelCreation(serverID, 0, &newChannelID)); /* Create as top-level channel */
printf("\nCreated channel: %llu\n\n", (unsigned long long)newChannelID);
return;
on_error:
printf("Error creating channel: %d\n", error);
}
void deleteChannel(uint64 serverID) {
uint64 channelID;
int n;
unsigned int error;
/* Query channel ID from user */
printf("\nEnter ID of channel to delete: ");
n = scanf("%llu", (unsigned long long*)&channelID);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
/* Delete channel */
if((error = ts3server_channelDelete(serverID, channelID, 0)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error deleting channel: %s\n\n", errormsg);
ts3server_freeMemory(errormsg);
}
}
}
void renameChannel(uint64 serverID) {
uint64 channelID;
int n;
unsigned int error;
char name[BUFSIZ];
/* Query channel ID from user */
printf("\nEnter ID of channel to rename: ");
n = scanf("%llu", (unsigned long long*)&channelID);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
/* Query new channel name from user */
enterName(name);
/* Change channel name and flush changes */
CHECK_ERROR(ts3server_setChannelVariableAsString(serverID, channelID, CHANNEL_NAME, name));
CHECK_ERROR(ts3server_flushChannelVariable(serverID, channelID));
printf("Renamed channel %llu\n\n", (unsigned long long)channelID);
return;
on_error:
printf("Error renaming channel: %d\n\n", error);
}
void moveClient(uint64 serverID) {
anyID clientIDArray[2]; /* We only want to move one client plus terminating null end-marker */
uint64 newChannelID; /* ID of channel to move the client into */
unsigned int error;
int n;
/* Query client ID from user */
printf("\nEnter ID of client to move: ");
n = scanf("%hu", &clientIDArray[0]);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
clientIDArray[1] = 0; /* Add end-marker */
/* Query channel ID from user */
printf("\nEnter ID of channel to move client into: ");
n = scanf("%llu", (unsigned long long*)&newChannelID);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
/* Move client and check for error */
if((error = ts3server_clientMove(serverID, newChannelID, clientIDArray)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error moving client: %s\n\n", errormsg);
ts3server_freeMemory(errormsg);
}
return;
}
printf("Client %d moved to channel %llu\n", clientIDArray[0], (unsigned long long)newChannelID);
}
uint64 createVirtualServer(const char* name, int port, unsigned int maxClients) {
char buffer[BUFSIZ] = { 0 };
char filename[BUFSIZ];
char port_str[20];
char *keyPair;
uint64 serverID;
unsigned int error;
/* Assemble filename: keypair_<port>.txt */
strcpy(filename, "keypair_");
sprintf(port_str, "%d", port);
strcat(filename, port_str);
strcat(filename, ".txt");
/* Try reading keyPair from file */
if(readKeyPairFromFile(filename, buffer) == 0) {
keyPair = buffer; /* Id read from file */
} else {
keyPair = ""; /* No Id saved, start virtual server with empty keyPair string */
}
/* Create the virtual server with specified port, name, keyPair and max clients */
printf("Create virtual server using keypair '%s'\n", keyPair);
printf("Create virtual server with %d slots\n", maxClients);
//listen on any address on ipv4 and ipv6 (it is also possible to enter multiple ipv4 and ipv6 addresses here)
if((error = ts3server_createVirtualServer(port, "0.0.0.0, ::", name, keyPair, maxClients, &serverID)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error creating virtual server: %s (%d)\n", errormsg, error);
ts3server_freeMemory(errormsg);
}
return 0;
}
/* If we didn't load the keyPair before, query it from virtual server and save to file */
if(!*buffer) {
if((error = ts3server_getVirtualServerKeyPair(serverID, &keyPair)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error querying keyPair: %s\n\n", errormsg);
ts3server_freeMemory(errormsg);
}
return 0;
}
/* Save keyPair to file "keypair_<port>.txt"*/
if(writeKeyPairToFile(filename, keyPair) != 0) {
ts3server_freeMemory(keyPair);
return 0;
}
ts3server_freeMemory(keyPair);
}
return serverID;
}
uint64 startVirtualServer() {
int n;
int port;
unsigned int maxClients;
char name[BUFSIZ];
/* Ask user for server port */
printf("\nEnter server port (default 9987): ");
n = scanf("%d", &port);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return 0;
}
printf("\nEnter server capacity (default %d): ", MAX_CLIENTS);
n = scanf("%d", &maxClients);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return 0;
}
/* Ask user for server name */
enterName(name);
return createVirtualServer(name, port, maxClients);
}
void editVirtualServer() {
int n;
uint64 serverID;
int currentSlotCount, newSlotCount;
unsigned int error;
printf("\nEnter ID of virtual server to edit: ");
n = scanf("%llu", (unsigned long long*)&serverID);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
if((error = ts3server_getVirtualServerVariableAsInt(serverID, VIRTUALSERVER_MAXCLIENTS, &currentSlotCount)) != ERROR_ok) {
printf("Error getting the current capcity of virtual server: %d\n\n", error);
return;
}
printf("\nEnter new capacity of virtual server (currently %d): ", currentSlotCount);
n = scanf("%d", &newSlotCount);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
if((error = ts3server_setVirtualServerVariableAsInt(serverID, VIRTUALSERVER_MAXCLIENTS, newSlotCount)) != ERROR_ok) {
printf("Error setting the new capacity: %d\n\n", error);
return;
}
if((error = ts3server_flushVirtualServerVariable(serverID)) != ERROR_ok) {
printf("Error flushing server variable updates %d\n\n", error);
return;
}
}
void stopVirtualServer() {
int n;
uint64 serverID;
unsigned int error;
printf("\nEnter ID of virtual server to stop: ");
n = scanf("%llu", (unsigned long long*)&serverID);
emptyInputBuffer();
if(n == 0) {
printf("Invalid input. Please enter a number.\n\n");
return;
}
if((error = ts3server_stopVirtualServer(serverID)) != ERROR_ok) {
printf("Error stopping virtual server: %d\n\n", error);
}
}
int main(int argc, char **argv) {
char *version;
short abort = 0;
uint64 serverID;
unsigned int error;
int unknownInput = 0;
uint64* ids;
int i;
/* Create struct for callback function pointers */
struct ServerLibFunctions funcs;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ServerLibFunctions));
/* Now assign the used callback function pointers */
funcs.onClientConnected = onClientConnected;
funcs.onClientDisconnected = onClientDisconnected;
funcs.onClientMoved = onClientMoved;
funcs.onChannelCreated = onChannelCreated;
funcs.onChannelEdited = onChannelEdited;
funcs.onChannelDeleted = onChannelDeleted;
funcs.onServerTextMessageEvent = onServerTextMessageEvent;
funcs.onChannelTextMessageEvent = onChannelTextMessageEvent;
funcs.onUserLoggingMessageEvent = onUserLoggingMessageEvent;
funcs.onClientStartTalkingEvent = onClientStartTalkingEvent;
funcs.onClientStopTalkingEvent = onClientStopTalkingEvent;
funcs.onAccountingErrorEvent = onAccountingErrorEvent;
funcs.onCustomPacketEncryptEvent = onCustomPacketEncryptEvent;
funcs.onCustomPacketDecryptEvent = onCustomPacketDecryptEvent;
#ifdef USE_VOICEDATAEVENT
funcs.onVoiceDataEvent = onVoiceDataEvent;
#endif
#ifdef CUSTOM_PASSWORDS
funcs.onClientPasswordEncrypt = onClientPasswordEncrypt;
funcs.onCustomServerPasswordCheck = onCustomServerPasswordCheck;
funcs.onCustomChannelPasswordCheck = onCustomChannelPasswordCheck;
#endif
/* Initialize server lib with callbacks */
if((error = ts3server_initServerLib(&funcs, LogType_FILE | LogType_CONSOLE | LogType_USERLOGGING, NULL, argc, (const char* const *)argv)) != ERROR_ok) {
char* errormsg;
if(ts3server_getGlobalErrorMessage(error, &errormsg) == ERROR_ok) {
printf("Error initialzing serverlib: %s\n", errormsg);
ts3server_freeMemory(errormsg);
}
return 1;
}
printf("Server running\n");
/* Query and print server lib version */
if((error = ts3server_getServerLibVersion(&version)) != ERROR_ok) {
printf("Error querying server lib version: %d\n", error);
return 1;
}
printf("Server lib version: %s\n", version);
ts3server_freeMemory(version); /* Release dynamically allocated memory */
/* Create a virtual server on localhost using default port 9987 with max 10 slots */
serverID = createVirtualServer("TS3 SDK Test Server", 9987, MAX_CLIENTS);
printf("Created virtual server\n");
/* Set welcome message */
if((error = ts3server_setVirtualServerVariableAsString(serverID, VIRTUALSERVER_WELCOMEMESSAGE, "Hello TeamSpeak")) != ERROR_ok) {
printf("Error setting server welcomemessage: %d\n", error);
return 1;
}
printf("Welcome message set.\n");
/* Set server password */
if((error = ts3server_setVirtualServerVariableAsString(serverID, VIRTUALSERVER_PASSWORD, "secret")) != ERROR_ok) {
printf("Error setting server password: %d\n", error);
return 1;
}
printf("Password set.\n");
/* Flush above two changes to server */
if((error = ts3server_flushVirtualServerVariable(serverID)) != ERROR_ok) {
printf("Error flushing server variables: %d\n", error);
return 1;
}
printf("Variables flushed.\n");
/* Set codec quality of channel(s) */
uint64* channelList = NULL;
if ((error = ts3server_getChannelList(serverID, &channelList)) != ERROR_ok) {
printf("Couldn't get channel list: %d\n", error);
return 1;
}
printf("Received channel list.\n");
uint64* channelIDPtr = NULL;
for (channelIDPtr = channelList; *channelIDPtr != (uint64)NULL; ++channelIDPtr) {
if ((error = ts3server_setChannelVariableAsInt(serverID, *channelIDPtr, CHANNEL_CODEC_QUALITY, 10)) != ERROR_ok) {
printf("Couldn't set channel codec quality: %d\n", error);
ts3server_freeMemory(channelList);
return 1;
}
if ((error = ts3server_flushChannelVariable(serverID, *channelIDPtr)) != ERROR_ok) {
if (error != ERROR_ok_no_update) {
printf("Error flushing channel variables: %d\n", error);
ts3server_freeMemory(channelList);
return 1;
}
}
}
ts3server_freeMemory(channelList);
/* Simple commandline interface */
printf("\nTeamSpeak 3 server commandline interface\n");
showHelp();
while(!abort) {
int c;
if(unknownInput == 0) {
printf("\nEnter Command (h for help)> ");
}
unknownInput = 0;
c = getchar();
switch(c) {
case 'q':
printf("\nShutting down server...\n");
abort = 1;
break;
case 'h':
showHelp();
break;
case 'v':
showVirtualServers();
break;
case 'c':
showChannels(serverID);
break;
case 'l':
showClients(serverID);
break;
case 'n':
{
char name[BUFSIZ];
createDefaultChannelName(name);
createChannel(serverID, name);
break;
}
case 'N':
{
char name[BUFSIZ];
emptyInputBuffer();
enterName(name);
createChannel(serverID, name);
break;
}
case 'd':
deleteChannel(serverID);
break;
case 'r':
renameChannel(serverID);
break;
case 'm':
moveClient(serverID);
break;
case 'C':
startVirtualServer();
break;
case 'E':
editVirtualServer();
break;
case 'S':
stopVirtualServer();
break;
default:
unknownInput = 1;
}
SLEEP(50);
}
/* Stop virtual servers to make sure connected clients are notified instead of dropped */
if((error = ts3server_getVirtualServerList(&ids)) != ERROR_ok) { /* Get array of virtual server IDs */
printf("Error getting virtual server list: %d\n", error);
} else {
for(i=0; ids[i]; i++) {
if((error = ts3server_stopVirtualServer(ids[i])) != ERROR_ok) {
printf("Error stopping virtual server: %d\n", error);
break;
}
}
ts3server_freeMemory(ids);
}
/* Shutdown server lib */
if((error = ts3server_destroyServerLib()) != ERROR_ok) {
printf("Error destroying server lib: %d\n", error);
return 1;
}
return 0;
}