Merge branch 'master' into jgrpp
# Conflicts: # src/network/core/os_abstraction.h # src/network/core/tcp_content.h # src/network/core/udp.cpp # src/table/currency_settings.ini # src/table/settings.h.preamble
This commit is contained in:
@@ -17,6 +17,7 @@ add_files(
|
||||
tcp_connect.cpp
|
||||
tcp_content.cpp
|
||||
tcp_content.h
|
||||
tcp_content_type.h
|
||||
tcp_game.cpp
|
||||
tcp_game.h
|
||||
tcp_http.cpp
|
||||
|
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
static const int DEFAULT_CONNECT_TIMEOUT_SECONDS = 3; ///< Allow connect() three seconds to connect.
|
||||
|
||||
/**
|
||||
* Get the hostname; in case it wasn't given the
|
||||
* IPv4 dotted representation is given.
|
||||
@@ -314,29 +316,53 @@ static SOCKET ConnectLoopProc(addrinfo *runp)
|
||||
|
||||
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, strerror(errno));
|
||||
DEBUG(net, 1, "[%s] could not create %s socket: %s", type, family, NetworkGetLastErrorString());
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (!SetNoDelay(sock)) DEBUG(net, 1, "[%s] setting TCP_NODELAY failed", type);
|
||||
|
||||
if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed", type);
|
||||
|
||||
int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
/* Emscripten is asynchronous, and as such a connect() is still in
|
||||
* progress by the time the call returns. */
|
||||
if (err != 0 && errno != EINPROGRESS)
|
||||
#else
|
||||
if (err != 0)
|
||||
#endif
|
||||
{
|
||||
DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno));
|
||||
if (err != 0 && NetworkGetLastError() != EINPROGRESS) {
|
||||
DEBUG(net, 1, "[%s] could not connect to %s over %s: %s", type, address, family, NetworkGetLastErrorString());
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
/* Connection succeeded */
|
||||
if (!SetNonBlocking(sock)) DEBUG(net, 0, "[%s] setting non-blocking mode failed", type);
|
||||
fd_set write_fd;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&write_fd);
|
||||
FD_SET(sock, &write_fd);
|
||||
|
||||
/* Wait for connect() to either connect, timeout or fail. */
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = DEFAULT_CONNECT_TIMEOUT_SECONDS;
|
||||
int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv);
|
||||
if (n < 0) {
|
||||
DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address, NetworkGetLastErrorString());
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
/* If no fd is selected, the timeout has been reached. */
|
||||
if (n == 0) {
|
||||
DEBUG(net, 1, "[%s] timed out while connecting to %s", type, address);
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
/* Retrieve last error, if any, on the socket. */
|
||||
err = GetSocketError(sock);
|
||||
if (err != 0) {
|
||||
DEBUG(net, 1, "[%s] could not connect to %s: %s", type, address, NetworkGetErrorString(err));
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
/* Connection succeeded. */
|
||||
DEBUG(net, 1, "[%s] connected to %s", type, address);
|
||||
|
||||
return sock;
|
||||
@@ -367,7 +393,7 @@ static SOCKET ListenLoopProc(addrinfo *runp)
|
||||
|
||||
SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, strerror(errno));
|
||||
DEBUG(net, 0, "[%s] could not create %s socket on port %s: %s", type, family, address, NetworkGetLastErrorString());
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
@@ -378,24 +404,24 @@ static SOCKET ListenLoopProc(addrinfo *runp)
|
||||
int on = 1;
|
||||
/* The (const char*) cast is needed for windows!! */
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) {
|
||||
DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, strerror(errno));
|
||||
DEBUG(net, 3, "[%s] could not set reusable %s sockets for port %s: %s", type, family, address, NetworkGetLastErrorString());
|
||||
}
|
||||
|
||||
#ifndef __OS2__
|
||||
if (runp->ai_family == AF_INET6 &&
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) == -1) {
|
||||
DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, strerror(errno));
|
||||
DEBUG(net, 3, "[%s] could not disable IPv4 over IPv6 on port %s: %s", type, address, NetworkGetLastErrorString());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) {
|
||||
DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, strerror(errno));
|
||||
DEBUG(net, 1, "[%s] could not bind on %s port %s: %s", type, family, address, NetworkGetLastErrorString());
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
|
||||
DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, strerror(errno));
|
||||
DEBUG(net, 1, "[%s] could not listen at %s port %s: %s", type, family, address, NetworkGetLastErrorString());
|
||||
closesocket(sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "../../debug.h"
|
||||
#include "os_abstraction.h"
|
||||
#include "packet.h"
|
||||
#include "../../string_func.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
@@ -48,6 +49,22 @@ void NetworkCoreShutdown()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
/**
|
||||
* Return the string representation of the given error from the OS's network functions.
|
||||
* @param error The error number (from \c NetworkGetLastError()).
|
||||
* @return The error message, potentially an empty string but never \c nullptr.
|
||||
*/
|
||||
const char *NetworkGetErrorString(int error)
|
||||
{
|
||||
static char buffer[512];
|
||||
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) {
|
||||
seprintf(buffer, lastof(buffer), "Unknown error %d", error);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/**
|
||||
* Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
|
||||
|
@@ -23,9 +23,21 @@
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define GET_LAST_ERROR() WSAGetLastError()
|
||||
/**
|
||||
* Get the last error code from any of the OS's network functions.
|
||||
* What it returns and when it is reset, is implementation defined.
|
||||
* @return The last error code.
|
||||
*/
|
||||
#define NetworkGetLastError() WSAGetLastError()
|
||||
#undef EWOULDBLOCK
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#undef ECONNRESET
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#undef EINPROGRESS
|
||||
#define EINPROGRESS WSAEWOULDBLOCK
|
||||
|
||||
const char *NetworkGetErrorString(int error);
|
||||
|
||||
/* Windows has some different names for some types */
|
||||
typedef unsigned long in_addr_t;
|
||||
|
||||
@@ -64,7 +76,8 @@ typedef unsigned long in_addr_t;
|
||||
# define INVALID_SOCKET -1
|
||||
# define ioctlsocket ioctl
|
||||
# define closesocket close
|
||||
# define GET_LAST_ERROR() (errno)
|
||||
# define NetworkGetLastError() (errno)
|
||||
# define NetworkGetErrorString(error) (strerror(error))
|
||||
# define SD_RECEIVE SHUT_RD
|
||||
# define SD_SEND SHUT_WR
|
||||
# define SD_BOTH SHUT_RDWR
|
||||
@@ -117,7 +130,8 @@ typedef unsigned long in_addr_t;
|
||||
# define INVALID_SOCKET -1
|
||||
# define ioctlsocket ioctl
|
||||
# define closesocket close
|
||||
# define GET_LAST_ERROR() (sock_errno())
|
||||
# define NetworkGetLastError() (sock_errno())
|
||||
# define NetworkGetErrorString(error) (strerror(error))
|
||||
# define SD_RECEIVE SHUT_RD
|
||||
# define SD_SEND SHUT_WR
|
||||
# define SD_BOTH SHUT_RDWR
|
||||
@@ -192,6 +206,15 @@ static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return the string representation of the last error from the OS's network functions.
|
||||
* @return The error message, potentially an empty string but never \c nullptr.
|
||||
*/
|
||||
static inline const char *NetworkGetLastErrorString()
|
||||
{
|
||||
return NetworkGetErrorString(NetworkGetLastError());
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to set the socket into non-blocking mode.
|
||||
* @param d The socket to set the non-blocking more for.
|
||||
@@ -269,6 +292,20 @@ static inline bool ShutdownSocket(SOCKET d, bool read, bool write, uint linger_t
|
||||
return shutdown(d, how) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error from a socket, if any.
|
||||
* @param d The socket to get the error from.
|
||||
* @return The errno on the socket.
|
||||
*/
|
||||
static inline int GetSocketError(SOCKET d)
|
||||
{
|
||||
int err;
|
||||
socklen_t len = sizeof(err);
|
||||
getsockopt(d, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Make sure these structures have the size we expect them to be */
|
||||
static_assert(sizeof(in_addr) == 4); ///< IPv4 addresses should be 4 bytes.
|
||||
static_assert(sizeof(in6_addr) == 16); ///< IPv6 addresses should be 16 bytes.
|
||||
|
@@ -98,11 +98,11 @@ SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down)
|
||||
Packet *p = this->packet_queue.front().get();
|
||||
res = p->TransferOut<int>(send, this->sock, 0);
|
||||
if (res == -1) {
|
||||
int err = GET_LAST_ERROR();
|
||||
int err = NetworkGetLastError();
|
||||
if (err != EWOULDBLOCK) {
|
||||
/* Something went wrong.. close client! */
|
||||
if (!closing_down) {
|
||||
DEBUG(net, 0, "send failed with error %d", err);
|
||||
DEBUG(net, 0, "send failed with error %s", NetworkGetErrorString(err));
|
||||
this->CloseConnection();
|
||||
}
|
||||
return SPS_CLOSED;
|
||||
@@ -148,10 +148,10 @@ std::unique_ptr<Packet> NetworkTCPSocketHandler::ReceivePacket()
|
||||
while (p->RemainingBytesToTransfer() != 0) {
|
||||
res = p->TransferIn<int>(recv, this->sock, 0);
|
||||
if (res == -1) {
|
||||
int err = GET_LAST_ERROR();
|
||||
int err = NetworkGetLastError();
|
||||
if (err != EWOULDBLOCK) {
|
||||
/* Something went wrong... (104 is connection reset by peer) */
|
||||
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
|
||||
/* Something went wrong... (ECONNRESET is connection reset by peer) */
|
||||
if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err));
|
||||
this->CloseConnection();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -176,10 +176,10 @@ std::unique_ptr<Packet> NetworkTCPSocketHandler::ReceivePacket()
|
||||
while (p->RemainingBytesToTransfer() != 0) {
|
||||
res = p->TransferIn<int>(recv, this->sock, 0);
|
||||
if (res == -1) {
|
||||
int err = GET_LAST_ERROR();
|
||||
int err = NetworkGetLastError();
|
||||
if (err != EWOULDBLOCK) {
|
||||
/* Something went wrong... (104 is connection reset by peer) */
|
||||
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
|
||||
/* Something went wrong... (ECONNRESET is connection reset by peer) */
|
||||
if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err));
|
||||
this->CloseConnection();
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -10,14 +10,12 @@
|
||||
*/
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#ifndef OPENTTD_MSU
|
||||
#include "../../textfile_gui.h"
|
||||
#include "../../newgrf_config.h"
|
||||
#include "../../base_media_base.h"
|
||||
#include "../../ai/ai.hpp"
|
||||
#include "../../game/game.hpp"
|
||||
#include "../../fios.h"
|
||||
#endif /* OPENTTD_MSU */
|
||||
#include "tcp_content.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
@@ -92,7 +90,6 @@ bool ContentInfo::IsValid() const
|
||||
return this->state < ContentInfo::INVALID && this->type >= CONTENT_TYPE_BEGIN && this->type < CONTENT_TYPE_END;
|
||||
}
|
||||
|
||||
#ifndef OPENTTD_MSU
|
||||
/**
|
||||
* Search a textfile file next to this file in the content list.
|
||||
* @param type The type of the textfile to search for.
|
||||
@@ -139,7 +136,6 @@ const char *ContentInfo::GetTextfile(TextfileType type) const
|
||||
if (tmp == nullptr) return nullptr;
|
||||
return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp);
|
||||
}
|
||||
#endif /* OPENTTD_MSU */
|
||||
|
||||
void NetworkContentSocketHandler::Close()
|
||||
{
|
||||
@@ -235,7 +231,6 @@ bool NetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) { return this->
|
||||
bool NetworkContentSocketHandler::Receive_CLIENT_CONTENT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_CONTENT); }
|
||||
bool NetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_CONTENT); }
|
||||
|
||||
#ifndef OPENTTD_MSU
|
||||
/**
|
||||
* Helper to get the subdirectory a #ContentInfo is located in.
|
||||
* @param type The type of content.
|
||||
@@ -260,4 +255,3 @@ Subdirectory GetContentInfoSubDir(ContentType type)
|
||||
case CONTENT_TYPE_HEIGHTMAP: return HEIGHTMAP_DIR;
|
||||
}
|
||||
}
|
||||
#endif /* OPENTTD_MSU */
|
||||
|
@@ -16,81 +16,7 @@
|
||||
#include "tcp.h"
|
||||
#include "packet.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
/** The values in the enum are important; they are used as database 'keys' */
|
||||
enum ContentType {
|
||||
CONTENT_TYPE_BEGIN = 1, ///< Helper to mark the begin of the types
|
||||
CONTENT_TYPE_BASE_GRAPHICS = 1, ///< The content consists of base graphics
|
||||
CONTENT_TYPE_NEWGRF = 2, ///< The content consists of a NewGRF
|
||||
CONTENT_TYPE_AI = 3, ///< The content consists of an AI
|
||||
CONTENT_TYPE_AI_LIBRARY = 4, ///< The content consists of an AI library
|
||||
CONTENT_TYPE_SCENARIO = 5, ///< The content consists of a scenario
|
||||
CONTENT_TYPE_HEIGHTMAP = 6, ///< The content consists of a heightmap
|
||||
CONTENT_TYPE_BASE_SOUNDS = 7, ///< The content consists of base sounds
|
||||
CONTENT_TYPE_BASE_MUSIC = 8, ///< The content consists of base music
|
||||
CONTENT_TYPE_GAME = 9, ///< The content consists of a game script
|
||||
CONTENT_TYPE_GAME_LIBRARY = 10, ///< The content consists of a GS library
|
||||
CONTENT_TYPE_END, ///< Helper to mark the end of the types
|
||||
};
|
||||
|
||||
/** Enum with all types of TCP content packets. The order MUST not be changed **/
|
||||
enum PacketContentType {
|
||||
PACKET_CONTENT_CLIENT_INFO_LIST, ///< Queries the content server for a list of info of a given content type
|
||||
PACKET_CONTENT_CLIENT_INFO_ID, ///< Queries the content server for information about a list of internal IDs
|
||||
PACKET_CONTENT_CLIENT_INFO_EXTID, ///< Queries the content server for information about a list of external IDs
|
||||
PACKET_CONTENT_CLIENT_INFO_EXTID_MD5, ///< Queries the content server for information about a list of external IDs and MD5
|
||||
PACKET_CONTENT_SERVER_INFO, ///< Reply of content server with information about content
|
||||
PACKET_CONTENT_CLIENT_CONTENT, ///< Request a content file given an internal ID
|
||||
PACKET_CONTENT_SERVER_CONTENT, ///< Reply with the content of the given ID
|
||||
PACKET_CONTENT_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||
};
|
||||
|
||||
/** Unique identifier for the content. */
|
||||
enum ContentID {
|
||||
INVALID_CONTENT_ID = UINT32_MAX, ///< Sentinel for invalid content.
|
||||
};
|
||||
|
||||
/** Container for all important information about a piece of content. */
|
||||
struct ContentInfo {
|
||||
/** The state the content can be in. */
|
||||
enum State {
|
||||
UNSELECTED, ///< The content has not been selected
|
||||
SELECTED, ///< The content has been manually selected
|
||||
AUTOSELECTED, ///< The content has been selected as dependency
|
||||
ALREADY_HERE, ///< The content is already at the client side
|
||||
DOES_NOT_EXIST, ///< The content does not exist in the content system
|
||||
INVALID, ///< The content's invalid
|
||||
};
|
||||
|
||||
ContentType type; ///< Type of content
|
||||
ContentID id; ///< Unique (server side) ID for the content
|
||||
uint32 filesize; ///< Size of the file
|
||||
char filename[48]; ///< Filename (for the .tar.gz; only valid on download)
|
||||
char name[64]; ///< Name of the content
|
||||
char version[16]; ///< Version of the content
|
||||
char url[96]; ///< URL related to the content
|
||||
char description[512]; ///< Description of the content
|
||||
uint32 unique_id; ///< Unique ID; either GRF ID or shortname
|
||||
byte md5sum[16]; ///< The MD5 checksum
|
||||
uint8 dependency_count; ///< Number of dependencies
|
||||
ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids)
|
||||
uint8 tag_count; ///< Number of tags
|
||||
char (*tags)[32]; ///< Malloced array of tags (strings)
|
||||
State state; ///< Whether the content info is selected (for download)
|
||||
bool upgrade; ///< This item is an upgrade
|
||||
|
||||
ContentInfo();
|
||||
~ContentInfo();
|
||||
|
||||
void TransferFrom(ContentInfo *other);
|
||||
|
||||
size_t Size() const;
|
||||
bool IsSelected() const;
|
||||
bool IsValid() const;
|
||||
#ifndef OPENTTD_MSU
|
||||
const char *GetTextfile(TextfileType type) const;
|
||||
#endif /* OPENTTD_MSU */
|
||||
};
|
||||
#include "tcp_content_type.h"
|
||||
|
||||
/** Base socket handler for all Content TCP sockets */
|
||||
class NetworkContentSocketHandler : public NetworkTCPSocketHandler {
|
||||
@@ -203,8 +129,6 @@ public:
|
||||
bool ReceivePackets();
|
||||
};
|
||||
|
||||
#ifndef OPENTTD_MSU
|
||||
Subdirectory GetContentInfoSubDir(ContentType type);
|
||||
#endif /* OPENTTD_MSU */
|
||||
|
||||
#endif /* NETWORK_CORE_TCP_CONTENT_H */
|
||||
|
88
src/network/core/tcp_content_type.h
Normal file
88
src/network/core/tcp_content_type.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tcp_content_type.h Basic types related to the content on the content server.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_CORE_TCP_CONTENT_TYPE_H
|
||||
#define NETWORK_CORE_TCP_CONTENT_TYPE_H
|
||||
|
||||
/** The values in the enum are important; they are used as database 'keys' */
|
||||
enum ContentType {
|
||||
CONTENT_TYPE_BEGIN = 1, ///< Helper to mark the begin of the types
|
||||
CONTENT_TYPE_BASE_GRAPHICS = 1, ///< The content consists of base graphics
|
||||
CONTENT_TYPE_NEWGRF = 2, ///< The content consists of a NewGRF
|
||||
CONTENT_TYPE_AI = 3, ///< The content consists of an AI
|
||||
CONTENT_TYPE_AI_LIBRARY = 4, ///< The content consists of an AI library
|
||||
CONTENT_TYPE_SCENARIO = 5, ///< The content consists of a scenario
|
||||
CONTENT_TYPE_HEIGHTMAP = 6, ///< The content consists of a heightmap
|
||||
CONTENT_TYPE_BASE_SOUNDS = 7, ///< The content consists of base sounds
|
||||
CONTENT_TYPE_BASE_MUSIC = 8, ///< The content consists of base music
|
||||
CONTENT_TYPE_GAME = 9, ///< The content consists of a game script
|
||||
CONTENT_TYPE_GAME_LIBRARY = 10, ///< The content consists of a GS library
|
||||
CONTENT_TYPE_END, ///< Helper to mark the end of the types
|
||||
};
|
||||
|
||||
/** Enum with all types of TCP content packets. The order MUST not be changed **/
|
||||
enum PacketContentType {
|
||||
PACKET_CONTENT_CLIENT_INFO_LIST, ///< Queries the content server for a list of info of a given content type
|
||||
PACKET_CONTENT_CLIENT_INFO_ID, ///< Queries the content server for information about a list of internal IDs
|
||||
PACKET_CONTENT_CLIENT_INFO_EXTID, ///< Queries the content server for information about a list of external IDs
|
||||
PACKET_CONTENT_CLIENT_INFO_EXTID_MD5, ///< Queries the content server for information about a list of external IDs and MD5
|
||||
PACKET_CONTENT_SERVER_INFO, ///< Reply of content server with information about content
|
||||
PACKET_CONTENT_CLIENT_CONTENT, ///< Request a content file given an internal ID
|
||||
PACKET_CONTENT_SERVER_CONTENT, ///< Reply with the content of the given ID
|
||||
PACKET_CONTENT_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||
};
|
||||
|
||||
/** Unique identifier for the content. */
|
||||
enum ContentID {
|
||||
INVALID_CONTENT_ID = UINT32_MAX, ///< Sentinel for invalid content.
|
||||
};
|
||||
|
||||
/** Container for all important information about a piece of content. */
|
||||
struct ContentInfo {
|
||||
/** The state the content can be in. */
|
||||
enum State {
|
||||
UNSELECTED, ///< The content has not been selected
|
||||
SELECTED, ///< The content has been manually selected
|
||||
AUTOSELECTED, ///< The content has been selected as dependency
|
||||
ALREADY_HERE, ///< The content is already at the client side
|
||||
DOES_NOT_EXIST, ///< The content does not exist in the content system
|
||||
INVALID, ///< The content's invalid
|
||||
};
|
||||
|
||||
ContentType type; ///< Type of content
|
||||
ContentID id; ///< Unique (server side) ID for the content
|
||||
uint32 filesize; ///< Size of the file
|
||||
char filename[48]; ///< Filename (for the .tar.gz; only valid on download)
|
||||
char name[64]; ///< Name of the content
|
||||
char version[16]; ///< Version of the content
|
||||
char url[96]; ///< URL related to the content
|
||||
char description[512]; ///< Description of the content
|
||||
uint32 unique_id; ///< Unique ID; either GRF ID or shortname
|
||||
byte md5sum[16]; ///< The MD5 checksum
|
||||
uint8 dependency_count; ///< Number of dependencies
|
||||
ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids)
|
||||
uint8 tag_count; ///< Number of tags
|
||||
char (*tags)[32]; ///< Malloced array of tags (strings)
|
||||
State state; ///< Whether the content info is selected (for download)
|
||||
bool upgrade; ///< This item is an upgrade
|
||||
|
||||
ContentInfo();
|
||||
~ContentInfo();
|
||||
|
||||
void TransferFrom(ContentInfo *other);
|
||||
|
||||
size_t Size() const;
|
||||
bool IsSelected() const;
|
||||
bool IsValid() const;
|
||||
const char *GetTextfile(TextfileType type) const;
|
||||
};
|
||||
|
||||
#endif /* NETWORK_CORE_TCP_CONTENT_TYPE_H */
|
@@ -228,10 +228,10 @@ int NetworkHTTPSocketHandler::Receive()
|
||||
for (;;) {
|
||||
ssize_t res = recv(this->sock, (char *)this->recv_buffer + this->recv_pos, lengthof(this->recv_buffer) - this->recv_pos, 0);
|
||||
if (res == -1) {
|
||||
int err = GET_LAST_ERROR();
|
||||
int err = NetworkGetLastError();
|
||||
if (err != EWOULDBLOCK) {
|
||||
/* Something went wrong... (104 is connection reset by peer) */
|
||||
if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
|
||||
/* Something went wrong... (ECONNRESET is connection reset by peer) */
|
||||
if (err != ECONNRESET) DEBUG(net, 0, "recv failed with error %s", NetworkGetErrorString(err));
|
||||
return -1;
|
||||
}
|
||||
/* Connection would block, so stop for now */
|
||||
|
@@ -64,7 +64,7 @@ public:
|
||||
DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str());
|
||||
|
||||
if (p.TransferOut<int>(send, s, 0) < 0) {
|
||||
DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
|
||||
DEBUG(net, 0, "send failed with error %s", NetworkGetLastErrorString());
|
||||
}
|
||||
closesocket(s);
|
||||
break;
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
p.PrepareToSend();
|
||||
|
||||
if (p.TransferOut<int>(send, s, 0) < 0) {
|
||||
DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
|
||||
DEBUG(net, 0, "send failed with error %s", NetworkGetLastErrorString());
|
||||
}
|
||||
closesocket(s);
|
||||
|
||||
|
@@ -130,7 +130,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
|
||||
/* Enable broadcast */
|
||||
unsigned long val = 1;
|
||||
if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
|
||||
DEBUG(net, 1, "[udp] setting broadcast failed with: %i", GET_LAST_ERROR());
|
||||
DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkGetLastErrorString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
|
||||
DEBUG(net, 7, "[udp] sendto(%s)", NetworkAddressDumper().GetAddressAsString(&send));
|
||||
|
||||
/* Check for any errors, but ignore it otherwise */
|
||||
if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %i", NetworkAddressDumper().GetAddressAsString(&send), GET_LAST_ERROR());
|
||||
if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", NetworkAddressDumper().GetAddressAsString(&send), NetworkGetLastErrorString());
|
||||
|
||||
if (!all) break;
|
||||
}
|
||||
|
@@ -718,16 +718,16 @@ public:
|
||||
|
||||
|
||||
/* Used by clients, to connect to a server */
|
||||
void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const char *join_server_password, const char *join_company_password)
|
||||
void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password, const char *join_company_password)
|
||||
{
|
||||
if (!_network_available) return;
|
||||
|
||||
if (address.GetPort() == 0) return;
|
||||
if (port == 0) return;
|
||||
|
||||
if (!NetworkValidateClientName()) return;
|
||||
|
||||
strecpy(_settings_client.network.last_host, address.GetHostname(), lastof(_settings_client.network.last_host));
|
||||
_settings_client.network.last_port = address.GetPort();
|
||||
strecpy(_settings_client.network.last_host, hostname, lastof(_settings_client.network.last_host));
|
||||
_settings_client.network.last_port = port;
|
||||
_network_join_as = join_as;
|
||||
_network_join_server_password = join_server_password;
|
||||
_network_join_company_password = join_company_password;
|
||||
@@ -738,7 +738,7 @@ void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const c
|
||||
_network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
|
||||
ShowJoinStatusWindow();
|
||||
|
||||
new TCPClientConnecter(address);
|
||||
new TCPClientConnecter(NetworkAddress(hostname, port));
|
||||
}
|
||||
|
||||
static void NetworkInitGameInfo()
|
||||
@@ -1099,12 +1099,13 @@ static void NetworkGenerateServerId()
|
||||
seprintf(_settings_client.network.network_id, lastof(_settings_client.network.network_id), "%s", hex_output);
|
||||
}
|
||||
|
||||
void NetworkStartDebugLog(NetworkAddress address)
|
||||
void NetworkStartDebugLog(const char *hostname, uint16 port)
|
||||
{
|
||||
extern SOCKET _debug_socket; // Comes from debug.c
|
||||
|
||||
DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort());
|
||||
DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", hostname, port);
|
||||
|
||||
NetworkAddress address(hostname, port);
|
||||
SOCKET s = address.Connect();
|
||||
if (s == INVALID_SOCKET) {
|
||||
DEBUG(net, 0, "Failed to open socket for redirection DEBUG()");
|
||||
|
@@ -17,7 +17,6 @@
|
||||
// #define DEBUG_DUMP_COMMANDS
|
||||
// #define DEBUG_FAILED_DUMP_COMMANDS
|
||||
|
||||
#include "core/address.h"
|
||||
#include "network_type.h"
|
||||
#include "../console_type.h"
|
||||
#include "../gfx_type.h"
|
||||
@@ -48,12 +47,12 @@ void NetworkGameLoop();
|
||||
void NetworkBackgroundLoop();
|
||||
void ParseConnectionString(const char **port, char *connection_string);
|
||||
void ParseGameConnectionString(const char **company, const char **port, char *connection_string);
|
||||
void NetworkStartDebugLog(NetworkAddress address);
|
||||
void NetworkStartDebugLog(const char *hostname, uint16 port);
|
||||
void NetworkPopulateCompanyStats(NetworkCompanyStats *stats);
|
||||
|
||||
void NetworkUpdateClientInfo(ClientID client_id);
|
||||
void NetworkClientsToSpectators(CompanyID cid);
|
||||
void NetworkClientConnectGame(NetworkAddress address, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
|
||||
void NetworkClientConnectGame(const char *hostname, uint16 port, CompanyID join_as, const char *join_server_password = nullptr, const char *join_company_password = nullptr);
|
||||
void NetworkClientRequestMove(CompanyID company, const char *pass = "");
|
||||
void NetworkClientSendRcon(const char *password, const char *command);
|
||||
void NetworkClientSendSettingsPassword(const char *password);
|
||||
|
@@ -1485,15 +1485,15 @@ struct NetworkLobbyWindow : public Window {
|
||||
|
||||
case WID_NL_JOIN: // Join company
|
||||
/* Button can be clicked only when it is enabled. */
|
||||
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), this->company);
|
||||
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, this->company);
|
||||
break;
|
||||
|
||||
case WID_NL_NEW: // New company
|
||||
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_NEW_COMPANY);
|
||||
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_NEW_COMPANY);
|
||||
break;
|
||||
|
||||
case WID_NL_SPECTATE: // Spectate game
|
||||
NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port), COMPANY_SPECTATOR);
|
||||
NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port, COMPANY_SPECTATOR);
|
||||
break;
|
||||
|
||||
case WID_NL_REFRESH: // Refresh
|
||||
|
Reference in New Issue
Block a user