From 060f4dcecaca3703785684f1bff045d0c5f9a631 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 Feb 2013 12:56:57 -0800 Subject: [PATCH] use AgentData class to abstract implemenation of linked data --- domain/src/main.cpp | 14 +++- interface/CMakeLists.txt | 10 +-- interface/src/Audio.cpp | 4 +- interface/src/Audio.h | 3 +- interface/src/AudioData.h | 5 +- interface/src/Head.cpp | 14 ++-- interface/src/Head.h | 156 +++++++++++++++++++------------------- interface/src/main.cpp | 129 ++++--------------------------- shared/src/Agent.cpp | 4 +- shared/src/AgentData.h | 3 +- shared/src/AgentList.cpp | 57 ++++++++++++-- shared/src/AgentList.h | 8 +- 12 files changed, 181 insertions(+), 226 deletions(-) diff --git a/domain/src/main.cpp b/domain/src/main.cpp index 85412a5ec3..5044854ca2 100644 --- a/domain/src/main.cpp +++ b/domain/src/main.cpp @@ -36,18 +36,24 @@ unsigned char packetData[MAX_PACKET_SIZE]; const int LOGOFF_CHECK_INTERVAL = 5000; +#define DEBUG_TO_SELF 0 + int lastActiveCount = 0; AgentList agentList(DOMAIN_LISTEN_PORT); -int listForBroadcast(unsigned char *listBuffer) { +int listForBroadcast(unsigned char *listBuffer, sockaddr *agentPublicAddress, sockaddr *agentLocalAddress, char agentType) { unsigned char *currentBufferPos = listBuffer + 1; unsigned char *startPointer = currentBufferPos; for(std::vector::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) { *currentBufferPos++ = agent->type; - currentBufferPos += packSocket(currentBufferPos, agent->publicSocket); - currentBufferPos += packSocket(currentBufferPos, agent->localSocket); + if (DEBUG_TO_SELF || !agent->matches(agentPublicAddress, agentLocalAddress, agentType)) { + *currentBufferPos++ = agent->type; + + currentBufferPos += packSocket(currentBufferPos, agent->publicSocket); + currentBufferPos += packSocket(currentBufferPos, agent->localSocket); + } } return 1 + (currentBufferPos - startPointer); // 1 is added for the leading 'D' @@ -71,7 +77,7 @@ int main(int argc, const char * argv[]) agentList.addOrUpdateAgent((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType); - int listBytes = listForBroadcast(broadcastPacket); + int listBytes = listForBroadcast(broadcastPacket, (sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType); if (listBytes > 0) { agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, listBytes); diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 30bbfa56ec..0685aca6cd 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -9,12 +9,12 @@ set(PORTAUDIO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/portaudio) project(interface) if (APPLE) - # link in required OS X frameworks and include the right GL headers - set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") - set(GL_HEADERS "#include \n#include ") + # link in required OS X frameworks and include the right GL headers + set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon") + set(GL_HEADERS "#include \n#include ") else (APPLE) - # include the right GL headers for UNIX - set(GL_HEADERS "#include \n#include \n#include ") + # include the right GL headers for UNIX + set(GL_HEADERS "#include \n#include \n#include ") endif (APPLE) # create the InterfaceConfig.h file based on GL_HEADERS above diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 72cfa628aa..a5bb02d41f 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -272,7 +272,7 @@ void *receiveAudioViaUDP(void *args) { * @return Returns true if successful or false if an error occurred. Use Audio::getError() to retrieve the error code. */ -Audio::Audio(Head *mainHead, Oscilloscope * s) +Audio::Audio(Oscilloscope * s) { paError = Pa_Initialize(); if (paError != paNoError) goto error; @@ -292,8 +292,6 @@ Audio::Audio(Head *mainHead, Oscilloscope * s) pthread_create(&audioReceiveThread, NULL, receiveAudioViaUDP, (void *) &threadArgs); - audioData->linkedHead = mainHead; - paError = Pa_OpenDefaultStream(&stream, 2, // input channels 2, // output channels diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 82c20549d3..5cbe869e98 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -11,14 +11,13 @@ #include #include -#include "Head.h" #include "AudioData.h" #include "Oscilloscope.h" class Audio { public: // initializes audio I/O - Audio(Head* mainHead, Oscilloscope * s); + Audio(Oscilloscope * s); void render(); void render(int screenWidth, int screenHeight); diff --git a/interface/src/AudioData.h b/interface/src/AudioData.h index e66e89d314..26468d492b 100644 --- a/interface/src/AudioData.h +++ b/interface/src/AudioData.h @@ -12,13 +12,10 @@ #include #include #include "AudioRingBuffer.h" -#include "Head.h" #include "UDPSocket.h" class AudioData { - public: - Head *linkedHead; - + public: AudioRingBuffer *ringBuffer; UDPSocket *audioSocket; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index fdd3a7e2c9..1de3ebad5a 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -12,7 +12,6 @@ #include "Head.h" #include "Util.h" #include "SerialInterface.h" -#include "Audio.h" float skinColor[] = {1.0, 0.84, 0.66}; float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; @@ -60,6 +59,10 @@ Head::Head() setNoise(0); } +Head::~Head() { + // all data is primitive, do nothing +} + void Head::reset() { Pitch = Yaw = Roll = 0; @@ -328,7 +331,6 @@ void Head::render(int faceToFace, float * myLocation) } - // Transmit data to agents requesting it int Head::getBroadcastData(char* data) @@ -341,12 +343,12 @@ int Head::getBroadcastData(char* data) return strlen(data); } -void Head::recvBroadcastData(char * data, int size) -{ - sscanf(data, "%f,%f,%f,%f,%f,%f,%f,%f", &Pitch, &Yaw, &Roll, +void Head::parseData(void *data, int size) { + // parse head data for this agent + sscanf((char *)data, "%f,%f,%f,%f,%f,%f,%f,%f", + &Pitch, &Yaw, &Roll, &position.x, &position.y, &position.z, &loudness, &averageLoudness); - //printf("%f,%f,%f,%f,%f,%f\n", Pitch, Yaw, Roll, position.x, position.y, position.z); } void Head::SetNewHeadTarget(float pitch, float yaw) diff --git a/interface/src/Head.h b/interface/src/Head.h index c0a51e0bfc..7dc8ef7588 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -10,6 +10,7 @@ #define __interface__head__ #include +#include "AgentData.h" #include "Field.h" #include "world.h" #include "InterfaceConfig.h" @@ -17,83 +18,84 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; -class Head { - float noise; - float Pitch; - float Yaw; - float Roll; - float PitchRate; - float YawRate; - float RollRate; - float EyeballPitch[2]; - float EyeballYaw[2]; - float EyebrowPitch[2]; - float EyebrowRoll[2]; - float EyeballScaleX, EyeballScaleY, EyeballScaleZ; - float interPupilDistance; - float interBrowDistance; - float NominalPupilSize; - float PupilSize; - float MouthPitch; - float MouthYaw; - float MouthWidth; - float MouthHeight; - float leanForward; - float leanSideways; - float PitchTarget; - float YawTarget; - float NoiseEnvelope; - float PupilConverge; - float scale; - - // Sound loudness information - float loudness; - float averageLoudness; - - glm::vec3 position; - int eyeContact; - eyeContactTargets eyeContactTarget; - void readSensors(); - float renderYaw, renderPitch; // Pitch from view frustum when this is own head. - - -public: - Head(void); - void reset(); - void UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity); - void setNoise (float mag) { noise = mag; } - void setPitch(float p) {Pitch = p; } - void setYaw(float y) {Yaw = y; } - void setRoll(float r) {Roll = r; }; - void setScale(float s) {scale = s; }; - void setRenderYaw(float y) {renderYaw = y;} - void setRenderPitch(float p) {renderPitch = p;} - float getRenderYaw() {return renderYaw;} - float getRenderPitch() {return renderPitch;} - void setLeanForward(float dist); - void setLeanSideways(float dist); - void addPitch(float p) {Pitch -= p; } - void addYaw(float y){Yaw -= y; } - void addRoll(float r){Roll += r; } - void addLean(float x, float z); - float getPitch() {return Pitch;} - float getRoll() {return Roll;} - float getYaw() {return Yaw;} - - void render(int faceToFace, float * myLocation); - void simulate(float); - // Send and receive network data - int getBroadcastData(char* data); - void recvBroadcastData(char * data, int size); - - float getLoudness() {return loudness;}; - float getAverageLoudness() {return averageLoudness;}; - void setAverageLoudness(float al) {averageLoudness = al;}; - void setLoudness(float l) {loudness = l;}; - - void SetNewHeadTarget(float, float); - glm::vec3 getPos() { return position; }; - void setPos(glm::vec3 newpos) { position = newpos; }; +class Head : public AgentData { + public: + Head(); + ~Head(); + void reset(); + void UpdatePos(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity); + void setNoise (float mag) { noise = mag; } + void setPitch(float p) {Pitch = p; } + void setYaw(float y) {Yaw = y; } + void setRoll(float r) {Roll = r; }; + void setScale(float s) {scale = s; }; + void setRenderYaw(float y) {renderYaw = y;} + void setRenderPitch(float p) {renderPitch = p;} + float getRenderYaw() {return renderYaw;} + float getRenderPitch() {return renderPitch;} + void setLeanForward(float dist); + void setLeanSideways(float dist); + void addPitch(float p) {Pitch -= p; } + void addYaw(float y){Yaw -= y; } + void addRoll(float r){Roll += r; } + void addLean(float x, float z); + float getPitch() {return Pitch;} + float getRoll() {return Roll;} + float getYaw() {return Yaw;} + + void render(int faceToFace, float * myLocation); + void simulate(float); + + // Send and receive network data + int getBroadcastData(char * data); + void parseData(void *data, int size); + + float getLoudness() {return loudness;}; + float getAverageLoudness() {return averageLoudness;}; + void setAverageLoudness(float al) {averageLoudness = al;}; + void setLoudness(float l) {loudness = l;}; + + void SetNewHeadTarget(float, float); + glm::vec3 getPos() { return position; }; + void setPos(glm::vec3 newpos) { position = newpos; }; + private: + float noise; + float Pitch; + float Yaw; + float Roll; + float PitchRate; + float YawRate; + float RollRate; + float EyeballPitch[2]; + float EyeballYaw[2]; + float EyebrowPitch[2]; + float EyebrowRoll[2]; + float EyeballScaleX, EyeballScaleY, EyeballScaleZ; + float interPupilDistance; + float interBrowDistance; + float NominalPupilSize; + float PupilSize; + float MouthPitch; + float MouthYaw; + float MouthWidth; + float MouthHeight; + float leanForward; + float leanSideways; + float PitchTarget; + float YawTarget; + float NoiseEnvelope; + float PupilConverge; + float scale; + + // Sound loudness information + float loudness; + float averageLoudness; + + glm::vec3 position; + int eyeContact; + eyeContactTargets eyeContactTarget; + void readSensors(); + float renderYaw, renderPitch; // Pitch from view frustum when this is own head. }; #endif \ No newline at end of file diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 60f828f8a5..4e1f08b935 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -107,7 +107,7 @@ Lattice lattice(160,100); Finger myFinger(WIDTH, HEIGHT); Field field; -Audio audio(&myHead, &audioScope); +Audio audio(&audioScope); #define RENDER_FRAME_MSECS 8 int steps_per_frame = 0; @@ -512,7 +512,7 @@ void update_pos(float frametime) const int MAX_BROADCAST_STRING = 200; char broadcast_string[MAX_BROADCAST_STRING]; int broadcast_bytes = myHead.getBroadcastData(broadcast_string); -// broadcastToAgents(&agentSocket, broadcast_string, broadcast_bytes, sendToSelf); + agentList.broadcastToAgents(broadcast_string, broadcast_bytes); } int render_test_spot = WIDTH/2; @@ -560,8 +560,12 @@ void display(void) // Draw field vectors if (display_field) field.render(); - // Render heads of other agents -// render_agents(sendToSelf, &location[0]); + // Render heads of other agents + for(std::vector::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) { + if (agent->linkedData != NULL) { + ((Head *)agent->linkedData)->render(0, &location[0]); + } + } if (display_hand) myHand.render(); @@ -647,22 +651,6 @@ void display(void) char agents[100]; sprintf(agents, "Agents nearby: %d\n", nearbyAgents); drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0); - - -#ifdef MARKER_CAPTURE - /* Render marker acquisition stuff */ - pthread_mutex_lock(&frame_lock); - if(marker_capture_frame){ - marker_acq_view.render(marker_capture_frame); // render the acquisition view, if it's visible. - } - // Draw marker images, if requested. - if (marker_capture_enabled && marker_capture_display && marker_capture_frame){ - marker_capturer.glDrawIplImage(marker_capture_frame, WIDTH - 140, 10, 0.1, -0.1); - marker_capturer.glDrawIplImage(marker_capture_blob_frame, WIDTH - 280, 10, 0.1, -0.1); - } - pthread_mutex_unlock(&frame_lock); - /* Done rendering marker acquisition stuff */ -#endif glPopMatrix(); @@ -694,22 +682,6 @@ void key(unsigned char k, int x, int y) // Process keypresses if (k == 'q') ::terminate(); - // marker capture -#ifdef MARKER_CAPTURE - if(k == 'x'){ - printf("Toggling marker capture display.\n"); - marker_capture_display = !marker_capture_display; - marker_capture_display ? marker_acq_view.show() : marker_acq_view.hide(); - } - - // delegate keypresses to the marker acquisition view when it's visible; - // override other key mappings by returning... - if(marker_acq_view.visible){ - marker_acq_view.handle_key(k); - return; - } -#endif - if (k == '/') stats_on = !stats_on; // toggle stats if (k == 'n') { @@ -762,7 +734,7 @@ void *networkReceive(void *args) { sockaddr senderAddress; ssize_t bytesReceived; - unsigned char *incomingPacket = new unsigned char[MAX_PACKET_SIZE]; + char *incomingPacket = new char[MAX_PACKET_SIZE]; while (true) { if (agentList.getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) { @@ -770,49 +742,6 @@ void *networkReceive(void *args) bytescount += bytesReceived; agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); - - -// // If packet is a Mouse data packet, copy it over -// if (incomingPacket[0] == 'P') { -// // -// // Got Ping, reply immediately! -// // -// //printf("Replying to ping!\n"); -// char reply[] = "R"; -// agentList.getAgentSocket()->send(&senderAddress, reply, 1); -// } else if (incomingPacket[0] == 'R') { -// // -// // Got Reply, record as appropriate -// // -//// setAgentPing(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port)); -// -// } else if (incomingPacket[0] == 'M') { -// // -// // mouse location packet -// // -// sscanf(incomingPacket, "M %d %d", &target_x, &target_y); -// target_display = 1; -// //printf("X = %d Y = %d\n", target_x, target_y); -// } else if (incomingPacket[0] == 'D') { -// // -// // Message from domainserver -// // -// //printf("agent list received!\n"); -// nearbyAgents = agentList.updateList(&incomingPacket[1]); -// std::cout << "Received " << nearbyAgents << " from DS!\n"; -//// kludgyMixerUpdate(audio); -// } else if (incomingPacket[0] == 'H') { -// // -// // Broadcast packet from another agent -// // -// //printf("broadcast received"); -//// update_agent(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), &incomingPacket[1], bytesReceived - 1); -// } else if (incomingPacket[0] == 'T') { -// // Received a self-test packet (to get one's own IP), copy it to local variable! -//// printf("My Address: %s:%u\n", -//// inet_ntoa(senderAddress.sin_addr), -//// senderAddress.sin_port); -// } } } @@ -915,14 +844,9 @@ void mouseoverFunc( int x, int y) } } - -#ifdef MARKER_CAPTURE -void *poll_marker_capture(void *threadarg){ - while(1){ - marker_capturer.tick(); - } +void attachNewHeadToAgent(Agent *newAgent) { + newAgent->linkedData = new Head(); } -#endif int main(int argc, char** argv) { @@ -952,13 +876,6 @@ int main(int argc, char** argv) } } else printf("Using static domainserver IP: %s\n", DOMAIN_IP); - //std::cout << "Test address: " << inet_ntoa(testAddress.sin_addr) << "\n"; - - //gethostbyname(hostname); - // Send one test packet to detect own IP, port: - //char selfTest[] = "T"; - //agentSocket.send((char *)"127.0.0.1", AGENT_UDP_PORT, selfTest, 1); - printf("Testing stats math... "); StDev stdevtest; stdevtest.reset(); @@ -983,6 +900,8 @@ int main(int argc, char** argv) printf("Stdev=FAIL "); printf("\n"); + // the callback for our instance of AgentList is attachNewHeadToAgent + agentList.newAgentCallback = &attachNewHeadToAgent; // create thread for receipt of data via UDP pthread_t networkReceiveThread; @@ -1014,28 +933,8 @@ int main(int argc, char** argv) glutTimerFunc(1000, Timer, 0); -#ifdef MARKER_CAPTURE - - if (marker_capture_enabled) { - // start capture thread - if (pthread_mutex_init(&frame_lock, NULL) != 0){ - printf("Frame lock mutext init failed. Exiting.\n"); - return 1; - } - pthread_t capture_thread; - pthread_create(&capture_thread, NULL, poll_marker_capture, NULL); - } -#endif - glutMainLoop(); - -#ifdef MARKER_CAPTURE - if (marker_capture_enabled) { - pthread_mutex_destroy(&frame_lock); - pthread_exit(NULL); - } -#endif - + pthread_join(networkReceiveThread, NULL); ::terminate(); return EXIT_SUCCESS; diff --git a/shared/src/Agent.cpp b/shared/src/Agent.cpp index 7db0fb96fa..9fa1d0d178 100644 --- a/shared/src/Agent.cpp +++ b/shared/src/Agent.cpp @@ -44,8 +44,10 @@ Agent::Agent(const Agent &otherAgent) { type = otherAgent.type; + + linkedData = (AgentData *) malloc(sizeof(otherAgent.linkedData)); // copy over linkedData - linkedData = NULL; + memcpy((void*)linkedData, (void *)otherAgent.linkedData, sizeof(otherAgent.linkedData)); } Agent& Agent::operator=(Agent otherAgent) { diff --git a/shared/src/AgentData.h b/shared/src/AgentData.h index 667588fed1..e39f5ade6b 100644 --- a/shared/src/AgentData.h +++ b/shared/src/AgentData.h @@ -11,7 +11,8 @@ class AgentData { public: - virtual ~AgentData(); + virtual ~AgentData() = 0; + virtual void parseData(void * data, int size) = 0; }; #endif diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index 9b1d63e51b..3c30f2a596 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -21,14 +21,19 @@ UDPSocket * AgentList::getAgentSocket() { return &agentSocket; } -void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { - switch (packetData[0]) { +void AgentList::processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes) { + switch (((char *)packetData)[0]) { case 'D': { // list of agents from domain server - updateList(packetData, dataBytes); + updateList((unsigned char *)packetData, dataBytes); break; } + case 'H': + { + // head data from another agent + updateAgentWithData(senderAddress, packetData, dataBytes); + } case 'P': { // ping from another agent @@ -45,6 +50,30 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD } } +void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes) { + // find the agent by the sockaddr + int agentIndex = indexOfMatchingAgent(senderAddress); + + if (agentIndex != -1) { + Agent matchingAgent = agents[agentIndex]; + + if (matchingAgent.linkedData != NULL) { + matchingAgent.linkedData->parseData(packetData, dataBytes); + } + } + +} + +int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) { + for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { + if (socketMatch(agent->activeSocket, senderAddress)) { + return agent - agents.begin(); + } + } + + return -1; +} + int AgentList::updateList(unsigned char *packetData, size_t dataBytes) { int readAgents = 0; @@ -84,9 +113,16 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, // we didn't have this agent, so add them Agent newAgent = Agent(publicSocket, localSocket, agentType); + if (socketMatch(publicSocket, localSocket)) { + // likely debugging scenario with DS + agent on local network + // set the agent active right away + newAgent.activeSocket = newAgent.localSocket; + } + std::cout << "Added agent - " << &newAgent << "\n"; - - agents.push_back(newAgent); + + newAgentCallback(&newAgent); + agents.push_back(newAgent); return true; } else { @@ -95,6 +131,16 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, } } +void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes) { + for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { + if (agent->activeSocket != NULL) { + // we know which socket is good for this agent, send there + agentSocket.send((sockaddr *)agent->activeSocket, broadcastData, sizeof(&broadcastData)); + } + } +} + + void AgentList::pingAgents() { for(std::vector::iterator agent = agents.begin(); agent != agents.end(); agent++) { char payload[] = "P"; @@ -126,6 +172,7 @@ void AgentList::handlePingReply(sockaddr *agentAddress) { if (matchedSocket != NULL) { // matched agent, stop checking // update the agent's ping + agent->activeSocket = matchedSocket; break; } } diff --git a/shared/src/AgentList.h b/shared/src/AgentList.h index 6f34c7b3b9..e1964eb6f5 100644 --- a/shared/src/AgentList.h +++ b/shared/src/AgentList.h @@ -21,17 +21,19 @@ class AgentList { AgentList(); AgentList(int socketListenPort); std::vector agents; + void(*newAgentCallback)(Agent *); UDPSocket* getAgentSocket(); int updateList(unsigned char *packetData, size_t dataBytes); bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType); - void processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); - void broadcastToAgents(char *broadcastData, size_t dataBytes, bool sendToSelf); + void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes); + void broadcastToAgents(char *broadcastData, size_t dataBytes); void pingAgents(); private: UDPSocket agentSocket; - + int indexOfMatchingAgent(sockaddr *senderAddress); + void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes); void handlePingReply(sockaddr *agentAddress); };