1
- #define WIN32_LEAN_AND_MEAN
1
+ #include <assert.h>
2
+ #include <stddef.h>
3
+ #include <stdio.h>
2
4
3
- #include <stddef.h> // size_t
4
5
#ifdef _WIN32
6
+ #define WIN32_LEAN_AND_MEAN
5
7
#include <windows.h>
6
8
#endif
7
9
10
+ #ifdef __linux__
11
+ #include <unistd.h>
12
+ #endif
13
+
14
+ #include "lib.h"
8
15
#include "net.h"
9
16
#include "pevent.h"
10
17
11
- static int lib_load (void );
12
- static int lib_has_new_version (void );
13
-
14
18
struct state {
15
19
void * buf ;
16
- void * lib ;
17
- peventf * on_pevent ;
18
- #ifdef _WIN32
19
- FILETIME lib_write_time ;
20
- #endif
20
+ struct lib gameserver ;
21
21
};
22
22
23
23
static struct state state = {0 };
24
24
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 )
60
26
{
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 ;
69
48
break ;
70
49
}
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 );
72
56
}
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 );
80
72
#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
+ }
81
82
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 );
85
85
86
86
union ppayload payload = {0 };
87
87
payload .pevent_socket .socket = socket ;
@@ -90,15 +90,15 @@ static void handle_net_event(int socket, enum net_event event, void *read, size_
90
90
91
91
switch (event ) {
92
92
case net_conn :
93
- state . on_pevent (& state .buf , pevent_socket_connection , & payload );
93
+ on_pevent (& state .buf , pevent_socket_connection , & payload );
94
94
break ;
95
95
96
96
case net_closed :
97
- state . on_pevent (& state .buf , pevent_socket_disconnected , & payload );
97
+ on_pevent (& state .buf , pevent_socket_disconnected , & payload );
98
98
break ;
99
99
100
100
case net_read :
101
- state . on_pevent (& state .buf , pevent_socket_request , & payload );
101
+ on_pevent (& state .buf , pevent_socket_request , & payload );
102
102
break ;
103
103
104
104
default :
@@ -108,13 +108,28 @@ static void handle_net_event(int socket, enum net_event event, void *read, size_
108
108
109
109
int main ()
110
110
{
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" );
112
121
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 ))
115
128
return 0 ;
116
129
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 );
118
133
net_listen (socket , handle_net_event );
119
134
120
135
return 0 ;
0 commit comments