/** * 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 Bulk Data Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnBulkDataPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // Established Peer if(peer != NULL && ( (context->mode == ADHOC_MATCHING_MODE_PARENT && peer->state == ADHOC_MATCHING_PEER_CHILD) || (context->mode == ADHOC_MATCHING_MODE_CHILD && (peer->state == ADHOC_MATCHING_PEER_CHILD || peer->state == ADHOC_MATCHING_PEER_PARENT)) || (context->mode == ADHOC_MATCHING_MODE_P2P && peer->state == ADHOC_MATCHING_PEER_P2P))) { // Complete Packet Header available if(length > 5) { // Extract Data Length int datalen = 0; memcpy(&datalen, context->rxbuf + 1, sizeof(datalen)); // Complete Valid Packet available if(datalen > 0 && length >= (5 + datalen)) { // Extract Data void * data = context->rxbuf + 5; // Spawn Data Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_DATA, sendermac, datalen, data); } } } }
/** * 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); } } } } }
/** * Tell Established Peers of abandoned Child * @param context Matching Context Pointer * @param mac Dead Child's MAC */ void _sendDeathPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac) { // Find abandoned Child SceNetAdhocMatchingMemberInternal * deadkid = _findPeer(context, mac); // Found abandoned Child if(deadkid != NULL) { // Packet Buffer uint8_t packet[7]; // Set Opcode packet[0] = ADHOC_MATCHING_PACKET_DEATH; // Set abandoned Child MAC memcpy(packet + 1, mac, sizeof(SceNetEtherAddr)); // Iterate Peers SceNetAdhocMatchingMemberInternal * peer = context->peerlist; for(; peer != NULL; peer = peer->next) { // Skip dead Child if(peer == deadkid) continue; // Send only to children if(peer->state == ADHOC_MATCHING_PEER_CHILD) { // Send Packet sceNetAdhocPdpSend(context->socket, &peer->mac, context->port, packet, sizeof(packet), 0, ADHOC_F_NONBLOCK); } } } }
/** * Send Join Packet to Player * @param context Matching Context Pointer * @param mac Target Player MAC * @param optlen Optional Data Length * @param opt Optional Data */ void _sendJoinPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac, int optlen, void * opt) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, mac); // Valid Peer if(peer != NULL && peer->state == ADHOC_MATCHING_PEER_OUTGOING_REQUEST) { // Allocate Join Message Buffer uint8_t * join = (uint8_t *)_malloc(5 + optlen); // Allocated Join Message Buffer if(join != NULL) { // Join Opcode join[0] = ADHOC_MATCHING_PACKET_JOIN; // Optional Data Length memcpy(join + 1, &optlen, sizeof(optlen)); // Copy Optional Data if(optlen > 0) memcpy(join + 5, opt, optlen); // Send Data sceNetAdhocPdpSend(context->socket, mac, context->port, join, 5 + optlen, 0, ADHOC_F_NONBLOCK); // Free Memory _free(join); } } }
/** * Abort Data-Sending to Matching Target * @param id Matching Context ID * @param target Target MAC * @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 */ int proNetAdhocMatchingAbortSendData(int id, const SceNetEtherAddr * target) { // Initialized Library if(_init == 1) { // Valid Arguments if(target != NULL) { // Find Matching Context SceNetAdhocMatchingContext * context = _findMatchingContext(id); // Found Context if(context != NULL) { // Running Context if(context->running) { // Find Target Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, (SceNetEtherAddr *)target); // Found Peer if(peer != NULL) { // Peer is sending if(peer->sending) { // Set Peer as Bulk Idle peer->sending = 0; // Stop Bulk Data Sending (if in progress) _abortBulkTransfer(context, peer); } // Return Success return 0; } // Peer not found return ADHOC_MATCHING_UNKNOWN_TARGET; } // Context not running 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 Ping Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC */ void _actOnPingPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // Found Peer if(peer != NULL) { // Update Receive Timer peer->lastping = sceKernelGetSystemTimeWide(); } }
/** * 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); } } } }
/** * Send Cancel Packet to Player * @param context Matching Context Pointer * @param mac Target Player MAC * @param optlen Optional Data Length * @param opt Optional Data */ void _sendCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac, int optlen, void * opt) { // Allocate Cancel Message Buffer uint8_t * cancel = (uint8_t *)_malloc(5 + optlen); // Allocated Cancel Message Buffer if(cancel != NULL) { // Cancel Opcode cancel[0] = ADHOC_MATCHING_PACKET_CANCEL; // Optional Data Length memcpy(cancel + 1, &optlen, sizeof(optlen)); // Copy Optional Data if(optlen > 0) memcpy(cancel + 5, opt, optlen); // Send Data sceNetAdhocPdpSend(context->socket, mac, context->port, cancel, 5 + optlen, 0, ADHOC_F_NONBLOCK); // Free Memory _free(cancel); } // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, mac); // Found Peer if(peer != NULL) { // Child Mode Fallback - Delete All if(context->mode == ADHOC_MATCHING_MODE_CHILD) { // Delete Peer List _clearPeerList(context); } // Delete Peer else _deletePeer(context, peer); } }
/** * Handle Bye Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC */ void _actOnByePacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, sendermac); // We know this guy if(peer != NULL) { // P2P or Child Bye if((context->mode == ADHOC_MATCHING_MODE_PARENT && peer->state == ADHOC_MATCHING_PEER_CHILD) || (context->mode == ADHOC_MATCHING_MODE_CHILD && peer->state == ADHOC_MATCHING_PEER_CHILD) || (context->mode == ADHOC_MATCHING_MODE_P2P && peer->state == ADHOC_MATCHING_PEER_P2P)) { // Spawn Leave / Kick Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_BYE, sendermac, 0, NULL); // Delete Peer _deletePeer(context, peer); } // Parent Bye else if(context->mode == ADHOC_MATCHING_MODE_CHILD && peer->state == ADHOC_MATCHING_PEER_PARENT) { // 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_BYE, &item->mac, 0, NULL); } } // Delete Peer from List _clearPeerList(context); } } }
/** * Send Bulk Data Packet to Player * @param context Matching Context Pointer * @param mac Target Player MAC * @param datalen Data Length * @param data Data */ void _sendBulkDataPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac, int datalen, void * data) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, mac); // Valid Peer (rest is already checked in send.c) if(peer != NULL) { // Allocate Send Message Buffer uint8_t * send = (uint8_t *)_malloc(5 + datalen); // Allocated Send Message Buffer if(send != NULL) { // Send Opcode send[0] = ADHOC_MATCHING_PACKET_BULK; // Data Length memcpy(send + 1, &datalen, sizeof(datalen)); // Copy Data memcpy(send + 5, data, datalen); // Send Data sceNetAdhocPdpSend(context->socket, mac, context->port, send, 5 + datalen, 0, ADHOC_F_NONBLOCK); // Free Memory _free(send); // Remove Busy Bit from Peer peer->sending = 0; // Spawn Data Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_DATA_ACK, 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); } } } } } } }
/** * Handle Join Packet * @param context Matching Context Pointer * @param sendermac Packet Sender MAC * @param length Packet Length */ void _actOnJoinPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * sendermac, uint32_t length) { // Not a child mode context if(context->mode != ADHOC_MATCHING_MODE_CHILD) { // We still got a unoccupied slot in our room (Parent / P2P) if((context->mode == ADHOC_MATCHING_MODE_PARENT && _countChildren(context) < (context->maxpeers - 1)) || (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); // If we got the peer in the table already and are a parent, there is nothing left to be done. // This is because the only way a parent can know of a child is via a join request... // If we thus know of a possible child, then we already had a previous join request thus no need for double tapping. if(peer != NULL && context->mode == ADHOC_MATCHING_MODE_PARENT) return; // New Peer 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_INCOMING_REQUEST; // Initialize Ping Timer peer->lastping = sceKernelGetSystemTimeWide(); // Link Peer into List peer->next = context->peerlist; context->peerlist = peer; // Spawn Request Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_REQUEST, sendermac, optlen, opt); // Return Success return; } } // Existing Peer (this case is only reachable for P2P mode) else { // Set Peer State peer->state = ADHOC_MATCHING_PEER_INCOMING_REQUEST; // Spawn Request Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_REQUEST, sendermac, optlen, opt); // Return Success return; } } } } // Auto-Reject Player _sendCancelPacket(context, sendermac, 0, NULL); } }
/** * Send Accept Packet to Player * @param context Matching Context Pointer * @param mac Target Player MAC * @param optlen Optional Data Length * @param opt Optional Data */ void _sendAcceptPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac, int optlen, void * opt) { // Find Peer SceNetAdhocMatchingMemberInternal * peer = _findPeer(context, mac); // Found Peer if(peer != NULL && (peer->state == ADHOC_MATCHING_PEER_CHILD || peer->state == ADHOC_MATCHING_PEER_P2P)) { // Required Sibling Buffer uint32_t siblingbuflen = 0; // Parent Mode if(context->mode == ADHOC_MATCHING_MODE_PARENT) siblingbuflen = sizeof(SceNetEtherAddr) * (_countConnectedPeers(context) - 2); // Sibling Count int siblingcount = siblingbuflen / sizeof(SceNetEtherAddr); // Allocate Accept Message Buffer uint8_t * accept = (uint8_t *)_malloc(9 + optlen + siblingbuflen); // Allocated Accept Message Buffer if(accept != NULL) { // Accept Opcode accept[0] = ADHOC_MATCHING_PACKET_ACCEPT; // Optional Data Length memcpy(accept + 1, &optlen, sizeof(optlen)); // Sibling Count memcpy(accept + 5, &siblingcount, sizeof(siblingcount)); // Copy Optional Data if(optlen > 0) memcpy(accept + 9, opt, optlen); // Parent Mode Extra Data required if(context->mode == ADHOC_MATCHING_MODE_PARENT && siblingcount > 0) { // Create MAC Array Pointer uint8_t * siblingmacs = (uint8_t *)(accept + 9 + optlen); // MAC Writing Pointer int i = 0; // Iterate Peer List SceNetAdhocMatchingMemberInternal * item = context->peerlist; for(; item != NULL; item = item->next) { // Ignore Target if(item == peer) continue; // Copy Child MAC if(item->state == ADHOC_MATCHING_PEER_CHILD) { // Clone MAC the stupid memcpy way to shut up PSP CPU memcpy(siblingmacs + sizeof(SceNetEtherAddr) * i++, &item->mac, sizeof(SceNetEtherAddr)); } } } // Send Data sceNetAdhocPdpSend(context->socket, mac, context->port, accept, 9 + optlen + siblingbuflen, 0, ADHOC_F_NONBLOCK); // Free Memory _free(accept); // Spawn Local Established Event _spawnLocalEvent(context, ADHOC_MATCHING_EVENT_ESTABLISHED, mac, 0, NULL); } } }