mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-17 10:03:50 +01:00
Merge pull request #1367 from CIB/master
Implemented socket_talk, a quick way for inter-process communication
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="DLLSocket" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="bin\Debug\DLLSocket" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj\Debug\" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Option createStaticLib="1" />
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-DBUILD_DLL" />
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="user32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="bin\Release\DLLSocket" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj\Release\" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Option createStaticLib="1" />
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-DBUILD_DLL" />
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add library="user32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Unit filename="main.cpp" />
|
||||
<Unit filename="main.h" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<debugger />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
g++ -static -shared -O3 -fPIC main.cpp -o DLLSocket.so
|
||||
@@ -0,0 +1,133 @@
|
||||
// OS-specific networking includes
|
||||
// -------------------------------
|
||||
#ifdef __WIN32
|
||||
#include <winsock2.h>
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
extern "C" {
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
}
|
||||
|
||||
typedef int SOCKET;
|
||||
typedef sockaddr_in SOCKADDR_IN;
|
||||
typedef sockaddr SOCKADDR;
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
// Socket used for all communications
|
||||
SOCKET sock;
|
||||
|
||||
// Address of the remote server
|
||||
SOCKADDR_IN addr;
|
||||
|
||||
// Buffer used to return dynamic strings to the caller
|
||||
#define BUFFER_SIZE 1024
|
||||
char return_buffer[BUFFER_SIZE];
|
||||
|
||||
// exposed functions
|
||||
// ------------------------------
|
||||
|
||||
const char* SUCCESS = "1\0"; // string representing success
|
||||
|
||||
#ifdef __WIN32
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLL_EXPORT __attribute__ ((visibility ("default")))
|
||||
#endif
|
||||
|
||||
// arg1: ip(in the xx.xx.xx.xx format)
|
||||
// arg2: port(a short)
|
||||
// return: NULL on failure, SUCCESS otherwise
|
||||
extern "C" DLL_EXPORT const char* establish_connection(int n, char *v[])
|
||||
{
|
||||
// extract args
|
||||
// ------------
|
||||
if(n < 2) return 0;
|
||||
const char* ip = v[0];
|
||||
const char* port_s = v[1];
|
||||
unsigned short port = atoi(port_s);
|
||||
|
||||
// set up network stuff
|
||||
// --------------------
|
||||
#ifdef __WIN32
|
||||
WSADATA wsa;
|
||||
WSAStartup(MAKEWORD(2,0),&wsa);
|
||||
#endif
|
||||
sock = socket(AF_INET,SOCK_DGRAM,0);
|
||||
|
||||
// make the socket non-blocking
|
||||
// ----------------------------
|
||||
#ifdef __WIN32
|
||||
unsigned long iMode=1;
|
||||
ioctlsocket(sock,FIONBIO,&iMode);
|
||||
#else
|
||||
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
// establish a connection to the server
|
||||
// ------------------------------------
|
||||
memset(&addr,0,sizeof(SOCKADDR_IN));
|
||||
addr.sin_family=AF_INET;
|
||||
addr.sin_port=htons(port);
|
||||
|
||||
// convert the string representation of the ip to a byte representation
|
||||
addr.sin_addr.s_addr=inet_addr(ip);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// arg1: string message to send
|
||||
// return: NULL on failure, SUCCESS otherwise
|
||||
extern "C" DLL_EXPORT const char* send_message(int n, char *v[])
|
||||
{
|
||||
// extract the args
|
||||
if(n < 1) return 0;
|
||||
const char* msg = v[0];
|
||||
|
||||
// send the message
|
||||
int rc = sendto(sock,msg,strlen(msg),0,(SOCKADDR*)&addr,sizeof(SOCKADDR));
|
||||
|
||||
// check for errors
|
||||
if (rc != -1) {
|
||||
return SUCCESS;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// no args
|
||||
// return: message if any received, NULL otherwise
|
||||
extern "C" DLL_EXPORT const char* recv_message(int n, char *v[])
|
||||
{
|
||||
SOCKADDR_IN sender; // we will store the sender address here
|
||||
|
||||
socklen_t sender_byte_length = sizeof(sender);
|
||||
|
||||
// Try receiving messages until we receive one that's valid, or there are no more messages
|
||||
while(1) {
|
||||
int rc = recvfrom(sock, return_buffer, BUFFER_SIZE,0,(SOCKADDR*) &sender,&sender_byte_length);
|
||||
if(rc > 0) {
|
||||
// we could read something
|
||||
|
||||
if(sender.sin_addr.s_addr != addr.sin_addr.s_addr) {
|
||||
continue; // not our connection, ignore and try again
|
||||
} else {
|
||||
return_buffer[rc] = '0'; // 0-terminate the string
|
||||
return return_buffer;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break; // no more messages, stop trying to receive
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import subprocess
|
||||
import socket
|
||||
import urlparse
|
||||
|
||||
UDP_IP="127.0.0.1"
|
||||
UDP_PORT=8019
|
||||
|
||||
sock = socket.socket( socket.AF_INET, # Internet
|
||||
socket.SOCK_DGRAM ) # UDP
|
||||
sock.bind( (UDP_IP,UDP_PORT) )
|
||||
|
||||
last_ticker_state = None
|
||||
|
||||
def handle_message(data, addr):
|
||||
global last_ticker_state
|
||||
|
||||
params = urlparse.parse_qs(data)
|
||||
print(data)
|
||||
|
||||
try:
|
||||
if params["type"][0] == "log" and str(params["log"][0]) and str(params["message"][0]):
|
||||
open(params["log"][0],"a+").write(params["message"][0]+"\n")
|
||||
except IOError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
if params["type"][0] == "ticker_state" and str(params["message"][0]):
|
||||
last_ticker_state = str(params["message"][0])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
if params["type"][0] == "startup" and last_ticker_state:
|
||||
open("crashlog.txt","a+").write("Server exited, last ticker state was: "+last_ticker_state+"\n")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
while True:
|
||||
data, addr = sock.recvfrom( 1024 ) # buffer size is 1024 bytes
|
||||
handle_message(data,addr)
|
||||
@@ -206,6 +206,7 @@
|
||||
#define FILE_DIR "icons/vending_icons"
|
||||
#define FILE_DIR "interface"
|
||||
#define FILE_DIR "maps"
|
||||
#define FILE_DIR "maps/backup"
|
||||
#define FILE_DIR "maps/RandomZLevels"
|
||||
#define FILE_DIR "sound"
|
||||
#define FILE_DIR "sound/AI"
|
||||
@@ -378,6 +379,7 @@
|
||||
#include "code\game\shuttle_engines.dm"
|
||||
#include "code\game\skincmd.dm"
|
||||
#include "code\game\smoothwall.dm"
|
||||
#include "code\game\socket_talk.dm"
|
||||
#include "code\game\sound.dm"
|
||||
#include "code\game\specops_shuttle.dm"
|
||||
#include "code\game\status.dm"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
var/vote_period = 60 // length of voting period (seconds, default 1 minute)
|
||||
var/vote_no_default = 0 // vote does not default to nochange/norestart (tbi)
|
||||
var/vote_no_dead = 0 // dead people can't vote (tbi)
|
||||
var/socket_talk = 0 // use socket_talk to communicate with other processes
|
||||
// var/enable_authentication = 0 // goon authentication
|
||||
var/del_new_on_log = 1 // del's new players if they log before they spawn in
|
||||
var/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
|
||||
@@ -309,6 +310,9 @@
|
||||
if("ticklag")
|
||||
Ticklag = text2num(value)
|
||||
|
||||
if("socket_talk")
|
||||
socket_talk = text2num(value)
|
||||
|
||||
if("tickcomp")
|
||||
Tickcomp = 1
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
|
||||
src.update_status()
|
||||
|
||||
socket_talk = new /datum/socket_talk()
|
||||
master_controller = new /datum/controller/game_controller()
|
||||
spawn(-1)
|
||||
master_controller.setup()
|
||||
|
||||
@@ -22,17 +22,30 @@ datum/controller/game_controller
|
||||
var/global/ticker_ready = 0
|
||||
|
||||
proc
|
||||
keepalive()
|
||||
setup()
|
||||
setup_objects()
|
||||
process()
|
||||
set_debug_state(txt)
|
||||
|
||||
keepalive()
|
||||
spawn while(1)
|
||||
sleep(10)
|
||||
|
||||
// Notify the other process that we're still there
|
||||
socket_talk.send_keepalive()
|
||||
|
||||
setup()
|
||||
if(master_controller && (master_controller != src))
|
||||
del(src)
|
||||
return
|
||||
//There can be only one master.
|
||||
|
||||
socket_talk = new /datum/socket_talk()
|
||||
|
||||
// notify the other process that we started up
|
||||
socket_talk.send_raw("type=startup")
|
||||
|
||||
if(!air_master)
|
||||
air_master = new /datum/controller/air_system()
|
||||
air_master.setup()
|
||||
@@ -73,6 +86,8 @@ datum/controller/game_controller
|
||||
|
||||
setupfactions()
|
||||
|
||||
spawn keepalive()
|
||||
|
||||
spawn
|
||||
ticker.pregame()
|
||||
|
||||
@@ -109,7 +124,7 @@ datum/controller/game_controller
|
||||
// This should describe what is currently being done by the master controller
|
||||
// Useful for crashlogs and similar, because that way it's easy to tell what
|
||||
// was going on when the server crashed.
|
||||
|
||||
socket_talk.send_raw("type=ticker_state&message=[txt]")
|
||||
return
|
||||
|
||||
process()
|
||||
@@ -141,6 +156,9 @@ datum/controller/game_controller
|
||||
powernets_ready = 0
|
||||
ticker_ready = 0
|
||||
|
||||
// Notify the other process that we're still there
|
||||
socket_talk.send_keepalive()
|
||||
|
||||
// the fact that the air master is not in the master controller
|
||||
// will make it very hard to find out whether it's responsible
|
||||
// for crashes
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Module used for fast interprocess communication between BYOND and other processes
|
||||
|
||||
/datum/socket_talk
|
||||
var
|
||||
enabled = 0
|
||||
New()
|
||||
..()
|
||||
src.enabled = config.socket_talk
|
||||
|
||||
if(enabled)
|
||||
call("DLLSocket.so","establish_connection")("127.0.0.1","8019")
|
||||
|
||||
proc
|
||||
send_raw(message)
|
||||
if(enabled)
|
||||
return call("DLLSocket.so","send_message")(message)
|
||||
receive_raw()
|
||||
if(enabled)
|
||||
return call("DLLSocket.so","recv_message")()
|
||||
send_log(var/log, var/message)
|
||||
return send_raw("type=log&log=[log]&message=[message]")
|
||||
send_keepalive()
|
||||
return send_raw("type=keepalive")
|
||||
|
||||
|
||||
var/global/datum/socket_talk/socket_talk
|
||||
@@ -163,5 +163,8 @@ TICKLAG 0.9
|
||||
## Defines if Tick Compensation is used. It results in a minor slowdown of movement of all mobs, but attempts to result in a level movement speed across all ticks. Recommended if tickrate is lowered.
|
||||
TICKCOMP 0
|
||||
|
||||
## Whether the server will talk to other processes through socket_talk
|
||||
SOCKET_TALK 0
|
||||
|
||||
## Uncomment to restrict non-admins using humanoid alien races
|
||||
USEALIENWHITELIST
|
||||
|
||||
Reference in New Issue
Block a user