Files
ppsspp/Core/HLE/proAdhocServer.h
T
libretroadmin f1208a7a5a Make threading lock-free
The core and the headless tools no longer use mutexes, condition variables,
spinlocks, std::atomic, std::thread or volatile flags. Threads hand off through
libretro-common's retro_atomic and rthreads plus a few small pieces on top of
them in Common/Thread: Thread, MpscQueue, EventCounter, ParkingLot waits and
ReaderGate. Every wait blocks until it's woken; nothing polls on a timer.

State that only one thread touches just loses its lock. The PSP filesystem,
sceIo and the savedata dialog now belong to the emulation thread: async reads
and writes run when they're queued and complete later in emulated time, and
the IO and savedata threads are gone. The friend finder only talks to the
adhoc server and hands what it gets to the emulation thread. GPU init always
runs on the thread that starts the game.

The Vulkan render and compile queues, pipeline and render pass caches, delete
list and SPIR-V cache, the GL render queue, the software renderer's jit caches,
the file loader caches, the web debugger, UPnP, input, savestates, logging and
the GE debugger all hand off through queues and atomics. The IR jit's spinning
profiler thread goes.

A CPU thread with nothing to run now sleeps until work is queued instead of
spinning. Headless with --debugger waits for a client while stopped, and ends
the run once every client that connected has left. Web server shutdown keeps
servicing the CPU queue until the server has finished.
2026-10-09 04:56:16 +02:00

380 lines
8.4 KiB
C++

// Copyright (c) 2014- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// proAdhocServer
// This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
// All credit goes to him!
#pragma once
#include <cstdint>
#include <time.h>
#include "proAdhoc.h"
#include "Common/Thread/Thread.h"
// Server Listening Port
//#define SERVER_PORT 27312
// Listener Connection Backlog (aka. Max Concurrent Logins)
#define SERVER_LISTEN_BACKLOG 128
// Server User Maximum
#define SERVER_USER_MAXIMUM 1024
// Server User Timeout (in seconds)
#define SERVER_USER_TIMEOUT 15
// Server SQLite3 Database
#define SERVER_DATABASE "database.db"
// Server Status Logfile
#define SERVER_STATUS_XMLOUT "www/status.xml"
// Server Shutdown Message
#define SERVER_SHUTDOWN_MESSAGE "ADHOC SERVER HUB IS SHUTTING DOWN!"
typedef struct db_crosslink{
char id_from[PRODUCT_CODE_LENGTH + 1]; //SceNetAdhocctlProductCode id_from;
char id_to[PRODUCT_CODE_LENGTH + 1]; //SceNetAdhocctlProductCode id_to;
} db_crosslink;
typedef struct db_productid {
char id[PRODUCT_CODE_LENGTH + 1]; //SceNetAdhocctlProductCode id;
char name[ADHOCCTL_NICKNAME_LEN]; //Title name
} db_productid;
/* PSPSTRUCTS */
// Ethernet Address (MAC)
/*#define ETHER_ADDR_LEN 6
typedef struct SceNetEtherAddr {
uint8_t data[ETHER_ADDR_LEN];
} SceNetEtherAddr;
// Adhoc Virtual Network Name (1234ABCD)
#define ADHOCCTL_GROUPNAME_LEN 8
typedef struct SceNetAdhocctlGroupName {
uint8_t data[ADHOCCTL_GROUPNAME_LEN];
} SceNetAdhocctlGroupName;
// Player Nickname
#define ADHOCCTL_NICKNAME_LEN 128
typedef struct SceNetAdhocctlNickname {
uint8_t data[ADHOCCTL_NICKNAME_LEN];
} SceNetAdhocctlNickname;*/
/* PACKETS */
/*#define OPCODE_PING 0
#define OPCODE_LOGIN 1
#define OPCODE_CONNECT 2
#define OPCODE_DISCONNECT 3
#define OPCODE_SCAN 4
#define OPCODE_SCAN_COMPLETE 5
#define OPCODE_CONNECT_BSSID 6
#define OPCODE_CHAT 7
// PSP Product Code
#define PRODUCT_CODE_LENGTH 9
typedef struct
{
// Game Product Code (ex. ULUS12345)
char data[PRODUCT_CODE_LENGTH];
} PACK SceNetAdhocctlProductCode; // __attribute__((packed))
// Basic Packet
typedef struct
{
uint8_t opcode;
} PACK SceNetAdhocctlPacketBase;
// C2S Login Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
SceNetEtherAddr mac;
SceNetAdhocctlNickname name;
SceNetAdhocctlProductCode game;
} PACK SceNetAdhocctlLoginPacketC2S;
// C2S Connect Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
SceNetAdhocctlGroupName group;
} PACK SceNetAdhocctlConnectPacketC2S;
// C2S Chat Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
char message[64];
} PACK SceNetAdhocctlChatPacketC2S;
// S2C Connect Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
SceNetAdhocctlNickname name;
SceNetEtherAddr mac;
uint32_t ip;
} PACK SceNetAdhocctlConnectPacketS2C;
// S2C Disconnect Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
uint32_t ip;
} PACK SceNetAdhocctlDisconnectPacketS2C;
// S2C Scan Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
SceNetAdhocctlGroupName group;
SceNetEtherAddr mac;
} PACK SceNetAdhocctlScanPacketS2C;
// S2C Connect BSSID Packet
typedef struct
{
SceNetAdhocctlPacketBase base;
SceNetEtherAddr mac;
} PACK SceNetAdhocctlConnectBSSIDPacketS2C;
// S2C Chat Packet
typedef struct
{
SceNetAdhocctlChatPacketC2S base;
SceNetAdhocctlNickname name;
} PACK SceNetAdhocctlChatPacketS2C;*/
/* USER */
// User States
#define USER_STATE_WAITING 0
#define USER_STATE_LOGGED_IN 1
#define USER_STATE_TIMED_OUT 2
// PSP Resolver Information
typedef struct
{
// PSP MAC Address
SceNetEtherAddr mac;
// PSP Hotspot IP Address
uint32_t ip;
// PSP Player Name
SceNetAdhocctlNickname name;
} SceNetAdhocctlResolverInfo;
// Type Prototypes
typedef struct SceNetAdhocctlGameNode SceNetAdhocctlGameNode;
typedef struct SceNetAdhocctlGroupNode SceNetAdhocctlGroupNode;
// Double-Linked User List
typedef struct SceNetAdhocctlUserNode {
// Next Element
struct SceNetAdhocctlUserNode * next;
// Previous Element
struct SceNetAdhocctlUserNode * prev;
// Next Element (Group)
struct SceNetAdhocctlUserNode * group_next;
// Previous Element
struct SceNetAdhocctlUserNode * group_prev;
// Resolver Information
SceNetAdhocctlResolverInfo resolver;
// Game Link
SceNetAdhocctlGameNode * game;
// Group Link
SceNetAdhocctlGroupNode * group;
// TCP Socket
int stream;
// Last Ping Update
time_t last_recv;
// RX Buffer
uint8_t rx[1024];
uint32_t rxpos;
// rxpos at the end of the last pass: a change means another packet may be buffered.
uint32_t rxseen;
} SceNetAdhocctlUserNode;
// Double-Linked Game List
struct SceNetAdhocctlGameNode {
// Next Element
struct SceNetAdhocctlGameNode * next;
// Previous Element
struct SceNetAdhocctlGameNode * prev;
// PSP Game Product Code
SceNetAdhocctlProductCode game;
// Number of Players
uint32_t playercount;
// Number of Groups
uint32_t groupcount;
// Double-Linked Group List
SceNetAdhocctlGroupNode * group;
};
// Double-Linked Group List
struct SceNetAdhocctlGroupNode {
// Next Element
struct SceNetAdhocctlGroupNode * next;
// Previous Element
struct SceNetAdhocctlGroupNode * prev;
// Game Link
SceNetAdhocctlGameNode * game;
// PSP Adhoc Group Name
SceNetAdhocctlGroupName group;
// Number of Players
uint32_t playercount;
// Double-Linked Player List
SceNetAdhocctlUserNode * player;
};
// User Count
extern uint32_t _db_user_count;
// User Database
extern SceNetAdhocctlUserNode * _db_user;
// Game Database
extern SceNetAdhocctlGameNode * _db_game;
void __AdhocServerInit();
/**
* Login User into Database (Stream)
* @param fd Socket
* @param ip IP Address (Network Order)
*/
void login_user_stream(int fd, uint32_t ip);
/**
* Login User into Database (Login Data)
* @param user User Node
* @param data Login Packet
*/
void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S * data);
/**
* Logout User from Database
* @param user User Node
*/
void logout_user(SceNetAdhocctlUserNode * user);
/**
* Free Database Memory
*/
void free_database();
/**
* Connect User to Game Group
* @param user User Node
* @param group Group Name
*/
void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group);
/**
* Disconnect User from Game Group
* @param user User Node
*/
void disconnect_user(SceNetAdhocctlUserNode * user);
/**
* Send Game Group List
* @param user User Node
*/
void send_scan_results(SceNetAdhocctlUserNode * user);
/**
* Spread Chat Message in P2P Network
* @param user Sender User Node
* @param message Chat Message
*/
void spread_message(SceNetAdhocctlUserNode *user, const char *message);
/**
* Get User State
* @param user User Node
*/
int get_user_state(SceNetAdhocctlUserNode * user);
/**
* Clear RX Buffer
* @param user User Node
* @param clear Number of Bytes to clear (-1 for all)
*/
void clear_user_rxbuf(SceNetAdhocctlUserNode * user, int clear);
/**
* Patch Game Product Code
* @param product To-be-patched Product Code
* @param from If the Product Code matches this...
* @param to ... then change it to this one.
*/
void game_product_relink(SceNetAdhocctlProductCode * product, char * from, char * to);
/**
* Game Product Override (used for mixing multi-region games)
* @param product IN: Source Product OUT: Override Product
*/
void game_product_override(SceNetAdhocctlProductCode * product);
/* STATUS */
/**
* Update Status Logfile
*/
void update_status();
/**
* Server Entry Point
* @param argc Number of Arguments
* @param argv Arguments
* @return OS Error Code
*/
int proAdhocServerThread(int port); // (int argc, char * argv[])
//extern int _status;
extern retro_atomic_int_t adhocServerRunning;
extern Thread adhocServerThread;
// Make the wake before starting the thread; wake it after clearing adhocServerRunning.
void AdhocServerPrepare();
void AdhocServerWake();