1 // Copyright (c) 2013- PPSSPP Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
21 // This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
22 // All credit goes to him!
25 #include "util/text/parsers.h"
26 #include "Core/Core.h"
27 #include "Core/HLE/sceKernelInterrupt.h"
28 #include "Core/HLE/sceKernelThread.h"
29 #include "Core/HLE/sceKernelMemory.h"
30 #include "UI/OnScreenDisplay.h"
32 #include "i18n/i18n.h"
34 uint32_t fakePoolSize
= 0;
35 SceNetAdhocMatchingContext
* contexts
= NULL
;
37 bool friendFinderRunning
= false;
38 SceNetAdhocctlPeerInfo
* friends
= NULL
;
39 SceNetAdhocctlScanInfo
* networks
= NULL
;
40 SceNetAdhocctlScanInfo
* newnetworks
= NULL
;
41 int threadStatus
= ADHOCCTL_STATE_DISCONNECTED
;
43 bool IsAdhocctlInCB
= false;
44 int actionAfterMatchingMipsCall
;
47 uint8_t broadcastMAC
[ETHER_ADDR_LEN
] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
50 SceNetAdhocctlParameter parameter
;
51 SceNetAdhocctlAdhocId product_code
;
52 std::thread friendFinderThread
;
53 recursive_mutex peerlock
;
54 SceNetAdhocPdpStat
* pdp
[255];
55 SceNetAdhocPtpStat
* ptp
[255];
57 int isLocalMAC(const SceNetEtherAddr
* addr
) {
58 SceNetEtherAddr saddr
;
61 // Compare MAC Addresses
62 int match
= memcmp((const void *)addr
, (const void *)&saddr
, ETHER_ADDR_LEN
);
68 int isPDPPortInUse(uint16_t port
) {
70 int i
= 0; for (; i
< 255; i
++) if (pdp
[i
] != NULL
&& pdp
[i
]->lport
== port
) return 1;
76 int isPTPPortInUse(uint16_t port
) {
78 int i
= 0; for(; i
< 255; i
++) if(ptp
[i
] != NULL
&& ptp
[i
]->lport
== port
) return 1;
84 SceNetAdhocMatchingMemberInternal
* addMember(SceNetAdhocMatchingContext
* context
, SceNetEtherAddr
* mac
) {
85 if (context
== NULL
|| mac
== NULL
) return NULL
;
87 SceNetAdhocMatchingMemberInternal
* peer
= findPeer(context
, mac
);
88 // Member is not added yet
90 peer
= (SceNetAdhocMatchingMemberInternal
*)malloc(sizeof(SceNetAdhocMatchingMemberInternal
));
92 memset(peer
, 0, sizeof(SceNetAdhocMatchingMemberInternal
));
94 peer
->next
= context
->peerlist
;
95 context
->peerlist
= peer
;
101 void addFriend(SceNetAdhocctlConnectPacketS2C
* packet
) {
102 if (packet
== NULL
) return;
104 // Multithreading Lock
107 SceNetAdhocctlPeerInfo
* peer
= findFriend(&packet
->mac
);
110 peer
->nickname
= packet
->name
;
111 peer
->mac_addr
= packet
->mac
;
112 peer
->ip_addr
= packet
->ip
;
114 peer
->last_recv
= CoreTiming::GetGlobalTimeUsScaled();
118 // Allocate Structure
119 peer
= (SceNetAdhocctlPeerInfo
*)malloc(sizeof(SceNetAdhocctlPeerInfo
));
120 // Allocated Structure
123 memset(peer
, 0, sizeof(SceNetAdhocctlPeerInfo
));
126 peer
->nickname
= packet
->name
;
129 peer
->mac_addr
= packet
->mac
;
132 peer
->ip_addr
= packet
->ip
;
135 peer
->last_recv
= CoreTiming::GetGlobalTimeUsScaled();
137 // Link to existing Peers
138 peer
->next
= friends
;
140 // Link into Peerlist
145 // Multithreading Unlock
149 SceNetAdhocctlPeerInfo
* findFriend(SceNetEtherAddr
* MAC
) {
150 if (MAC
== NULL
) return NULL
;
153 SceNetAdhocctlPeerInfo
* peer
= friends
;
156 for (; peer
!= NULL
; peer
= peer
->next
) {
157 if (IsMatch(peer
->mac_addr
, *MAC
)) break;
160 // Return found friend
164 void changeBlockingMode(int fd
, int nonblocking
) {
165 unsigned long on
= 1;
166 unsigned long off
= 0;
169 // Change to Non-Blocking Mode
170 ioctlsocket(fd
, FIONBIO
, &on
);
173 // Change to Blocking Mode
174 ioctlsocket(fd
, FIONBIO
, &off
);
177 if(nonblocking
== 1) fcntl(fd
, F_SETFL
, O_NONBLOCK
);
180 int flags
= fcntl(fd
, F_GETFL
);
181 // Remove Non-Blocking Flag
182 fcntl(fd
, F_SETFL
, flags
& ~O_NONBLOCK
);
187 int countAvailableNetworks(void) {
192 SceNetAdhocctlScanInfo
* group
= networks
;
195 for (; group
!= NULL
; group
= group
->next
) count
++;
197 // Return Network Count
201 SceNetAdhocctlScanInfo
* findGroup(SceNetEtherAddr
* MAC
) {
202 if (MAC
== NULL
) return NULL
;
205 SceNetAdhocctlScanInfo
* group
= networks
;
208 for (; group
!= NULL
; group
= group
->next
) {
209 if (IsMatch(group
->bssid
.mac_addr
, *MAC
)) break;
212 // Return found group
216 void freeGroupsRecursive(SceNetAdhocctlScanInfo
* node
) {
218 if (node
== NULL
) return;
220 // Increase Recursion Depth
221 freeGroupsRecursive(node
->next
);
227 void deleteAllPDP(void) {
229 int i
= 0; for (; i
< 255; i
++) {
231 if (pdp
[i
] != NULL
) {
233 closesocket(pdp
[i
]->id
);
244 void deleteAllPTP(void) {
246 int i
= 0; for (; i
< 255; i
++) {
248 if (ptp
[i
] != NULL
) {
250 closesocket(ptp
[i
]->id
);
261 void deleteFriendByIP(uint32_t ip
) {
262 // Previous Peer Reference
263 SceNetAdhocctlPeerInfo
* prev
= NULL
;
266 SceNetAdhocctlPeerInfo
* peer
= friends
;
269 for (; peer
!= NULL
; peer
= peer
->next
) {
271 if (peer
->ip_addr
== ip
) {
272 // Instead of removing it from the list we'll make it timeout since most Matching games are moving group and may still need the peer data
275 // Multithreading Lock
278 // Unlink Left (Beginning)
279 if(prev == NULL)friends = peer->next;
281 // Unlink Left (Other)
282 else prev->next = peer->next;
284 // Multithreading Unlock
295 // Set Previous Reference
296 // TODO: Should this be used by something?
301 int findFreeMatchingID(void) {
302 // Minimum Matching ID
305 // Maximum Matching ID
308 // Find highest Matching ID
309 SceNetAdhocMatchingContext
* item
= contexts
; for (; item
!= NULL
; item
= item
->next
) {
311 if (max
< item
->id
) max
= item
->id
;
314 // Find unoccupied ID
315 int i
= min
; for (; i
< max
; i
++) {
316 // Found unoccupied ID
317 if (findMatchingContext(i
) == NULL
) return i
;
320 // Append at virtual end
324 SceNetAdhocMatchingContext
* findMatchingContext(int id
) {
325 // Iterate Matching Context List
326 SceNetAdhocMatchingContext
* item
= contexts
; for (; item
!= NULL
; item
= item
->next
) { // Found Matching ID
327 if (item
->id
== id
) return item
;
335 * Find Outgoing Request Target Peer
336 * @param context Matching Context Pointer
337 * @return Internal Peer Reference or... NULL
339 SceNetAdhocMatchingMemberInternal
* findOutgoingRequest(SceNetAdhocMatchingContext
* context
)
341 // Iterate Peer List for Matching Target
342 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
; for (; peer
!= NULL
; peer
= peer
->next
)
344 // Found Peer in List
345 if (peer
->state
== PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST
) return peer
;
353 * Remove unneeded Peer Data after being accepted to a match
354 * @param context Matching Context Pointer
356 void postAcceptCleanPeerList(SceNetAdhocMatchingContext
* context
)
362 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
;
365 // Save next Peer just in case we have to delete this one
366 SceNetAdhocMatchingMemberInternal
* next
= peer
->next
;
369 if (peer
->state
!= PSP_ADHOC_MATCHING_PEER_CHILD
&& peer
->state
!= PSP_ADHOC_MATCHING_PEER_P2P
&& peer
->state
!= PSP_ADHOC_MATCHING_PEER_PARENT
) deletePeer(context
, peer
);
380 * Add Sibling-Data that was sent with Accept-Datagram
381 * @param context Matching Context Pointer
382 * @param siblingcount Number of Siblings
383 * @param siblings Sibling MAC Array
385 void postAcceptAddSiblings(SceNetAdhocMatchingContext
* context
, int siblingcount
, SceNetEtherAddr
* siblings
)
387 // Cast Sibling MAC Array to uint8_t
388 // PSP CPU has a problem with non-4-byte aligned Pointer Access.
389 // As the buffer of "siblings" isn't properly aligned I don't want to risk a crash.
390 uint8_t * siblings_u8
= (uint8_t *)siblings
;
393 int i
= 0; for (; i
< siblingcount
; i
++)
396 SceNetAdhocMatchingMemberInternal
* sibling
= (SceNetAdhocMatchingMemberInternal
*)malloc(sizeof(SceNetAdhocMatchingMemberInternal
));
402 memset(sibling
, 0, sizeof(SceNetAdhocMatchingMemberInternal
));
405 memcpy(&sibling
->mac
, siblings_u8
+ sizeof(SceNetEtherAddr
) * i
, sizeof(SceNetEtherAddr
));
408 sibling
->state
= PSP_ADHOC_MATCHING_PEER_CHILD
;
410 // Initialize Ping Timer
411 sibling
->lastping
= CoreTiming::GetGlobalTimeUsScaled(); //real_time_now()*1000000.0;
413 // Link Peer, should check whether it's already added before
414 sibling
->next
= context
->peerlist
;
415 context
->peerlist
= sibling
;
417 // Spawn Established Event
418 spawnLocalEvent(context
, PSP_ADHOC_MATCHING_EVENT_ESTABLISHED
, &sibling
->mac
, 0, NULL
);
420 INFO_LOG(SCENET
, "Accepting Peer %02X:%02X:%02X:%02X:%02X:%02X", sibling
->mac
.data
[0], sibling
->mac
.data
[1], sibling
->mac
.data
[2], sibling
->mac
.data
[3], sibling
->mac
.data
[4], sibling
->mac
.data
[5]);
426 * Count Children Peers (for Parent)
427 * @param context Matching Context Pointer
428 * @return Number of Children
430 s32_le
countChildren(SceNetAdhocMatchingContext
* context
)
435 // Iterate Peer List for Matching Target
436 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
; for (; peer
!= NULL
; peer
= peer
->next
)
438 // Increase Children Counter
439 if (peer
->state
== PSP_ADHOC_MATCHING_PEER_CHILD
) count
++;
442 // Return Children Count
447 * Find Peer in Context by MAC
448 * @param context Matching Context Pointer
449 * @param mac Peer MAC Address
450 * @return Internal Peer Reference or... NULL
452 SceNetAdhocMatchingMemberInternal
* findPeer(SceNetAdhocMatchingContext
* context
, SceNetEtherAddr
* mac
)
454 // Iterate Peer List for Matching Target
455 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
; for (; peer
!= NULL
; peer
= peer
->next
)
457 // Found Peer in List
458 if (memcmp(&peer
->mac
, mac
, sizeof(SceNetEtherAddr
)) == 0)
460 // Return Peer Pointer
471 * @param context Matching Context Pointer
472 * @return Internal Peer Reference or... NULL
474 SceNetAdhocMatchingMemberInternal
* findParent(SceNetAdhocMatchingContext
* context
)
476 // Iterate Peer List for Matching Target
477 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
; for (; peer
!= NULL
; peer
= peer
->next
)
479 // Found Peer in List
480 if (peer
->state
== PSP_ADHOC_MATCHING_PEER_PARENT
) return peer
;
488 * Find P2P Buddy Peer
489 * @param context Matching Context Pointer
490 * @return Internal Peer Reference or... NULL
492 SceNetAdhocMatchingMemberInternal
* findP2P(SceNetAdhocMatchingContext
* context
)
494 // Iterate Peer List for Matching Target
495 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
;
496 for (; peer
!= NULL
; peer
= peer
->next
)
498 // Found Peer in List
499 if (peer
->state
== PSP_ADHOC_MATCHING_PEER_P2P
) return peer
;
507 * Delete Peer from List
508 * @param context Matching Context Pointer
509 * @param peer Internal Peer Reference
511 void deletePeer(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
)
514 if (context
!= NULL
&& peer
!= NULL
)
518 // Previous Peer Reference
519 SceNetAdhocMatchingMemberInternal
* previous
= NULL
;
522 SceNetAdhocMatchingMemberInternal
* item
= context
->peerlist
;
523 for (; item
!= NULL
; item
= item
->next
)
526 if (item
== peer
) break;
534 if (previous
!= NULL
) previous
->next
= item
->next
;
537 else context
->peerlist
= item
->next
;
539 INFO_LOG(SCENET
, "Removing Peer %02X:%02X:%02X:%02X:%02X:%02X", peer
->mac
.data
[0], peer
->mac
.data
[1], peer
->mac
.data
[2], peer
->mac
.data
[3], peer
->mac
.data
[4], peer
->mac
.data
[5]);
551 * Safely Link Thread Message to Event Thread Stack
552 * @param context Matching Context Pointer
553 * @param message Thread Message Pointer
555 void linkEVMessage(SceNetAdhocMatchingContext
* context
, ThreadMessage
* message
)
558 context
->eventlock
->lock();
561 message
->next
= context
->event_stack
;
562 context
->event_stack
= message
;
565 context
->eventlock
->unlock();
569 * Safely Link Thread Message to IO Thread Stack
570 * @param context Matching Context Pointer
571 * @param message Thread Message Pointer
573 void linkIOMessage(SceNetAdhocMatchingContext
* context
, ThreadMessage
* message
)
576 context
->inputlock
->lock();
579 message
->next
= context
->input_stack
;
580 context
->input_stack
= message
;
583 context
->inputlock
->unlock();
587 * Send Generic Thread Message
588 * @param context Matching Context Pointer
589 * @param stack ADHOC_MATCHING_EVENT_STACK or ADHOC_MATCHING_INPUT_STACK
590 * @param mac Target MAC
591 * @param opcode Message Opcode
592 * @param optlen Optional Data Length
593 * @param opt Optional Data
595 void sendGenericMessage(SceNetAdhocMatchingContext
* context
, int stack
, SceNetEtherAddr
* mac
, int opcode
, int optlen
, const void * opt
)
597 // Calculate Required Memory Size
598 uint32_t size
= sizeof(ThreadMessage
) + optlen
;
601 uint8_t * memory
= (uint8_t *)malloc(size
);
607 memset(memory
, 0, size
);
610 ThreadMessage
* header
= (ThreadMessage
*)memory
;
612 // Set Message Opcode
613 header
->opcode
= opcode
;
615 // Set Peer MAC Address
618 // Set Optional Data Length
619 header
->optlen
= optlen
;
622 memcpy(memory
+ sizeof(ThreadMessage
), opt
, optlen
);
624 // Link Thread Message
625 if (stack
== PSP_ADHOC_MATCHING_EVENT_STACK
) linkEVMessage(context
, header
);
627 // Link Thread Message to Input Stack
628 else linkIOMessage(context
, header
);
635 // Out of Memory Emergency Delete
636 deletePeer(context
, findPeer(context
, mac
));
641 * Send Accept Message from P2P -> P2P or Parent -> Children
642 * @param context Matching Context Pointer
643 * @param peer Target Peer
644 * @param optlen Optional Data Length
645 * @param opt Optional Data
647 void sendAcceptMessage(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
, int optlen
, const void * opt
)
649 // Send Accept Message
650 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_ACCEPT
, optlen
, opt
);
654 * Send Join Request from P2P -> P2P or Children -> Parent
655 * @param context Matching Context Pointer
656 * @param peer Target Peer
657 * @param optlen Optional Data Length
658 * @param opt Optional Data
660 void sendJoinRequest(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
, int optlen
, const void * opt
)
663 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_JOIN
, optlen
, opt
);
667 * Send Cancel Message to Peer (has various effects)
668 * @param context Matching Context Pointer
669 * @param peer Target Peer
670 * @param optlen Optional Data Length
671 * @param opt Optional Data
673 void sendCancelMessage(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
, int optlen
, const void * opt
)
675 // Send Cancel Message
676 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_CANCEL
, optlen
, opt
);
680 * Send Bulk Data to Peer
681 * @param context Matching Context Pointer
682 * @param peer Target Peer
683 * @param datalen Data Length
686 void sendBulkData(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
, int datalen
, const void * data
)
688 // Send Bulk Data Message
689 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_BULK
, datalen
, data
);
693 * Abort Bulk Data Transfer (if in progress)
694 * @param context Matching Context Pointer
695 * @param peer Target Peer
697 void abortBulkTransfer(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
)
699 // Send Bulk Data Abort Message
700 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_BULK_ABORT
, 0, NULL
);
704 * Notify all established Peers about new Kid in the Neighborhood
705 * @param context Matching Context Pointer
706 * @param peer New Kid
708 void sendBirthMessage(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
)
710 // Send Birth Message
711 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_BIRTH
, 0, NULL
);
715 * Notify all established Peers about abandoned Child
716 * @param context Matching Context Pointer
717 * @param peer Abandoned Child
719 void sendDeathMessage(SceNetAdhocMatchingContext
* context
, SceNetAdhocMatchingMemberInternal
* peer
)
721 // Send Death Message
722 sendGenericMessage(context
, PSP_ADHOC_MATCHING_INPUT_STACK
, &peer
->mac
, PSP_ADHOC_MATCHING_PACKET_DEATH
, 0, NULL
);
726 * Return Number of Connected Peers
727 * @param context Matching Context Pointer
728 * @return Number of Connected Peers
730 uint32_t countConnectedPeers(SceNetAdhocMatchingContext
* context
)
736 if (context
->mode
== PSP_ADHOC_MATCHING_MODE_PARENT
)
738 // Number of Children + 1 Parent (Self)
739 count
= countChildren(context
) + 1;
743 else if (context
->mode
== PSP_ADHOC_MATCHING_MODE_CHILD
)
745 // Default to 1 Child (Self)
748 // Connected to Parent
749 if (findParent(context
) != NULL
)
751 // Add Number of Siblings + 1 Parents
752 count
+= countChildren(context
) + 1;
759 // Default to 1 P2P Client (Self)
762 // Connected to another P2P Client
763 if (findP2P(context
) != NULL
)
775 * Spawn Local Event for Event Thread
776 * @param context Matching Context Pointer
777 * @param event Event ID
778 * @param mac Event Source MAC
779 * @param optlen Optional Data Length
780 * @param opt Optional Data
782 void spawnLocalEvent(SceNetAdhocMatchingContext
* context
, int event
, SceNetEtherAddr
* mac
, int optlen
, void * opt
)
785 sendGenericMessage(context
, PSP_ADHOC_MATCHING_EVENT_STACK
, mac
, event
, optlen
, opt
);
789 * Handle Timeouts in Matching Context
790 * @param context Matchi]ng Context Pointer
792 void handleTimeout(SceNetAdhocMatchingContext
* context
)
796 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
; while (peer
!= NULL
)
798 // Get Next Pointer (to avoid crash on memory freeing)
799 SceNetAdhocMatchingMemberInternal
* next
= peer
->next
;
801 u64_le now
= CoreTiming::GetGlobalTimeUsScaled(); //real_time_now()*1000000.0
803 if ((now
- peer
->lastping
) >= context
->timeout
)
805 // Spawn Timeout Event
806 if ((context
->mode
== PSP_ADHOC_MATCHING_MODE_CHILD
&& (peer
->state
== PSP_ADHOC_MATCHING_PEER_CHILD
|| peer
->state
== PSP_ADHOC_MATCHING_PEER_PARENT
)) ||
807 (context
->mode
== PSP_ADHOC_MATCHING_MODE_PARENT
&& peer
->state
== PSP_ADHOC_MATCHING_PEER_CHILD
) ||
808 (context
->mode
== PSP_ADHOC_MATCHING_MODE_P2P
&& peer
->state
== PSP_ADHOC_MATCHING_PEER_P2P
))
809 spawnLocalEvent(context
, PSP_ADHOC_MATCHING_EVENT_TIMEOUT
, &peer
->mac
, 0, NULL
);
811 INFO_LOG(SCENET
, "TimedOut Peer %02X:%02X:%02X:%02X:%02X:%02X (%lldms)", peer
->mac
.data
[0], peer
->mac
.data
[1], peer
->mac
.data
[2], peer
->mac
.data
[3], peer
->mac
.data
[4], peer
->mac
.data
[5], (context
->timeout
/1000));
813 // Delete Peer from List
814 deletePeer(context
, peer
);
824 * Recursive Stack Cleaner
825 * @param node Current Thread Message Node
827 void clearStackRecursive(ThreadMessage
* node
)
830 if (node
!= NULL
) clearStackRecursive(node
->next
);
832 // Free Last Existing Node of List (NULL is handled in _free)
838 * @param context Matching Context Pointer
839 * @param stack ADHOC_MATCHING_EVENT_STACK or ADHOC_MATCHING_INPUT_STACK
841 void clearStack(SceNetAdhocMatchingContext
* context
, int stack
)
843 if (context
== NULL
) return;
846 if (stack
== PSP_ADHOC_MATCHING_EVENT_STACK
)
848 context
->eventlock
->lock();
849 // Free Memory Recursively
850 clearStackRecursive(context
->event_stack
);
853 context
->event_stack
= NULL
;
855 context
->eventlock
->unlock();
861 context
->inputlock
->lock();
862 // Free Memory Recursively
863 clearStackRecursive(context
->input_stack
);
866 context
->input_stack
= NULL
;
868 context
->inputlock
->unlock();
874 * @param context Matching Context Pointer
876 void clearPeerList(SceNetAdhocMatchingContext
* context
)
882 SceNetAdhocMatchingMemberInternal
* peer
= context
->peerlist
;
886 context
->peerlist
= peer
->next
; //SceNetAdhocMatchingMemberInternal * next = peer->next;
889 free(peer
); //deletePeer(context, peer);
892 peer
= context
->peerlist
; //peer = next;
899 bool IsMatchingInCallback(SceNetAdhocMatchingContext
* context
) {
901 if (context
== NULL
) return inCB
;
902 context
->eventlock
->lock(); //peerlock.lock();
903 inCB
= (/*context != NULL &&*/ context
->IsMatchingInCB
);
904 context
->eventlock
->unlock(); //peerlock.unlock();
908 void AfterMatchingMipsCall::run(MipsCall
&call
) {
909 if (context
== NULL
) return;
910 DEBUG_LOG(SCENET
, "Entering AfterMatchingMipsCall::run [ID=%i][Event=%d] [cbId: %u]", context
->id
, EventID
, call
.cbId
);
911 //u32 v0 = currentMIPS->r[MIPS_REG_V0];
912 if (__IsInInterrupt()) ERROR_LOG(SCENET
, "AfterMatchingMipsCall::run [ID=%i][Event=%d] is Returning Inside an Interrupt!", context
->id
, EventID
);
913 //while (__IsInInterrupt()) sleep_ms(1); // Must not sleep inside callback handler
914 context
->eventlock
->lock(); //peerlock.lock();
915 //SceNetAdhocMatchingContext * context = findMatchingContext(ID);
916 //if (context != NULL)
918 context
->IsMatchingInCB
= false;
920 context
->eventlock
->unlock(); //peerlock.unlock();
921 //call.setReturnValue(v0);
922 DEBUG_LOG(SCENET
, "Leaving AfterMatchingMipsCall::run [ID=%i][Event=%d] [retV0: %08x]", context
->id
, EventID
, currentMIPS
->r
[MIPS_REG_V0
]);
925 void AfterMatchingMipsCall::SetContextID(u32 ContextID
, u32 eventId
) {
928 context
= findMatchingContext(ContextID
);
932 // Make sure MIPS calls have been fully executed before the next notifyAdhocctlHandlers
933 void notifyAdhocctlHandlers(u32 flag
, u32 error
) {
934 __UpdateAdhocctlHandlers(flag
, error
);
935 // TODO: We should use after action instead of guessing the time like this
936 sleep_ms(20); // Ugly workaround to give time for the mips callback to fully executed, usually only need <16ms
939 // Matching callback is void function: typedef void(*SceNetAdhocMatchingHandler)(int id, int event, SceNetEtherAddr * peer, int optlen, void * opt);
940 // Important! The MIPS call need to be fully executed before the next MIPS call invoked, as the game (ie. DBZ Tag Team) may need to prepare something for the next callback event to use
941 // Note: Must not lock peerlock within this function to prevent race-condition with other thread whos owning peerlock and trying to lock context->eventlock owned by this thread
942 void notifyMatchingHandler(SceNetAdhocMatchingContext
* context
, ThreadMessage
* msg
, void * opt
, u32
&bufAddr
, u32
&bufLen
, u32_le
* args
) {
943 //u32_le args[5] = { 0, 0, 0, 0, 0 };
944 if ((s32
)bufLen
< (msg
->optlen
+ 8)) {
945 bufLen
= msg
->optlen
+ 8;
946 if (Memory::IsValidAddress(bufAddr
)) userMemory
.Free(bufAddr
);
947 bufAddr
= userMemory
.Alloc(bufLen
);
948 INFO_LOG(SCENET
, "MatchingHandler: Alloc(%i -> %i) = %08x", msg
->optlen
+ 8, bufLen
, bufAddr
);
950 u8
* optPtr
= Memory::GetPointer(bufAddr
);
951 memcpy(optPtr
, &msg
->mac
, sizeof(msg
->mac
));
952 if (msg
->optlen
> 0) memcpy(optPtr
+ 8, opt
, msg
->optlen
);
953 args
[0] = context
->id
;
954 args
[1] = msg
->opcode
;
955 args
[2] = bufAddr
; // PSP_GetScratchpadMemoryBase() + 0x6000;
956 args
[3] = msg
->optlen
;
957 args
[4] = args
[2] + 8;
958 args
[5] = context
->handler
.entryPoint
; //not part of callback argument, just borrowing a space to store callback address so i don't need to search the context first later
960 context
->IsMatchingInCB
= true;
961 // ScheduleEvent_Threadsafe_Immediate seems to get mixed up with interrupt (returning from mipscall inside an interrupt) and getting invalid address before returning from interrupt
962 __UpdateMatchingHandler((u64
) args
);
964 // Make sure MIPS call have been fully executed before the next notifyMatchingHandler
966 while (/*(after != NULL) &&*/ IsMatchingInCallback(context
) && (count
< 250)) {
970 if (count
>= 250) ERROR_LOG(SCENET
, "MatchingHandler: Callback Failed to Return within %dms!", count
);
971 //sleep_ms(20); // Wait a little more (for context switching may be?) to prevent DBZ Tag Team from getting connection lost, but this will cause lags on Lord of Arcana
974 void freeFriendsRecursive(SceNetAdhocctlPeerInfo
* node
) {
976 if (node
== NULL
) return;
978 // Increase Recursion Depth
979 freeFriendsRecursive(node
->next
);
991 SceNetAdhocctlChatPacketC2S chat
;
992 chat
.base
.opcode
= OPCODE_CHAT
;
995 uint64_t lastping
= 0;
997 // Last Time Reception got updated
998 uint64_t lastreceptionupdate
= 0;
1003 INFO_LOG(SCENET
, "FriendFinder: Begin of Friend Finder Thread");
1006 while (friendFinderRunning
) {
1007 // Acquire Network Lock
1008 //_acquireNetworkLock();
1011 now
= real_time_now()*1000000.0; // should be in microseconds, but it seems real_time_now() returns in seconds
1012 if (now
- lastping
>= PSP_ADHOCCTL_PING_TIMEOUT
) { //100 // We need to use lower interval to prevent getting timeout at Pro Adhoc Server through internet
1013 // original code : ((sceKernelGetSystemTimeWide() - lastping) >= ADHOCCTL_PING_TIMEOUT)
1018 uint8_t opcode
= OPCODE_PING
;
1020 // Send Ping to Server, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP)
1021 int iResult
= send(metasocket
, (const char *)&opcode
, 1, 0);
1022 /*if (iResult == SOCKET_ERROR) {
1023 ERROR_LOG(SCENET, "FriendFinder: Socket Error (%i) when sending OPCODE_PING", errno);
1024 //friendFinderRunning = false;
1028 // Send Chat Messages
1029 //while(popFromOutbox(chat.message))
1031 // // Send Chat to Server
1032 // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0);
1035 // Wait for Incoming Data
1036 int received
= recv(metasocket
, (char *)(rx
+ rxpos
), sizeof(rx
) - rxpos
, 0);
1038 // Free Network Lock
1039 //_freeNetworkLock();
1046 // Log Incoming Traffic
1047 //printf("Received %d Bytes of Data from Server\n", received);
1048 INFO_LOG(SCENET
, "Received %d Bytes of Data from Adhoc Server", received
);
1054 if (rx
[0] == OPCODE_CONNECT_BSSID
) {
1055 INFO_LOG(SCENET
, "FriendFinder: Incoming OPCODE_CONNECT_BSSID");
1056 // Enough Data available
1057 if (rxpos
>= (int)sizeof(SceNetAdhocctlConnectBSSIDPacketS2C
)) {
1059 SceNetAdhocctlConnectBSSIDPacketS2C
* packet
= (SceNetAdhocctlConnectBSSIDPacketS2C
*)rx
;
1061 parameter
.bssid
.mac_addr
= packet
->mac
;
1063 threadStatus
= ADHOCCTL_STATE_CONNECTED
;
1064 // Notify Event Handlers
1065 notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT
, 0);
1068 memmove(rx
, rx
+ sizeof(SceNetAdhocctlConnectBSSIDPacketS2C
), sizeof(rx
) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C
));
1070 // Fix RX Buffer Length
1071 rxpos
-= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C
);
1076 else if (rx
[0] == OPCODE_CHAT
) {
1077 INFO_LOG(SCENET
, "FriendFinder: Incoming OPCODE_CHAT");
1078 // Enough Data available
1079 if (rxpos
>= (int)sizeof(SceNetAdhocctlChatPacketS2C
)) {
1081 SceNetAdhocctlChatPacketS2C
* packet
= (SceNetAdhocctlChatPacketS2C
*)rx
;
1083 // Fix for Idiots that try to troll the "ME" Nametag
1084 if (strcasecmp((char *)packet
->name
.data
, "ME") == 0) strcpy((char *)packet
->name
.data
, "NOT ME");
1086 // Add Incoming Chat to HUD
1087 //printf("Receive chat message %s", packet->base.message);
1088 DEBUG_LOG(SCENET
, "Received chat message %s", packet
->base
.message
);
1091 memmove(rx
, rx
+ sizeof(SceNetAdhocctlChatPacketS2C
), sizeof(rx
) - sizeof(SceNetAdhocctlChatPacketS2C
));
1093 // Fix RX Buffer Length
1094 rxpos
-= sizeof(SceNetAdhocctlChatPacketS2C
);
1099 else if (rx
[0] == OPCODE_CONNECT
) {
1100 DEBUG_LOG(SCENET
, "FriendFinder: OPCODE_CONNECT");
1101 // Enough Data available
1102 if (rxpos
>= (int)sizeof(SceNetAdhocctlConnectPacketS2C
)) {
1103 // Log Incoming Peer
1104 INFO_LOG(SCENET
, "Incoming Peer Data...");
1107 SceNetAdhocctlConnectPacketS2C
* packet
= (SceNetAdhocctlConnectPacketS2C
*)rx
;
1112 // Update HUD User Count
1113 #ifdef LOCALHOST_AS_PEER
1114 setUserCount(getActivePeerCount());
1116 // setUserCount(getActivePeerCount()+1);
1120 memmove(rx
, rx
+ sizeof(SceNetAdhocctlConnectPacketS2C
), sizeof(rx
) - sizeof(SceNetAdhocctlConnectPacketS2C
));
1122 // Fix RX Buffer Length
1123 rxpos
-= sizeof(SceNetAdhocctlConnectPacketS2C
);
1127 // Disconnect Packet
1128 else if (rx
[0] == OPCODE_DISCONNECT
) {
1129 DEBUG_LOG(SCENET
, "FriendFinder: OPCODE_DISCONNECT");
1130 // Enough Data available
1131 if (rxpos
>= (int)sizeof(SceNetAdhocctlDisconnectPacketS2C
)) {
1132 // Log Incoming Peer Delete Request
1133 INFO_LOG(SCENET
, "FriendFinder: Incoming Peer Data Delete Request...");
1136 SceNetAdhocctlDisconnectPacketS2C
* packet
= (SceNetAdhocctlDisconnectPacketS2C
*)rx
;
1138 // Delete User by IP, should delete by MAC since IP can be shared (behind NAT) isn't?
1139 deleteFriendByIP(packet
->ip
);
1141 // Update HUD User Count
1142 #ifdef LOCALHOST_AS_PEER
1143 setUserCount(_getActivePeerCount());
1145 //setUserCount(_getActivePeerCount()+1);
1149 memmove(rx
, rx
+ sizeof(SceNetAdhocctlDisconnectPacketS2C
), sizeof(rx
) - sizeof(SceNetAdhocctlDisconnectPacketS2C
));
1151 // Fix RX Buffer Length
1152 rxpos
-= sizeof(SceNetAdhocctlDisconnectPacketS2C
);
1157 else if (rx
[0] == OPCODE_SCAN
) {
1158 DEBUG_LOG(SCENET
, "FriendFinder: OPCODE_SCAN");
1159 // Enough Data available
1160 if (rxpos
>= (int)sizeof(SceNetAdhocctlScanPacketS2C
)) {
1161 // Log Incoming Network Information
1162 INFO_LOG(SCENET
, "Incoming Group Information...");
1164 SceNetAdhocctlScanPacketS2C
* packet
= (SceNetAdhocctlScanPacketS2C
*)rx
;
1166 // Multithreading Lock
1169 // Should only add non-existing group (or replace an existing group) to prevent Ford Street Racing from showing a strange game session list
1170 /*SceNetAdhocctlScanInfo * group = findGroup(&packet->mac);
1172 if (group != NULL) {
1174 group->group_name = packet->group;
1177 group->bssid.mac_addr = packet->mac;
1181 // Allocate Structure Data
1182 SceNetAdhocctlScanInfo
* group
= (SceNetAdhocctlScanInfo
*)malloc(sizeof(SceNetAdhocctlScanInfo
));
1184 // Allocated Structure Data
1187 // Clear Memory, should this be done only when allocating new group?
1188 memset(group
, 0, sizeof(SceNetAdhocctlScanInfo
));
1190 // Link to existing Groups
1191 group
->next
= newnetworks
;
1194 group
->group_name
= packet
->group
;
1197 group
->bssid
.mac_addr
= packet
->mac
;
1199 // Link into Group List
1200 newnetworks
= group
;
1204 // Multithreading Unlock
1208 memmove(rx
, rx
+ sizeof(SceNetAdhocctlScanPacketS2C
), sizeof(rx
) - sizeof(SceNetAdhocctlScanPacketS2C
));
1210 // Fix RX Buffer Length
1211 rxpos
-= sizeof(SceNetAdhocctlScanPacketS2C
);
1215 // Scan Complete Packet
1216 else if (rx
[0] == OPCODE_SCAN_COMPLETE
) {
1217 DEBUG_LOG(SCENET
, "FriendFinder: OPCODE_SCAN_COMPLETE");
1218 // Log Scan Completion
1219 INFO_LOG(SCENET
, "FriendFinder: Incoming Scan complete response...");
1221 // Reset current networks to prevent leaving host to be listed again
1223 freeGroupsRecursive(networks
);
1224 networks
= newnetworks
;
1229 threadStatus
= ADHOCCTL_STATE_DISCONNECTED
;
1231 // Notify Event Handlers
1232 notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN
, 0);
1233 //int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++)
1235 // // Active Handler
1236 // if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]);
1240 memmove(rx
, rx
+ 1, sizeof(rx
) - 1);
1242 // Fix RX Buffer Length
1246 // Original value was 10 ms, I think 100 is just fine
1247 sleep_ms(1); // Using 1ms for faster response just like AdhocServer
1249 // Don't do anything if it's paused, otherwise the log will be flooded
1250 while (Core_IsStepping() && friendFinderRunning
) sleep_ms(1);
1253 // Groups/Networks should be deallocated isn't?
1255 // Prevent the games from having trouble to reInitiate Adhoc (the next NetInit -> PdpCreate after NetTerm)
1256 threadStatus
= ADHOCCTL_STATE_DISCONNECTED
;
1259 INFO_LOG(SCENET
, "FriendFinder: End of Friend Finder Thread");
1265 int getActivePeerCount(void) {
1269 // #ifdef LOCALHOST_AS_PEER
1270 // // Increase for Localhost
1275 SceNetAdhocctlPeerInfo
* peer
= friends
;
1278 for (; peer
!= NULL
; peer
= peer
->next
) {
1287 int getLocalIp(sockaddr_in
* SocketAddress
){
1288 #if defined(_MSC_VER)
1289 // Get local host name
1290 char szHostName
[128] = "";
1292 if(::gethostname(szHostName
, sizeof(szHostName
))) {
1295 // Get local IP addresses
1296 struct hostent
*pHost
= 0;
1297 pHost
= ::gethostbyname(szHostName
);
1299 memcpy(&SocketAddress
->sin_addr
, pHost
->h_addr_list
[0], pHost
->h_length
);
1304 SocketAddress
->sin_addr
.s_addr
= inet_addr("192.168.12.1");
1309 uint32_t getLocalIp(int sock
) {
1310 struct sockaddr_in localAddr
;
1311 localAddr
.sin_addr
.s_addr
= INADDR_ANY
;
1312 socklen_t addrLen
= sizeof(localAddr
);
1313 getsockname(sock
, (struct sockaddr
*)&localAddr
, &addrLen
);
1314 return localAddr
.sin_addr
.s_addr
;
1317 void getLocalMac(SceNetEtherAddr
* addr
){
1318 // Read MAC Address from config
1319 uint8_t mac
[ETHER_ADDR_LEN
] = {0};
1320 if (!ParseMacAddress(g_Config
.sMACAddress
.c_str(), mac
)) {
1321 ERROR_LOG(SCENET
, "Error parsing mac address %s", g_Config
.sMACAddress
.c_str());
1323 memcpy(addr
, mac
, ETHER_ADDR_LEN
);
1326 uint16_t getLocalPort(int sock
) {
1327 struct sockaddr_in localAddr
;
1328 localAddr
.sin_port
= 0;
1329 socklen_t addrLen
= sizeof(localAddr
);
1330 getsockname(sock
, (struct sockaddr
*)&localAddr
, &addrLen
);
1331 return ntohs(localAddr
.sin_port
);
1334 int getSockBufferSize(int sock
, int opt
) { // opt = SO_RCVBUF/SO_SNDBUF
1336 socklen_t m
= sizeof(n
);
1337 getsockopt(sock
, SOL_SOCKET
, opt
, (char *)&n
, &m
); // in linux the value is twice of the value being set using setsockopt
1341 int setSockBufferSize(int sock
, int opt
, int size
) { // opt = SO_RCVBUF/SO_SNDBUF
1342 int n
= size
; // 8192; //16384
1343 return setsockopt(sock
, SOL_SOCKET
, opt
, (char *)&n
, sizeof(n
));
1347 * Return the Number of Players with the chosen Nickname in the Local Users current Network
1348 * @param nickname To-be-searched Nickname
1349 * @return Number of matching Players
1351 int getNicknameCount(const char * nickname
)
1356 // Local Nickname Matches
1357 if (strcmp((char *)parameter
.nickname
.data
, nickname
) == 0) count
++;
1360 SceNetAdhocctlPeerInfo
* peer
= friends
;
1363 for (; peer
!= NULL
; peer
= peer
->next
)
1366 if (strcmp((char *)peer
->nickname
.data
, nickname
) == 0) count
++;
1374 * PDP Socket Counter
1375 * @return Number of internal PDP Sockets
1377 int getPDPSocketCount(void)
1383 int i
= 0; for (; i
< 255; i
++) if (pdp
[i
] != NULL
) counter
++;
1385 // Return Socket Count
1389 int getPTPSocketCount(void) {
1394 int i
= 0; for (; i
< 255; i
++) if (ptp
[i
] != NULL
) counter
++;
1396 // Return Socket Count
1400 int initNetwork(SceNetAdhocctlAdhocId
*adhoc_id
){
1402 metasocket
= (int)INVALID_SOCKET
;
1403 metasocket
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
1404 if (metasocket
== INVALID_SOCKET
){
1405 ERROR_LOG(SCENET
, "Invalid socket");
1408 struct sockaddr_in server_addr
;
1409 server_addr
.sin_family
= AF_INET
;
1410 server_addr
.sin_port
= htons(SERVER_PORT
); //27312 // Maybe read this from config too
1413 addrinfo
* resultAddr
;
1416 serverIp
.s_addr
= INADDR_NONE
;
1418 iResult
= getaddrinfo(g_Config
.proAdhocServer
.c_str(),0,NULL
,&resultAddr
);
1420 ERROR_LOG(SCENET
, "DNS Error (%s)\n", g_Config
.proAdhocServer
.c_str());
1421 osm
.Show("DNS Error connecting to " + g_Config
.proAdhocServer
, 8.0f
);
1424 for (ptr
= resultAddr
; ptr
!= NULL
; ptr
= ptr
->ai_next
) {
1425 switch (ptr
->ai_family
) {
1427 serverIp
= ((sockaddr_in
*)ptr
->ai_addr
)->sin_addr
;
1432 memset(¶meter
, 0, sizeof(parameter
));
1433 strcpy((char *)¶meter
.nickname
.data
, g_Config
.sNickName
.c_str());
1434 parameter
.channel
= 1; // Fake Channel 1
1435 getLocalMac(¶meter
.bssid
.mac_addr
);
1437 server_addr
.sin_addr
= serverIp
;
1438 iResult
= connect(metasocket
,(sockaddr
*)&server_addr
,sizeof(server_addr
));
1439 if (iResult
== SOCKET_ERROR
) {
1440 uint8_t * sip
= (uint8_t *)&server_addr
.sin_addr
.s_addr
;
1442 snprintf(buffer
, sizeof(buffer
), "Socket error (%i) when connecting to %s/%u.%u.%u.%u:%u", errno
, g_Config
.proAdhocServer
.c_str(), sip
[0], sip
[1], sip
[2], sip
[3], ntohs(server_addr
.sin_port
));
1443 ERROR_LOG(SCENET
, "%s", buffer
);
1444 osm
.Show(std::string(buffer
), 8.0f
);
1448 // Prepare Login Packet
1449 SceNetAdhocctlLoginPacketC2S packet
;
1450 packet
.base
.opcode
= OPCODE_LOGIN
;
1451 SceNetEtherAddr addres
;
1452 getLocalMac(&addres
);
1453 packet
.mac
= addres
;
1454 strcpy((char *)packet
.name
.data
, g_Config
.sNickName
.c_str());
1455 memcpy(packet
.game
.data
, adhoc_id
->data
, ADHOCCTL_ADHOCID_LEN
);
1456 int sent
= send(metasocket
, (char*)&packet
, sizeof(packet
), 0);
1457 changeBlockingMode(metasocket
, 1); // Change to non-blocking
1459 I18NCategory
*n
= GetI18NCategory("Networking");
1460 osm
.Show(n
->T("Network Initialized"), 1.0);
1468 bool isBroadcastMAC(const SceNetEtherAddr
* addr
) {
1470 if (memcmp(addr
->data
, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN
) == 0) return true;
1475 bool resolveIP(uint32_t ip
, SceNetEtherAddr
* mac
) {
1478 uint32 localIp
= addr
.sin_addr
.s_addr
;
1485 // Multithreading Lock
1489 SceNetAdhocctlPeerInfo
* peer
= friends
;
1492 for (; peer
!= NULL
; peer
= peer
->next
) {
1493 // Found Matching Peer
1494 if (peer
->ip_addr
== ip
) {
1496 *mac
= peer
->mac_addr
;
1498 // Multithreading Unlock
1506 // Multithreading Unlock
1513 bool resolveMAC(SceNetEtherAddr
* mac
, uint32_t * ip
) {
1514 // Get Local MAC Address
1515 SceNetEtherAddr localMac
;
1516 getLocalMac(&localMac
);
1517 // Local MAC Requested
1518 if (memcmp(&localMac
, mac
, sizeof(SceNetEtherAddr
)) == 0) {
1519 // Get Local IP Address
1520 sockaddr_in sockAddr
;
1521 getLocalIp(&sockAddr
);
1522 *ip
= sockAddr
.sin_addr
.s_addr
;
1523 return true; // return succes
1526 // Multithreading Lock
1530 SceNetAdhocctlPeerInfo
* peer
= friends
;
1533 for (; peer
!= NULL
; peer
= peer
->next
) {
1534 // Found Matching Peer
1535 if (memcmp(&peer
->mac_addr
, mac
, sizeof(SceNetEtherAddr
)) == 0) {
1537 *ip
= peer
->ip_addr
;
1539 // Multithreading Unlock
1547 // Multithreading Unlock
1554 bool validNetworkName(const SceNetAdhocctlGroupName
* group_name
) {
1559 if (group_name
!= NULL
) {
1560 // Iterate Name Characters
1561 int i
= 0; for (; i
< ADHOCCTL_GROUPNAME_LEN
&& valid
; i
++) {
1563 if (group_name
->data
[i
] == 0) break;
1566 if (group_name
->data
[i
] < '0' || group_name
->data
[i
] > '9') {
1568 if (group_name
->data
[i
] < 'A' || group_name
->data
[i
] > 'Z') {
1570 if (group_name
->data
[i
] < 'a' || group_name
->data
[i
] > 'z') {
1582 u64
join32(u32 num1
, u32 num2
){
1583 return (u64
)num2
<< 32 | num1
;
1586 void split64(u64 num
, int buff
[]){
1587 int num1
= (int)(num
&firstMask
);
1588 int num2
= (int)((num
&secondMask
) >> 32);
1593 const char* getMatchingEventStr(int code
) {
1594 const char *buf
= NULL
;
1596 case PSP_ADHOC_MATCHING_EVENT_HELLO
:
1597 buf
= "HELLO"; break;
1598 case PSP_ADHOC_MATCHING_EVENT_REQUEST
:
1599 buf
= "JOIN"; break;
1600 case PSP_ADHOC_MATCHING_EVENT_LEAVE
:
1601 buf
= "LEAVE"; break;
1602 case PSP_ADHOC_MATCHING_EVENT_DENY
:
1603 buf
= "REJECT"; break;
1604 case PSP_ADHOC_MATCHING_EVENT_CANCEL
:
1605 buf
= "CANCEL"; break;
1606 case PSP_ADHOC_MATCHING_EVENT_ACCEPT
:
1607 buf
= "ACCEPT"; break;
1608 case PSP_ADHOC_MATCHING_EVENT_ESTABLISHED
:
1609 buf
= "ESTABLISHED"; break;
1610 case PSP_ADHOC_MATCHING_EVENT_TIMEOUT
:
1611 buf
= "TIMEOUT"; break;
1612 case PSP_ADHOC_MATCHING_EVENT_ERROR
:
1613 buf
= "ERROR"; break;
1614 case PSP_ADHOC_MATCHING_EVENT_BYE
:
1615 buf
= "DISCONNECT"; break;
1616 case PSP_ADHOC_MATCHING_EVENT_DATA
:
1617 buf
= "DATA"; break;
1618 case PSP_ADHOC_MATCHING_EVENT_DATA_ACK
:
1619 buf
= "DATA_ACK"; break;
1620 case PSP_ADHOC_MATCHING_EVENT_DATA_TIMEOUT
:
1621 buf
= "DATA_TIMEOUT"; break;
1622 case PSP_ADHOC_MATCHING_EVENT_INTERNAL_PING
:
1623 buf
= "INTERNAL_PING"; break;
1630 const char* getMatchingOpcodeStr(int code
) {
1631 const char *buf
= NULL
;
1633 case PSP_ADHOC_MATCHING_PACKET_PING
:
1634 buf
= "PING"; break;
1635 case PSP_ADHOC_MATCHING_PACKET_HELLO
:
1636 buf
= "HELLO"; break;
1637 case PSP_ADHOC_MATCHING_PACKET_JOIN
:
1638 buf
= "JOIN"; break;
1639 case PSP_ADHOC_MATCHING_PACKET_ACCEPT
:
1640 buf
= "ACCEPT"; break;
1641 case PSP_ADHOC_MATCHING_PACKET_CANCEL
:
1642 buf
= "CANCEL"; break;
1643 case PSP_ADHOC_MATCHING_PACKET_BULK
:
1644 buf
= "BULK"; break;
1645 case PSP_ADHOC_MATCHING_PACKET_BULK_ABORT
:
1646 buf
= "BULK_ABORT"; break;
1647 case PSP_ADHOC_MATCHING_PACKET_BIRTH
:
1648 buf
= "BIRTH"; break;
1649 case PSP_ADHOC_MATCHING_PACKET_DEATH
:
1650 buf
= "DEATH"; break;
1651 case PSP_ADHOC_MATCHING_PACKET_BYE
: