This commit is contained in:
Nayla Hanegan 2023-04-05 04:26:12 -04:00
commit 7db3945cc1
No known key found for this signature in database
GPG key ID: BAFE9001DA16CFA2
58 changed files with 980 additions and 496 deletions

3
.gitmodules vendored
View file

@ -51,3 +51,6 @@
[submodule "Externals/gtest"]
path = Externals/gtest
url = https://github.com/google/googletest.git
[submodule "Externals/rcheevos/rcheevos"]
path = Externals/rcheevos/rcheevos
url = https://github.com/RetroAchievements/rcheevos.git

View file

@ -72,6 +72,7 @@ option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence, show the current gam
option(USE_MGBA "Enables GBA controllers emulation using libmgba" ON)
option(ENABLE_AUTOUPDATE "Enables support for automatic updates" ON)
option(STEAM "Creates a build for Steam" OFF)
option(USE_RETRO_ACHIEVEMENTS "Enables integration with retroachievements.org" ON)
# Maintainers: if you consider blanket disabling this for your users, please
# consider the following points:
@ -975,6 +976,10 @@ add_subdirectory(Externals/rangeset)
add_subdirectory(Externals/FatFs)
if (USE_RETRO_ACHIEVEMENTS)
add_subdirectory(Externals/rcheevos)
endif()
########################################
# Pre-build events: Define configuration variables and write SCM info header
#

View file

@ -61,7 +61,20 @@ endif()
include_directories(${PROJECT_SOURCE_DIR}/include)
add_library(enet STATIC
set(INCLUDE_FILES_PREFIX include/enet)
set(INCLUDE_FILES
${INCLUDE_FILES_PREFIX}/callbacks.h
${INCLUDE_FILES_PREFIX}/enet.h
${INCLUDE_FILES_PREFIX}/list.h
${INCLUDE_FILES_PREFIX}/protocol.h
${INCLUDE_FILES_PREFIX}/time.h
${INCLUDE_FILES_PREFIX}/types.h
${INCLUDE_FILES_PREFIX}/unix.h
${INCLUDE_FILES_PREFIX}/utility.h
${INCLUDE_FILES_PREFIX}/win32.h
)
set(SOURCE_FILES
callbacks.c
compress.c
host.c
@ -70,9 +83,22 @@ add_library(enet STATIC
peer.c
protocol.c
unix.c
win32.c
)
win32.c)
source_group(include FILES ${INCLUDE_FILES})
source_group(source FILES ${SOURCE_FILES})
add_library(enet STATIC
${INCLUDE_FILES}
${SOURCE_FILES}
)
dolphin_disable_warnings_msvc(enet)
if (MINGW)
target_link_libraries(enet winmm ws2_32)
endif()
if(HAIKU)
target_link_libraries(enet network)
endif(HAIKU)

View file

@ -1,4 +1,25 @@
ENet 1.3.17 (November 15, 2020):
* fixes for sender getting too far ahead of receiver that can cause instability with reliable packets
ENet 1.3.16 (September 8, 2020):
* fix bug in unreliable fragment queuing
* use single output queue for reliable and unreliable packets for saner ordering
* revert experimental throttle changes that were less stable than prior algorithm
ENet 1.3.15 (April 20, 2020):
* quicker RTT initialization
* use fractional precision for RTT calculations
* fixes for packet throttle with low RTT variance
* miscellaneous socket bug fixes
ENet 1.3.14 (January 27, 2019):
* bug fix for enet_peer_disconnect_later()
* use getaddrinfo and getnameinfo where available
* miscellaneous cleanups
ENet 1.3.13 (April 30, 2015):

View file

@ -38,7 +38,7 @@ PROJECT_NAME = "ENet"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v1.3.13
PROJECT_NUMBER = v1.3.17
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View file

@ -1,4 +1,4 @@
Copyright (c) 2002-2015 Lee Salzman
Copyright (c) 2002-2020 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View file

@ -16,7 +16,7 @@ enetinclude_HEADERS = \
lib_LTLIBRARIES = libenet.la
libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c
# see info '(libtool) Updating version info' before making a release
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:1:0
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:5:0
AM_CPPFLAGS = -I$(top_srcdir)/include
ACLOCAL_AMFLAGS = -Im4

View file

@ -1,4 +1,4 @@
Please visit the ENet homepage at http://enet.bespin.org for installation
Please visit the ENet homepage at http://sauerbraten.org/enet/ for installation
and usage instructions.
If you obtained this package from github, the quick description on how to build

View file

@ -1,4 +1,4 @@
AC_INIT([libenet], [1.3.13])
AC_INIT([libenet], [1.3.17])
AC_CONFIG_SRCDIR([include/enet/enet.h])
AM_INIT_AUTOMAKE([foreign])

View file

@ -1,7 +1,7 @@
/**
@page License License
Copyright (c) 2002-2015 Lee Salzman
Copyright (c) 2002-2020 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View file

@ -36,7 +36,7 @@ portable, and easily embeddable.
You can retrieve the source to ENet by downloading it in either .tar.gz form
or accessing the github distribution directly.
The most recent stable release (1.3.13) can be downloaded <a class="el" href="download/enet-1.3.13.tar.gz">here</a>.
The most recent stable release (1.3.17) can be downloaded <a class="el" href="download/enet-1.3.17.tar.gz">here</a>.
The last release that is protocol compatible with the 1.2 series or earlier (1.2.5) can be downloaded <a class="el" href="download/enet-1.2.5.tar.gz">here</a>.
You can find the most recent ENet source at <a class="el" href="https://github.com/lsalzman/enet">the github repository</a>.
@ -53,7 +53,7 @@ The <a class="el" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">en
/**
@page IRCChannel IRC Channel
Join the \#enet channel on the <a class="el" href="http://freenode.net">freenode IRC network (irc.freenode.net)</a> for real-time discussion about the ENet library.
Join the \#enet channel on the <a class="el" href="https://libera.chat">Libera Chat IRC network (irc.libera.chat)</a> for real-time discussion about the ENet library.
*/

View file

@ -102,8 +102,8 @@ may be simultaneously open.
client = enet_host_create (NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
2 /* allow up 2 channels to be used, 0 and 1 */,
57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
0 /* assume any amount of incoming bandwidth */,
0 /* assume any amount of outgoing bandwidth */);
if (client == NULL)
{

19
Externals/enet/host.c vendored
View file

@ -96,6 +96,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
host -> totalSentPackets = 0;
host -> totalReceivedData = 0;
host -> totalReceivedPackets = 0;
host -> totalQueued = 0;
host -> connectedPeers = 0;
host -> bandwidthLimitedPeers = 0;
@ -123,9 +124,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> sentUnreliableCommands);
enet_list_clear (& currentPeer -> outgoingReliableCommands);
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
enet_list_clear (& currentPeer -> outgoingCommands);
enet_list_clear (& currentPeer -> outgoingSendReliableCommands);
enet_list_clear (& currentPeer -> dispatchedCommands);
enet_peer_reset (currentPeer);
@ -161,6 +161,16 @@ enet_host_destroy (ENetHost * host)
enet_free (host);
}
enet_uint32
enet_host_random (ENetHost * host)
{
/* Mulberry32 by Tommy Ettinger */
enet_uint32 n = (host -> randomSeed += 0x6D2B79F5U);
n = (n ^ (n >> 15)) * (n | 1U);
n ^= n + (n ^ (n >> 7)) * (n | 61U);
return n ^ (n >> 14);
}
/** Initiates a connection to a foreign host.
@param host host seeking the connection
@param address destination for the connection
@ -200,7 +210,8 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC
currentPeer -> channelCount = channelCount;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address;
currentPeer -> connectID = ++ host -> randomSeed;
currentPeer -> connectID = enet_host_random (host);
currentPeer -> mtu = host -> mtu;
if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;

View file

@ -25,7 +25,7 @@ extern "C"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
#define ENET_VERSION_PATCH 13
#define ENET_VERSION_PATCH 17
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
@ -62,7 +62,8 @@ typedef enum _ENetSocketOption
ENET_SOCKOPT_RCVTIMEO = 6,
ENET_SOCKOPT_SNDTIMEO = 7,
ENET_SOCKOPT_ERROR = 8,
ENET_SOCKOPT_NODELAY = 9
ENET_SOCKOPT_NODELAY = 9,
ENET_SOCKOPT_TTL = 10
} ENetSocketOption;
typedef enum _ENetSocketShutdown
@ -138,7 +139,11 @@ typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
* (not supported for reliable packets)
*
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
*
* ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable
* (instead of reliable) sends if it exceeds the MTU
*
* ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into
@sa ENetPacketFlag
*/
typedef struct _ENetPacket
@ -165,7 +170,7 @@ typedef struct _ENetOutgoingCommand
enet_uint16 unreliableSequenceNumber;
enet_uint32 sentTime;
enet_uint32 roundTripTimeout;
enet_uint32 roundTripTimeoutLimit;
enet_uint32 queueTime;
enet_uint32 fragmentOffset;
enet_uint16 fragmentLength;
enet_uint16 sendAttempts;
@ -246,6 +251,12 @@ typedef struct _ENetChannel
ENetList incomingUnreliableCommands;
} ENetChannel;
typedef enum _ENetPeerFlag
{
ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0),
ENET_PEER_FLAG_CONTINUE_SENDING = (1 << 1)
} ENetPeerFlag;
/**
* An ENet peer which data packets may be sent or received from.
*
@ -303,11 +314,11 @@ typedef struct _ENetPeer
enet_uint16 outgoingReliableSequenceNumber;
ENetList acknowledgements;
ENetList sentReliableCommands;
ENetList sentUnreliableCommands;
ENetList outgoingReliableCommands;
ENetList outgoingUnreliableCommands;
ENetList outgoingSendReliableCommands;
ENetList outgoingCommands;
ENetList dispatchedCommands;
int needsDispatch;
enet_uint16 flags;
enet_uint16 reserved;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
@ -366,7 +377,7 @@ typedef struct _ENetHost
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
enet_uint32 serviceTime;
ENetList dispatchQueue;
int continueSending;
enet_uint32 totalQueued;
size_t packetSize;
enet_uint16 headerFlags;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
@ -405,7 +416,7 @@ typedef enum _ENetEventType
ENET_EVENT_TYPE_CONNECT = 1,
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_pper_disconnect, if
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
@ -505,6 +516,17 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock
/** @defgroup Address ENet address functions
@{
*/
/** Attempts to parse the printable form of the IP address in the parameter hostName
and sets the host field in the address parameter if successful.
@param address destination to store the parsed IP address
@param hostName IP address to parse
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@ -555,6 +577,7 @@ ENET_API void enet_host_channel_limit (ENetHost *, size_t);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *);
extern enet_uint32 enet_host_random_seed (void);
extern enet_uint32 enet_host_random (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
@ -568,12 +591,13 @@ ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *);
extern int enet_peer_has_outgoing_commands (ENetPeer *);
extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_on_connect (ENetPeer *);
extern void enet_peer_on_disconnect (ENetPeer *);

View file

@ -9,6 +9,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

View file

@ -7,6 +7,7 @@
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y))
#endif /* __ENET_UTILITY_H__ */

View file

@ -11,6 +11,8 @@
#pragma warning (disable: 4244) // 64bit to 32bit int
#pragma warning (disable: 4018) // signed/unsigned mismatch
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif

View file

@ -98,54 +98,47 @@ enet_packet_resize (ENetPacket * packet, size_t dataLength)
return 0;
}
static int initializedCRC32 = 0;
static enet_uint32 crcTable [256];
static enet_uint32
reflect_crc (int val, int bits)
static const enet_uint32 crcTable [256] =
{
int result = 0, bit;
for (bit = 0; bit < bits; bit ++)
{
if(val & 1) result |= 1 << (bits - 1 - bit);
val >>= 1;
}
return result;
}
static void
initialize_crc32 (void)
{
int byte;
for (byte = 0; byte < 256; ++ byte)
{
enet_uint32 crc = reflect_crc (byte, 8) << 24;
int offset;
for(offset = 0; offset < 8; ++ offset)
{
if (crc & 0x80000000)
crc = (crc << 1) ^ 0x04c11db7;
else
crc <<= 1;
}
crcTable [byte] = reflect_crc (crc, 32);
}
initializedCRC32 = 1;
}
0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x5005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
enet_uint32
enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
{
enet_uint32 crc = 0xFFFFFFFF;
if (! initializedCRC32) initialize_crc32 ();
while (bufferCount -- > 0)
{
const enet_uint8 * data = (const enet_uint8 *) buffers -> data,

87
Externals/enet/peer.c vendored
View file

@ -66,7 +66,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
peer -> packetThrottle = peer -> packetThrottleLimit;
}
else
if (rtt < peer -> lastRoundTripTime)
if (rtt <= peer -> lastRoundTripTime)
{
peer -> packetThrottle += peer -> packetThrottleAcceleration;
@ -90,6 +90,13 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
}
/** Queues a packet to be sent.
On success, ENet will assume ownership of the packet, and so enet_packet_destroy
should not be called on it thereafter. On failure, the caller still must destroy
the packet on its own as ENet has not queued the packet. The caller can also
check the packet's referenceCount field after sending to check if ENet queued
the packet and thus incremented the referenceCount.
@param peer destination for the packet
@param channelID channel on which to send
@param packet packet to send
@ -99,7 +106,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
int
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
{
ENetChannel * channel = & peer -> channels [channelID];
ENetChannel * channel;
ENetProtocol command;
size_t fragmentLength;
@ -108,6 +115,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
packet -> dataLength > peer -> host -> maximumPacketSize)
return -1;
channel = & peer -> channels [channelID];
fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
if (peer -> host -> checksum != NULL)
fragmentLength -= sizeof(enet_uint32);
@ -268,7 +276,7 @@ enet_peer_reset_outgoing_commands (ENetList * queue)
}
static void
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand)
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand, ENetIncomingCommand * excludeCommand)
{
ENetListIterator currentCommand;
@ -278,6 +286,9 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm
currentCommand = enet_list_next (currentCommand);
if (incomingCommand == excludeCommand)
continue;
enet_list_remove (& incomingCommand -> incomingCommandList);
if (incomingCommand -> packet != NULL)
@ -298,7 +309,7 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm
static void
enet_peer_reset_incoming_commands (ENetList * queue)
{
enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue));
enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue), NULL);
}
void
@ -306,20 +317,19 @@ enet_peer_reset_queues (ENetPeer * peer)
{
ENetChannel * channel;
if (peer -> needsDispatch)
if (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)
{
enet_list_remove (& peer -> dispatchList);
peer -> needsDispatch = 0;
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
}
while (! enet_list_empty (& peer -> acknowledgements))
enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingSendReliableCommands);
enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
if (peer -> channels != NULL && peer -> channelCount > 0)
@ -418,6 +428,7 @@ enet_peer_reset (ENetPeer * peer)
peer -> outgoingUnsequencedGroup = 0;
peer -> eventData = 0;
peer -> totalWaitingData = 0;
peer -> flags = 0;
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
@ -560,6 +571,17 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
}
}
int
enet_peer_has_outgoing_commands (ENetPeer * peer)
{
if (enet_list_empty (& peer -> outgoingCommands) &&
enet_list_empty (& peer -> outgoingSendReliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
return 0;
return 1;
}
/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
@param peer peer to request a disconnection
@param data data describing the disconnection
@ -570,9 +592,7 @@ void
enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
{
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
! (enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands)))
enet_peer_has_outgoing_commands (peer))
{
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
peer -> eventData = data;
@ -616,8 +636,6 @@ enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command,
void
enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
{
ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
if (outgoingCommand -> command.header.channelID == 0xFF)
@ -628,6 +646,9 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
{
ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
++ channel -> outgoingReliableSequenceNumber;
@ -652,12 +673,13 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
}
outgoingCommand -> sendAttempts = 0;
outgoingCommand -> sentTime = 0;
outgoingCommand -> roundTripTimeout = 0;
outgoingCommand -> roundTripTimeoutLimit = 0;
outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
outgoingCommand -> queueTime = ++ peer -> host -> totalQueued;
switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK)
{
@ -673,10 +695,11 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin
break;
}
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
if ((outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0 &&
outgoingCommand -> packet != NULL)
enet_list_insert (enet_list_end (& peer -> outgoingSendReliableCommands), outgoingCommand);
else
enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand);
}
ENetOutgoingCommand *
@ -699,7 +722,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command,
}
void
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
{
ENetListIterator droppedCommand, startCommand, currentCommand;
@ -724,11 +747,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
if (! peer -> needsDispatch)
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> needsDispatch = 1;
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
droppedCommand = currentCommand;
@ -752,11 +775,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
if (! peer -> needsDispatch)
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> needsDispatch = 1;
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
}
}
@ -768,21 +791,21 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel *
{
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
if (! peer -> needsDispatch)
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> needsDispatch = 1;
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
droppedCommand = currentCommand;
}
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand);
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand, queuedCommand);
}
void
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
{
ENetListIterator currentCommand;
@ -809,15 +832,15 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch
enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
if (! peer -> needsDispatch)
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
peer -> needsDispatch = 1;
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
if (! enet_list_empty (& channel -> incomingUnreliableCommands))
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, queuedCommand);
}
ENetIncomingCommand *
@ -975,11 +998,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command,
{
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
enet_peer_dispatch_incoming_reliable_commands (peer, channel);
enet_peer_dispatch_incoming_reliable_commands (peer, channel, incomingCommand);
break;
default:
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, incomingCommand);
break;
}

View file

@ -9,7 +9,7 @@
#include "enet/time.h"
#include "enet/enet.h"
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
static const size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
{
0,
sizeof (ENetProtocolAcknowledge),
@ -48,11 +48,11 @@ enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState st
{
enet_protocol_change_state (host, peer, state);
if (! peer -> needsDispatch)
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
{
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
peer -> needsDispatch = 1;
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
}
}
@ -63,7 +63,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
{
ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
peer -> needsDispatch = 0;
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
switch (peer -> state)
{
@ -101,7 +101,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
if (! enet_list_empty (& peer -> dispatchedCommands))
{
peer -> needsDispatch = 1;
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
}
@ -159,13 +159,16 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e
}
static void
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer, ENetList * sentUnreliableCommands)
{
ENetOutgoingCommand * outgoingCommand;
while (! enet_list_empty (& peer -> sentUnreliableCommands))
if (enet_list_empty (sentUnreliableCommands))
return;
do
{
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
outgoingCommand = (ENetOutgoingCommand *) enet_list_front (sentUnreliableCommands);
enet_list_remove (& outgoingCommand -> outgoingCommandList);
@ -182,7 +185,36 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
}
enet_free (outgoingCommand);
} while (! enet_list_empty (sentUnreliableCommands));
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
! enet_peer_has_outgoing_commands (peer))
enet_peer_disconnect (peer, peer -> eventData);
}
static ENetOutgoingCommand *
enet_protocol_find_sent_reliable_command (ENetList * list, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
{
ENetListIterator currentCommand;
for (currentCommand = enet_list_begin (list);
currentCommand != enet_list_end (list);
currentCommand = enet_list_next (currentCommand))
{
ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE))
continue;
if (outgoingCommand -> sendAttempts < 1)
break;
if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
outgoingCommand -> command.header.channelID == channelID)
return outgoingCommand;
}
return NULL;
}
static ENetProtocolCommand
@ -206,21 +238,9 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl
if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
{
for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
currentCommand != enet_list_end (& peer -> outgoingReliableCommands);
currentCommand = enet_list_next (currentCommand))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
outgoingCommand -> command.header.channelID == channelID)
break;
}
if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands))
return ENET_PROTOCOL_COMMAND_NONE;
outgoingCommand = enet_protocol_find_sent_reliable_command (& peer -> outgoingCommands, reliableSequenceNumber, channelID);
if (outgoingCommand == NULL)
outgoingCommand = enet_protocol_find_sent_reliable_command (& peer -> outgoingSendReliableCommands, reliableSequenceNumber, channelID);
wasSent = 0;
}
@ -320,6 +340,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
peer -> connectID = command -> connect.connectID;
peer -> address = host -> receivedAddress;
peer -> mtu = host -> mtu;
peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
@ -364,6 +385,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
mtu = ENET_PROTOCOL_MAXIMUM_MTU;
if (mtu < peer -> mtu)
peer -> mtu = mtu;
if (host -> outgoingBandwidth == 0 &&
@ -531,7 +553,8 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
* currentData += fragmentLength;
if (fragmentLength > host -> maximumPacketSize ||
if (fragmentLength <= 0 ||
fragmentLength > host -> maximumPacketSize ||
* currentData < host -> receivedData ||
* currentData > & host -> receivedData [host -> receivedDataLength])
return -1;
@ -555,6 +578,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
fragmentNumber >= fragmentCount ||
totalLength > host -> maximumPacketSize ||
totalLength < fragmentCount ||
fragmentOffset >= totalLength ||
fragmentLength > totalLength - fragmentOffset)
return -1;
@ -614,7 +638,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet
fragmentLength);
if (startCommand -> fragmentsRemaining <= 0)
enet_peer_dispatch_incoming_reliable_commands (peer, channel);
enet_peer_dispatch_incoming_reliable_commands (peer, channel, NULL);
}
return 0;
@ -732,7 +756,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer,
fragmentLength);
if (startCommand -> fragmentsRemaining <= 0)
enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, NULL);
}
return 0;
@ -842,24 +866,32 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
return 0;
peer -> lastReceiveTime = host -> serviceTime;
peer -> earliestTimeout = 0;
roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
roundTripTime = ENET_MAX (roundTripTime, 1);
if (peer -> lastReceiveTime > 0)
{
enet_peer_throttle (peer, roundTripTime);
peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
if (roundTripTime >= peer -> roundTripTime)
{
peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
enet_uint32 diff = roundTripTime - peer -> roundTripTime;
peer -> roundTripTimeVariance += diff / 4;
peer -> roundTripTime += diff / 8;
}
else
{
peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
enet_uint32 diff = peer -> roundTripTime - roundTripTime;
peer -> roundTripTimeVariance += diff / 4;
peer -> roundTripTime -= diff / 8;
}
}
else
{
peer -> roundTripTime = roundTripTime;
peer -> roundTripTimeVariance = (roundTripTime + 1) / 2;
}
if (peer -> roundTripTime < peer -> lowestRoundTripTime)
@ -872,12 +904,15 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
{
peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 1);
peer -> lowestRoundTripTime = peer -> roundTripTime;
peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
peer -> packetThrottleEpoch = host -> serviceTime;
}
peer -> lastReceiveTime = ENET_MAX (host -> serviceTime, 1);
peer -> earliestTimeout = 0;
receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
@ -899,9 +934,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer *
break;
case ENET_PEER_STATE_DISCONNECT_LATER:
if (enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
if (! enet_peer_has_outgoing_commands (peer))
enet_peer_disconnect (peer, peer -> eventData);
break;
@ -1253,7 +1286,7 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
}
}
return -1;
return 0;
}
static void
@ -1273,7 +1306,7 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
{
host -> continueSending = 1;
peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
break;
}
@ -1309,36 +1342,177 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
host -> bufferCount = buffer - host -> buffers;
}
static void
enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
static int
enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
{
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand, insertPosition, insertSendReliablePosition;
currentCommand = enet_list_begin (& peer -> sentReliableCommands);
insertPosition = enet_list_begin (& peer -> outgoingCommands);
insertSendReliablePosition = enet_list_begin (& peer -> outgoingSendReliableCommands);
while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
currentCommand = enet_list_next (currentCommand);
if (ENET_TIME_DIFFERENCE (host -> serviceTime, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
continue;
if (peer -> earliestTimeout == 0 ||
ENET_TIME_LESS (outgoingCommand -> sentTime, peer -> earliestTimeout))
peer -> earliestTimeout = outgoingCommand -> sentTime;
if (peer -> earliestTimeout != 0 &&
(ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
((1 << (outgoingCommand -> sendAttempts - 1)) >= peer -> timeoutLimit &&
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
{
enet_protocol_notify_disconnect (host, peer, event);
return 1;
}
++ peer -> packetsLost;
outgoingCommand -> roundTripTimeout *= 2;
if (outgoingCommand -> packet != NULL)
{
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
enet_list_insert (insertSendReliablePosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
}
else
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
! enet_list_empty (& peer -> sentReliableCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
}
}
return 0;
}
static int
enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetList * sentUnreliableCommands)
{
ENetProtocol * command = & host -> commands [host -> commandCount];
ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand;
currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
{
ENetListIterator currentCommand, currentSendReliableCommand;
ENetChannel *channel = NULL;
enet_uint16 reliableWindow = 0;
size_t commandSize;
int windowWrap = 0, canPing = 1;
currentCommand = enet_list_begin (& peer -> outgoingCommands);
currentSendReliableCommand = enet_list_begin (& peer -> outgoingSendReliableCommands);
for (;;)
{
if (currentCommand != enet_list_end (& peer -> outgoingCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands) &&
ENET_TIME_LESS (((ENetOutgoingCommand *) currentSendReliableCommand) -> queueTime, outgoingCommand -> queueTime))
goto useSendReliableCommand;
currentCommand = enet_list_next (currentCommand);
}
else
if (currentSendReliableCommand != enet_list_end (& peer -> outgoingSendReliableCommands))
{
useSendReliableCommand:
outgoingCommand = (ENetOutgoingCommand *) currentSendReliableCommand;
currentSendReliableCommand = enet_list_next (currentSendReliableCommand);
}
else
break;
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (channel != NULL)
{
if (windowWrap)
continue;
else
if (outgoingCommand -> sendAttempts < 1 &&
! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
(channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
channel -> usedReliableWindows & ((((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) << reliableWindow) |
(((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))))
{
windowWrap = 1;
currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
continue;
}
}
if (outgoingCommand -> packet != NULL)
{
enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
{
currentSendReliableCommand = enet_list_end (& peer -> outgoingSendReliableCommands);
continue;
}
}
canPing = 0;
}
commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
peer -> mtu - host -> packetSize < commandSize ||
(outgoingCommand -> packet != NULL &&
peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength))
(enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
{
host -> continueSending = 1;
peer -> flags |= ENET_PEER_FLAG_CONTINUE_SENDING;
break;
}
currentCommand = enet_list_next (currentCommand);
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
if (channel != NULL && outgoingCommand -> sendAttempts < 1)
{
channel -> usedReliableWindows |= 1 << reliableWindow;
++ channel -> reliableWindows [reliableWindow];
}
++ outgoingCommand -> sendAttempts;
if (outgoingCommand -> roundTripTimeout == 0)
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
if (enet_list_empty (& peer -> sentReliableCommands))
peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
enet_list_remove (& outgoingCommand -> outgoingCommandList));
outgoingCommand -> sentTime = host -> serviceTime;
host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
}
else
{
if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0)
{
peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
@ -1358,7 +1532,7 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee
enet_list_remove (& outgoingCommand -> outgoingCommandList);
enet_free (outgoingCommand);
if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands))
if (currentCommand == enet_list_end (& peer -> outgoingCommands))
break;
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
@ -1373,193 +1547,16 @@ enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * pee
}
}
buffer -> data = command;
buffer -> dataLength = commandSize;
host -> packetSize += buffer -> dataLength;
* command = outgoingCommand -> command;
enet_list_remove (& outgoingCommand -> outgoingCommandList);
if (outgoingCommand -> packet != NULL)
{
++ buffer;
buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
buffer -> dataLength = outgoingCommand -> fragmentLength;
host -> packetSize += buffer -> dataLength;
enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
enet_list_insert (enet_list_end (sentUnreliableCommands), outgoingCommand);
}
else
enet_free (outgoingCommand);
++ command;
++ buffer;
}
host -> commandCount = command - host -> commands;
host -> bufferCount = buffer - host -> buffers;
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
}
static int
enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
{
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand, insertPosition;
currentCommand = enet_list_begin (& peer -> sentReliableCommands);
insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
currentCommand = enet_list_next (currentCommand);
if (ENET_TIME_DIFFERENCE (host -> serviceTime, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
continue;
if (peer -> earliestTimeout == 0 ||
ENET_TIME_LESS (outgoingCommand -> sentTime, peer -> earliestTimeout))
peer -> earliestTimeout = outgoingCommand -> sentTime;
if (peer -> earliestTimeout != 0 &&
(ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
(outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
{
enet_protocol_notify_disconnect (host, peer, event);
return 1;
}
if (outgoingCommand -> packet != NULL)
peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
++ peer -> packetsLost;
outgoingCommand -> roundTripTimeout *= 2;
enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
! enet_list_empty (& peer -> sentReliableCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
}
}
return 0;
}
static int
enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
{
ENetProtocol * command = & host -> commands [host -> commandCount];
ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
ENetOutgoingCommand * outgoingCommand;
ENetListIterator currentCommand;
ENetChannel *channel;
enet_uint16 reliableWindow;
size_t commandSize;
int windowExceeded = 0, windowWrap = 0, canPing = 1;
currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
{
outgoingCommand = (ENetOutgoingCommand *) currentCommand;
channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (channel != NULL)
{
if (! windowWrap &&
outgoingCommand -> sendAttempts < 1 &&
! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
(channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) |
(((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))))
windowWrap = 1;
if (windowWrap)
{
currentCommand = enet_list_next (currentCommand);
continue;
}
}
if (outgoingCommand -> packet != NULL)
{
if (! windowExceeded)
{
enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
windowExceeded = 1;
}
if (windowExceeded)
{
currentCommand = enet_list_next (currentCommand);
continue;
}
}
canPing = 0;
commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
peer -> mtu - host -> packetSize < commandSize ||
(outgoingCommand -> packet != NULL &&
(enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
{
host -> continueSending = 1;
break;
}
currentCommand = enet_list_next (currentCommand);
if (channel != NULL && outgoingCommand -> sendAttempts < 1)
{
channel -> usedReliableWindows |= 1 << reliableWindow;
++ channel -> reliableWindows [reliableWindow];
}
++ outgoingCommand -> sendAttempts;
if (outgoingCommand -> roundTripTimeout == 0)
{
outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
}
if (enet_list_empty (& peer -> sentReliableCommands))
peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
enet_list_remove (& outgoingCommand -> outgoingCommandList));
outgoingCommand -> sentTime = host -> serviceTime;
buffer -> data = command;
buffer -> dataLength = commandSize;
host -> packetSize += buffer -> dataLength;
host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
* command = outgoingCommand -> command;
@ -1571,9 +1568,10 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
buffer -> dataLength = outgoingCommand -> fragmentLength;
host -> packetSize += outgoingCommand -> fragmentLength;
peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
}
else
if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE))
enet_free (outgoingCommand);
++ peer -> packetsSent;
@ -1584,6 +1582,11 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
host -> commandCount = command - host -> commands;
host -> bufferCount = buffer - host -> buffers;
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
! enet_peer_has_outgoing_commands (peer) &&
enet_list_empty (sentUnreliableCommands))
enet_peer_disconnect (peer, peer -> eventData);
return canPing;
}
@ -1592,22 +1595,24 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
{
enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
ENetPeer * currentPeer;
int sentLength;
int sentLength = 0;
size_t shouldCompress = 0;
ENetList sentUnreliableCommands;
host -> continueSending = 1;
enet_list_clear (& sentUnreliableCommands);
while (host -> continueSending)
for (host -> continueSending = 0,
currentPeer = host -> peers;
for (int sendPass = 0, continueSending = 0; sendPass <= continueSending; ++ sendPass)
for (ENetPeer * currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
currentPeer -> state == ENET_PEER_STATE_ZOMBIE ||
(sendPass > 0 && ! (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)))
continue;
currentPeer -> flags &= ~ ENET_PEER_FLAG_CONTINUE_SENDING;
host -> headerFlags = 0;
host -> commandCount = 0;
host -> bufferCount = 1;
@ -1624,24 +1629,22 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
return 1;
else
continue;
goto nextPeer;
}
if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) ||
enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) &&
if (((enet_list_empty (& currentPeer -> outgoingCommands) &&
enet_list_empty (& currentPeer -> outgoingSendReliableCommands)) ||
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands)) &&
enet_list_empty (& currentPeer -> sentReliableCommands) &&
ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval &&
currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
{
enet_peer_ping (currentPeer);
enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
enet_protocol_check_outgoing_commands (host, currentPeer, & sentUnreliableCommands);
}
if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
if (host -> commandCount == 0)
continue;
goto nextPeer;
if (currentPeer -> packetLossEpoch == 0)
currentPeer -> packetLossEpoch = host -> serviceTime;
@ -1652,21 +1655,11 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
#ifdef ENET_DEBUG
printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingCommands) + enet_list_size (& currentPeer -> outgoingSendReliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
#endif
currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
if (packetLoss >= currentPeer -> packetLoss)
{
currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
}
else
{
currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
}
currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4;
currentPeer -> packetLoss = (currentPeer -> packetLoss * 7 + packetLoss) / 8;
currentPeer -> packetLossEpoch = host -> serviceTime;
currentPeer -> packetsSent = 0;
@ -1724,13 +1717,17 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
enet_protocol_remove_sent_unreliable_commands (currentPeer);
enet_protocol_remove_sent_unreliable_commands (currentPeer, & sentUnreliableCommands);
if (sentLength < 0)
return -1;
host -> totalSentData += sentLength;
host -> totalSentPackets ++;
nextPeer:
if (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)
continueSending = sendPass + 1;
}
return 0;

42
Externals/enet/unix.c vendored
View file

@ -8,7 +8,6 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <unistd.h>
@ -51,10 +50,10 @@
#endif
#ifdef HAS_POLL
#include <sys/poll.h>
#include <poll.h>
#endif
#ifndef HAS_SOCKLEN_T
#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined)
typedef int socklen_t;
#endif
@ -101,6 +100,19 @@ enet_time_set (enet_uint32 newTimeBase)
timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
{
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
@ -136,7 +148,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
char buffer [2048];
int errnum;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__GNU__)
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
@ -153,14 +165,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
}
#endif
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
return 0;
return enet_address_set_host_ip (address, name);
}
int
@ -204,7 +209,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
return 0;
}
if (err != EAI_NONAME)
return 0;
return -1;
#else
struct in_addr in;
struct hostent * hostEntry = NULL;
@ -215,7 +220,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
in.s_addr = address -> host;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__GNU__)
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
@ -343,6 +348,10 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
@ -361,6 +370,11 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof (int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}

View file

@ -8,6 +8,7 @@
#include "enet/enet.h"
#include <windows.h>
#include <mmsystem.h>
#include <ws2ipdef.h>
static enet_uint32 timeBase = 0;
@ -59,6 +60,32 @@ enet_time_set (enet_uint32 newTimeBase)
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
{
enet_uint8 vals [4] = { 0, 0, 0, 0 };
int i;
for (i = 0; i < 4; ++ i)
{
const char * next = name + 1;
if (* name != '0')
{
long val = strtol (name, (char **) & next, 10);
if (val < 0 || val > 255 || next == name || next - name > 3)
return -1;
vals [i] = (enet_uint8) val;
}
if (* next != (i < 3 ? '.' : '\0'))
return -1;
name = next + 1;
}
memcpy (& address -> host, vals, sizeof (enet_uint32));
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
@ -67,13 +94,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
hostEntry = gethostbyname (name);
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
{
unsigned long host = inet_addr (name);
if (host == INADDR_NONE)
return -1;
address -> host = host;
return 0;
}
return enet_address_set_host_ip (address, name);
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
@ -211,6 +232,10 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
@ -228,6 +253,11 @@ enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof(int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
@ -296,7 +326,7 @@ enet_socket_send (ENetSocket socket,
size_t bufferCount)
{
struct sockaddr_in sin;
DWORD sentLength;
DWORD sentLength = 0;
if (address != NULL)
{
@ -334,7 +364,7 @@ enet_socket_receive (ENetSocket socket,
{
INT sinLength = sizeof (struct sockaddr_in);
DWORD flags = 0,
recvLength;
recvLength = 0;
struct sockaddr_in sin;
if (WSARecvFrom (socket,

49
Externals/rcheevos/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,49 @@
add_library(rcheevos
rcheevos/include/rc_api_editor.h
rcheevos/include/rc_api_info.h
rcheevos/include/rc_api_request.h
rcheevos/include/rc_api_runtime.h
rcheevos/include/rc_api_user.h
rcheevos/include/rc_consoles.h
rcheevos/include/rc_error.h
rcheevos/include/rc_hash.h
rcheevos/include/rcheevos.h
rcheevos/include/rc_runtime.h
rcheevos/include/rc_runtime_types.h
rcheevos/include/rc_url.h
rcheevos/src/rapi/rc_api_common.c
rcheevos/src/rapi/rc_api_common.h
rcheevos/src/rapi/rc_api_editor.c
rcheevos/src/rapi/rc_api_info.c
rcheevos/src/rapi/rc_api_runtime.c
rcheevos/src/rapi/rc_api_user.c
rcheevos/src/rcheevos/alloc.c
rcheevos/src/rcheevos/compat.c
rcheevos/src/rcheevos/condition.c
rcheevos/src/rcheevos/condset.c
rcheevos/src/rcheevos/consoleinfo.c
rcheevos/src/rcheevos/format.c
rcheevos/src/rcheevos/lboard.c
rcheevos/src/rcheevos/memref.c
rcheevos/src/rcheevos/operand.c
rcheevos/src/rcheevos/rc_compat.h
rcheevos/src/rcheevos/rc_internal.h
rcheevos/src/rcheevos/rc_validate.c
rcheevos/src/rcheevos/rc_validate.h
rcheevos/src/rcheevos/richpresence.c
rcheevos/src/rcheevos/runtime.c
rcheevos/src/rcheevos/runtime_progress.c
rcheevos/src/rcheevos/trigger.c
rcheevos/src/rcheevos/value.c
rcheevos/src/rhash/hash.c
rcheevos/src/rhash/md5.c
rcheevos/src/rhash/md5.h
rcheevos/src/rurl/url.c
)
target_include_directories(rcheevos PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/rcheevos/include")
target_include_directories(rcheevos INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
target_compile_definitions(rcheevos PRIVATE "RC_DISABLE_LUA=1" "RCHEEVOS_URL_SSL")
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
target_compile_definitions(rcheevos PRIVATE "_CRT_SECURE_NO_WARNINGS")
endif()

13
Externals/rcheevos/exports.props vendored Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(ExternalsDir)rcheevos;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(ExternalsDir)rcheevos\rcheevos.vcxproj">
<Project>{CC99A910-3752-4465-95AA-7DC240D92A99}</Project>
</ProjectReference>
</ItemGroup>
</Project>

1
Externals/rcheevos/rcheevos vendored Submodule

@ -0,0 +1 @@
Subproject commit c5304a61bcf256ae80fcd1c8f64ad9646aaea757

71
Externals/rcheevos/rcheevos.vcxproj vendored Normal file
View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Project="..\..\Source\VSProps\Base.Macros.props" />
<Import Project="$(VSPropsDir)Base.Targets.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{CC99A910-3752-4465-95AA-7DC240D92A99}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VSPropsDir)Base.props" />
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
<ClCompile Include="rcheevos\src\rapi\rc_api_common.c" />
<ClCompile Include="rcheevos\src\rapi\rc_api_editor.c" />
<ClCompile Include="rcheevos\src\rapi\rc_api_info.c" />
<ClCompile Include="rcheevos\src\rapi\rc_api_runtime.c" />
<ClCompile Include="rcheevos\src\rapi\rc_api_user.c" />
<ClCompile Include="rcheevos\src\rcheevos\alloc.c" />
<ClCompile Include="rcheevos\src\rcheevos\compat.c" />
<ClCompile Include="rcheevos\src\rcheevos\condition.c" />
<ClCompile Include="rcheevos\src\rcheevos\condset.c" />
<ClCompile Include="rcheevos\src\rcheevos\consoleinfo.c" />
<ClCompile Include="rcheevos\src\rcheevos\format.c" />
<ClCompile Include="rcheevos\src\rcheevos\lboard.c" />
<ClCompile Include="rcheevos\src\rcheevos\memref.c" />
<ClCompile Include="rcheevos\src\rcheevos\operand.c" />
<ClCompile Include="rcheevos\src\rcheevos\rc_validate.c" />
<ClCompile Include="rcheevos\src\rcheevos\richpresence.c" />
<ClCompile Include="rcheevos\src\rcheevos\runtime.c" />
<ClCompile Include="rcheevos\src\rcheevos\runtime_progress.c" />
<ClCompile Include="rcheevos\src\rcheevos\trigger.c" />
<ClCompile Include="rcheevos\src\rcheevos\value.c" />
<ClCompile Include="rcheevos\src\rhash\hash.c" />
<ClCompile Include="rcheevos\src\rhash\md5.c" />
<ClCompile Include="rcheevos\src\rurl\url.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="rcheevos\include\rcheevos.h" />
<ClInclude Include="rcheevos\include\rc_api_editor.h" />
<ClInclude Include="rcheevos\include\rc_api_info.h" />
<ClInclude Include="rcheevos\include\rc_api_request.h" />
<ClInclude Include="rcheevos\include\rc_api_runtime.h" />
<ClInclude Include="rcheevos\include\rc_api_user.h" />
<ClInclude Include="rcheevos\include\rc_consoles.h" />
<ClInclude Include="rcheevos\include\rc_error.h" />
<ClInclude Include="rcheevos\include\rc_hash.h" />
<ClInclude Include="rcheevos\include\rc_runtime.h" />
<ClInclude Include="rcheevos\include\rc_runtime_types.h" />
<ClInclude Include="rcheevos\include\rc_url.h" />
<ClInclude Include="rcheevos\src\rapi\rc_api_common.h" />
<ClInclude Include="rcheevos\src\rcheevos\rc_compat.h" />
<ClInclude Include="rcheevos\src\rcheevos\rc_internal.h" />
<ClInclude Include="rcheevos\src\rcheevos\rc_validate.h" />
<ClInclude Include="rcheevos\src\rhash\md5.h" />
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>RC_DISABLE_LUA;RCHEEVOS_URL_SSL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)rcheevos\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -112,6 +112,7 @@
#define LOGGER_CONFIG "Logger.ini"
#define DUALSHOCKUDPCLIENT_CONFIG "DSUClient.ini"
#define FREELOOK_CONFIG "FreeLook.ini"
#define RETROACHIEVEMENTS_CONFIG "RetroAchievements.ini"
// Files in the directory returned by GetUserPath(D_LOGS_IDX)
#define MAIN_LOG "dolphin.log"

View file

@ -160,7 +160,8 @@ static const std::map<System, std::string> system_to_name = {
{System::DualShockUDPClient, "DualShockUDPClient"},
{System::FreeLook, "FreeLook"},
{System::Session, "Session"},
{System::GameSettingsOnly, "GameSettingsOnly"}};
{System::GameSettingsOnly, "GameSettingsOnly"},
{System::Achievements, "Achievements"}};
const std::string& GetSystemName(System system)
{

View file

@ -34,6 +34,7 @@ enum class System
FreeLook,
Session,
GameSettingsOnly,
Achievements,
};
constexpr std::array<LayerType, 7> SEARCH_ORDER{{

View file

@ -847,6 +847,8 @@ static void RebuildUserDirectories(unsigned int dir_index)
s_user_paths[F_DUALSHOCKUDPCLIENTCONFIG_IDX] =
s_user_paths[D_CONFIG_IDX] + DUALSHOCKUDPCLIENT_CONFIG;
s_user_paths[F_FREELOOKCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + FREELOOK_CONFIG;
s_user_paths[F_RETROACHIEVEMENTSCONFIG_IDX] =
s_user_paths[D_CONFIG_IDX] + RETROACHIEVEMENTS_CONFIG;
s_user_paths[F_MAINLOG_IDX] = s_user_paths[D_LOGS_IDX] + MAIN_LOG;
s_user_paths[F_MEM1DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM1_DUMP;
s_user_paths[F_MEM2DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM2_DUMP;

View file

@ -85,6 +85,7 @@ enum
F_DUALSHOCKUDPCLIENTCONFIG_IDX,
F_FREELOOKCONFIG_IDX,
F_GBABIOS_IDX,
F_RETROACHIEVEMENTSCONFIG_IDX,
NUM_PATH_INDICES
};

View file

@ -333,6 +333,7 @@ bool EnsureTraversalClient(const std::string& server, u16 server_port, u16 liste
g_MainNetHost.reset();
return false;
}
host->mtu = std::min(host->mtu, NetPlay::MAX_ENET_MTU);
g_MainNetHost.reset(host);
g_TraversalClient.reset(new TraversalClient(g_MainNetHost.get(), server, server_port));
}

View file

@ -124,7 +124,7 @@ public:
if (m_idle && !m_cancelling.load())
return;
m_wait_cond_var.wait(lg, [&] { return m_idle && m_cancelling.load(); });
m_wait_cond_var.wait(lg, [&] { return m_idle && !m_cancelling; });
}
// If the worker polls IsCanceling(), it can abort its work when Cancelling

View file

@ -0,0 +1,114 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef USE_RETRO_ACHIEVEMENTS
#include "Core/AchievementManager.h"
#include "Common/HttpRequest.h"
#include "Common/WorkQueueThread.h"
#include "Config/AchievementSettings.h"
#include "Core/Core.h"
AchievementManager* AchievementManager::GetInstance()
{
static AchievementManager s_instance;
return &s_instance;
}
void AchievementManager::Init()
{
if (!m_is_runtime_initialized && Config::Get(Config::RA_ENABLED))
{
rc_runtime_init(&m_runtime);
m_is_runtime_initialized = true;
m_queue.Reset("AchievementManagerQueue", [](const std::function<void()>& func) { func(); });
LoginAsync("", [](ResponseType r_type) {});
}
}
AchievementManager::ResponseType AchievementManager::Login(const std::string& password)
{
return VerifyCredentials(password);
}
void AchievementManager::LoginAsync(const std::string& password, const LoginCallback& callback)
{
m_queue.EmplaceItem([this, password, callback] { callback(VerifyCredentials(password)); });
}
bool AchievementManager::IsLoggedIn() const
{
return m_login_data.response.succeeded;
}
void AchievementManager::Logout()
{
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
rc_api_destroy_login_response(&m_login_data);
m_login_data.response.succeeded = 0;
}
void AchievementManager::Shutdown()
{
m_is_runtime_initialized = false;
m_queue.Shutdown();
// DON'T log out - keep those credentials for next run.
rc_api_destroy_login_response(&m_login_data);
m_login_data.response.succeeded = 0;
rc_runtime_destroy(&m_runtime);
}
AchievementManager::ResponseType AchievementManager::VerifyCredentials(const std::string& password)
{
std::string username = Config::Get(Config::RA_USERNAME);
std::string api_token = Config::Get(Config::RA_API_TOKEN);
rc_api_login_request_t login_request = {
.username = username.c_str(), .api_token = api_token.c_str(), .password = password.c_str()};
ResponseType r_type = Request<rc_api_login_request_t, rc_api_login_response_t>(
login_request, &m_login_data, rc_api_init_login_request, rc_api_process_login_response);
if (r_type == ResponseType::SUCCESS)
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, m_login_data.api_token);
return r_type;
}
// Every RetroAchievements API call, with only a partial exception for fetch_image, follows
// the same design pattern (here, X is the name of the call):
// Create a specific rc_api_X_request_t struct and populate with the necessary values
// Call rc_api_init_X_request to convert this into a generic rc_api_request_t struct
// Perform the HTTP request using the url and post_data in the rc_api_request_t struct
// Call rc_api_process_X_response to convert the raw string HTTP response into a
// rc_api_X_response_t struct
// Use the data in the rc_api_X_response_t struct as needed
// Call rc_api_destroy_X_response when finished with the response struct to free memory
template <typename RcRequest, typename RcResponse>
AchievementManager::ResponseType AchievementManager::Request(
RcRequest rc_request, RcResponse* rc_response,
const std::function<int(rc_api_request_t*, const RcRequest*)>& init_request,
const std::function<int(RcResponse*, const char*)>& process_response)
{
rc_api_request_t api_request;
Common::HttpRequest http_request;
init_request(&api_request, &rc_request);
auto http_response = http_request.Post(api_request.url, api_request.post_data);
rc_api_destroy_request(&api_request);
if (http_response.has_value() && http_response->size() > 0)
{
const std::string response_str(http_response->begin(), http_response->end());
process_response(rc_response, response_str.c_str());
if (rc_response->response.succeeded)
{
return ResponseType::SUCCESS;
}
else
{
Logout();
return ResponseType::INVALID_CREDENTIALS;
}
}
else
{
return ResponseType::CONNECTION_FAILED;
}
}
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -0,0 +1,54 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef USE_RETRO_ACHIEVEMENTS
#include <functional>
#include <mutex>
#include <string>
#include <thread>
#include <rcheevos/include/rc_api_user.h>
#include <rcheevos/include/rc_runtime.h>
#include "Common/Event.h"
#include "Common/WorkQueueThread.h"
class AchievementManager
{
public:
enum class ResponseType
{
SUCCESS,
INVALID_CREDENTIALS,
CONNECTION_FAILED,
UNKNOWN_FAILURE
};
using LoginCallback = std::function<void(ResponseType)>;
static AchievementManager* GetInstance();
void Init();
ResponseType Login(const std::string& password);
void LoginAsync(const std::string& password, const LoginCallback& callback);
bool IsLoggedIn() const;
void Logout();
void Shutdown();
private:
AchievementManager() = default;
ResponseType VerifyCredentials(const std::string& password);
template <typename RcRequest, typename RcResponse>
ResponseType Request(RcRequest rc_request, RcResponse* rc_response,
const std::function<int(rc_api_request_t*, const RcRequest*)>& init_request,
const std::function<int(RcResponse*, const char*)>& process_response);
rc_runtime_t m_runtime{};
bool m_is_runtime_initialized = false;
rc_api_login_response_t m_login_data{};
Common::WorkQueueThread<std::function<void()>> m_queue;
}; // class AchievementManager
#endif // USE_RETRO_ACHIEVEMENTS

View file

@ -1,4 +1,6 @@
add_library(core
AchievementManager.cpp
AchievementManager.h
ActionReplay.cpp
ActionReplay.h
ARDecrypt.cpp
@ -21,6 +23,8 @@ add_library(core
CheatSearch.cpp
CheatSearch.h
CommonTitles.h
Config/AchievementSettings.cpp
Config/AchievementSettings.h
Config/DefaultLocale.cpp
Config/DefaultLocale.h
Config/FreeLookSettings.cpp
@ -751,3 +755,8 @@ if(MSVC)
# Add precompiled header
target_link_libraries(core PRIVATE use_pch)
endif()
if(USE_RETRO_ACHIEVEMENTS)
target_link_libraries(core PRIVATE rcheevos)
target_compile_definitions(core PRIVATE -DUSE_RETRO_ACHIEVEMENTS)
endif()

View file

@ -0,0 +1,16 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/Config/AchievementSettings.h"
#include <string>
#include "Common/Config/Config.h"
namespace Config
{
// Configuration Information
const Info<bool> RA_ENABLED{{System::Achievements, "Achievements", "Enabled"}, false};
const Info<std::string> RA_USERNAME{{System::Achievements, "Achievements", "Username"}, ""};
const Info<std::string> RA_API_TOKEN{{System::Achievements, "Achievements", "ApiToken"}, ""};
} // namespace Config

View file

@ -0,0 +1,14 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "Common/Config/Config.h"
namespace Config
{
// Configuration Information
extern const Info<bool> RA_ENABLED;
extern const Info<std::string> RA_USERNAME;
extern const Info<std::string> RA_API_TOKEN;
} // namespace Config

View file

@ -94,6 +94,7 @@ const std::map<Config::System, int> system_to_ini = {
{Config::System::Debugger, F_DEBUGGERCONFIG_IDX},
{Config::System::DualShockUDPClient, F_DUALSHOCKUDPCLIENTCONFIG_IDX},
{Config::System::FreeLook, F_FREELOOKCONFIG_IDX},
{Config::System::Achievements, F_RETROACHIEVEMENTSCONFIG_IDX},
// Config::System::Session should not be added to this list
};

View file

@ -7,6 +7,7 @@
#include <vector>
#include "Common/Config/Config.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/UISettings.h"
@ -37,6 +38,12 @@ bool IsSettingSaveable(const Config::Location& config_location)
&Config::WIIMOTE_3_SOURCE.GetLocation(),
&Config::WIIMOTE_4_SOURCE.GetLocation(),
&Config::WIIMOTE_BB_SOURCE.GetLocation(),
// Achievements
&Config::RA_ENABLED.GetLocation(),
&Config::RA_USERNAME.GetLocation(),
&Config::RA_API_TOKEN.GetLocation(),
};
return std::any_of(begin(s_setting_saveable), end(s_setting_saveable),

View file

@ -144,6 +144,8 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay
return;
}
m_client->mtu = std::min(m_client->mtu, NetPlay::MAX_ENET_MTU);
ENetAddress addr;
enet_address_set_host(&addr, address.c_str());
addr.port = port;

View file

@ -220,6 +220,7 @@ enum class SyncCodeID : u8
constexpr u32 MAX_NAME_LENGTH = 30;
constexpr size_t CHUNKED_DATA_UNIT_SIZE = 16384;
constexpr u32 MAX_ENET_MTU = 1392; // see https://github.com/lsalzman/enet/issues/132
enum : u8
{

View file

@ -151,7 +151,10 @@ NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI*
serverAddr.port = port;
m_server = enet_host_create(&serverAddr, 10, CHANNEL_COUNT, 0, 0);
if (m_server != nullptr)
{
m_server->mtu = std::min(m_server->mtu, NetPlay::MAX_ENET_MTU);
m_server->intercept = ENetUtil::InterceptCallback;
}
SetupIndex();
}

View file

@ -161,6 +161,7 @@
<ClInclude Include="Common\WindowsRegistry.h" />
<ClInclude Include="Common\WindowSystemInfo.h" />
<ClInclude Include="Common\WorkQueueThread.h" />
<ClInclude Include="Core\AchievementManager.h" />
<ClInclude Include="Core\ActionReplay.h" />
<ClInclude Include="Core\ARDecrypt.h" />
<ClInclude Include="Core\Boot\Boot.h" />
@ -172,6 +173,7 @@
<ClInclude Include="Core\CheatGeneration.h" />
<ClInclude Include="Core\CheatSearch.h" />
<ClInclude Include="Core\CommonTitles.h" />
<ClInclude Include="Core\Config\AchievementSettings.h" />
<ClInclude Include="Core\Config\DefaultLocale.h" />
<ClInclude Include="Core\Config\FreeLookSettings.h" />
<ClInclude Include="Core\Config\GraphicsSettings.h" />
@ -795,6 +797,7 @@
<ClCompile Include="Common\UPnP.cpp" />
<ClCompile Include="Common\WindowsRegistry.cpp" />
<ClCompile Include="Common\Version.cpp" />
<ClCompile Include="Core\AchievementManager.cpp" />
<ClCompile Include="Core\ActionReplay.cpp" />
<ClCompile Include="Core\ARDecrypt.cpp" />
<ClCompile Include="Core\Boot\Boot_BS2Emu.cpp" />
@ -805,6 +808,7 @@
<ClCompile Include="Core\BootManager.cpp" />
<ClCompile Include="Core\CheatGeneration.cpp" />
<ClCompile Include="Core\CheatSearch.cpp" />
<ClCompile Include="Core\Config\AchievementSettings.cpp" />
<ClCompile Include="Core\Config\DefaultLocale.cpp" />
<ClCompile Include="Core\Config\FreeLookSettings.cpp" />
<ClCompile Include="Core\Config\GraphicsSettings.cpp" />

View file

@ -52,6 +52,7 @@
<Import Project="$(ExternalsDir)minizip\exports.props" />
<Import Project="$(ExternalsDir)picojson\exports.props" />
<Import Project="$(ExternalsDir)pugixml\exports.props" />
<Import Project="$(ExternalsDir)rcheevos\exports.props" />
<Import Project="$(ExternalsDir)SDL\exports.props" />
<Import Project="$(ExternalsDir)SFML\exports.props" />
<Import Project="$(ExternalsDir)soundtouch\exports.props" />

View file

@ -616,18 +616,8 @@ if(APPLE)
if(MACOS_CODE_SIGNING)
# Code sign make file builds
add_custom_command(TARGET dolphin-emu
POST_BUILD COMMAND
/usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY}" --deep --options=runtime --entitlements "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Dolphin.app" || true)
# Code sign builds for build systems that do have release/debug variants (Xcode)
add_custom_command(TARGET dolphin-emu
POST_BUILD COMMAND
/usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY}" --deep --options=runtime --entitlements "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmuDebug.entitlements" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/Dolphin.app" || true)
add_custom_command(TARGET dolphin-emu
POST_BUILD COMMAND
/usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY}" --deep --options=runtime --entitlements "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmu.entitlements" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/Dolphin.app" || true)
add_custom_command(TARGET dolphin-emu POST_BUILD
COMMAND /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY}" --deep --options=runtime --entitlements "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements" "$<TARGET_BUNDLE_DIR:dolphin-emu>")
endif()
else()
install(TARGETS dolphin-emu RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
@ -687,3 +677,8 @@ endif()
if(USE_DISCORD_PRESENCE)
target_compile_definitions(dolphin-emu PRIVATE -DUSE_DISCORD_PRESENCE)
endif()
if(USE_RETRO_ACHIEVEMENTS)
target_link_libraries(dolphin-emu PRIVATE rcheevos)
target_compile_definitions(dolphin-emu PRIVATE -DUSE_RETRO_ACHIEVEMENTS)
endif()

View file

@ -62,6 +62,7 @@ void FilesystemWidget::CreateWidgets()
m_tree_view = new QTreeView(this);
m_tree_view->setModel(m_tree_model);
m_tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
m_tree_model->setParent(m_tree_view);
auto* header = m_tree_view->header();

View file

@ -47,6 +47,7 @@ void LogConfigWidget::CreateWidgets()
m_verbosity_warning = new QRadioButton(tr("Warning"));
m_verbosity_info = new QRadioButton(tr("Info"));
m_verbosity_debug = new QRadioButton(tr("Debug"));
m_verbosity_debug->setVisible(Common::Log::MAX_LOGLEVEL == Common::Log::LogLevel::LDEBUG);
auto* outputs = new QGroupBox(tr("Logger Outputs"));
auto* outputs_layout = new QVBoxLayout;
@ -77,10 +78,7 @@ void LogConfigWidget::CreateWidgets()
verbosity_layout->addWidget(m_verbosity_error);
verbosity_layout->addWidget(m_verbosity_warning);
verbosity_layout->addWidget(m_verbosity_info);
if constexpr (Common::Log::MAX_LOGLEVEL == Common::Log::LogLevel::LDEBUG)
{
verbosity_layout->addWidget(m_verbosity_debug);
}
layout->addWidget(outputs);
outputs_layout->addWidget(m_out_file);

View file

@ -249,12 +249,12 @@ void MemoryWidget::CreateWidgets()
QMenuBar* menubar = new QMenuBar(sidebar);
menubar->setNativeMenuBar(false);
QMenu* menu_import = new QMenu(tr("&Import"));
QMenu* menu_import = new QMenu(tr("&Import"), menubar);
menu_import->addAction(tr("&Load file to current address"), this,
&MemoryWidget::OnSetValueFromFile);
menubar->addMenu(menu_import);
QMenu* menu_export = new QMenu(tr("&Export"));
QMenu* menu_export = new QMenu(tr("&Export"), menubar);
menu_export->addAction(tr("Dump &MRAM"), this, &MemoryWidget::OnDumpMRAM);
menu_export->addAction(tr("Dump &ExRAM"), this, &MemoryWidget::OnDumpExRAM);
menu_export->addAction(tr("Dump &ARAM"), this, &MemoryWidget::OnDumpARAM);

View file

@ -439,6 +439,7 @@
<Import Project="$(ExternalsDir)mbedtls\exports.props" />
<Import Project="$(ExternalsDir)mGBA\exports.props" />
<Import Project="$(ExternalsDir)picojson\exports.props" />
<Import Project="$(ExternalsDir)rcheevos\exports.props" />
<Import Project="$(ExternalsDir)SFML\exports.props" />
<Import Project="$(ExternalsDir)soundtouch\exports.props" />
<Import Project="$(ExternalsDir)zstd\exports.props" />

View file

@ -37,6 +37,7 @@
#include "Common/Version.h"
#include "Common/WindowSystemInfo.h"
#include "Core/AchievementManager.h"
#include "Core/Boot/Boot.h"
#include "Core/BootManager.h"
#include "Core/CommonTitles.h"
@ -222,6 +223,11 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
InitControllers();
#ifdef USE_RETRO_ACHIEVEMENTS
// This has to be done before CreateComponents() so it's initialized.
AchievementManager::GetInstance()->Init();
#endif // USE_RETRO_ACHIEVEMENTS
CreateComponents();
ConnectGameList();
@ -301,6 +307,10 @@ MainWindow::~MainWindow()
Settings::Instance().ResetNetPlayClient();
Settings::Instance().ResetNetPlayServer();
#ifdef USE_RETRO_ACHIEVEMENTS
AchievementManager::GetInstance()->Shutdown();
#endif // USE_RETRO_ACHIEVEMENTS
delete m_render_widget;
delete m_netplay_dialog;

View file

@ -488,10 +488,11 @@ void RenderWidget::PassEventToPresenter(const QEvent* event)
const u32 key = static_cast<u32>(key_event->key() & 0x1FF);
const char* chars = nullptr;
QByteArray utf8;
if (is_down)
{
auto utf8 = key_event->text().toUtf8();
utf8 = key_event->text().toUtf8();
if (utf8.size())
chars = utf8.constData();

View file

@ -189,7 +189,8 @@ void InterfacePane::CreateInGame()
m_vboxlayout_hide_mouse->addWidget(m_radio_cursor_visible_never);
m_vboxlayout_hide_mouse->addWidget(m_radio_cursor_visible_always);
m_checkbox_lock_mouse = new QCheckBox(tr("Lock Mouse Cursor"));
// this ends up not being managed unless _WIN32, so lets not leak
m_checkbox_lock_mouse = new QCheckBox(tr("Lock Mouse Cursor"), this);
m_checkbox_lock_mouse->setToolTip(tr("Will lock the Mouse Cursor to the Render Widget as long as "
"it has focus. You can set a hotkey to unlock it."));

View file

@ -47,17 +47,14 @@ if (${IBTOOL} STREQUAL "IBTOOL-NOTFOUND")
endif()
foreach(sb ${STORYBOARDS})
set(MacUpdater_BIN_DIR ${CMAKE_BINARY_DIR}/Binaries)
if (CMAKE_GENERATOR STREQUAL Xcode)
string(APPEND MacUpdater_BIN_DIR "/\${CONFIGURATION}")
endif()
add_custom_command(TARGET MacUpdater POST_BUILD
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
--compile ${MacUpdater_BUNDLE_PATH}/Contents/Resources/${sb}c
${CMAKE_CURRENT_SOURCE_DIR}/${sb}
set(output ${CMAKE_CURRENT_BINARY_DIR}/${sb}c)
set(input ${CMAKE_CURRENT_SOURCE_DIR}/${sb})
add_custom_command(OUTPUT ${output}
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text --compile ${output} ${input}
DEPENDS ${input}
COMMENT "Compiling Storyboard ${sb}...")
target_sources(MacUpdater PRIVATE ${output})
set_source_files_properties(${output} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
endforeach()
if(MACOS_CODE_SIGNING)
@ -65,14 +62,6 @@ if(MACOS_CODE_SIGNING)
set(MACOS_CODE_SIGNING_IDENTITY_UPDATER "${MACOS_CODE_SIGNING_IDENTITY}")
endif()
# Make file build code sign
add_custom_command(TARGET MacUpdater POST_BUILD
COMMAND test ${MacUpdater_BUNDLE_PATH} || /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY_UPDATER}" --deep --options runtime ${MacUpdater_BUNDLE_PATH})
# Xcode build code sign
add_custom_command(TARGET MacUpdater POST_BUILD
COMMAND test "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/${MacUpdater_NAME}.app" || /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY_UPDATER}" --deep --options runtime "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/${MacUpdater_NAME}.app")
add_custom_command(TARGET MacUpdater POST_BUILD
COMMAND test "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/${MacUpdater_NAME}.app" || /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY_UPDATER}" --deep --options runtime "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/${MacUpdater_NAME}.app")
COMMAND /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY_UPDATER}" --deep --options runtime $<TARGET_BUNDLE_DIR:MacUpdater>)
endif()

View file

@ -26,8 +26,7 @@ CommandBufferManager::~CommandBufferManager()
if (m_use_threaded_submission)
{
WaitForWorkerThreadIdle();
m_submit_loop->Stop();
m_submit_thread.join();
m_submit_thread.Shutdown();
}
DestroyCommandBuffers();
@ -221,40 +220,11 @@ VkDescriptorSet CommandBufferManager::AllocateDescriptorSet(VkDescriptorSetLayou
bool CommandBufferManager::CreateSubmitThread()
{
m_submit_loop = std::make_unique<Common::BlockingLoop>();
m_submit_thread = std::thread([this]() {
Common::SetCurrentThreadName("Vulkan CommandBufferManager SubmitThread");
m_submit_loop->Run([this]() {
PendingCommandBufferSubmit submit;
{
std::lock_guard<std::mutex> guard(m_pending_submit_lock);
if (m_pending_submits.empty())
{
m_submit_loop->AllowSleep();
m_submit_worker_idle = true;
m_submit_worker_condvar.notify_all();
return;
}
submit = m_pending_submits.front();
m_pending_submits.pop_front();
}
m_submit_thread.Reset("VK submission thread", [this](PendingCommandBufferSubmit submit) {
SubmitCommandBuffer(submit.command_buffer_index, submit.present_swap_chain,
submit.present_image_index);
CmdBufferResources& resources = m_command_buffers[submit.command_buffer_index];
resources.waiting_for_submit.store(false, std::memory_order_release);
{
std::lock_guard<std::mutex> guard(m_pending_submit_lock);
if (m_pending_submits.empty())
{
m_submit_worker_idle = true;
m_submit_worker_condvar.notify_all();
}
}
});
});
return true;
@ -265,8 +235,7 @@ void CommandBufferManager::WaitForWorkerThreadIdle()
if (!m_use_threaded_submission)
return;
std::unique_lock lock{m_pending_submit_lock};
m_submit_worker_condvar.wait(lock, [&] { return m_submit_worker_idle; });
m_submit_thread.WaitForCompletion();
}
void CommandBufferManager::WaitForFenceCounter(u64 fence_counter)
@ -352,14 +321,7 @@ void CommandBufferManager::SubmitCommandBuffer(bool submit_on_worker_thread,
{
resources.waiting_for_submit.store(true, std::memory_order_relaxed);
// Push to the pending submit queue.
{
std::lock_guard<std::mutex> guard(m_pending_submit_lock);
m_submit_worker_idle = false;
m_pending_submits.push_back({present_swap_chain, present_image_index, m_current_cmd_buffer});
}
// Wake up the worker thread for a single iteration.
m_submit_loop->Wakeup();
m_submit_thread.Push({present_swap_chain, present_image_index, m_current_cmd_buffer});
}
else
{

View file

@ -14,6 +14,7 @@
#include <utility>
#include <vector>
#include <Common/WorkQueueThread.h>
#include "Common/BlockingLoop.h"
#include "Common/Flag.h"
#include "Common/Semaphore.h"
@ -146,19 +147,14 @@ private:
u32 m_current_cmd_buffer = 0;
// Threaded command buffer execution
std::thread m_submit_thread;
std::unique_ptr<Common::BlockingLoop> m_submit_loop;
struct PendingCommandBufferSubmit
{
VkSwapchainKHR present_swap_chain;
u32 present_image_index;
u32 command_buffer_index;
};
Common::WorkQueueThread<PendingCommandBufferSubmit> m_submit_thread;
VkSemaphore m_present_semaphore = VK_NULL_HANDLE;
std::deque<PendingCommandBufferSubmit> m_pending_submits;
std::mutex m_pending_submit_lock;
std::condition_variable m_submit_worker_condvar;
bool m_submit_worker_idle = true;
Common::Flag m_last_present_failed;
Common::Flag m_last_present_done;
VkResult m_last_present_result = VK_SUCCESS;

View file

@ -45,6 +45,7 @@
<PreprocessorDefinitions Condition="'$(AutoUpdate)'!='false'">AUTOUPDATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>HAVE_SDL2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Steam)'=='true'">STEAM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_RETRO_ACHIEVEMENTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<!-- Warnings one may want to ignore when using Level4.
4201 nonstandard extension used : nameless struct/union

View file

@ -86,6 +86,8 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spng", "..\Externals\libspng\spng.vcxproj", "{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SCMRevGen", "Core\Common\SCMRevGen.vcxproj", "{41279555-F94F-4EBC-99DE-AF863C10C5C4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rcheevos", "..\Externals\rcheevos\rcheevos.vcxproj", "{CC99A910-3752-4465-95AA-7DC240D92A99}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@ -418,6 +420,14 @@ Global
{41279555-F94F-4EBC-99DE-AF863C10C5C4}.Release|ARM64.Build.0 = Release|ARM64
{41279555-F94F-4EBC-99DE-AF863C10C5C4}.Release|x64.ActiveCfg = Release|x64
{41279555-F94F-4EBC-99DE-AF863C10C5C4}.Release|x64.Build.0 = Release|x64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|ARM64.Build.0 = Debug|ARM64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|x64.ActiveCfg = Debug|x64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Debug|x64.Build.0 = Debug|x64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|ARM64.ActiveCfg = Release|ARM64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|ARM64.Build.0 = Release|ARM64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|x64.ActiveCfg = Release|x64
{CC99A910-3752-4465-95AA-7DC240D92A99}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -454,6 +464,7 @@ Global
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{3F17D282-A77D-4931-B844-903AD0809A5E} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{447B7B1E-1D74-4AEF-B2B9-6EB41C5D5313} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
{CC99A910-3752-4465-95AA-7DC240D92A99} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {64B0A343-3B94-4522-9C24-6937FE5EFB22}