/** * Handle Death Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnDeathPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // Valid Circumstances if(peer != NULL && context->mode == ADHOC_MATCHING_MODE_CHILD && peer == _findParent(context)) { // Complete Packet available if(length >= (1 + sizeof(SceNetEtherAddr))) { // Extract Child MAC SceNetEtherAddr mac; memcpy(&mac, context->rxbuf + 1, sizeof(SceNetEtherAddr)); // Find Peer SceNetAdhocMatchingMemberInternal * deadkid = _findPeer(context, &mac); // Valid Sibling if(deadkid->state == ADHOC_MATCHING_PEER_CHILD) { // Spawn Leave Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_LEAVE, &mac, 0, NULL); // Delete Peer _deletePeer(context, deadkid); } } } }
/** * Handle Hello Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnHelloPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Interested in Hello Data if((context->mode == ADHOC_MATCHING_MODE_CHILD && _findParent(context) == NULL) || (context->mode == ADHOC_MATCHING_MODE_P2P && _findP2P(context) == NULL)) { // Complete Packet Header available if(length >= 5) { // Extract Optional Data Length int optlen = 0; memcpy(&optlen, context->rxbuf + 1, sizeof(optlen)); // Complete Valid Packet available if(optlen >= 0 && length >= (5 + optlen)) { // Set Default Null Data void * opt = NULL; // Extract Optional Data Pointer if(optlen > 0) opt = context->rxbuf + 5; // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // Peer not found if(peer == NULL) { // Allocate Memory peer = (SceNetAdhocMatchingMemberInternal *)_malloc(sizeof(SceNetAdhocMatchingMemberInternal)); // Allocated Memory if(peer != NULL) { // Clear Memory memset(peer, 0, sizeof(SceNetAdhocMatchingMemberInternal)); // Copy Sender MAC peer->mac = *sendermac; // Set Peer State peer->state = ADHOC_MATCHING_PEER_OFFER; // Initialize Ping Timer peer->lastping = sceKernelGetSystemTimeWide(); // Link Peer into List peer->next = context->peerlist; context->peerlist = peer; } } // Peer available now if(peer != NULL) { // Spawn Hello Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_HELLO, sendermac, optlen, opt); } } } } }
/** * Handle Birth Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnBirthPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // Valid Circumstances if(peer != NULL && context->mode == ADHOC_MATCHING_MODE_CHILD && peer == _findParent(context)) { // Complete Packet available if(length >= (1 + sizeof(SceNetEtherAddr))) { // Extract Child MAC SceNetEtherAddr mac; memcpy(&mac, context->rxbuf + 1, sizeof(SceNetEtherAddr)); // Allocate Memory (If this fails... we are f****d.) SceNetAdhocMatchingMemberInternal * sibling = (SceNetAdhocMatchingMemberInternal *)_malloc(sizeof(SceNetAdhocMatchingMemberInternal)); // Allocated Memory if(sibling != NULL) { // Clear Memory memset(sibling, 0, sizeof(SceNetAdhocMatchingMemberInternal)); // Save MAC Address sibling->mac = mac; // Set Peer State sibling->state = ADHOC_MATCHING_PEER_CHILD; // Initialize Ping Timer peer->lastping = sceKernelGetSystemTimeWide(); // Link Peer sibling->next = context->peerlist; context->peerlist = sibling; // Spawn Established Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_ESTABLISHED, &sibling->mac, 0, NULL); } } } }
/** * Select / Accept Matching Target * @param id Matching Context ID * @param target Target MAC * @param optlen Length of Optional Data * @param opt Optional Data * @return 0 on success or... ADHOC_MATCHING_NOT_INITIALIZED, ADHOC_MATCHING_INVALID_ARG, ADHOC_MATCHING_INVALID_ID, ADHOC_MATCHING_NOT_RUNNING, ADHOC_MATCHING_UNKNOWN_TARGET, ADHOC_MATCHING_INVALID_OPTLEN, ADHOC_MATCHING_TARGET_NOT_READY, ADHOC_MATCHING_EXCEED_MAXNUM, ADHOC_MATCHING_NO_SPACE, ADHOC_MATCHING_REQUEST_IN_PROGRESS, ADHOC_MATCHING_ALREADY_ESTABLISHED */ int proNetAdhocMatchingSelectTarget(int id, const SceNetEtherAddr * target, int optlen, const void * opt) { // Initialized Library if(_init == 1) { // Valid Arguments if(target != NULL) { // Find Matching Context for ID SceNetAdhocMatchingContext * context = _findMatchingContext(id); // Found Matching Context if(context != NULL) { // Running Context if(context->running) { // Search Result SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, (SceNetEtherAddr *)target); // Found Peer in List if(peer != NULL) { // Valid Optional Data Length if((optlen == 0 && opt == NULL) || (optlen > 0 && opt != NULL)) { // Host Mode if(context->mode == ADHOC_MATCHING_MODE_PARENT) { // Already Connected if(peer->state == ADHOC_MATCHING_PEER_CHILD) return ADHOC_MATCHING_ALREADY_ESTABLISHED; // Not enough space if(_countChildren(context) == (context->maxpeers - 1)) return ADHOC_MATCHING_EXCEED_MAXNUM; // Requesting Peer if(peer->state == ADHOC_MATCHING_PEER_INCOMING_REQUEST) { // Accept Peer in Group peer->state = ADHOC_MATCHING_PEER_CHILD; // Send Accept Confirmation to Peer _sendAcceptMessage(context, peer, optlen, opt); // Tell Children about new Sibling _sendBirthMessage(context, peer); // Return Success return 0; } } // Client Mode else if(context->mode == ADHOC_MATCHING_MODE_CHILD) { // Already connected if(_findParent(context) != NULL) return ADHOC_MATCHING_ALREADY_ESTABLISHED; // Outgoing Request in Progress if(_findOutgoingRequest(context) != NULL) return ADHOC_MATCHING_REQUEST_IN_PROGRESS; // Valid Offer if(peer->state == ADHOC_MATCHING_PEER_OFFER) { // Switch into Join Request Mode peer->state = ADHOC_MATCHING_PEER_OUTGOING_REQUEST; // Send Join Request to Peer _sendJoinRequest(context, peer, optlen, opt); // Return Success return 0; } } // P2P Mode else { // Already connected if(_findP2P(context) != NULL) return ADHOC_MATCHING_ALREADY_ESTABLISHED; // Outgoing Request in Progress if(_findOutgoingRequest(context) != NULL) return ADHOC_MATCHING_REQUEST_IN_PROGRESS; // Join Request Mode if(peer->state == ADHOC_MATCHING_PEER_OFFER) { // Switch into Join Request Mode peer->state = ADHOC_MATCHING_PEER_OUTGOING_REQUEST; // Send Join Request to Peer _sendJoinRequest(context, peer, optlen, opt); // Return Success return 0; } // Requesting Peer else if(peer->state == ADHOC_MATCHING_PEER_INCOMING_REQUEST) { // Accept Peer in Group peer->state = ADHOC_MATCHING_PEER_P2P; // Send Accept Confirmation to Peer _sendAcceptMessage(context, peer, optlen, opt); // Return Success return 0; } } // How did this happen?! It shouldn't! return ADHOC_MATCHING_TARGET_NOT_READY; } // Invalid Optional Data Length return ADHOC_MATCHING_INVALID_OPTLEN; } // Peer not found return ADHOC_MATCHING_UNKNOWN_TARGET; } // Idle Context return ADHOC_MATCHING_NOT_RUNNING; } // Invalid Matching ID return ADHOC_MATCHING_INVALID_ID; } // Invalid Arguments return ADHOC_MATCHING_INVALID_ARG; } // Uninitialized Library return ADHOC_MATCHING_NOT_INITIALIZED; }
/** * Handle Cancel Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // Get Parent SceNetAdhocMatchingMemberInternal * parent = _findParent(context); // Get Outgoing Join Request SceNetAdhocMatchingMemberInternal * request = _findOutgoingRequest(context); // Get P2P Partner SceNetAdhocMatchingMemberInternal * p2p = _findP2P(context); // Interest Condition fulfilled if(peer != NULL) { // Complete Packet Header available if(length >= 5) { // Extract Optional Data Length int optlen = 0; memcpy(&optlen, context->rxbuf + 1, sizeof(optlen)); // Complete Valid Packet available if(optlen >= 0 && length >= (5 + optlen)) { // Set Default Null Data void * opt = NULL; // Extract Optional Data Pointer if(optlen > 0) opt = context->rxbuf + 5; // Child Mode if(context->mode == ADHOC_MATCHING_MODE_CHILD) { // Join Request denied if(request == peer) { // Spawn Deny Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_DENY, sendermac, optlen, opt); // Delete Peer from List _deletePeer(context, peer); } // Kicked from Room else if(parent == peer) { // Iterate Peers SceNetAdhocMatchingMemberInternal * item = context->peerlist; for(; item != NULL; item = item->next) { // Established Peer if(item->state == ADHOC_MATCHING_PEER_CHILD || item->state == ADHOC_MATCHING_PEER_PARENT) { // Spawn Leave / Kick Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_LEAVE, &item->mac, optlen, opt); } } // Delete Peer from List _clearPeerList(context); } } // Parent Mode else if(context->mode == ADHOC_MATCHING_MODE_PARENT) { // Cancel Join Request if(peer->state == ADHOC_MATCHING_PEER_INCOMING_REQUEST) { // Spawn Request Cancel Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_CANCEL, sendermac, optlen, opt); // Delete Peer from List _deletePeer(context, peer); } // Leave Room else if(peer->state == ADHOC_MATCHING_PEER_CHILD) { // Spawn Leave / Kick Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_LEAVE, sendermac, optlen, opt); // Delete Peer from List _deletePeer(context, peer); } } // P2P Mode else { // Join Request denied if(request == peer) { // Spawn Deny Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_DENY, sendermac, optlen, opt); // Delete Peer from List _deletePeer(context, peer); } // Kicked from Room else if(p2p == peer) { // Spawn Leave / Kick Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_LEAVE, sendermac, optlen, opt); // Delete Peer from List _deletePeer(context, peer); } // Cancel Join Request else if(peer->state == ADHOC_MATCHING_PEER_INCOMING_REQUEST) { // Spawn Request Cancel Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_CANCEL, sendermac, optlen, opt); // Delete Peer from List _deletePeer(context, peer); } } } } } }
/** * Handle Accept Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnAcceptPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Not a parent context if(context->mode != ADHOC_MATCHING_MODE_PARENT) { // Don't have a master yet if((context->mode == ADHOC_MATCHING_MODE_CHILD && _findParent(context) == NULL) || (context->mode == ADHOC_MATCHING_MODE_P2P && _findP2P(context) == NULL)) { // Complete Packet Header available if(length >= 9) { // Extract Optional Data Length int optlen = 0; memcpy(&optlen, context->rxbuf + 1, sizeof(optlen)); // Extract Sibling Count int siblingcount = 0; memcpy(&siblingcount, context->rxbuf + 5, sizeof(siblingcount)); // Complete Valid Packet available if(optlen >= 0 && length >= (9 + optlen + sizeof(SceNetEtherAddr) * siblingcount)) { // Set Default Null Data void * opt = NULL; // Extract Optional Data Pointer if(optlen > 0) opt = context->rxbuf + 9; // Sibling MAC Array Null Data SceNetEtherAddr * siblings = NULL; // Extract Optional Sibling MAC Array if(siblingcount > 0) siblings = (SceNetEtherAddr *)(context->rxbuf + 9 + optlen); // Find Outgoing Request SceNetAdhocMatchingMemberInternal * request = _findOutgoingRequest(context); // We are waiting for a answer to our request... if(request != NULL) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // It's the answer we wanted! if(request == peer) { // Change Peer State peer->state = (context->mode == ADHOC_MATCHING_MODE_CHILD) ? (ADHOC_MATCHING_PEER_PARENT) : (ADHOC_MATCHING_PEER_P2P); // Remove Unneeded Peer Information _postAcceptCleanPeerList(context); // Add Sibling Peers if(context->mode == ADHOC_MATCHING_MODE_CHILD) _postAcceptAddSiblings(context, siblingcount, siblings); // IMPORTANT! The Event Order here is ok! // Internally the Event Stack appends to the front, so the order will be switched around. // Spawn Established Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_ESTABLISHED, sendermac, 0, NULL); // Spawn Accept Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_ACCEPT, sendermac, optlen, opt); } } } } } } }