diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 05e1583fca..fceedc6678 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -135,7 +135,11 @@ int main(int argc, const char * argv[]) !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) { if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) { // this is an agent of which there can be multiple, just add them to the packet - currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); + // don't send avatar agents to other avatars, that will come from avatar mixer + if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) { + currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); + } + } else { // solo agent, we need to only send newest if (newestSoloAgents[agent->getType()] == NULL || diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index f3b0d4cb65..d1bbf5e65b 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -149,7 +149,7 @@ Head::Head(const Head &otherAvatar) { _bodyPitch = otherAvatar._bodyPitch; _bodyRoll = otherAvatar._bodyRoll; _bodyYawDelta = otherAvatar._bodyYawDelta; - _mousePressed = otherAvatar._mousePressed; + _mousePressed = otherAvatar._mousePressed; _mode = otherAvatar._mode; _isMine = otherAvatar._isMine; _renderYaw = otherAvatar._renderYaw; @@ -892,45 +892,25 @@ void Head::initializeSkeleton() { //---------------------------------------------------------------------------- // parental hierarchy //---------------------------------------------------------------------------- - - //---------------------------------------------------------------------------- - // spine and head - //---------------------------------------------------------------------------- _bone[ AVATAR_BONE_PELVIS_SPINE ].parent = AVATAR_BONE_NULL; _bone[ AVATAR_BONE_MID_SPINE ].parent = AVATAR_BONE_PELVIS_SPINE; _bone[ AVATAR_BONE_CHEST_SPINE ].parent = AVATAR_BONE_MID_SPINE; _bone[ AVATAR_BONE_NECK ].parent = AVATAR_BONE_CHEST_SPINE; _bone[ AVATAR_BONE_HEAD ].parent = AVATAR_BONE_NECK; - - //---------------------------------------------------------------------------- - // left chest and arm - //---------------------------------------------------------------------------- _bone[ AVATAR_BONE_LEFT_CHEST ].parent = AVATAR_BONE_MID_SPINE; _bone[ AVATAR_BONE_LEFT_SHOULDER ].parent = AVATAR_BONE_LEFT_CHEST; _bone[ AVATAR_BONE_LEFT_UPPER_ARM ].parent = AVATAR_BONE_LEFT_SHOULDER; _bone[ AVATAR_BONE_LEFT_FOREARM ].parent = AVATAR_BONE_LEFT_UPPER_ARM; _bone[ AVATAR_BONE_LEFT_HAND ].parent = AVATAR_BONE_LEFT_FOREARM; - - //---------------------------------------------------------------------------- - // right chest and arm - //---------------------------------------------------------------------------- _bone[ AVATAR_BONE_RIGHT_CHEST ].parent = AVATAR_BONE_MID_SPINE; _bone[ AVATAR_BONE_RIGHT_SHOULDER ].parent = AVATAR_BONE_RIGHT_CHEST; _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].parent = AVATAR_BONE_RIGHT_SHOULDER; _bone[ AVATAR_BONE_RIGHT_FOREARM ].parent = AVATAR_BONE_RIGHT_UPPER_ARM; _bone[ AVATAR_BONE_RIGHT_HAND ].parent = AVATAR_BONE_RIGHT_FOREARM; - - //---------------------------------------------------------------------------- - // left pelvis and leg - //---------------------------------------------------------------------------- _bone[ AVATAR_BONE_LEFT_PELVIS ].parent = AVATAR_BONE_PELVIS_SPINE; _bone[ AVATAR_BONE_LEFT_THIGH ].parent = AVATAR_BONE_LEFT_PELVIS; _bone[ AVATAR_BONE_LEFT_SHIN ].parent = AVATAR_BONE_LEFT_THIGH; _bone[ AVATAR_BONE_LEFT_FOOT ].parent = AVATAR_BONE_LEFT_SHIN; - - //---------------------------------------------------------------------------- - // right pelvis and leg - //---------------------------------------------------------------------------- _bone[ AVATAR_BONE_RIGHT_PELVIS ].parent = AVATAR_BONE_PELVIS_SPINE; _bone[ AVATAR_BONE_RIGHT_THIGH ].parent = AVATAR_BONE_RIGHT_PELVIS; _bone[ AVATAR_BONE_RIGHT_SHIN ].parent = AVATAR_BONE_RIGHT_THIGH; @@ -944,12 +924,12 @@ void Head::initializeSkeleton() { _bone[ AVATAR_BONE_CHEST_SPINE ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 ); _bone[ AVATAR_BONE_NECK ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 ); _bone[ AVATAR_BONE_HEAD ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 ); - _bone[ AVATAR_BONE_LEFT_CHEST ].defaultPosePosition = glm::vec3( -0.06, 0.06, 0.0 ); + _bone[ AVATAR_BONE_LEFT_CHEST ].defaultPosePosition = glm::vec3( -0.05, 0.05, 0.0 ); _bone[ AVATAR_BONE_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.03, 0.0, 0.0 ); _bone[ AVATAR_BONE_LEFT_UPPER_ARM ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); _bone[ AVATAR_BONE_LEFT_FOREARM ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); _bone[ AVATAR_BONE_LEFT_HAND ].defaultPosePosition = glm::vec3( 0.0, -0.05, 0.0 ); - _bone[ AVATAR_BONE_RIGHT_CHEST ].defaultPosePosition = glm::vec3( 0.06, 0.06, 0.0 ); + _bone[ AVATAR_BONE_RIGHT_CHEST ].defaultPosePosition = glm::vec3( 0.05, 0.05, 0.0 ); _bone[ AVATAR_BONE_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.03, 0.0, 0.0 ); _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); _bone[ AVATAR_BONE_RIGHT_FOREARM ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); @@ -971,12 +951,12 @@ void Head::initializeSkeleton() { _bone[ AVATAR_BONE_HEAD ].radius = 0.02; _bone[ AVATAR_BONE_LEFT_CHEST ].radius = 0.025; _bone[ AVATAR_BONE_LEFT_SHOULDER ].radius = 0.02; - _bone[ AVATAR_BONE_LEFT_UPPER_ARM ].radius = 0.02; + _bone[ AVATAR_BONE_LEFT_UPPER_ARM ].radius = 0.015; _bone[ AVATAR_BONE_LEFT_FOREARM ].radius = 0.015; _bone[ AVATAR_BONE_LEFT_HAND ].radius = 0.01; _bone[ AVATAR_BONE_RIGHT_CHEST ].radius = 0.025; _bone[ AVATAR_BONE_RIGHT_SHOULDER ].radius = 0.02; - _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].radius = 0.02; + _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].radius = 0.015; _bone[ AVATAR_BONE_RIGHT_FOREARM ].radius = 0.015; _bone[ AVATAR_BONE_RIGHT_HAND ].radius = 0.01; _bone[ AVATAR_BONE_LEFT_PELVIS ].radius = 0.02; @@ -1157,16 +1137,12 @@ void Head::updateHandMovement() { if ( _usingBodySprings ) { if ( _closestOtherAvatar != -1 ) { if ( _mousePressed ) { + + + glm::vec3 handToHandVector( _otherAvatarHandPosition[ _closestOtherAvatar ]); + handToHandVector -= _bone[ AVATAR_BONE_RIGHT_HAND ].position; - /* - glm::vec3 handShakePull( DEBUG_otherAvatarListPosition[ closestOtherAvatar ]); - handShakePull -= _bone[ AVATAR_BONE_RIGHT_HAND ].position; - - handShakePull *= 1.0; - - transformedHandMovement += handShakePull; - */ - + //_bone[ AVATAR_BONE_RIGHT_HAND ].springyVelocity -= handPull; _bone[ AVATAR_BONE_RIGHT_HAND ].position = _otherAvatarHandPosition[ _closestOtherAvatar ]; } } @@ -1250,7 +1226,7 @@ void Head::renderBody() { //renderBoneAsBlock( (AvatarBoneID)b); //render bone orientation - //renderOrientationDirections( _bone[b].position, _bone[b].orientation, 0.05f ); + renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 ); if ( _usingBodySprings ) { glColor3fv( skinColor ); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index fb7a11aef2..c9e6b3186f 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -114,7 +114,7 @@ float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { } -void VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { +int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char command = *sourceBuffer; unsigned char *voxelData = sourceBuffer + 1; @@ -154,6 +154,7 @@ void VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { } setupNewVoxelsForDrawing(); + return numBytes; } void VoxelSystem::setupNewVoxelsForDrawing() { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index e133b4c039..4c309a92ea 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -26,7 +26,7 @@ public: VoxelSystem(); ~VoxelSystem(); - void parseData(unsigned char* sourceBuffer, int numBytes); + int parseData(unsigned char* sourceBuffer, int numBytes); VoxelSystem* clone() const; void init(); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c71a94da9a..1c075a62d9 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1456,8 +1456,7 @@ void *networkReceive(void *args) case PACKET_HEADER_BULK_AVATAR_DATA: AgentList::getInstance()->processBulkAgentData(&senderAddress, incomingPacket, - bytesReceived, - BYTES_PER_AVATAR); + bytesReceived); break; default: AgentList::getInstance()->processAgentData(&senderAddress, incomingPacket, bytesReceived); @@ -1500,7 +1499,7 @@ void idle(void) { // // Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents // - updateAvatar( 1.f/FPS ); + updateAvatar(deltaTime); //loop through all the other avatars and simulate them. AgentList * agentList = AgentList::getInstance(); @@ -1509,14 +1508,9 @@ void idle(void) { if (agent->getLinkedData() != NULL) { Head *avatar = (Head *)agent->getLinkedData(); - -//printf( "simulating remote avatar\n" ); - avatar->simulate(deltaTime); } } - - //updateAvatarHand(1.f/FPS); field.simulate (deltaTime); myAvatar.simulate(deltaTime); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 4189575e67..d36894a793 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -95,7 +95,9 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { } // called on the other agents - assigns it to my views of the others -void AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { +int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { + unsigned char* startPosition = sourceBuffer; + // increment to push past the packet header sourceBuffer++; @@ -126,6 +128,8 @@ void AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += sizeof(_cameraNearClip); memcpy(&_cameraFarClip, sourceBuffer, sizeof(_cameraFarClip)); sourceBuffer += sizeof(_cameraFarClip); + + return sourceBuffer - startPosition; } glm::vec3 AvatarData::getBodyPosition() { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 819333d558..ea735c62fe 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -13,8 +13,6 @@ #include -const int BYTES_PER_AVATAR = 94; - class AvatarData : public AgentData { public: AvatarData(); @@ -27,7 +25,7 @@ public: void setHandPosition(glm::vec3 handPosition); int getBroadcastData(unsigned char* destinationBuffer); - void parseData(unsigned char* sourceBuffer, int numBytes); + int parseData(unsigned char* sourceBuffer, int numBytes); float getBodyYaw(); void setBodyYaw(float bodyYaw); diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index 637a1bc58a..26290e1c1a 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -23,11 +23,19 @@ using shared_lib::printLog; Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType, uint16_t thisAgentId) { - publicSocket = new sockaddr; - memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr)); + if (agentPublicSocket != NULL) { + publicSocket = new sockaddr; + memcpy(publicSocket, agentPublicSocket, sizeof(sockaddr)); + } else { + publicSocket = NULL; + } - localSocket = new sockaddr; - memcpy(localSocket, agentLocalSocket, sizeof(sockaddr)); + if (agentLocalSocket != NULL) { + localSocket = new sockaddr; + memcpy(localSocket, agentLocalSocket, sizeof(sockaddr)); + } else { + localSocket = NULL; + } type = agentType; agentId = thisAgentId; @@ -44,11 +52,19 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent } Agent::Agent(const Agent &otherAgent) { - publicSocket = new sockaddr; - memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr)); + if (otherAgent.publicSocket != NULL) { + publicSocket = new sockaddr; + memcpy(publicSocket, otherAgent.publicSocket, sizeof(sockaddr)); + } else { + publicSocket = NULL; + } - localSocket = new sockaddr; - memcpy(localSocket, otherAgent.localSocket, sizeof(sockaddr)); + if (otherAgent.localSocket != NULL) { + localSocket = new sockaddr; + memcpy(localSocket, otherAgent.localSocket, sizeof(sockaddr)); + } else { + localSocket = NULL; + } agentId = otherAgent.agentId; diff --git a/libraries/shared/src/AgentData.h b/libraries/shared/src/AgentData.h index 640798b52b..f8bef16b41 100644 --- a/libraries/shared/src/AgentData.h +++ b/libraries/shared/src/AgentData.h @@ -12,7 +12,7 @@ class AgentData { public: virtual ~AgentData() = 0; - virtual void parseData(unsigned char* sourceBuffer, int numBytes) = 0; + virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0; virtual AgentData* clone() const = 0; }; diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index b89c9aa70c..77a726bc56 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -106,7 +106,7 @@ void AgentList::processAgentData(sockaddr *senderAddress, unsigned char *packetD } } -void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes, int numBytesPerAgent) { +void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) { // find the avatar mixer in our agent list and update the lastRecvTime from it int bulkSendAgentIndex = indexOfMatchingAgent(senderAddress); @@ -118,7 +118,7 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac unsigned char *startPosition = packetData; unsigned char *currentPosition = startPosition + 1; - unsigned char packetHolder[numBytesPerAgent + 1]; + unsigned char packetHolder[numTotalBytes]; packetHolder[0] = PACKET_HEADER_HEAD_DATA; @@ -126,29 +126,36 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac while ((currentPosition - startPosition) < numTotalBytes) { currentPosition += unpackAgentId(currentPosition, &agentID); - memcpy(packetHolder + 1, currentPosition, numBytesPerAgent); + memcpy(packetHolder + 1, currentPosition, numTotalBytes - (currentPosition - startPosition)); int matchingAgentIndex = indexOfMatchingAgent(agentID); - if (matchingAgentIndex >= 0) { + if (matchingAgentIndex < 0) { + // we're missing this agent, we need to add it to the list + addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID); - updateAgentWithData(&agents[matchingAgentIndex], packetHolder, numBytesPerAgent + 1); + // theoretically if we can lock the vector we could assume this is size - 1 + matchingAgentIndex = indexOfMatchingAgent(agentID); } - currentPosition += numBytesPerAgent; + currentPosition += updateAgentWithData(&agents[matchingAgentIndex], + packetHolder, + numTotalBytes - (currentPosition - startPosition)); } } -void AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { +int AgentList::updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { // find the agent by the sockaddr int agentIndex = indexOfMatchingAgent(senderAddress); if (agentIndex != -1) { - updateAgentWithData(&agents[agentIndex], packetData, dataBytes); + return updateAgentWithData(&agents[agentIndex], packetData, dataBytes); + } else { + return 0; } } -void AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) { +int AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes) { agent->setLastRecvTimeUsecs(usecTimestampNow()); agent->recordBytesReceived(dataBytes); @@ -158,7 +165,7 @@ void AgentList::updateAgentWithData(Agent *agent, unsigned char *packetData, int } } - agent->getLinkedData()->parseData(packetData, dataBytes); + return agent->getLinkedData()->parseData(packetData, dataBytes); } int AgentList::indexOfMatchingAgent(sockaddr *senderAddress) { @@ -219,11 +226,15 @@ int AgentList::updateList(unsigned char *packetData, size_t dataBytes) { bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId) { std::vector::iterator agent; - for (agent = agents.begin(); agent != agents.end(); agent++) { - if (agent->matches(publicSocket, localSocket, agentType)) { - // we already have this agent, stop checking - break; + if (publicSocket != NULL) { + for (agent = agents.begin(); agent != agents.end(); agent++) { + if (agent->matches(publicSocket, localSocket, agentType)) { + // we already have this agent, stop checking + break; + } } + } else { + agent = agents.end(); } if (agent == agents.end()) { @@ -316,7 +327,8 @@ void *pingUnknownAgents(void *args) { for(std::vector::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++) { - if (agent->getActiveSocket() == NULL) { + if (agent->getActiveSocket() == NULL + && (agent->getPublicSocket() != NULL && agent->getLocalSocket() != 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); diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index adc66333f9..f62d527116 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -50,10 +50,10 @@ public: bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId); void processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); - void processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes, int numBytesPerAgent); + void processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes); - void updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); - void updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes); + int updateAgentWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); + int updateAgentWithData(Agent *agent, unsigned char *packetData, int dataBytes); void broadcastToAgents(unsigned char *broadcastData, size_t dataBytes, const char* agentTypes, int numAgentTypes); char getOwnerType(); diff --git a/libraries/shared/src/AudioRingBuffer.cpp b/libraries/shared/src/AudioRingBuffer.cpp index 2197d03706..5180e238cb 100644 --- a/libraries/shared/src/AudioRingBuffer.cpp +++ b/libraries/shared/src/AudioRingBuffer.cpp @@ -105,7 +105,7 @@ void AudioRingBuffer::setBearing(float newBearing) { bearing = newBearing; } -void AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { +int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { if (numBytes > (bufferLengthSamples * sizeof(int16_t))) { unsigned char *dataPtr = sourceBuffer + 1; @@ -140,7 +140,9 @@ void AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { if (endOfLastWrite >= buffer + ringBufferLengthSamples) { endOfLastWrite = buffer; - } + } + + return numBytes; } short AudioRingBuffer::diffLastWriteNextOutput() diff --git a/libraries/shared/src/AudioRingBuffer.h b/libraries/shared/src/AudioRingBuffer.h index a87331f330..48620aa133 100644 --- a/libraries/shared/src/AudioRingBuffer.h +++ b/libraries/shared/src/AudioRingBuffer.h @@ -18,7 +18,7 @@ class AudioRingBuffer : public AgentData { ~AudioRingBuffer(); AudioRingBuffer(const AudioRingBuffer &otherRingBuffer); - void parseData(unsigned char* sourceBuffer, int numBytes); + int parseData(unsigned char* sourceBuffer, int numBytes); AudioRingBuffer* clone() const; int16_t* getNextOutput(); diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 42da682d7b..000f0e3d7d 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -28,20 +28,24 @@ using shared_lib::printLog; sockaddr_in destSockaddr, senderAddress; bool socketMatch(sockaddr *first, sockaddr *second) { - // utility function that indicates if two sockets are equivalent - - // currently only compares two IPv4 addresses - // expandable to IPv6 by adding else if for AF_INET6 - - if (first->sa_family != second->sa_family) { - // not the same family, can't be equal - return false; - } else if (first->sa_family == AF_INET) { - sockaddr_in *firstIn = (sockaddr_in *) first; - sockaddr_in *secondIn = (sockaddr_in *) second; + if (first != NULL && second != NULL) { + // utility function that indicates if two sockets are equivalent - return firstIn->sin_addr.s_addr == secondIn->sin_addr.s_addr + // currently only compares two IPv4 addresses + // expandable to IPv6 by adding else if for AF_INET6 + + if (first->sa_family != second->sa_family) { + // not the same family, can't be equal + return false; + } else if (first->sa_family == AF_INET) { + sockaddr_in *firstIn = (sockaddr_in *) first; + sockaddr_in *secondIn = (sockaddr_in *) second; + + return firstIn->sin_addr.s_addr == secondIn->sin_addr.s_addr && firstIn->sin_port == secondIn->sin_port; + } else { + return false; + } } else { return false; }