mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 15:50:37 +02:00
Merge pull request #21 from birarda/19170B
Leo's Avatar Mixer + birarda's AgentData updates
This commit is contained in:
commit
002d35932e
17 changed files with 503 additions and 140 deletions
|
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.8)
|
||||||
project(hifi)
|
project(hifi)
|
||||||
|
|
||||||
add_subdirectory(space)
|
add_subdirectory(space)
|
||||||
|
add_subdirectory(avatar)
|
||||||
add_subdirectory(domain)
|
add_subdirectory(domain)
|
||||||
add_subdirectory(mixer)
|
add_subdirectory(mixer)
|
||||||
add_subdirectory(voxel)
|
add_subdirectory(voxel)
|
||||||
|
|
17
avatar/CMakeLists.txt
Normal file
17
avatar/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
project(avatar)
|
||||||
|
|
||||||
|
# grab the implemenation and header files
|
||||||
|
file(GLOB AVATAR_SRCS src/*.cpp src/*.h)
|
||||||
|
|
||||||
|
# add the executable
|
||||||
|
add_executable(avatar ${AVATAR_SRCS})
|
||||||
|
|
||||||
|
# link the shared hifi library
|
||||||
|
include(../LinkHifiShared.cmake)
|
||||||
|
link_hifi_shared_library(avatar)
|
||||||
|
|
||||||
|
# link the threads library
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(avatar ${CMAKE_THREAD_LIBS_INIT})
|
116
avatar/src/AvatarAgentData.cpp
Normal file
116
avatar/src/AvatarAgentData.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
//
|
||||||
|
// AvatarAgentData.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 4/9/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AvatarAgentData.h"
|
||||||
|
|
||||||
|
AvatarAgentData::AvatarAgentData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarAgentData::~AvatarAgentData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarAgentData* AvatarAgentData::clone() const {
|
||||||
|
return new AvatarAgentData(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::parseData(void *data, int size) {
|
||||||
|
char* packetData = (char *)data + 1;
|
||||||
|
|
||||||
|
// Extract data from packet
|
||||||
|
sscanf(packetData,
|
||||||
|
PACKET_FORMAT,
|
||||||
|
&_pitch,
|
||||||
|
&_yaw,
|
||||||
|
&_roll,
|
||||||
|
&_headPositionX,
|
||||||
|
&_headPositionY,
|
||||||
|
&_headPositionZ,
|
||||||
|
&_loudness,
|
||||||
|
&_averageLoudness,
|
||||||
|
&_handPositionX,
|
||||||
|
&_handPositionY,
|
||||||
|
&_handPositionZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getPitch() {
|
||||||
|
return _pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getYaw() {
|
||||||
|
return _yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getRoll() {
|
||||||
|
return _roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHeadPositionX() {
|
||||||
|
return _headPositionX;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHeadPositionY() {
|
||||||
|
return _headPositionY;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHeadPositionZ() {
|
||||||
|
return _headPositionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getLoudness() {
|
||||||
|
return _loudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getAverageLoudness() {
|
||||||
|
return _averageLoudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHandPositionX() {
|
||||||
|
return _handPositionX;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHandPositionY() {
|
||||||
|
return _handPositionY;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AvatarAgentData::getHandPositionZ() {
|
||||||
|
return _handPositionZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setPitch(float pitch) {
|
||||||
|
_pitch = pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setYaw(float yaw) {
|
||||||
|
_yaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setRoll(float roll) {
|
||||||
|
_roll = roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setHeadPosition(float x, float y, float z) {
|
||||||
|
_headPositionX = x;
|
||||||
|
_headPositionY = y;
|
||||||
|
_headPositionZ = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setLoudness(float loudness) {
|
||||||
|
_loudness = loudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setAverageLoudness(float averageLoudness) {
|
||||||
|
_averageLoudness = averageLoudness;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarAgentData::setHandPosition(float x, float y, float z) {
|
||||||
|
_handPositionX = x;
|
||||||
|
_handPositionY = y;
|
||||||
|
_handPositionZ = z;
|
||||||
|
}
|
58
avatar/src/AvatarAgentData.h
Normal file
58
avatar/src/AvatarAgentData.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// AvatarAgentData.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 4/9/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__AvatarAgentData__
|
||||||
|
#define __hifi__AvatarAgentData__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <AgentData.h>
|
||||||
|
|
||||||
|
const char PACKET_FORMAT[] = "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f";
|
||||||
|
|
||||||
|
class AvatarAgentData : public AgentData {
|
||||||
|
public:
|
||||||
|
AvatarAgentData();
|
||||||
|
~AvatarAgentData();
|
||||||
|
|
||||||
|
void parseData(void *data, int size);
|
||||||
|
AvatarAgentData* clone() const;
|
||||||
|
|
||||||
|
float getPitch();
|
||||||
|
void setPitch(float pitch);
|
||||||
|
float getYaw();
|
||||||
|
void setYaw(float yaw);
|
||||||
|
float getRoll();
|
||||||
|
void setRoll(float roll);
|
||||||
|
float getHeadPositionX();
|
||||||
|
float getHeadPositionY();
|
||||||
|
float getHeadPositionZ();
|
||||||
|
void setHeadPosition(float x, float y, float z);
|
||||||
|
float getLoudness();
|
||||||
|
void setLoudness(float loudness);
|
||||||
|
float getAverageLoudness();
|
||||||
|
void setAverageLoudness(float averageLoudness);
|
||||||
|
float getHandPositionX();
|
||||||
|
float getHandPositionY();
|
||||||
|
float getHandPositionZ();
|
||||||
|
void setHandPosition(float x, float y, float z);
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _pitch;
|
||||||
|
float _yaw;
|
||||||
|
float _roll;
|
||||||
|
float _headPositionX;
|
||||||
|
float _headPositionY;
|
||||||
|
float _headPositionZ;
|
||||||
|
float _loudness;
|
||||||
|
float _averageLoudness;
|
||||||
|
float _handPositionX;
|
||||||
|
float _handPositionY;
|
||||||
|
float _handPositionZ;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__AvatarAgentData__) */
|
131
avatar/src/main.cpp
Normal file
131
avatar/src/main.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
//
|
||||||
|
// main.cpp
|
||||||
|
// Avatar Mixer
|
||||||
|
//
|
||||||
|
// Created by Leonardo Murillo on 03/25/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// The avatar mixer receives head, hand and positional data from all connected
|
||||||
|
// agents, 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 <AgentList.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <AgentTypes.h>
|
||||||
|
#include <StdDev.h>
|
||||||
|
#include <UDPSocket.h>
|
||||||
|
|
||||||
|
#include "AvatarAgentData.h"
|
||||||
|
|
||||||
|
const int AVATAR_LISTEN_PORT = 55444;
|
||||||
|
const unsigned short BROADCAST_INTERVAL_USECS = 20 * 1000 * 1000;
|
||||||
|
|
||||||
|
AgentList agentList(AGENT_TYPE_AVATAR_MIXER, AVATAR_LISTEN_PORT);
|
||||||
|
|
||||||
|
unsigned char *addAgentToBroadcastPacket(unsigned char *currentPosition, Agent *agentToAdd) {
|
||||||
|
currentPosition += packSocket(currentPosition, agentToAdd->getPublicSocket());
|
||||||
|
|
||||||
|
AvatarAgentData *agentData = (AvatarAgentData *)agentToAdd->getLinkedData();
|
||||||
|
|
||||||
|
int bytesWritten = sprintf((char *)currentPosition,
|
||||||
|
PACKET_FORMAT,
|
||||||
|
agentData->getPitch(),
|
||||||
|
agentData->getYaw(),
|
||||||
|
agentData->getRoll(),
|
||||||
|
agentData->getHeadPositionX(),
|
||||||
|
agentData->getHeadPositionY(),
|
||||||
|
agentData->getHeadPositionZ(),
|
||||||
|
agentData->getLoudness(),
|
||||||
|
agentData->getAverageLoudness(),
|
||||||
|
agentData->getHandPositionX(),
|
||||||
|
agentData->getHandPositionY(),
|
||||||
|
agentData->getHandPositionZ());
|
||||||
|
|
||||||
|
currentPosition += bytesWritten;
|
||||||
|
return currentPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void attachAvatarDataToAgent(Agent *newAgent) {
|
||||||
|
if (newAgent->getLinkedData() == NULL) {
|
||||||
|
newAgent->setLinkedData(new AvatarAgentData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
|
agentList.linkedDataCreateCallback = attachAvatarDataToAgent;
|
||||||
|
|
||||||
|
agentList.startDomainServerCheckInThread();
|
||||||
|
agentList.startSilentAgentRemovalThread();
|
||||||
|
agentList.startPingUnknownAgentsThread();
|
||||||
|
|
||||||
|
sockaddr *agentAddress = new sockaddr;
|
||||||
|
char *packetData = new char[MAX_PACKET_SIZE];
|
||||||
|
ssize_t receivedBytes = 0;
|
||||||
|
|
||||||
|
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
||||||
|
*broadcastPacket = PACKET_HEADER_AVATAR_SERVER;
|
||||||
|
|
||||||
|
unsigned char* currentBufferPosition = NULL;
|
||||||
|
int agentIndex = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (agentList.getAgentSocket().receive(agentAddress, packetData, &receivedBytes)) {
|
||||||
|
switch (packetData[0]) {
|
||||||
|
case PACKET_HEADER_HEAD_DATA:
|
||||||
|
// this is positional data from an agent
|
||||||
|
agentList.updateAgentWithData(agentAddress, (void *)packetData, receivedBytes);
|
||||||
|
|
||||||
|
currentBufferPosition = broadcastPacket + 1;
|
||||||
|
agentIndex = 0;
|
||||||
|
|
||||||
|
// send back a packet with other active agent data to this agent
|
||||||
|
for (std::vector<Agent>::iterator avatarAgent = agentList.getAgents().begin();
|
||||||
|
avatarAgent != agentList.getAgents().end();
|
||||||
|
avatarAgent++) {
|
||||||
|
if (avatarAgent->getLinkedData() != NULL
|
||||||
|
&& agentIndex != agentList.indexOfMatchingAgent(agentAddress)) {
|
||||||
|
currentBufferPosition = addAgentToBroadcastPacket(currentBufferPosition, &*avatarAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
agentIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
agentList.getAgentSocket().send(agentAddress,
|
||||||
|
broadcastPacket,
|
||||||
|
currentBufferPosition - broadcastPacket);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// hand this off to the AgentList
|
||||||
|
agentList.processAgentData(agentAddress, (void *)packetData, receivedBytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
agentList.stopDomainServerCheckInThread();
|
||||||
|
agentList.stopSilentAgentRemovalThread();
|
||||||
|
agentList.stopPingUnknownAgentsThread();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -127,9 +127,12 @@ int main(int argc, const char * argv[])
|
||||||
currentBufferPos = broadcastPacket + 1;
|
currentBufferPos = broadcastPacket + 1;
|
||||||
startPointer = currentBufferPos;
|
startPointer = currentBufferPos;
|
||||||
|
|
||||||
for(std::vector<Agent>::iterator agent = agentList.getAgents().begin(); agent != agentList.getAgents().end(); agent++) {
|
for(std::vector<Agent>::iterator agent = agentList.getAgents().begin();
|
||||||
|
agent != agentList.getAgents().end();
|
||||||
|
agent++) {
|
||||||
|
|
||||||
if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
if (DEBUG_TO_SELF ||
|
||||||
|
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||||
if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->getType()) == NULL) {
|
if (strchr(SOLO_AGENT_TYPES_STRING, (int) agent->getType()) == NULL) {
|
||||||
// this is an agent of which there can be multiple, just add them to the packet
|
// this is an agent of which there can be multiple, just add them to the packet
|
||||||
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent));
|
currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent));
|
||||||
|
@ -155,7 +158,9 @@ int main(int argc, const char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) {
|
if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) {
|
||||||
agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress, broadcastPacket, packetBytesWithoutLeadingChar + 1);
|
agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress,
|
||||||
|
broadcastPacket,
|
||||||
|
packetBytesWithoutLeadingChar + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,7 @@ const float DEFAULT_Y = -1.5;
|
||||||
const float DEFAULT_Z = 2.0;
|
const float DEFAULT_Z = 2.0;
|
||||||
const float DEFAULT_TRANSMITTER_HZ = 60.0;
|
const float DEFAULT_TRANSMITTER_HZ = 60.0;
|
||||||
|
|
||||||
Hand::Hand(glm::vec3 initcolor)
|
Hand::Hand(glm::vec3 initcolor) {
|
||||||
{
|
|
||||||
color = initcolor;
|
color = initcolor;
|
||||||
reset();
|
reset();
|
||||||
noise = 0.0; //0.2;
|
noise = 0.0; //0.2;
|
||||||
|
@ -51,8 +50,7 @@ Hand::Hand(const Hand &otherHand) {
|
||||||
renderPointer = otherHand.renderPointer;
|
renderPointer = otherHand.renderPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::reset()
|
void Hand::reset() {
|
||||||
{
|
|
||||||
position.x = DEFAULT_X;
|
position.x = DEFAULT_X;
|
||||||
position.y = DEFAULT_Y;
|
position.y = DEFAULT_Y;
|
||||||
position.z = DEFAULT_Z;
|
position.z = DEFAULT_Z;
|
||||||
|
@ -64,8 +62,7 @@ void Hand::reset()
|
||||||
transmitterHz = DEFAULT_TRANSMITTER_HZ;
|
transmitterHz = DEFAULT_TRANSMITTER_HZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::render(int isMine)
|
void Hand::render(int isMine) {
|
||||||
{
|
|
||||||
const float POINTER_LENGTH = 20.0;
|
const float POINTER_LENGTH = 20.0;
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
|
@ -89,22 +86,7 @@ void Hand::render(int isMine)
|
||||||
glutSolidCube(1.0);
|
glutSolidCube(1.0);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
if (1) {
|
|
||||||
// Render debug info from the transmitter
|
|
||||||
/*
|
|
||||||
glPushMatrix();
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
//gluOrtho2D(0, WIDTH, HEIGHT, 0);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glDisable(GL_LIGHTING);
|
|
||||||
glPopMatrix();
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::addAngularVelocity (float pRate, float yRate, float rRate) {
|
void Hand::addAngularVelocity (float pRate, float yRate, float rRate) {
|
||||||
|
@ -159,8 +141,7 @@ void Hand::processTransmitterData(char *packetData, int numBytes) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::simulate(float deltaTime)
|
void Hand::simulate(float deltaTime) {
|
||||||
{
|
|
||||||
const float ANGULAR_SPRING_CONSTANT = 0.25;
|
const float ANGULAR_SPRING_CONSTANT = 0.25;
|
||||||
const float ANGULAR_DAMPING_COEFFICIENT = 5*2.0f*powf(ANGULAR_SPRING_CONSTANT,0.5f);
|
const float ANGULAR_DAMPING_COEFFICIENT = 5*2.0f*powf(ANGULAR_SPRING_CONSTANT,0.5f);
|
||||||
const float LINEAR_SPRING_CONSTANT = 100;
|
const float LINEAR_SPRING_CONSTANT = 100;
|
||||||
|
|
|
@ -200,21 +200,6 @@ timeval timerStart, timerEnd;
|
||||||
timeval lastTimeIdle;
|
timeval lastTimeIdle;
|
||||||
double elapsedTime;
|
double elapsedTime;
|
||||||
|
|
||||||
#ifdef MARKER_CAPTURE
|
|
||||||
|
|
||||||
/*** Marker Capture ***/
|
|
||||||
#define MARKER_CAPTURE_INTERVAL 1
|
|
||||||
MarkerCapture marker_capturer(CV_CAP_ANY); // Create a new marker capturer, attached to any valid camera.
|
|
||||||
MarkerAcquisitionView marker_acq_view(&marker_capturer);
|
|
||||||
bool marker_capture_enabled = true;
|
|
||||||
bool marker_capture_display = true;
|
|
||||||
IplImage* marker_capture_frame;
|
|
||||||
IplImage* marker_capture_blob_frame;
|
|
||||||
pthread_mutex_t frame_lock;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Every second, check the frame rates and other stuff
|
// Every second, check the frame rates and other stuff
|
||||||
void Timer(int extra)
|
void Timer(int extra)
|
||||||
{
|
{
|
||||||
|
@ -229,9 +214,6 @@ void Timer(int extra)
|
||||||
glutTimerFunc(1000,Timer,0);
|
glutTimerFunc(1000,Timer,0);
|
||||||
gettimeofday(&timerStart, NULL);
|
gettimeofday(&timerStart, NULL);
|
||||||
|
|
||||||
// Ping the agents we can see
|
|
||||||
agentList.pingAgents();
|
|
||||||
|
|
||||||
// if we haven't detected gyros, check for them now
|
// if we haven't detected gyros, check for them now
|
||||||
if (!serialPort.active) {
|
if (!serialPort.active) {
|
||||||
serialPort.pair();
|
serialPort.pair();
|
||||||
|
@ -478,11 +460,12 @@ void simulateHead(float frametime)
|
||||||
myAvatar.setAverageLoudness(averageLoudness);
|
myAvatar.setAverageLoudness(averageLoudness);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Send my streaming head data to agents that are nearby and need to see it!
|
// Send my stream of head/hand data to the avatar mixer and voxel server
|
||||||
const int MAX_BROADCAST_STRING = 200;
|
char broadcastString[200];
|
||||||
char broadcast_string[MAX_BROADCAST_STRING];
|
int broadcastBytes = myAvatar.getBroadcastData(broadcastString);
|
||||||
int broadcast_bytes = myAvatar.getBroadcastData(broadcast_string);
|
const char broadcastReceivers[2] = {AGENT_TYPE_VOXEL, AGENT_TYPE_AVATAR_MIXER};
|
||||||
agentList.broadcastToAgents(broadcast_string, broadcast_bytes,AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE);
|
|
||||||
|
agentList.broadcastToAgents(broadcastString, broadcastBytes, broadcastReceivers, 2);
|
||||||
|
|
||||||
// If I'm in paint mode, send a voxel out to VOXEL server agents.
|
// If I'm in paint mode, send a voxel out to VOXEL server agents.
|
||||||
if (::paintOn) {
|
if (::paintOn) {
|
||||||
|
@ -501,8 +484,8 @@ void simulateHead(float frametime)
|
||||||
::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 &&
|
::paintingVoxel.y >= 0.0 && ::paintingVoxel.y <= 1.0 &&
|
||||||
::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) {
|
::paintingVoxel.z >= 0.0 && ::paintingVoxel.z <= 1.0) {
|
||||||
|
|
||||||
if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL,0,1,&::paintingVoxel,bufferOut,sizeOut)){
|
if (createVoxelEditMessage(PACKET_HEADER_SET_VOXEL, 0, 1, &::paintingVoxel, bufferOut, sizeOut)){
|
||||||
agentList.broadcastToAgents((char*)bufferOut, sizeOut,AgentList::AGENTS_OF_TYPE_VOXEL);
|
agentList.broadcastToAgents((char*)bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
|
||||||
delete bufferOut;
|
delete bufferOut;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1023,15 +1006,15 @@ void testPointToVoxel()
|
||||||
void sendVoxelServerEraseAll() {
|
void sendVoxelServerEraseAll() {
|
||||||
char message[100];
|
char message[100];
|
||||||
sprintf(message,"%c%s",'Z',"erase all");
|
sprintf(message,"%c%s",'Z',"erase all");
|
||||||
int messageSize = strlen(message)+1;
|
int messageSize = strlen(message) + 1;
|
||||||
::agentList.broadcastToAgents(message, messageSize,AgentList::AGENTS_OF_TYPE_VOXEL);
|
::agentList.broadcastToAgents(message, messageSize, &AGENT_TYPE_VOXEL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendVoxelServerAddScene() {
|
void sendVoxelServerAddScene() {
|
||||||
char message[100];
|
char message[100];
|
||||||
sprintf(message,"%c%s",'Z',"add scene");
|
sprintf(message,"%c%s",'Z',"add scene");
|
||||||
int messageSize = strlen(message)+1;
|
int messageSize = strlen(message) + 1;
|
||||||
::agentList.broadcastToAgents(message, messageSize,AgentList::AGENTS_OF_TYPE_VOXEL);
|
::agentList.broadcastToAgents(message, messageSize, &AGENT_TYPE_VOXEL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shiftPaintingColor()
|
void shiftPaintingColor()
|
||||||
|
@ -1207,9 +1190,7 @@ void key(unsigned char k, int x, int y)
|
||||||
if (k == '.') addRandomSphere(wantColorRandomizer);
|
if (k == '.') addRandomSphere(wantColorRandomizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Receive packets from other agents/servers and decide what to do with them!
|
// Receive packets from other agents/servers and decide what to do with them!
|
||||||
//
|
|
||||||
void *networkReceive(void *args)
|
void *networkReceive(void *args)
|
||||||
{
|
{
|
||||||
sockaddr senderAddress;
|
sockaddr senderAddress;
|
||||||
|
@ -1221,19 +1202,26 @@ void *networkReceive(void *args)
|
||||||
packetCount++;
|
packetCount++;
|
||||||
bytesCount += bytesReceived;
|
bytesCount += bytesReceived;
|
||||||
|
|
||||||
if (incomingPacket[0] == PACKET_HEADER_TRANSMITTER_DATA) {
|
switch (incomingPacket[0]) {
|
||||||
// Pass everything but transmitter data to the agent list
|
case PACKET_HEADER_TRANSMITTER_DATA:
|
||||||
myAvatar.hand->processTransmitterData(incomingPacket, bytesReceived);
|
myAvatar.hand->processTransmitterData(incomingPacket, bytesReceived);
|
||||||
} else if (incomingPacket[0] == PACKET_HEADER_VOXEL_DATA ||
|
break;
|
||||||
incomingPacket[0] == PACKET_HEADER_Z_COMMAND ||
|
case PACKET_HEADER_VOXEL_DATA:
|
||||||
incomingPacket[0] == PACKET_HEADER_ERASE_VOXEL) {
|
case PACKET_HEADER_Z_COMMAND:
|
||||||
voxels.parseData(incomingPacket, bytesReceived);
|
case PACKET_HEADER_ERASE_VOXEL:
|
||||||
} else {
|
voxels.parseData(incomingPacket, bytesReceived);
|
||||||
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
break;
|
||||||
|
case PACKET_HEADER_HEAD_DATA:
|
||||||
|
agentList.processBulkAgentData(&senderAddress, incomingPacket, bytesReceived, sizeof(float) * 11);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete[] incomingPacket;
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1401,9 +1389,10 @@ int main(int argc, const char * argv[])
|
||||||
int wsaresult = WSAStartup( MAKEWORD(2,2), &WsaData );
|
int wsaresult = WSAStartup( MAKEWORD(2,2), &WsaData );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// start the thread which checks for silent agents
|
// start the agentList threads
|
||||||
agentList.startSilentAgentRemovalThread();
|
agentList.startSilentAgentRemovalThread();
|
||||||
agentList.startDomainServerCheckInThread();
|
agentList.startDomainServerCheckInThread();
|
||||||
|
agentList.startPingUnknownAgentsThread();
|
||||||
|
|
||||||
glutInit(&argc, (char**)argv);
|
glutInit(&argc, (char**)argv);
|
||||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace starfield {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Stars.cpp: read %d stars, rendering %ld\n",
|
fprintf(stderr, "Stars.cpp: read %d stars, rendering %ld\n",
|
||||||
_valRecordsRead, _ptrVertices->size());
|
_valRecordsRead, _ptrVertices->size());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace starfield {
|
||||||
InputVertex(float azimuth, float altitude, unsigned color) {
|
InputVertex(float azimuth, float altitude, unsigned color) {
|
||||||
|
|
||||||
_valColor = (color >> 16 & 0xffu) | (color & 0xff00u) |
|
_valColor = (color >> 16 & 0xffu) | (color & 0xff00u) |
|
||||||
(color << 16 & 0xff0000u) | 0xff000000u;
|
(color << 16 & 0xff0000u) | 0xff000000u;
|
||||||
|
|
||||||
azimuth = angleConvert<Degrees,Radians>(azimuth);
|
azimuth = angleConvert<Degrees,Radians>(azimuth);
|
||||||
altitude = angleConvert<Degrees,Radians>(altitude);
|
altitude = angleConvert<Degrees,Radians>(altitude);
|
||||||
|
|
|
@ -61,7 +61,7 @@ const int AGENT_LOOPBACK_MODIFIER = 307;
|
||||||
|
|
||||||
const int LOOPBACK_SANITY_CHECK = 0;
|
const int LOOPBACK_SANITY_CHECK = 0;
|
||||||
|
|
||||||
AgentList agentList(AGENT_TYPE_MIXER, MIXER_LISTEN_PORT);
|
AgentList agentList(AGENT_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
|
||||||
StDev stdev;
|
StDev stdev;
|
||||||
|
|
||||||
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ Agent::Agent(const Agent &otherAgent) {
|
||||||
linkedData = NULL;
|
linkedData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMutex = otherAgent.deleteMutex;
|
pthread_mutex_init(&deleteMutex, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Agent& Agent::operator=(Agent otherAgent) {
|
Agent& Agent::operator=(Agent otherAgent) {
|
||||||
|
@ -83,7 +83,6 @@ void Agent::swap(Agent &first, Agent &second) {
|
||||||
swap(first.type, second.type);
|
swap(first.type, second.type);
|
||||||
swap(first.linkedData, second.linkedData);
|
swap(first.linkedData, second.linkedData);
|
||||||
swap(first.agentId, second.agentId);
|
swap(first.agentId, second.agentId);
|
||||||
swap(first.deleteMutex, second.deleteMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Agent::~Agent() {
|
Agent::~Agent() {
|
||||||
|
@ -100,7 +99,8 @@ char Agent::getType() const {
|
||||||
const char* AGENT_TYPE_NAME_DOMAIN = "Domain";
|
const char* AGENT_TYPE_NAME_DOMAIN = "Domain";
|
||||||
const char* AGENT_TYPE_NAME_VOXEL = "Voxel Server";
|
const char* AGENT_TYPE_NAME_VOXEL = "Voxel Server";
|
||||||
const char* AGENT_TYPE_NAME_INTERFACE = "Client Interface";
|
const char* AGENT_TYPE_NAME_INTERFACE = "Client Interface";
|
||||||
const char* AGENT_TYPE_NAME_MIXER = "Audio Mixer";
|
const char* AGENT_TYPE_NAME_AUDIO_MIXER = "Audio Mixer";
|
||||||
|
const char* AGENT_TYPE_NAME_AVATAR_MIXER = "Avatar Mixer";
|
||||||
const char* AGENT_TYPE_NAME_UNKNOWN = "Unknown";
|
const char* AGENT_TYPE_NAME_UNKNOWN = "Unknown";
|
||||||
|
|
||||||
const char* Agent::getTypeName() const {
|
const char* Agent::getTypeName() const {
|
||||||
|
@ -115,9 +115,12 @@ const char* Agent::getTypeName() const {
|
||||||
case AGENT_TYPE_INTERFACE:
|
case AGENT_TYPE_INTERFACE:
|
||||||
name = AGENT_TYPE_NAME_INTERFACE;
|
name = AGENT_TYPE_NAME_INTERFACE;
|
||||||
break;
|
break;
|
||||||
case AGENT_TYPE_MIXER:
|
case AGENT_TYPE_AUDIO_MIXER:
|
||||||
name = AGENT_TYPE_NAME_MIXER;
|
name = AGENT_TYPE_NAME_AUDIO_MIXER;
|
||||||
break;
|
break;
|
||||||
|
case AGENT_TYPE_AVATAR_MIXER:
|
||||||
|
name = AGENT_TYPE_NAME_AVATAR_MIXER;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ const int DOMAINSERVER_PORT = 40102;
|
||||||
|
|
||||||
bool silentAgentThreadStopFlag = false;
|
bool silentAgentThreadStopFlag = false;
|
||||||
bool domainServerCheckinStopFlag = false;
|
bool domainServerCheckinStopFlag = false;
|
||||||
|
bool pingUnknownAgentThreadStopFlag = false;
|
||||||
pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
int unpackAgentId(unsigned char *packedData, uint16_t *agentId) {
|
int unpackAgentId(unsigned char *packedData, uint16_t *agentId) {
|
||||||
|
@ -50,6 +51,7 @@ AgentList::~AgentList() {
|
||||||
// stop the spawned threads, if they were started
|
// stop the spawned threads, if they were started
|
||||||
stopSilentAgentRemovalThread();
|
stopSilentAgentRemovalThread();
|
||||||
stopDomainServerCheckInThread();
|
stopDomainServerCheckInThread();
|
||||||
|
stopPingUnknownAgentsThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Agent>& AgentList::getAgents() {
|
std::vector<Agent>& AgentList::getAgents() {
|
||||||
|
@ -71,48 +73,71 @@ unsigned int AgentList::getSocketListenPort() {
|
||||||
void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
|
void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
|
||||||
switch (((char *)packetData)[0]) {
|
switch (((char *)packetData)[0]) {
|
||||||
case PACKET_HEADER_DOMAIN: {
|
case PACKET_HEADER_DOMAIN: {
|
||||||
// list of agents from domain server
|
|
||||||
updateList((unsigned char *)packetData, dataBytes);
|
updateList((unsigned char *)packetData, dataBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PACKET_HEADER_HEAD_DATA: {
|
|
||||||
// head data from another agent
|
|
||||||
updateAgentWithData(senderAddress, packetData, dataBytes);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PACKET_HEADER_PING: {
|
case PACKET_HEADER_PING: {
|
||||||
// ping from another agent
|
|
||||||
//std::cout << "Got ping from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n";
|
|
||||||
agentSocket.send(senderAddress, &PACKET_HEADER_PING_REPLY, 1);
|
agentSocket.send(senderAddress, &PACKET_HEADER_PING_REPLY, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PACKET_HEADER_PING_REPLY: {
|
case PACKET_HEADER_PING_REPLY: {
|
||||||
// ping reply from another agent
|
|
||||||
//std::cout << "Got ping reply from " << inet_ntoa(((sockaddr_in *)senderAddress)->sin_addr) << "\n";
|
|
||||||
handlePingReply(senderAddress);
|
handlePingReply(senderAddress);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AgentList::processBulkAgentData(sockaddr *senderAddress, void *packetData, int numTotalBytes, int numBytesPerAgent) {
|
||||||
|
// find the avatar mixer in our agent list and update the lastRecvTime from it
|
||||||
|
int bulkSendAgentIndex = indexOfMatchingAgent(senderAddress);
|
||||||
|
|
||||||
|
if (bulkSendAgentIndex >= 0) {
|
||||||
|
Agent *bulkSendAgent = &agents[bulkSendAgentIndex];
|
||||||
|
bulkSendAgent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *startPosition = (unsigned char *)packetData;
|
||||||
|
unsigned char *currentPosition = startPosition + 1;
|
||||||
|
unsigned char *packetHolder = new unsigned char[numBytesPerAgent + 1];
|
||||||
|
|
||||||
|
packetHolder[0] = PACKET_HEADER_HEAD_DATA;
|
||||||
|
|
||||||
|
uint16_t agentID = -1;
|
||||||
|
|
||||||
|
while ((currentPosition - startPosition) < numTotalBytes) {
|
||||||
|
currentPosition += unpackAgentId(currentPosition, &agentID);
|
||||||
|
memcpy(packetHolder + 1, currentPosition, numBytesPerAgent);
|
||||||
|
|
||||||
|
int matchingAgentIndex = indexOfMatchingAgent(agentID);
|
||||||
|
if (matchingAgentIndex >= 0) {
|
||||||
|
updateAgentWithData(&agents[matchingAgentIndex], packetHolder, numBytesPerAgent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPosition += numBytesPerAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] packetHolder;
|
||||||
|
}
|
||||||
|
|
||||||
void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
|
void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes) {
|
||||||
// find the agent by the sockaddr
|
// find the agent by the sockaddr
|
||||||
int agentIndex = indexOfMatchingAgent(senderAddress);
|
int agentIndex = indexOfMatchingAgent(senderAddress);
|
||||||
|
|
||||||
if (agentIndex != -1) {
|
if (agentIndex != -1) {
|
||||||
Agent *matchingAgent = &agents[agentIndex];
|
updateAgentWithData(&agents[agentIndex], packetData, dataBytes);
|
||||||
|
|
||||||
matchingAgent->setLastRecvTimeUsecs(usecTimestampNow());
|
|
||||||
|
|
||||||
if (matchingAgent->getLinkedData() == NULL) {
|
|
||||||
if (linkedDataCreateCallback != NULL) {
|
|
||||||
linkedDataCreateCallback(matchingAgent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
matchingAgent->getLinkedData()->parseData(packetData, dataBytes);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentList::updateAgentWithData(Agent *agent, void *packetData, int dataBytes) {
|
||||||
|
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||||
|
|
||||||
|
if (agent->getLinkedData() == NULL) {
|
||||||
|
if (linkedDataCreateCallback != NULL) {
|
||||||
|
linkedDataCreateCallback(agent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
agent->getLinkedData()->parseData(packetData, dataBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
||||||
|
@ -125,6 +150,16 @@ int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AgentList::indexOfMatchingAgent(uint16_t agentID) {
|
||||||
|
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||||
|
if (agent->getActiveSocket() != NULL && agent->getAgentId() == agentID) {
|
||||||
|
return agent - agents.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t AgentList::getLastAgentId() {
|
uint16_t AgentList::getLastAgentId() {
|
||||||
return lastAgentId;
|
return lastAgentId;
|
||||||
}
|
}
|
||||||
|
@ -176,12 +211,12 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
||||||
Agent newAgent = Agent(publicSocket, localSocket, agentType, agentId);
|
Agent newAgent = Agent(publicSocket, localSocket, agentType, agentId);
|
||||||
|
|
||||||
if (socketMatch(publicSocket, localSocket)) {
|
if (socketMatch(publicSocket, localSocket)) {
|
||||||
// likely debugging scenario with DS + agent on local network
|
// likely debugging scenario with two agents on local network
|
||||||
// set the agent active right away
|
// set the agent active right away
|
||||||
newAgent.activatePublicSocket();
|
newAgent.activatePublicSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newAgent.getType() == AGENT_TYPE_MIXER && audioMixerSocketUpdate != NULL) {
|
if (newAgent.getType() == AGENT_TYPE_AUDIO_MIXER && audioMixerSocketUpdate != NULL) {
|
||||||
// this is an audio mixer
|
// this is an audio mixer
|
||||||
// for now that means we need to tell the audio class
|
// for now that means we need to tell the audio class
|
||||||
// to use the local socket information the domain server gave us
|
// to use the local socket information the domain server gave us
|
||||||
|
@ -200,7 +235,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (agent->getType() == AGENT_TYPE_MIXER || agent->getType() == AGENT_TYPE_VOXEL) {
|
if (agent->getType() == AGENT_TYPE_AUDIO_MIXER || agent->getType() == AGENT_TYPE_VOXEL) {
|
||||||
// until the Audio class also uses our agentList, we need to update
|
// until the Audio class also uses our agentList, we need to update
|
||||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||||
|
@ -211,54 +246,72 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXXBHG - do we want to move these?
|
void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes) {
|
||||||
const char* AgentList::AGENTS_OF_TYPE_VOXEL = "V";
|
|
||||||
const char* AgentList::AGENTS_OF_TYPE_INTERFACE = "I";
|
|
||||||
const char* AgentList::AGENTS_OF_TYPE_VOXEL_AND_INTERFACE = "VI";
|
|
||||||
|
|
||||||
void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes,const char* agentTypes) {
|
|
||||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||||
// only send to the AgentTypes we are asked to send to.
|
// only send to the AgentTypes we are asked to send to.
|
||||||
if (agent->getActiveSocket() != NULL && strchr(agentTypes,agent->getType())) {
|
if (agent->getActiveSocket() != NULL && memchr(agentTypes, agent->getType(), numAgentTypes)) {
|
||||||
// we know which socket is good for this agent, send there
|
// we know which socket is good for this agent, send there
|
||||||
agentSocket.send(agent->getActiveSocket(), broadcastData, dataBytes);
|
agentSocket.send(agent->getActiveSocket(), broadcastData, dataBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentList::pingAgents() {
|
|
||||||
char payload[1];
|
|
||||||
*payload = PACKET_HEADER_PING;
|
|
||||||
|
|
||||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
|
||||||
if (agent->getType() == AGENT_TYPE_INTERFACE) {
|
|
||||||
if (agent->getActiveSocket() != NULL) {
|
|
||||||
// we know which socket is good for this agent, send there
|
|
||||||
agentSocket.send(agent->getActiveSocket(), payload, 1);
|
|
||||||
} else {
|
|
||||||
// ping both of the sockets for the agent so we can figure out
|
|
||||||
// which socket we can use
|
|
||||||
agentSocket.send(agent->getPublicSocket(), payload, 1);
|
|
||||||
agentSocket.send(agent->getLocalSocket(), payload, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AgentList::handlePingReply(sockaddr *agentAddress) {
|
void AgentList::handlePingReply(sockaddr *agentAddress) {
|
||||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||||
// check both the public and local addresses for each agent to see if we find a match
|
// check both the public and local addresses for each agent to see if we find a match
|
||||||
// prioritize the private address so that we prune erroneous local matches
|
// prioritize the private address so that we prune erroneous local matches
|
||||||
if (socketMatch(agent->getPublicSocket(), agentAddress)) {
|
if (socketMatch(agent->getPublicSocket(), agentAddress)) {
|
||||||
agent->activatePublicSocket();
|
agent->activatePublicSocket();
|
||||||
|
std::cout << "Activated public socket for agent " << &*agent << "\n";
|
||||||
break;
|
break;
|
||||||
} else if (socketMatch(agent->getLocalSocket(), agentAddress)) {
|
} else if (socketMatch(agent->getLocalSocket(), agentAddress)) {
|
||||||
agent->activateLocalSocket();
|
agent->activateLocalSocket();
|
||||||
|
std::cout << "Activated local socket for agent " << &*agent << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *pingUnknownAgents(void *args) {
|
||||||
|
|
||||||
|
AgentList *agentList = (AgentList *)args;
|
||||||
|
const int PING_INTERVAL_USECS = 1 * 1000000;
|
||||||
|
|
||||||
|
timeval lastSend;
|
||||||
|
|
||||||
|
while (!pingUnknownAgentThreadStopFlag) {
|
||||||
|
gettimeofday(&lastSend, NULL);
|
||||||
|
|
||||||
|
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
|
||||||
|
agent != agentList->getAgents().end();
|
||||||
|
agent++) {
|
||||||
|
if (agent->getActiveSocket() == NULL) {
|
||||||
|
// ping both of the sockets for the agent so we can figure out
|
||||||
|
// which socket we can use
|
||||||
|
agentList->getAgentSocket().send(agent->getPublicSocket(), &PACKET_HEADER_PING, 1);
|
||||||
|
agentList->getAgentSocket().send(agent->getLocalSocket(), &PACKET_HEADER_PING, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double usecToSleep = PING_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||||
|
|
||||||
|
if (usecToSleep > 0) {
|
||||||
|
usleep(usecToSleep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentList::startPingUnknownAgentsThread() {
|
||||||
|
pthread_create(&pingUnknownAgentsThread, NULL, pingUnknownAgents, (void *)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentList::stopPingUnknownAgentsThread() {
|
||||||
|
pingUnknownAgentThreadStopFlag = true;
|
||||||
|
pthread_join(pingUnknownAgentsThread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void *removeSilentAgents(void *args) {
|
void *removeSilentAgents(void *args) {
|
||||||
std::vector<Agent> *agents = (std::vector<Agent> *)args;
|
std::vector<Agent> *agents = (std::vector<Agent> *)args;
|
||||||
double checkTimeUSecs, sleepTime;
|
double checkTimeUSecs, sleepTime;
|
||||||
|
@ -289,7 +342,6 @@ void *removeSilentAgents(void *args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sleepTime = AGENT_SILENCE_THRESHOLD_USECS - (usecTimestampNow() - checkTimeUSecs);
|
sleepTime = AGENT_SILENCE_THRESHOLD_USECS - (usecTimestampNow() - checkTimeUSecs);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sleep( static_cast<int>(1000.0f*sleepTime) );
|
Sleep( static_cast<int>(1000.0f*sleepTime) );
|
||||||
|
@ -313,6 +365,8 @@ void AgentList::stopSilentAgentRemovalThread() {
|
||||||
|
|
||||||
void *checkInWithDomainServer(void *args) {
|
void *checkInWithDomainServer(void *args) {
|
||||||
|
|
||||||
|
const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
||||||
|
|
||||||
AgentList *parentAgentList = (AgentList *)args;
|
AgentList *parentAgentList = (AgentList *)args;
|
||||||
|
|
||||||
timeval lastSend;
|
timeval lastSend;
|
||||||
|
@ -343,7 +397,7 @@ void *checkInWithDomainServer(void *args) {
|
||||||
|
|
||||||
parentAgentList->getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
|
parentAgentList->getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
|
||||||
|
|
||||||
double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend));
|
double usecToSleep = DOMAIN_SERVER_CHECK_IN_USECS - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||||
|
|
||||||
if (usecToSleep > 0) {
|
if (usecToSleep > 0) {
|
||||||
usleep(usecToSleep);
|
usleep(usecToSleep);
|
||||||
|
|
|
@ -28,7 +28,6 @@ extern char DOMAIN_HOSTNAME[];
|
||||||
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup
|
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup
|
||||||
extern const int DOMAINSERVER_PORT;
|
extern const int DOMAINSERVER_PORT;
|
||||||
|
|
||||||
|
|
||||||
class AgentList {
|
class AgentList {
|
||||||
|
|
||||||
UDPSocket agentSocket;
|
UDPSocket agentSocket;
|
||||||
|
@ -38,6 +37,7 @@ class AgentList {
|
||||||
uint16_t lastAgentId;
|
uint16_t lastAgentId;
|
||||||
pthread_t removeSilentAgentsThread;
|
pthread_t removeSilentAgentsThread;
|
||||||
pthread_t checkInWithDomainServerThread;
|
pthread_t checkInWithDomainServerThread;
|
||||||
|
pthread_t pingUnknownAgentsThread;
|
||||||
|
|
||||||
void handlePingReply(sockaddr *agentAddress);
|
void handlePingReply(sockaddr *agentAddress);
|
||||||
public:
|
public:
|
||||||
|
@ -50,15 +50,23 @@ public:
|
||||||
std::vector<Agent>& getAgents();
|
std::vector<Agent>& getAgents();
|
||||||
UDPSocket& getAgentSocket();
|
UDPSocket& getAgentSocket();
|
||||||
|
|
||||||
int updateList(unsigned char *packetData, size_t dataBytes);
|
|
||||||
int indexOfMatchingAgent(sockaddr *senderAddress);
|
|
||||||
uint16_t getLastAgentId();
|
uint16_t getLastAgentId();
|
||||||
void increaseAgentId();
|
void increaseAgentId();
|
||||||
|
|
||||||
|
int updateList(unsigned char *packetData, size_t dataBytes);
|
||||||
|
|
||||||
|
int indexOfMatchingAgent(sockaddr *senderAddress);
|
||||||
|
int indexOfMatchingAgent(uint16_t agentID);
|
||||||
|
|
||||||
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId);
|
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId);
|
||||||
|
|
||||||
void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
||||||
|
void processBulkAgentData(sockaddr *senderAddress, void *packetData, int numTotalBytes, int numBytesPerAgent);
|
||||||
|
|
||||||
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
||||||
void broadcastToAgents(char *broadcastData, size_t dataBytes, const char* agentTypes);
|
void updateAgentWithData(Agent *agent, void *packetData, int dataBytes);
|
||||||
void pingAgents();
|
|
||||||
|
void broadcastToAgents(char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes);
|
||||||
char getOwnerType();
|
char getOwnerType();
|
||||||
unsigned int getSocketListenPort();
|
unsigned int getSocketListenPort();
|
||||||
|
|
||||||
|
@ -66,10 +74,8 @@ public:
|
||||||
void stopSilentAgentRemovalThread();
|
void stopSilentAgentRemovalThread();
|
||||||
void startDomainServerCheckInThread();
|
void startDomainServerCheckInThread();
|
||||||
void stopDomainServerCheckInThread();
|
void stopDomainServerCheckInThread();
|
||||||
|
void startPingUnknownAgentsThread();
|
||||||
static const char* AGENTS_OF_TYPE_VOXEL;
|
void stopPingUnknownAgentsThread();
|
||||||
static const char* AGENTS_OF_TYPE_INTERFACE;
|
|
||||||
static const char* AGENTS_OF_TYPE_VOXEL_AND_INTERFACE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int unpackAgentId(unsigned char *packedData, uint16_t *agentId);
|
int unpackAgentId(unsigned char *packedData, uint16_t *agentId);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
const char AGENT_TYPE_DOMAIN = 'D';
|
const char AGENT_TYPE_DOMAIN = 'D';
|
||||||
const char AGENT_TYPE_VOXEL = 'V';
|
const char AGENT_TYPE_VOXEL = 'V';
|
||||||
const char AGENT_TYPE_INTERFACE = 'I'; // could also be injector???
|
const char AGENT_TYPE_INTERFACE = 'I'; // could also be injector???
|
||||||
const char AGENT_TYPE_MIXER = 'M';
|
const char AGENT_TYPE_AUDIO_MIXER = 'M';
|
||||||
|
const char AGENT_TYPE_AVATAR_MIXER = 'W';
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@ const char PACKET_HEADER_INJECT_AUDIO = 'I';
|
||||||
const char PACKET_HEADER_SET_VOXEL = 'S';
|
const char PACKET_HEADER_SET_VOXEL = 'S';
|
||||||
const char PACKET_HEADER_ERASE_VOXEL = 'E';
|
const char PACKET_HEADER_ERASE_VOXEL = 'E';
|
||||||
const char PACKET_HEADER_VOXEL_DATA = 'V';
|
const char PACKET_HEADER_VOXEL_DATA = 'V';
|
||||||
|
const char PACKET_HEADER_AVATAR_SERVER = 'X';
|
||||||
const char PACKET_HEADER_TRANSMITTER_DATA = 't';
|
const char PACKET_HEADER_TRANSMITTER_DATA = 't';
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -345,7 +345,7 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
// Now send this to the connected agents so they know to delete
|
// Now send this to the connected agents so they know to delete
|
||||||
printf("rebroadcasting delete voxel message to connected agents... agentList.broadcastToAgents()\n");
|
printf("rebroadcasting delete voxel message to connected agents... agentList.broadcastToAgents()\n");
|
||||||
agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_INTERFACE);
|
agentList.broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_INTERFACE, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
||||||
|
@ -373,7 +373,7 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
// Now send this to the connected agents so they can also process these messages
|
// Now send this to the connected agents so they can also process these messages
|
||||||
printf("rebroadcasting Z message to connected agents... agentList.broadcastToAgents()\n");
|
printf("rebroadcasting Z message to connected agents... agentList.broadcastToAgents()\n");
|
||||||
agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_INTERFACE);
|
agentList.broadcastToAgents(packetData,receivedBytes, &AGENT_TYPE_INTERFACE, 1);
|
||||||
}
|
}
|
||||||
// If we got a PACKET_HEADER_HEAD_DATA, then we're talking to an AGENT_TYPE_INTERFACE, and we
|
// If we got a PACKET_HEADER_HEAD_DATA, then we're talking to an AGENT_TYPE_INTERFACE, and we
|
||||||
// need to make sure we have it in our agentList.
|
// need to make sure we have it in our agentList.
|
||||||
|
|
Loading…
Reference in a new issue