Skip to content

Commit 17b52de

Browse files
committed
wip linux port.
1 parent 9133bfc commit 17b52de

17 files changed

+455
-97
lines changed

README

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
todo
2+
- fix linux implementation
3+
- add stop timer flag to stop the timer thread
4+
- wclose should signal instead of just setting the variable
5+
- implement lneedsreload in lib.c
6+
17
lineage 2 server emulator for the chronicle 4 written in c just for fun.
28

39
in windows, how to use?
@@ -17,8 +23,8 @@ TODO: in linux, how to use?
1723
- that's it, open your lineage 2 client and enjoy. accounts are created automatically
1824

1925
TODO: in linux, how to build?
20-
- install openssl lib
21-
- run build.sh
26+
- install openssl lib (sudo apt install libssl-dev)
27+
- run bash build.sh
2228

2329
notes
2430
- the login server uses the port 2106

bin/game_server

21.3 KB
Binary file not shown.

bin/game_server.dll

512 Bytes
Binary file not shown.

bin/game_server.exe

13 KB
Binary file not shown.

bin/game_server.so

70.4 KB
Binary file not shown.

bin/login_server

44.1 KB
Binary file not shown.

bin/login_server.exe

0 Bytes
Binary file not shown.

build.bat

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ cl %flags% ../login_server.c ../directory.c ../net_windows.c ../wqueue.c /Fe:log
1212

1313
cl %flags% /LD ../game_server_lib.c ../directory.c ../net_windows.c ../wqueue.c /Fe:game_server.dll /link -incremental:no /PDB:game_server_%random%.pdb /EXPORT:on_pevent Ws2_32.lib
1414

15-
cl %flags% ../game_server.c ../net_windows.c /Fe:game_server.exe /link /PDB:game_server.pdb Ws2_32.lib
15+
cl %flags% ../game_server.c ../net_windows.c ../lib.c /Fe:game_server.exe /link /PDB:game_server.pdb Ws2_32.lib
1616

1717
popd

build.sh

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#!/bin/bash
22

33
pushd bin
4-
gcc -Wall -o login_server ../login_server.c ../asocket_linux.c -I../openssl-1.1/x64/include -lcrypto
4+
5+
gcc -o login_server ../login_server.c ../directory.c ../net_linux.c ../wqueue.c -I../openssl-1.1/x64/include -lcrypto -lpthread
6+
7+
gcc -o game_server.so -fPIC -rdynamic -shared ../game_server_lib.c ../directory.c ../net_linux.c ../wqueue.c -lpthread
8+
9+
gcc -o game_server ../game_server.c ../net_linux.c ../lib.c -lpthread -ldl
10+
511
popd

directory.c

+43
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
#include <windows.h>
33
#endif
44

5+
#ifdef __linux__
6+
#include <dirent.h>
7+
#include <sys/stat.h>
8+
#endif
9+
510
#include <stdio.h>
611
#include "directory.h"
712

@@ -21,6 +26,13 @@ struct directory directory_open(char *path)
2126

2227
return result;
2328
#endif
29+
30+
#ifdef __linux__
31+
struct directory result = {0};
32+
result.path = path;
33+
result.handle = opendir(path);
34+
return result;
35+
#endif
2436
}
2537

2638
int directory_next(struct directory *directory)
@@ -44,6 +56,28 @@ int directory_next(struct directory *directory)
4456

4557
return 1;
4658
#endif
59+
60+
#ifdef __linux__
61+
if (!directory->handle)
62+
return 0;
63+
64+
struct dirent *entry = readdir(directory->handle);
65+
if (!entry) {
66+
closedir(directory->handle);
67+
directory->handle = 0;
68+
return 0;
69+
}
70+
71+
directory->is_directory = entry->d_type == DT_DIR;
72+
snprintf(directory->name, sizeof(directory->name) - 1, "%s", entry->d_name);
73+
snprintf(directory->full_path,
74+
sizeof(directory->full_path) - 1,
75+
"%s/%s",
76+
directory->path,
77+
directory->name);
78+
79+
return 1;
80+
#endif
4781
}
4882

4983
int directory_create(char *path)
@@ -52,5 +86,14 @@ int directory_create(char *path)
5286
if (CreateDirectory(path, 0) || GetLastError() == ERROR_ALREADY_EXISTS)
5387
return 1;
5488
#endif
89+
90+
#ifdef __linux__
91+
/*
92+
* create directoy for read and write.
93+
*/
94+
if (mkdir(path, 0666) == 0)
95+
return 1;
96+
#endif
97+
5598
return 0;
5699
}

directory.h

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#include <windows.h>
33
#endif
44

5+
#ifdef __linux__
6+
#include <dirent.h>
7+
#endif
8+
59
struct directory {
610
char *path;
711

@@ -14,6 +18,10 @@ struct directory {
1418
WIN32_FIND_DATA find_data;
1519
HANDLE handle;
1620
#endif
21+
22+
#ifdef __linux__
23+
DIR *handle;
24+
#endif
1725
};
1826

1927
#define in_directory(path) \

game_server.c

+86-71
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,87 @@
1-
#define WIN32_LEAN_AND_MEAN
1+
#include <assert.h>
2+
#include <stddef.h>
3+
#include <stdio.h>
24

3-
#include <stddef.h> // size_t
45
#ifdef _WIN32
6+
#define WIN32_LEAN_AND_MEAN
57
#include <windows.h>
68
#endif
79

10+
#ifdef __linux__
11+
#include <unistd.h>
12+
#endif
13+
14+
#include "lib.h"
815
#include "net.h"
916
#include "pevent.h"
1017

11-
static int lib_load(void);
12-
static int lib_has_new_version(void);
13-
1418
struct state {
1519
void *buf;
16-
void *lib;
17-
peventf *on_pevent;
18-
#ifdef _WIN32
19-
FILETIME lib_write_time;
20-
#endif
20+
struct lib gameserver;
2121
};
2222

2323
static struct state state = {0};
2424

25-
#ifdef _WIN32
26-
static int lib_load(void)
27-
{
28-
if (state.lib) {
29-
FreeLibrary(state.lib);
30-
state.lib = 0;
31-
}
32-
// create a copy of the dll and then load the copy,
33-
// not the original file, otherwise, windows will
34-
// complain when trying to make a change to it.
35-
if (CopyFile("game_server.dll", ".game_server.dll", FALSE) == 0)
36-
return 0;
37-
38-
state.lib = LoadLibraryA(".game_server.dll");
39-
if (!state.lib)
40-
return 0;
41-
42-
WIN32_FILE_ATTRIBUTE_DATA data = {0};
43-
GetFileAttributesEx("game_server.dll", GetFileExInfoStandard, &data);
44-
45-
state.lib_write_time = data.ftLastWriteTime;
46-
state.on_pevent = (peventf *) GetProcAddress(state.lib, "on_pevent");
47-
48-
return 1;
49-
}
50-
51-
static int lib_has_new_version(void)
52-
{
53-
WIN32_FILE_ATTRIBUTE_DATA data = {0};
54-
GetFileAttributesEx("game_server.dll", GetFileExInfoStandard, &data);
55-
int has_new_version = CompareFileTime(&state.lib_write_time, &data.ftLastWriteTime) != 0;
56-
return has_new_version;
57-
}
58-
59-
static void load_lib_if_required(void)
25+
static void handle_net_event(int socket, enum net_event event, void *read, size_t len)
6026
{
61-
if (lib_has_new_version()) {
62-
state.on_pevent(&state.buf, pevent_before_reload, 0);
63-
64-
int tries = 5;
65-
int loaded = 0;
66-
for (int i = 0; i < tries; i++) {
67-
if (lib_load()) {
68-
loaded = 1;
27+
enum lstatus lstatus = lfailed;
28+
peventf *on_pevent = 0;
29+
/*
30+
* try loading the library n amount of times.
31+
*/
32+
for (int i = 0; i < 5; i++) {
33+
lstatus = lload(&state.gameserver);
34+
if (lstatus == lneedsreload) {
35+
/*
36+
* before reloading the library, make sure
37+
* to run the before reload event.
38+
*/
39+
on_pevent = (peventf *) lfunction(&state.gameserver, "on_pevent");
40+
assert(on_pevent);
41+
on_pevent(&state.buf, pevent_before_reload, 0);
42+
/*
43+
* if the library can't be reloaded, just exit.
44+
*/
45+
lstatus = lload(&state.gameserver);
46+
if (lstatus != lreloaded) {
47+
lstatus = lfailed;
6948
break;
7049
}
71-
Sleep(1000);
50+
/*
51+
* library reloaded! run after reload event.
52+
*/
53+
on_pevent = (peventf *) lfunction(&state.gameserver, "on_pevent");
54+
assert(on_pevent);
55+
on_pevent(&state.buf, pevent_after_reload, 0);
7256
}
73-
74-
if (!loaded)
75-
ExitProcess(0);
76-
77-
state.on_pevent(&state.buf, pevent_after_reload, 0);
78-
}
79-
}
57+
/*
58+
* the library has been loaded, we can exit the loop.
59+
*/
60+
if (lstatus != lfailed)
61+
break;
62+
/*
63+
* before trying to load again, sleep for a second
64+
* letting the os make the required writing/processing
65+
* in case the library was updated.
66+
*/
67+
#ifdef _WIN32
68+
Sleep(1000);
69+
#endif
70+
#ifdef __linux__
71+
sleep(1);
8072
#endif
73+
}
74+
/*
75+
* if the library couldn't be loaded, crash the server.
76+
*/
77+
if (lstatus == lfailed) {
78+
fprintf(stderr, "failed to load library.\n");
79+
assert(!"game server library couldn't be loaded");
80+
return;
81+
}
8182

82-
static void handle_net_event(int socket, enum net_event event, void *read, size_t len)
83-
{
84-
load_lib_if_required();
83+
on_pevent = (peventf *) lfunction(&state.gameserver, "on_pevent");
84+
assert(on_pevent);
8585

8686
union ppayload payload = {0};
8787
payload.pevent_socket.socket = socket;
@@ -90,15 +90,15 @@ static void handle_net_event(int socket, enum net_event event, void *read, size_
9090

9191
switch (event) {
9292
case net_conn:
93-
state.on_pevent(&state.buf, pevent_socket_connection, &payload);
93+
on_pevent(&state.buf, pevent_socket_connection, &payload);
9494
break;
9595

9696
case net_closed:
97-
state.on_pevent(&state.buf, pevent_socket_disconnected, &payload);
97+
on_pevent(&state.buf, pevent_socket_disconnected, &payload);
9898
break;
9999

100100
case net_read:
101-
state.on_pevent(&state.buf, pevent_socket_request, &payload);
101+
on_pevent(&state.buf, pevent_socket_request, &payload);
102102
break;
103103

104104
default:
@@ -108,13 +108,28 @@ static void handle_net_event(int socket, enum net_event event, void *read, size_
108108

109109
int main()
110110
{
111-
if (!lib_load())
111+
#ifdef _WIN32
112+
state.gameserver.path = "game_server.dll";
113+
#endif
114+
115+
#ifdef __linux__
116+
state.gameserver.path = "game_server.so";
117+
#endif
118+
119+
if (lload(&state.gameserver) == lfailed) {
120+
fprintf(stderr, "failed to load game server library.\n");
112121
return 0;
113-
114-
if (!state.on_pevent(&state.buf, pevent_init, 0))
122+
}
123+
124+
peventf *on_pevent = (peventf *) lfunction(&state.gameserver, "on_pevent");
125+
assert(on_pevent);
126+
127+
if (!on_pevent(&state.buf, pevent_init, 0))
115128
return 0;
116129

117-
int socket = net_port(7777);
130+
unsigned short port = 7777;
131+
int socket = net_port(port);
132+
fprintf(stderr, "game server listening on port %d\n", port);
118133
net_listen(socket, handle_net_event);
119134

120135
return 0;

0 commit comments

Comments
 (0)