mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-29 11:24:30 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
12f82e39c5
29 changed files with 663 additions and 293 deletions
|
@ -13,9 +13,8 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
add_subdirectory(animation-server)
|
add_subdirectory(animation-server)
|
||||||
|
add_subdirectory(assignment-client)
|
||||||
add_subdirectory(assignment-server)
|
add_subdirectory(assignment-server)
|
||||||
add_subdirectory(avatar-mixer)
|
|
||||||
add_subdirectory(audio-mixer)
|
|
||||||
add_subdirectory(domain-server)
|
add_subdirectory(domain-server)
|
||||||
add_subdirectory(eve)
|
add_subdirectory(eve)
|
||||||
add_subdirectory(interface)
|
add_subdirectory(interface)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
set(TARGET_NAME "avatar-mixer")
|
set(TARGET_NAME assignment-client)
|
||||||
|
|
||||||
set(ROOT_DIR ..)
|
set(ROOT_DIR ..)
|
||||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||||
|
@ -8,15 +8,11 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||||
# setup for find modules
|
# setup for find modules
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||||
|
|
||||||
# setup the project
|
|
||||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||||
|
|
||||||
# include glm
|
# link in the shared library
|
||||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
|
||||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|
||||||
|
|
||||||
# link required hifi libraries
|
|
||||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
88
assignment-client/src/main.cpp
Normal file
88
assignment-client/src/main.cpp
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// main.cpp
|
||||||
|
// assignment-client
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 8/22/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <Assignment.h>
|
||||||
|
#include <AudioMixer.h>
|
||||||
|
#include <AvatarMixer.h>
|
||||||
|
#include <NodeList.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
const int ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000;
|
||||||
|
|
||||||
|
int main(int argc, char* const argv[]) {
|
||||||
|
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
|
// create a NodeList as an unassigned client
|
||||||
|
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_UNASSIGNED);
|
||||||
|
|
||||||
|
// change the timeout on the nodelist socket to be as often as we want to re-request
|
||||||
|
nodeList->getNodeSocket()->setBlockingReceiveTimeoutInUsecs(ASSIGNMENT_REQUEST_INTERVAL_USECS);
|
||||||
|
|
||||||
|
unsigned char packetData[MAX_PACKET_SIZE];
|
||||||
|
ssize_t receivedBytes = 0;
|
||||||
|
|
||||||
|
// loop the parameters to see if we were passed a pool
|
||||||
|
int parameter = -1;
|
||||||
|
const char ALLOWED_PARAMETERS[] = "p::";
|
||||||
|
const char POOL_PARAMETER_CHAR = 'p';
|
||||||
|
|
||||||
|
char* assignmentPool = NULL;
|
||||||
|
|
||||||
|
while ((parameter = getopt(argc, argv, ALLOWED_PARAMETERS)) != -1) {
|
||||||
|
if (parameter == POOL_PARAMETER_CHAR) {
|
||||||
|
// copy the passed assignment pool
|
||||||
|
int poolLength = strlen(optarg);
|
||||||
|
assignmentPool = new char[poolLength + sizeof(char)];
|
||||||
|
strcpy(assignmentPool, optarg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a request assignment, accept all assignments, pass the desired pool (if it exists)
|
||||||
|
Assignment requestAssignment(Assignment::Request, Assignment::All, assignmentPool);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// if we're here we have no assignment, so send a request
|
||||||
|
qDebug() << "Sending an assignment request -" << requestAssignment;
|
||||||
|
nodeList->sendAssignment(requestAssignment);
|
||||||
|
|
||||||
|
while (nodeList->getNodeSocket()->receive(packetData, &receivedBytes)) {
|
||||||
|
if (packetData[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT && packetVersionMatch(packetData)) {
|
||||||
|
|
||||||
|
// construct the deployed assignment from the packet data
|
||||||
|
Assignment deployedAssignment(packetData, receivedBytes);
|
||||||
|
|
||||||
|
qDebug() << "Received an assignment - " << deployedAssignment << "\n";
|
||||||
|
|
||||||
|
// switch our nodelist DOMAIN_IP to the ip receieved in the assignment
|
||||||
|
if (deployedAssignment.getDomainSocket()->sa_family == AF_INET) {
|
||||||
|
in_addr domainSocketAddr = ((sockaddr_in*) deployedAssignment.getDomainSocket())->sin_addr;
|
||||||
|
nodeList->setDomainIP(inet_ntoa(domainSocketAddr));
|
||||||
|
|
||||||
|
qDebug() << "Changed domain IP to " << inet_ntoa(domainSocketAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deployedAssignment.getType() == Assignment::AudioMixer) {
|
||||||
|
AudioMixer::run();
|
||||||
|
} else {
|
||||||
|
AvatarMixer::run();
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Assignment finished or never started - waiting for new assignment";
|
||||||
|
|
||||||
|
// reset our NodeList by switching back to unassigned and clearing the list
|
||||||
|
nodeList->setOwnerType(NODE_TYPE_UNASSIGNED);
|
||||||
|
nodeList->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,19 +12,17 @@
|
||||||
|
|
||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
#include <Assignment.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <UDPSocket.h>
|
#include <UDPSocket.h>
|
||||||
|
|
||||||
const int MAX_PACKET_SIZE_BYTES = 1400;
|
const int MAX_PACKET_SIZE_BYTES = 1400;
|
||||||
|
const long long NUM_DEFAULT_ASSIGNMENT_STALENESS_USECS = 10 * 1000 * 1000;
|
||||||
struct Assignment {
|
|
||||||
QString scriptFilename;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
std::queue<Assignment> assignmentQueue;
|
std::deque<Assignment*> assignmentQueue;
|
||||||
|
|
||||||
sockaddr_in senderSocket;
|
sockaddr_in senderSocket;
|
||||||
unsigned char senderData[MAX_PACKET_SIZE_BYTES] = {};
|
unsigned char senderData[MAX_PACKET_SIZE_BYTES] = {};
|
||||||
|
@ -33,46 +31,78 @@ int main(int argc, const char* argv[]) {
|
||||||
UDPSocket serverSocket(ASSIGNMENT_SERVER_PORT);
|
UDPSocket serverSocket(ASSIGNMENT_SERVER_PORT);
|
||||||
|
|
||||||
unsigned char assignmentPacket[MAX_PACKET_SIZE_BYTES];
|
unsigned char assignmentPacket[MAX_PACKET_SIZE_BYTES];
|
||||||
int numSendHeaderBytes = populateTypeAndVersion(assignmentPacket, PACKET_TYPE_SEND_ASSIGNMENT);
|
int numSendHeaderBytes = populateTypeAndVersion(assignmentPacket, PACKET_TYPE_DEPLOY_ASSIGNMENT);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (serverSocket.receive((sockaddr*) &senderSocket, &senderData, &receivedBytes)) {
|
if (serverSocket.receive((sockaddr*) &senderSocket, &senderData, &receivedBytes)) {
|
||||||
|
|
||||||
int numHeaderBytes = numBytesForPacketHeader(senderData);
|
|
||||||
|
|
||||||
if (senderData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) {
|
if (senderData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) {
|
||||||
qDebug() << "Assignment request received.\n";
|
// construct the requested assignment from the packet data
|
||||||
// grab the FI assignment in the queue, if it exists
|
Assignment requestAssignment(senderData, receivedBytes);
|
||||||
|
|
||||||
|
qDebug() << "Received request for assignment:" << requestAssignment;
|
||||||
|
qDebug() << "Current queue size is" << assignmentQueue.size();
|
||||||
|
|
||||||
|
// make sure there are assignments in the queue at all
|
||||||
if (assignmentQueue.size() > 0) {
|
if (assignmentQueue.size() > 0) {
|
||||||
Assignment firstAssignment = assignmentQueue.front();
|
|
||||||
assignmentQueue.pop();
|
|
||||||
|
|
||||||
QString scriptURL = QString("http://base8-compute.s3.amazonaws.com/%1").arg(firstAssignment.scriptFilename);
|
std::deque<Assignment*>::iterator assignment = assignmentQueue.begin();
|
||||||
|
|
||||||
qDebug() << "Sending assignment with URL" << scriptURL << "\n";
|
// enumerate assignments until we find one to give this client (if possible)
|
||||||
|
while (assignment != assignmentQueue.end()) {
|
||||||
|
|
||||||
int scriptURLBytes = scriptURL.size();
|
// if this assignment is stale then get rid of it and check the next one
|
||||||
memcpy(assignmentPacket + numSendHeaderBytes, scriptURL.toLocal8Bit().constData(), scriptURLBytes);
|
if (usecTimestampNow() - usecTimestamp(&((*assignment)->getTime()))
|
||||||
|
>= NUM_DEFAULT_ASSIGNMENT_STALENESS_USECS) {
|
||||||
|
delete *assignment;
|
||||||
|
assignment = assignmentQueue.erase(assignment);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eitherHasPool = ((*assignment)->getPool() || requestAssignment.getPool());
|
||||||
|
bool bothHavePool = ((*assignment)->getPool() && requestAssignment.getPool());
|
||||||
|
|
||||||
|
// make sure there is a pool match for the created and requested assignment
|
||||||
|
// or that neither has a designated pool
|
||||||
|
if ((eitherHasPool && bothHavePool
|
||||||
|
&& strcmp((*assignment)->getPool(), requestAssignment.getPool()) == 0)
|
||||||
|
|| !eitherHasPool) {
|
||||||
|
|
||||||
|
int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes);
|
||||||
|
|
||||||
// send the assignment
|
// send the assignment
|
||||||
serverSocket.send((sockaddr*) &senderSocket, assignmentPacket, numHeaderBytes + scriptURLBytes);
|
serverSocket.send((sockaddr*) &senderSocket,
|
||||||
|
assignmentPacket,
|
||||||
|
numSendHeaderBytes + numAssignmentBytes);
|
||||||
|
|
||||||
|
|
||||||
|
// delete this assignment now that it has been sent out
|
||||||
|
delete *assignment;
|
||||||
|
// remove it from the deque and make the iterator the next assignment
|
||||||
|
assignmentQueue.erase(assignment);
|
||||||
|
|
||||||
|
// stop looping - we've handed out an assignment
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// push forward the iterator
|
||||||
|
assignment++;
|
||||||
}
|
}
|
||||||
} else if (senderData[0] == PACKET_TYPE_SEND_ASSIGNMENT) {
|
}
|
||||||
Assignment newAssignment;
|
}
|
||||||
|
} else if (senderData[0] == PACKET_TYPE_CREATE_ASSIGNMENT && packetVersionMatch(senderData)) {
|
||||||
|
// construct the create assignment from the packet data
|
||||||
|
Assignment* createdAssignment = new Assignment(senderData, receivedBytes);
|
||||||
|
|
||||||
senderData[receivedBytes] = '\0';
|
qDebug() << "Received a created assignment:" << *createdAssignment;
|
||||||
newAssignment.scriptFilename = QString((const char*)senderData + numHeaderBytes);
|
qDebug() << "Current queue size is" << assignmentQueue.size();
|
||||||
|
|
||||||
qDebug() << "Added an assignment with script with filename" << newAssignment.scriptFilename << "\n";
|
// assignment server is on a public server
|
||||||
|
// assume that the address we now have for the sender is the public address/port
|
||||||
|
// and store that with the assignment so it can be given to the requestor later
|
||||||
|
createdAssignment->setDomainSocket((sockaddr*) &senderSocket);
|
||||||
|
|
||||||
// add this assignment to the queue
|
// add this assignment to the queue
|
||||||
|
assignmentQueue.push_back(createdAssignment);
|
||||||
// we're not a queue right now, only keep one assignment
|
|
||||||
if (assignmentQueue.size() > 0) {
|
|
||||||
assignmentQueue.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
assignmentQueue.push(newAssignment);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
audio-mixer/.gitignore
vendored
4
audio-mixer/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
socket
|
|
||||||
sftp-config.json
|
|
||||||
.DS_Store
|
|
||||||
*.raw
|
|
|
@ -1,27 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
|
|
||||||
set(ROOT_DIR ..)
|
|
||||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
|
||||||
|
|
||||||
# setup for find modules
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
|
||||||
|
|
||||||
set(TARGET_NAME audio-mixer)
|
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
|
||||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
|
||||||
|
|
||||||
# set up the external glm library
|
|
||||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
|
||||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|
||||||
|
|
||||||
# link the shared hifi library
|
|
||||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
|
||||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
|
||||||
|
|
||||||
# link the stk library
|
|
||||||
set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk)
|
|
||||||
find_package(STK REQUIRED)
|
|
||||||
target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES})
|
|
||||||
include_directories(${STK_INCLUDE_DIRS})
|
|
|
@ -2,7 +2,7 @@ MACRO(SETUP_HIFI_PROJECT TARGET INCLUDE_QT)
|
||||||
project(${TARGET})
|
project(${TARGET})
|
||||||
|
|
||||||
# grab the implemenation and header files
|
# grab the implemenation and header files
|
||||||
file(GLOB TARGET_SRCS src/*.cpp src/*.h)
|
file(GLOB TARGET_SRCS src/*.cpp src/*.h src/*.c)
|
||||||
|
|
||||||
# add the executable
|
# add the executable
|
||||||
add_executable(${TARGET} ${TARGET_SRCS})
|
add_executable(${TARGET} ${TARGET_SRCS})
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
// M - Audio Mixer
|
// M - Audio Mixer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "Assignment.h"
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
#include "NodeTypes.h"
|
#include "NodeTypes.h"
|
||||||
#include "Logstash.h"
|
#include "Logstash.h"
|
||||||
|
@ -46,14 +48,13 @@ unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* no
|
||||||
return currentPosition;
|
return currentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char * argv[])
|
int main(int argc, char* const argv[]) {
|
||||||
{
|
|
||||||
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, DOMAIN_LISTEN_PORT);
|
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_DOMAIN, DOMAIN_LISTEN_PORT);
|
||||||
// If user asks to run in "local" mode then we do NOT replace the IP
|
// If user asks to run in "local" mode then we do NOT replace the IP
|
||||||
// with the EC2 IP. Otherwise, we will replace the IP like we used to
|
// with the EC2 IP. Otherwise, we will replace the IP like we used to
|
||||||
// this allows developers to run a local domain without recompiling the
|
// this allows developers to run a local domain without recompiling the
|
||||||
// domain server
|
// domain server
|
||||||
bool isLocalMode = cmdOptionExists(argc, argv, "--local");
|
bool isLocalMode = cmdOptionExists(argc, (const char**) argv, "--local");
|
||||||
if (isLocalMode) {
|
if (isLocalMode) {
|
||||||
printf("NOTE: Running in local mode!\n");
|
printf("NOTE: Running in local mode!\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,7 +85,56 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
timeval lastStatSendTime = {};
|
timeval lastStatSendTime = {};
|
||||||
|
|
||||||
|
// loop the parameters to see if we were passed a pool for assignment
|
||||||
|
int parameter = -1;
|
||||||
|
const char ALLOWED_PARAMETERS[] = "p::-local::";
|
||||||
|
const char POOL_PARAMETER_CHAR = 'p';
|
||||||
|
|
||||||
|
char* assignmentPool = NULL;
|
||||||
|
|
||||||
|
while ((parameter = getopt(argc, argv, ALLOWED_PARAMETERS)) != -1) {
|
||||||
|
if (parameter == POOL_PARAMETER_CHAR) {
|
||||||
|
// copy the passed assignment pool
|
||||||
|
int poolLength = strlen(optarg);
|
||||||
|
assignmentPool = new char[poolLength + sizeof(char)];
|
||||||
|
strcpy(assignmentPool, optarg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// use a map to keep track of iterations of silence for assignment creation requests
|
||||||
|
const int ASSIGNMENT_SILENCE_MAX_ITERATIONS = 5;
|
||||||
|
std::map<Assignment*, int> assignmentSilenceCount;
|
||||||
|
|
||||||
|
// as a domain-server we will always want an audio mixer and avatar mixer
|
||||||
|
// setup the create assignments for those
|
||||||
|
Assignment audioAssignment(Assignment::Create, Assignment::AudioMixer, assignmentPool);
|
||||||
|
Assignment avatarAssignment(Assignment::Create, Assignment::AvatarMixer, assignmentPool);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
|
if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER)) {
|
||||||
|
if (assignmentSilenceCount[&audioAssignment] == ASSIGNMENT_SILENCE_MAX_ITERATIONS) {
|
||||||
|
nodeList->sendAssignment(audioAssignment);
|
||||||
|
assignmentSilenceCount[&audioAssignment] = 0;
|
||||||
|
} else {
|
||||||
|
assignmentSilenceCount[&audioAssignment]++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assignmentSilenceCount[&audioAssignment] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER)) {
|
||||||
|
if (assignmentSilenceCount[&avatarAssignment] == ASSIGNMENT_SILENCE_MAX_ITERATIONS) {
|
||||||
|
nodeList->sendAssignment(avatarAssignment);
|
||||||
|
assignmentSilenceCount[&avatarAssignment] = 0;
|
||||||
|
} else {
|
||||||
|
assignmentSilenceCount[&avatarAssignment]++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assignmentSilenceCount[&avatarAssignment] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
|
if (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
|
||||||
(packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) &&
|
(packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) &&
|
||||||
packetVersionMatch(packetData)) {
|
packetVersionMatch(packetData)) {
|
||||||
|
@ -117,6 +167,8 @@ int main(int argc, const char * argv[])
|
||||||
nodeType,
|
nodeType,
|
||||||
nodeList->getLastNodeID());
|
nodeList->getLastNodeID());
|
||||||
|
|
||||||
|
// if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it
|
||||||
|
if (newNode) {
|
||||||
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
|
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
|
||||||
nodeList->increaseNodeID();
|
nodeList->increaseNodeID();
|
||||||
}
|
}
|
||||||
|
@ -180,6 +232,7 @@ int main(int argc, const char * argv[])
|
||||||
broadcastPacket,
|
broadcastPacket,
|
||||||
(currentBufferPos - startPointer) + numHeaderBytes);
|
(currentBufferPos - startPointer) + numHeaderBytes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Logstash::shouldSendStats()) {
|
if (Logstash::shouldSendStats()) {
|
||||||
if (usecTimestampNow() - usecTimestamp(&lastStatSendTime) >= (NODE_COUNT_STAT_INTERVAL_MSECS * 1000)) {
|
if (usecTimestampNow() - usecTimestamp(&lastStatSendTime) >= (NODE_COUNT_STAT_INTERVAL_MSECS * 1000)) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
|
||||||
|
|
||||||
set(TARGET_NAME audio)
|
set(TARGET_NAME audio)
|
||||||
|
|
||||||
|
# set up the external glm library
|
||||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||||
setup_hifi_library(${TARGET_NAME})
|
setup_hifi_library(${TARGET_NAME})
|
||||||
|
|
||||||
|
@ -16,3 +17,9 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
|
# link the stk library
|
||||||
|
set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk)
|
||||||
|
find_package(STK REQUIRED)
|
||||||
|
target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES})
|
||||||
|
include_directories(${STK_INCLUDE_DIRS})
|
|
@ -1,9 +1,9 @@
|
||||||
//
|
//
|
||||||
// main.cpp
|
// AudioMixer.cpp
|
||||||
// mixer
|
// hifi
|
||||||
//
|
//
|
||||||
// Created by Stephen Birarda on 2/1/13.
|
// Created by Stephen Birarda on 8/22/13.
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -40,11 +40,13 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <StdDev.h>
|
#include <StdDev.h>
|
||||||
|
|
||||||
#include <AudioRingBuffer.h>
|
#include "AudioRingBuffer.h"
|
||||||
|
|
||||||
#include "AvatarAudioRingBuffer.h"
|
#include "AvatarAudioRingBuffer.h"
|
||||||
#include "InjectedAudioRingBuffer.h"
|
#include "InjectedAudioRingBuffer.h"
|
||||||
|
|
||||||
|
#include "AudioMixer.h"
|
||||||
|
|
||||||
const unsigned short MIXER_LISTEN_PORT = 55443;
|
const unsigned short MIXER_LISTEN_PORT = 55443;
|
||||||
|
|
||||||
const short JITTER_BUFFER_MSECS = 12;
|
const short JITTER_BUFFER_MSECS = 12;
|
||||||
|
@ -65,25 +67,10 @@ void attachNewBufferToNode(Node *newNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wantLocalDomain = false;
|
void AudioMixer::run() {
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
NodeList *nodeList = NodeList::getInstance();
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
nodeList->setOwnerType(NODE_TYPE_AUDIO_MIXER);
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
|
|
||||||
|
|
||||||
// Handle Local Domain testing with the --local command line
|
|
||||||
const char* local = "--local";
|
|
||||||
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
|
||||||
if (::wantLocalDomain) {
|
|
||||||
printf("Local Domain MODE!\n");
|
|
||||||
nodeList->setDomainIPToLocalhost();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* domainIP = getCmdOption(argc, argv, "--domain");
|
|
||||||
if (domainIP) {
|
|
||||||
NodeList::getInstance()->setDomainHostname(domainIP);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t receivedBytes = 0;
|
ssize_t receivedBytes = 0;
|
||||||
|
|
||||||
|
@ -123,6 +110,10 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (Logstash::shouldSendStats()) {
|
if (Logstash::shouldSendStats()) {
|
||||||
gettimeofday(&beginSendTime, NULL);
|
gettimeofday(&beginSendTime, NULL);
|
||||||
}
|
}
|
||||||
|
@ -400,7 +391,7 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// give the new audio data to the matching injector node
|
// give the new audio data to the matching injector node
|
||||||
nodeList->updateNodeWithData(matchingInjector, packetData, receivedBytes);
|
nodeList->updateNodeWithData(matchingInjector, packetData, receivedBytes);
|
||||||
} else if (packetData[0] == PACKET_TYPE_PING) {
|
} else if (packetData[0] == PACKET_TYPE_PING || packetData[0] == PACKET_TYPE_DOMAIN) {
|
||||||
|
|
||||||
// If the packet is a ping, let processNodeData handle it.
|
// If the packet is a ping, let processNodeData handle it.
|
||||||
nodeList->processNodeData(nodeAddress, packetData, receivedBytes);
|
nodeList->processNodeData(nodeAddress, packetData, receivedBytes);
|
||||||
|
@ -429,6 +420,4 @@ int main(int argc, const char* argv[]) {
|
||||||
std::cout << "Took too much time, not sleeping!\n";
|
std::cout << "Took too much time, not sleeping!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
17
libraries/audio/src/AudioMixer.h
Normal file
17
libraries/audio/src/AudioMixer.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// AudioMixer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 8/22/13.
|
||||||
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__AudioMixer__
|
||||||
|
#define __hifi__AudioMixer__
|
||||||
|
|
||||||
|
class AudioMixer {
|
||||||
|
public:
|
||||||
|
static void run();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__AudioMixer__) */
|
|
@ -9,7 +9,7 @@
|
||||||
#ifndef __hifi__InjectedAudioRingBuffer__
|
#ifndef __hifi__InjectedAudioRingBuffer__
|
||||||
#define __hifi__InjectedAudioRingBuffer__
|
#define __hifi__InjectedAudioRingBuffer__
|
||||||
|
|
||||||
#include <AudioInjector.h>
|
#include "AudioInjector.h"
|
||||||
|
|
||||||
#include "PositionalAudioRingBuffer.h"
|
#include "PositionalAudioRingBuffer.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
#include <AudioRingBuffer.h>
|
#include "AudioRingBuffer.h"
|
||||||
|
|
||||||
class PositionalAudioRingBuffer : public AudioRingBuffer {
|
class PositionalAudioRingBuffer : public AudioRingBuffer {
|
||||||
public:
|
public:
|
|
@ -1,40 +1,22 @@
|
||||||
//
|
//
|
||||||
// main.cpp
|
// AvatarMixer.cpp
|
||||||
// Avatar Mixer
|
// hifi
|
||||||
//
|
//
|
||||||
// Created by Leonardo Murillo on 03/25/13.
|
// Created by Stephen Birarda on 9/5/13.
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Original avatar-mixer main created by Leonardo Murillo on 03/25/13.
|
||||||
//
|
//
|
||||||
// The avatar mixer receives head, hand and positional data from all connected
|
// The avatar mixer receives head, hand and positional data from all connected
|
||||||
// nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms.
|
// nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms.
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <SharedUtil.h>
|
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <NodeTypes.h>
|
#include <SharedUtil.h>
|
||||||
#include <StdDev.h>
|
|
||||||
#include <UDPSocket.h>
|
|
||||||
|
|
||||||
#include "AvatarData.h"
|
#include "AvatarData.h"
|
||||||
|
|
||||||
const int AVATAR_LISTEN_PORT = 55444;
|
#include "AvatarMixer.h"
|
||||||
|
|
||||||
unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) {
|
unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) {
|
||||||
currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID());
|
currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID());
|
||||||
|
@ -98,17 +80,9 @@ void broadcastAvatarData(NodeList* nodeList, sockaddr* nodeAddress) {
|
||||||
nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket);
|
nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
void AvatarMixer::run() {
|
||||||
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
|
nodeList->setOwnerType(NODE_TYPE_AVATAR_MIXER);
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
|
||||||
|
|
||||||
// Handle Local Domain testing with the --local command line
|
|
||||||
const char* local = "--local";
|
|
||||||
if (cmdOptionExists(argc, argv, local)) {
|
|
||||||
printf("Local Domain MODE!\n");
|
|
||||||
nodeList->setDomainIPToLocalhost();
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
|
nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
|
||||||
|
|
||||||
|
@ -119,16 +93,19 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE];
|
unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
|
|
||||||
uint16_t nodeID = 0;
|
uint16_t nodeID = 0;
|
||||||
Node* avatarNode = NULL;
|
Node* avatarNode = NULL;
|
||||||
|
|
||||||
timeval lastDomainServerCheckIn = {};
|
timeval lastDomainServerCheckIn = {};
|
||||||
// we only need to hear back about avatar nodes from the DS
|
// we only need to hear back about avatar nodes from the DS
|
||||||
NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AGENT, 1);
|
nodeList->setNodeTypesOfInterest(&NODE_TYPE_AGENT, 1);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
|
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
|
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
|
||||||
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
|
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
|
||||||
gettimeofday(&lastDomainServerCheckIn, NULL);
|
gettimeofday(&lastDomainServerCheckIn, NULL);
|
||||||
|
@ -162,9 +139,6 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_DOMAIN:
|
|
||||||
// ignore the DS packet, for now nodes are added only when they communicate directly with us
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
// hand this off to the NodeList
|
// hand this off to the NodeList
|
||||||
nodeList->processNodeData(nodeAddress, packetData, receivedBytes);
|
nodeList->processNodeData(nodeAddress, packetData, receivedBytes);
|
||||||
|
@ -174,6 +148,4 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeList->stopSilentNodeRemovalThread();
|
nodeList->stopSilentNodeRemovalThread();
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
19
libraries/avatars/src/AvatarMixer.h
Normal file
19
libraries/avatars/src/AvatarMixer.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// AvatarMixer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 9/5/13.
|
||||||
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__AvatarMixer__
|
||||||
|
#define __hifi__AvatarMixer__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class AvatarMixer {
|
||||||
|
public:
|
||||||
|
static void run();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__AvatarMixer__) */
|
138
libraries/shared/src/Assignment.cpp
Normal file
138
libraries/shared/src/Assignment.cpp
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
//
|
||||||
|
// Assignment.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 8/22/13.
|
||||||
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "PacketHeaders.h"
|
||||||
|
|
||||||
|
#include "Assignment.h"
|
||||||
|
|
||||||
|
const char IPv4_ADDRESS_DESIGNATOR = 4;
|
||||||
|
const char IPv6_ADDRESS_DESIGNATOR = 6;
|
||||||
|
|
||||||
|
Assignment::Assignment(Assignment::Direction direction, Assignment::Type type, const char* pool) :
|
||||||
|
_direction(direction),
|
||||||
|
_type(type),
|
||||||
|
_pool(NULL),
|
||||||
|
_domainSocket(NULL)
|
||||||
|
{
|
||||||
|
// set the create time on this assignment
|
||||||
|
gettimeofday(&_time, NULL);
|
||||||
|
|
||||||
|
// copy the pool, if we got one
|
||||||
|
if (pool) {
|
||||||
|
int poolLength = strlen(pool);
|
||||||
|
|
||||||
|
// create the char array and make it large enough for string and null termination
|
||||||
|
_pool = new char[poolLength + sizeof(char)];
|
||||||
|
strcpy(_pool, pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) :
|
||||||
|
_pool(NULL),
|
||||||
|
_domainSocket(NULL)
|
||||||
|
{
|
||||||
|
// set the create time on this assignment
|
||||||
|
gettimeofday(&_time, NULL);
|
||||||
|
|
||||||
|
int numBytesRead = 0;
|
||||||
|
|
||||||
|
if (dataBuffer[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) {
|
||||||
|
_direction = Assignment::Request;
|
||||||
|
} else if (dataBuffer[0] == PACKET_TYPE_CREATE_ASSIGNMENT) {
|
||||||
|
_direction = Assignment::Create;
|
||||||
|
} else if (dataBuffer[0] == PACKET_TYPE_DEPLOY_ASSIGNMENT) {
|
||||||
|
_direction = Assignment::Deploy;
|
||||||
|
}
|
||||||
|
|
||||||
|
numBytesRead += numBytesForPacketHeader(dataBuffer);
|
||||||
|
|
||||||
|
memcpy(&_type, dataBuffer + numBytesRead, sizeof(Assignment::Type));
|
||||||
|
numBytesRead += sizeof(Assignment::Type);
|
||||||
|
|
||||||
|
if (dataBuffer[numBytesRead] != 0) {
|
||||||
|
int poolLength = strlen((const char*) dataBuffer + numBytesRead);
|
||||||
|
_pool = new char[poolLength + sizeof(char)];
|
||||||
|
strcpy(_pool, (char*) dataBuffer + numBytesRead);
|
||||||
|
numBytesRead += poolLength + sizeof(char);
|
||||||
|
} else {
|
||||||
|
numBytesRead += sizeof(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numBytes > numBytesRead) {
|
||||||
|
if (dataBuffer[numBytesRead++] == IPv4_ADDRESS_DESIGNATOR) {
|
||||||
|
// IPv4 address
|
||||||
|
sockaddr_in destinationSocket = {};
|
||||||
|
memcpy(&destinationSocket, dataBuffer + numBytesRead, sizeof(sockaddr_in));
|
||||||
|
destinationSocket.sin_family = AF_INET;
|
||||||
|
setDomainSocket((sockaddr*) &destinationSocket);
|
||||||
|
} else {
|
||||||
|
// IPv6 address
|
||||||
|
sockaddr_in6 destinationSocket = {};
|
||||||
|
memcpy(&destinationSocket, dataBuffer + numBytesRead, sizeof(sockaddr_in6));
|
||||||
|
setDomainSocket((sockaddr*) &destinationSocket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assignment::~Assignment() {
|
||||||
|
delete _domainSocket;
|
||||||
|
delete _pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Assignment::packToBuffer(unsigned char* buffer) {
|
||||||
|
int numPackedBytes = 0;
|
||||||
|
|
||||||
|
memcpy(buffer + numPackedBytes, &_type, sizeof(_type));
|
||||||
|
numPackedBytes += sizeof(_type);
|
||||||
|
|
||||||
|
if (_pool) {
|
||||||
|
int poolLength = strlen(_pool);
|
||||||
|
strcpy((char*) buffer + numPackedBytes, _pool);
|
||||||
|
|
||||||
|
numPackedBytes += poolLength + sizeof(char);
|
||||||
|
} else {
|
||||||
|
buffer[numPackedBytes] = '\0';
|
||||||
|
numPackedBytes += sizeof(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_domainSocket) {
|
||||||
|
buffer[numPackedBytes++] = (_domainSocket->sa_family == AF_INET) ? IPv4_ADDRESS_DESIGNATOR : IPv6_ADDRESS_DESIGNATOR;
|
||||||
|
|
||||||
|
int numSocketBytes = (_domainSocket->sa_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
|
||||||
|
|
||||||
|
memcpy(buffer + numPackedBytes, _domainSocket, numSocketBytes);
|
||||||
|
numPackedBytes += numSocketBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numPackedBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assignment::setDomainSocket(const sockaddr* domainSocket) {
|
||||||
|
|
||||||
|
if (_domainSocket) {
|
||||||
|
// delete the old _domainSocket if it exists
|
||||||
|
delete _domainSocket;
|
||||||
|
_domainSocket = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new sockaddr or sockaddr_in depending on what type of address this is
|
||||||
|
if (domainSocket->sa_family == AF_INET) {
|
||||||
|
_domainSocket = (sockaddr*) new sockaddr_in;
|
||||||
|
memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in));
|
||||||
|
} else {
|
||||||
|
_domainSocket = (sockaddr*) new sockaddr_in6;
|
||||||
|
memcpy(_domainSocket, domainSocket, sizeof(sockaddr_in6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const Assignment &assignment) {
|
||||||
|
debug << "T:" << assignment.getType() << "P:" << assignment.getPool();
|
||||||
|
return debug.nospace();
|
||||||
|
}
|
54
libraries/shared/src/Assignment.h
Normal file
54
libraries/shared/src/Assignment.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// Assignment.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 8/22/13.
|
||||||
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__Assignment__
|
||||||
|
#define __hifi__Assignment__
|
||||||
|
|
||||||
|
#include "NodeList.h"
|
||||||
|
|
||||||
|
class Assignment {
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
AudioMixer,
|
||||||
|
AvatarMixer,
|
||||||
|
All
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
Create,
|
||||||
|
Deploy,
|
||||||
|
Request
|
||||||
|
};
|
||||||
|
|
||||||
|
Assignment(Assignment::Direction direction, Assignment::Type type, const char* pool = NULL);
|
||||||
|
Assignment(const unsigned char* dataBuffer, int numBytes);
|
||||||
|
|
||||||
|
~Assignment();
|
||||||
|
|
||||||
|
Assignment::Direction getDirection() const { return _direction; }
|
||||||
|
Assignment::Type getType() const { return _type; }
|
||||||
|
const char* getPool() const { return _pool; }
|
||||||
|
const timeval& getTime() const { return _time; }
|
||||||
|
|
||||||
|
const sockaddr* getDomainSocket() { return _domainSocket; }
|
||||||
|
void setDomainSocket(const sockaddr* domainSocket);
|
||||||
|
|
||||||
|
int packToBuffer(unsigned char* buffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Assignment::Direction _direction;
|
||||||
|
Assignment::Type _type;
|
||||||
|
char* _pool;
|
||||||
|
sockaddr* _domainSocket;
|
||||||
|
timeval _time;
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const Assignment &assignment);
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__Assignment__) */
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
|
#include "Assignment.h"
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
#include "NodeTypes.h"
|
#include "NodeTypes.h"
|
||||||
#include "PacketHeaders.h"
|
#include "PacketHeaders.h"
|
||||||
|
@ -63,7 +64,8 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
|
||||||
_ownerType(newOwnerType),
|
_ownerType(newOwnerType),
|
||||||
_nodeTypesOfInterest(NULL),
|
_nodeTypesOfInterest(NULL),
|
||||||
_ownerID(UNKNOWN_NODE_ID),
|
_ownerID(UNKNOWN_NODE_ID),
|
||||||
_lastNodeID(UNKNOWN_NODE_ID + 1)
|
_lastNodeID(UNKNOWN_NODE_ID + 1),
|
||||||
|
_numNoReplyDomainCheckIns(0)
|
||||||
{
|
{
|
||||||
memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME));
|
memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME));
|
||||||
memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP));
|
memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP));
|
||||||
|
@ -328,9 +330,15 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeSocket.send(_domainIP, DEFAULT_DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
|
_nodeSocket.send(_domainIP, DEFAULT_DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
|
||||||
|
|
||||||
|
// increment the count of un-replied check-ins
|
||||||
|
_numNoReplyDomainCheckIns++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) {
|
int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) {
|
||||||
|
// this is a packet from the domain server, reset the count of un-replied check-ins
|
||||||
|
_numNoReplyDomainCheckIns = 0;
|
||||||
|
|
||||||
int readNodes = 0;
|
int readNodes = 0;
|
||||||
|
|
||||||
char nodeType;
|
char nodeType;
|
||||||
|
@ -366,13 +374,21 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte
|
||||||
return readNodes;
|
return readNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::sendAssignmentRequest() {
|
const char ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io";
|
||||||
const char ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io";
|
const sockaddr_in assignmentServerSocket = socketForHostnameAndHostOrderPort(ASSIGNMENT_SERVER_HOSTNAME,
|
||||||
|
ASSIGNMENT_SERVER_PORT);
|
||||||
|
|
||||||
static sockaddr_in assignmentServerSocket = socketForHostname(ASSIGNMENT_SERVER_HOSTNAME);
|
void NodeList::sendAssignment(Assignment& assignment) {
|
||||||
assignmentServerSocket.sin_port = htons(ASSIGNMENT_SERVER_PORT);
|
unsigned char assignmentPacket[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
_nodeSocket.send((sockaddr*) &assignmentServerSocket, &PACKET_TYPE_REQUEST_ASSIGNMENT, 1);
|
PACKET_TYPE assignmentPacketType = assignment.getDirection() == Assignment::Create
|
||||||
|
? PACKET_TYPE_CREATE_ASSIGNMENT
|
||||||
|
: PACKET_TYPE_REQUEST_ASSIGNMENT;
|
||||||
|
|
||||||
|
int numHeaderBytes = populateTypeAndVersion(assignmentPacket, assignmentPacketType);
|
||||||
|
int numAssignmentBytes = assignment.packToBuffer(assignmentPacket + numHeaderBytes);
|
||||||
|
|
||||||
|
_nodeSocket.send((sockaddr*) &assignmentServerSocket, assignmentPacket, numHeaderBytes + numAssignmentBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId) {
|
Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId) {
|
||||||
|
@ -388,6 +404,11 @@ Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, c
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node == end()) {
|
if (node == end()) {
|
||||||
|
// if we already had this node AND it's a solo type then bust out of here
|
||||||
|
if (soloNodeOfType(nodeType)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// we didn't have this node, so add them
|
// we didn't have this node, so add them
|
||||||
Node* newNode = new Node(publicSocket, localSocket, nodeType, nodeId);
|
Node* newNode = new Node(publicSocket, localSocket, nodeType, nodeId);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ const int MAX_NUM_NODES = 10000;
|
||||||
const int NODES_PER_BUCKET = 100;
|
const int NODES_PER_BUCKET = 100;
|
||||||
|
|
||||||
const int MAX_PACKET_SIZE = 1500;
|
const int MAX_PACKET_SIZE = 1500;
|
||||||
const unsigned short int NODE_SOCKET_LISTEN_PORT = 40103;
|
|
||||||
|
|
||||||
const int NODE_SILENCE_THRESHOLD_USECS = 2 * 1000000;
|
const int NODE_SILENCE_THRESHOLD_USECS = 2 * 1000000;
|
||||||
const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
||||||
|
@ -43,6 +42,9 @@ extern const int DEFAULT_DOMAINSERVER_PORT;
|
||||||
|
|
||||||
const int UNKNOWN_NODE_ID = 0;
|
const int UNKNOWN_NODE_ID = 0;
|
||||||
|
|
||||||
|
const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5;
|
||||||
|
|
||||||
|
class Assignment;
|
||||||
class NodeListIterator;
|
class NodeListIterator;
|
||||||
|
|
||||||
// Callers who want to hook add/kill callbacks should implement this class
|
// Callers who want to hook add/kill callbacks should implement this class
|
||||||
|
@ -55,7 +57,7 @@ public:
|
||||||
|
|
||||||
class NodeList {
|
class NodeList {
|
||||||
public:
|
public:
|
||||||
static NodeList* createInstance(char ownerType, unsigned short int socketListenPort = NODE_SOCKET_LISTEN_PORT);
|
static NodeList* createInstance(char ownerType, unsigned short int socketListenPort = 0);
|
||||||
static NodeList* getInstance();
|
static NodeList* getInstance();
|
||||||
|
|
||||||
typedef NodeListIterator iterator;
|
typedef NodeListIterator iterator;
|
||||||
|
@ -88,6 +90,8 @@ public:
|
||||||
int size() { return _numNodes; }
|
int size() { return _numNodes; }
|
||||||
int getNumAliveNodes() const;
|
int getNumAliveNodes() const;
|
||||||
|
|
||||||
|
int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; }
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
|
void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
|
||||||
|
@ -95,7 +99,7 @@ public:
|
||||||
void sendDomainServerCheckIn();
|
void sendDomainServerCheckIn();
|
||||||
int processDomainServerList(unsigned char *packetData, size_t dataBytes);
|
int processDomainServerList(unsigned char *packetData, size_t dataBytes);
|
||||||
|
|
||||||
void sendAssignmentRequest();
|
void sendAssignment(Assignment& assignment);
|
||||||
|
|
||||||
Node* nodeWithAddress(sockaddr *senderAddress);
|
Node* nodeWithAddress(sockaddr *senderAddress);
|
||||||
Node* nodeWithID(uint16_t nodeID);
|
Node* nodeWithID(uint16_t nodeID);
|
||||||
|
@ -146,6 +150,7 @@ private:
|
||||||
uint16_t _lastNodeID;
|
uint16_t _lastNodeID;
|
||||||
pthread_t removeSilentNodesThread;
|
pthread_t removeSilentNodesThread;
|
||||||
pthread_t checkInWithDomainServerThread;
|
pthread_t checkInWithDomainServerThread;
|
||||||
|
int _numNoReplyDomainCheckIns;
|
||||||
|
|
||||||
void handlePingReply(sockaddr *nodeAddress);
|
void handlePingReply(sockaddr *nodeAddress);
|
||||||
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
||||||
|
|
|
@ -67,7 +67,7 @@ int numBytesForPacketVersion(const unsigned char* packetVersion) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int numBytesForPacketHeader(unsigned char* packetHeader) {
|
int numBytesForPacketHeader(const unsigned char* packetHeader) {
|
||||||
// int numBytesType = numBytesForPacketType(packetHeader);
|
// int numBytesType = numBytesForPacketType(packetHeader);
|
||||||
// return numBytesType + numBytesForPacketVersion(packetHeader + numBytesType);
|
// return numBytesType + numBytesForPacketVersion(packetHeader + numBytesType);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e';
|
||||||
const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L';
|
const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L';
|
||||||
const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C';
|
const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C';
|
||||||
const PACKET_TYPE PACKET_TYPE_REQUEST_ASSIGNMENT = 'r';
|
const PACKET_TYPE PACKET_TYPE_REQUEST_ASSIGNMENT = 'r';
|
||||||
const PACKET_TYPE PACKET_TYPE_SEND_ASSIGNMENT = 's';
|
const PACKET_TYPE PACKET_TYPE_CREATE_ASSIGNMENT = 's';
|
||||||
|
const PACKET_TYPE PACKET_TYPE_DEPLOY_ASSIGNMENT = 'd';
|
||||||
const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#';
|
const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#';
|
||||||
const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION = 'J';
|
const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION = 'J';
|
||||||
const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION_REQUEST = 'j';
|
const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION_REQUEST = 'j';
|
||||||
|
@ -48,7 +49,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type);
|
||||||
bool packetVersionMatch(unsigned char* packetHeader);
|
bool packetVersionMatch(unsigned char* packetHeader);
|
||||||
|
|
||||||
int populateTypeAndVersion(unsigned char* destinationHeader, PACKET_TYPE type);
|
int populateTypeAndVersion(unsigned char* destinationHeader, PACKET_TYPE type);
|
||||||
int numBytesForPacketHeader(unsigned char* packetHeader);
|
int numBytesForPacketHeader(const unsigned char* packetHeader);
|
||||||
|
|
||||||
const int MAX_PACKET_HEADER_BYTES = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION);
|
const int MAX_PACKET_HEADER_BYTES = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION);
|
||||||
|
|
||||||
|
@ -57,6 +58,6 @@ const int MAX_PACKET_HEADER_BYTES = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION)
|
||||||
#define ADD_SCENE_COMMAND "add scene"
|
#define ADD_SCENE_COMMAND "add scene"
|
||||||
#define TEST_COMMAND "a message"
|
#define TEST_COMMAND "a message"
|
||||||
|
|
||||||
const int ASSIGNMENT_SERVER_PORT = 7007;
|
const unsigned short ASSIGNMENT_SERVER_PORT = 7007;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "PacketHeaders.h"
|
#include "PacketHeaders.h"
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
uint64_t usecTimestamp(timeval *time) {
|
uint64_t usecTimestamp(const timeval *time) {
|
||||||
return (time->tv_sec * 1000000 + time->tv_usec);
|
return (time->tv_sec * 1000000 + time->tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ static const float DECIMETER = 0.1f;
|
||||||
static const float CENTIMETER = 0.01f;
|
static const float CENTIMETER = 0.01f;
|
||||||
static const float MILLIIMETER = 0.001f;
|
static const float MILLIIMETER = 0.001f;
|
||||||
|
|
||||||
uint64_t usecTimestamp(timeval *time);
|
uint64_t usecTimestamp(const timeval *time);
|
||||||
uint64_t usecTimestampNow();
|
uint64_t usecTimestampNow();
|
||||||
|
|
||||||
float randFloat();
|
float randFloat();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -118,14 +119,18 @@ unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_in socketForHostname(const char* hostname) {
|
sockaddr_in socketForHostnameAndHostOrderPort(const char* hostname, unsigned short port) {
|
||||||
struct hostent* pHostInfo;
|
struct hostent* pHostInfo;
|
||||||
sockaddr_in newSocket;
|
sockaddr_in newSocket = {};
|
||||||
|
|
||||||
if ((pHostInfo = gethostbyname(hostname))) {
|
if ((pHostInfo = gethostbyname(hostname))) {
|
||||||
memcpy(&newSocket.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
memcpy(&newSocket.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port != 0) {
|
||||||
|
newSocket.sin_port = htons(port);
|
||||||
|
}
|
||||||
|
|
||||||
return newSocket;
|
return newSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +167,8 @@ UDPSocket::UDPSocket(unsigned short int listeningPort) :
|
||||||
_listeningPort = ntohs(bind_address.sin_port);
|
_listeningPort = ntohs(bind_address.sin_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set timeout on socket recieve to 0.5 seconds
|
const int DEFAULT_BLOCKING_SOCKET_TIMEOUT_USECS = 0.5 * 1000000;
|
||||||
struct timeval tv;
|
setBlockingReceiveTimeoutInUsecs(DEFAULT_BLOCKING_SOCKET_TIMEOUT_USECS);
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 500000;
|
|
||||||
setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv);
|
|
||||||
|
|
||||||
qDebug("Created UDP socket listening on port %hu.\n", _listeningPort);
|
qDebug("Created UDP socket listening on port %hu.\n", _listeningPort);
|
||||||
}
|
}
|
||||||
|
@ -223,6 +225,11 @@ void UDPSocket::setBlocking(bool blocking) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UDPSocket::setBlockingReceiveTimeoutInUsecs(int timeoutUsecs) {
|
||||||
|
struct timeval tv = {timeoutUsecs / 1000000, timeoutUsecs % 1000000};
|
||||||
|
setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
|
||||||
|
}
|
||||||
|
|
||||||
// Receive data on this socket with retrieving address of sender
|
// Receive data on this socket with retrieving address of sender
|
||||||
bool UDPSocket::receive(void* receivedData, ssize_t* receivedBytes) const {
|
bool UDPSocket::receive(void* receivedData, ssize_t* receivedBytes) const {
|
||||||
return receive((sockaddr*) &senderAddress, receivedData, receivedBytes);
|
return receive((sockaddr*) &senderAddress, receivedData, receivedBytes);
|
||||||
|
|
|
@ -22,12 +22,17 @@ class UDPSocket {
|
||||||
public:
|
public:
|
||||||
UDPSocket(unsigned short int listeningPort);
|
UDPSocket(unsigned short int listeningPort);
|
||||||
~UDPSocket();
|
~UDPSocket();
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
unsigned short int getListeningPort() const { return _listeningPort; }
|
unsigned short int getListeningPort() const { return _listeningPort; }
|
||||||
|
|
||||||
void setBlocking(bool blocking);
|
void setBlocking(bool blocking);
|
||||||
bool isBlocking() const { return blocking; }
|
bool isBlocking() const { return blocking; }
|
||||||
|
void setBlockingReceiveTimeoutInUsecs(int timeoutUsecs);
|
||||||
|
|
||||||
int send(sockaddr* destAddress, const void* data, size_t byteLength) const;
|
int send(sockaddr* destAddress, const void* data, size_t byteLength) const;
|
||||||
int send(char* destAddress, int destPort, const void* data, size_t byteLength) const;
|
int send(char* destAddress, int destPort, const void* data, size_t byteLength) const;
|
||||||
|
|
||||||
bool receive(void* receivedData, ssize_t* receivedBytes) const;
|
bool receive(void* receivedData, ssize_t* receivedBytes) const;
|
||||||
bool receive(sockaddr* recvAddress, void* receivedData, ssize_t* receivedBytes) const;
|
bool receive(sockaddr* recvAddress, void* receivedData, ssize_t* receivedBytes) const;
|
||||||
private:
|
private:
|
||||||
|
@ -42,6 +47,6 @@ int packSocket(unsigned char* packStore, sockaddr* socketToPack);
|
||||||
int unpackSocket(unsigned char* packedData, sockaddr* unpackDestSocket);
|
int unpackSocket(unsigned char* packedData, sockaddr* unpackDestSocket);
|
||||||
int getLocalAddress();
|
int getLocalAddress();
|
||||||
unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket);
|
unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket);
|
||||||
sockaddr_in socketForHostname(const char* hostname);
|
sockaddr_in socketForHostnameAndHostOrderPort(const char* hostname, unsigned short port = 0);
|
||||||
|
|
||||||
#endif /* defined(__interface__UDPSocket__) */
|
#endif /* defined(__interface__UDPSocket__) */
|
||||||
|
|
Loading…
Reference in a new issue