2
2
#Include Once "kageExterns.bi"
4
Declare Sub ServerThread(ByVal As Any Ptr)
13
'todo: make client array size resizable (ReDim)
14
Dim Shared As CLIENT Clients(MAX_CLIENTS-1)
15
Dim Shared As Integer g_clientCtr
17
Dim Shared As FDSOCKET hEngineConn
18
Dim Shared As SOCKADDR_IN Server, Client
19
Dim Shared As Integer g_ret, addrsize, g_index
20
Dim Shared As String net_sMsg
21
Dim Shared As String net_statMsg
22
Dim Shared As String net_errMsg
23
Dim Shared As Integer bNetConnState
25
Const MSG_TYPE_EXIT = 101
26
Const MSG_TYPE_SERVERFULL = 102
28
Const MSG_INDEX_TYPE = 0
29
Const MSG_INDEX_SENDER = 1
30
Const MSG_INDEX_RECEIVER = 2
31
Const MSG_INDEX_MESSAGE = 3
34
NETCONN_CLOSE = 0 ' Uninitialized.
35
NETCONN_INIT = 1 ' Connection is initialized
36
NETCONN_OPEN = 2 ' Connection is currently in use
37
NETCONN_EXIT = 3 ' Force exit Connection
40
Sub Engine_ServerStart(pAny As Any Ptr)
41
Server.sin_addr = INADDR_ANY
42
g_ret = NetBind(hEngineConn, @Server, SizeOf(SOCKADDR_IN))
44
Engine_Log "Socket Port-bind Error", 1
45
bNetConnState = NETCONN_CLOSE
49
g_ret = NetListen(hEngineConn, 3)
51
Engine_Log "Socket Listen Error", 1
52
bNetConnState = NETCONN_CLOSE
55
Dim As Integer l_clientMax = Cast(Integer, pAny) - 1 '1 is reserved for server
57
bNetConnState = NETCONN_OPEN
58
While bNetConnState <> NETCONN_EXIT
59
addrsize = SizeOf(SOCKADDR_IN)
60
'If g_clientCtr < l_clientMax Then
61
'g_ret = NetAccept(hEngineConn, @Client, @addrsize)
62
g_ret = NetAccept(hEngineConn, 0, 0)
65
net_statMsg = "server: accept"
66
If g_clientCtr < (MAX_CLIENTS - 1) Then
67
' get next free client
69
While Clients(g_index).hClient <> 0
72
Clients(g_index).hClient = g_ret
73
Clients(g_index).hThread = ThreadCreate(@Engine_ServerStartThread, Cast(Any Ptr, g_index))
75
net_statMsg = "server: connections=" & Str(g_clientCtr)
77
net_errMsg = "Server Full Error"
78
Engine_Log net_errMsg, 1
79
Engine_Send(net_errMsg, MSG_TYPE_SERVERFULL)
81
ElseIf g_ret = WSAEWOULDBLOCK Then
83
ElseIf g_ret = -1 Then
86
' * TODO: list as you go along
88
Engine_Log "g_ret " & g_ret, 1
89
net_errMsg = "Server Accept Error"
90
Engine_Log net_errMsg, 1
91
bNetConnState = NETCONN_EXIT
98
bNetConnState = NETCONN_CLOSE
100
net_statMsg = "Server Close"
103
' for use by Engine_ServerStart
104
Sub Engine_ServerStartThread(ByVal lpany As Any Ptr)
105
Dim As Integer l_ret, l_index = Cast(Integer, lpAny)
107
Dim sDataCopy As String
110
Dim sMsgTrim() As String
112
Dim lngMsgType As Long 'A value indicating the type of message this is
113
net_statMsg = "connected client(" & l_index & ")"
114
Clients(l_index).blnExit = 0
115
While Clients(l_index).blnExit = 0 Or bNetConnState <> NETCONN_EXIT
116
l_ret = NetReceiveString(Clients(l_index).hClient, sData)
118
'sData = "thread: l_ret<1"
119
'Clients(l_index).blnExit = 1
121
Engine_Log "sData " & sData, 1
125
Split sData, Chr(2), sMsg()
127
Split sMsg(MSG_INDEX_MESSAGE), Chr(3), sMsgTrim()
129
sMsg(MSG_INDEX_MESSAGE) = sMsgTrim(0)
131
lngMsgType = CLng(sMsg(MSG_INDEX_TYPE))
133
If lngMsgType > 2400 Then
135
lngMsgType = lngMsgType - 2400
138
If CLng(sMsg(MSG_INDEX_RECEIVER)) = 0 Or CLng(sMsg(MSG_INDEX_RECEIVER)) = kseNet.playerID Then
139
sData = sMsg(MSG_INDEX_SENDER) & Chr(2) & sMsg(MSG_INDEX_MESSAGE) 'removed sMsg(2); message is for receiver
140
'TODO: get sender info; lngMsgType should be the index of the user who sent data/msg
142
sNetData = sNetData & kseVARSEPARATOR & "KSNET" & kseVALUESEP & lngMsgType & Chr(2) & sData
143
Engine_NetDataPush(lngMsgType, CInt(sMsg(MSG_INDEX_SENDER)), kseNet.playerID, sMsg(MSG_INDEX_MESSAGE))
145
sNetMsg = sNetMsg & kseVARSEPARATOR & "KSNET" & kseVALUESEP & lngMsgType & Chr(2) & sData
146
Engine_NetDataPush(lngMsgType, CInt(sMsg(MSG_INDEX_SENDER)), kseNet.playerID, sMsg(MSG_INDEX_MESSAGE))
151
'TODO: only send copies to fellow Clients every once in a while -- not always
152
If CInt(sMsg(MSG_INDEX_TYPE)) <> MSG_TYPE_EXIT Then
153
For i = 0 To MAX_CLIENTS - 1
154
If Clients(i).hThread <> 0 And i <> l_index Then
155
Engine_Send(sMsg(MSG_INDEX_MESSAGE), CInt(sMsg(MSG_INDEX_TYPE)),Clients(i).hClient) ' 4 is _3 Chr(2) and 1 Chr(3)_
160
If iGotMessage > 0 Then kseFunction(iGotMessage).RunScript()
162
sData = Mid(sDataCopy, _
163
Len(sMsg(MSG_INDEX_TYPE)) + _
164
Len(sMsg(MSG_INDEX_SENDER)) + _
165
Len(sMsg(MSG_INDEX_RECEIVER)) + _
166
Len(sMsg(MSG_INDEX_MESSAGE)) + 5) ' 3 Chr(2) and 1 Chr(3) and 1 offset
171
net_statMsg = "thread:(" & Str(l_index) &") got a message " & sData
172
If InStr(sData,"exit") Then
173
Clients(l_index).blnExit = 1
174
NetClose Clients(l_index).hClient
175
bNetConnState = NETCONN_EXIT
177
' net_statMsg = "thread:(" & Str(l_index) &") send ok"
178
' Engine_Send("ok", 102,Clients(l_index).hClient)
182
net_statMsg = "disconnected client(" & l_index & ")"
183
NetClose Clients(l_index).hClient
184
Clients(l_index).hClient = 0
188
Sub Engine_ClientStart(pAny As Any Ptr)
191
Dim sDataCopy As String
193
Dim sMsgTrim() As String
195
Dim lngMsgType As Long 'A value indicating the type of message this is
196
bNetConnState = NETCONN_OPEN
197
While bNetConnState <> NETCONN_CLOSE
199
' kseNet.sockMain.get(sData)
201
l_ret = NetReceiveString(hEngineConn, sData)
203
'bNetConnState = NETCONN_EXIT
205
Engine_Log "sData " & sData, 1
208
Split sData, Chr(2), sMsg()
210
Split sMsg(MSG_INDEX_MESSAGE), Chr(3), sMsgTrim()
212
sMsg(MSG_INDEX_MESSAGE) = sMsgTrim(0)
214
lngMsgType = CLng(sMsg(MSG_INDEX_TYPE))
216
If lngMsgType > 2400 Then
218
lngMsgType = lngMsgType - 2400
221
If CLng(sMsg(MSG_INDEX_RECEIVER)) = 0 Or CLng(sMsg(MSG_INDEX_RECEIVER)) = kseNet.playerID Then
222
sData = sMsg(MSG_INDEX_SENDER) & Chr(2) & sMsg(MSG_INDEX_MESSAGE) 'removed sMsg(2); message is for receiver
223
'TODO: get sender info; lngMsgType should be the index of the user who sent data/msg
225
sNetData = sNetData & kseVARSEPARATOR & "KSNET" & kseVALUESEP & lngMsgType & Chr(2) & sData
226
Engine_NetDataPush(lngMsgType, CInt(sMsg(MSG_INDEX_SENDER)), kseNet.playerID, sMsg(MSG_INDEX_MESSAGE))
228
sNetMsg = sNetMsg & kseVARSEPARATOR & "KSNET" & kseVALUESEP & lngMsgType & Chr(2) & sData
229
Engine_NetDataPush(lngMsgType, CInt(sMsg(MSG_INDEX_SENDER)), kseNet.playerID, sMsg(MSG_INDEX_MESSAGE))
233
sData = Mid(sDataCopy, _
234
Len(sMsg(MSG_INDEX_TYPE)) + _
235
Len(sMsg(MSG_INDEX_SENDER)) + _
236
Len(sMsg(MSG_INDEX_RECEIVER)) + _
237
Len(sMsg(MSG_INDEX_MESSAGE)) + 5) ' 3 Chr(2) and 1 Chr(3) and 1 offset
241
If CInt(sMsg(MSG_INDEX_TYPE)) = MSG_TYPE_EXIT Then
242
If iGotDisconnected > 0 Then kseFunction(iGotDisconnected).RunScript()
244
If iGotMessage > 0 Then kseFunction(iGotMessage).RunScript()
5
252
' Used by engine for parsing and interpreting
943
1177
' Call DPLAY.Open(oSessionData, DPOPEN_CREATE)
944
1178
' 'add host in this session -- assign name
945
1179
' kseNet.playerID = DPLAY.CreatePlayer(kseNet.playerName, "", 0, 0)
948
1180
kseNet.hMaxplayer = IIf(kseNet.hMaxplayer < 2, 2, kseNet.hMaxplayer)
950
iStat = kseNet.sockMain.UDP_server(kseNET_PORT)
952
'print translate_error( iStat )
953
Engine_Log "Socket unavailable", 1
956
iStat = kseNet.sockMain.UDP_server(kseNET_PORT, kseNet.hMaxplayer)
958
Engine_Log "Unavailable to open socket", 1
1181
Dim As Any Ptr threadMain = ThreadCreate(@Engine_ServerStart, Cast(Any Ptr, kseNet.hMaxplayer))
1182
While bNetConnState = NETCONN_INIT
1183
Sleep 1 'wait for engine to fully open or close-due-to-error
1185
If bNetConnState = NETCONN_CLOSE Then
961
1188
kseNet.Connected = 1
1190
' l_ret = kseNet.sockMain.UDP_server(kseNET_PORT)', kseNet.hMaxplayer
1192
' 'print translate_error( iStat )
1193
' Engine_Log "Socket unavailable", 1
1199
Private Sub Engine_NetQuit()
1200
If bNetConnState <> NETCONN_CLOSE Then
1201
If kseNet.Hosting = 1 Then
1203
bNetConnState = NETCONN_EXIT
1204
' While bNetConnState <> NETCONN_CLOSE
1209
If g_clientCtr > 0 Then
1210
For i = 0 To MAX_CLIENTS - 1
1211
Clients(i).blnExit = 1
1215
For i = 0 To MAX_CLIENTS - 1
1216
If Clients(i).hThread <> 0 Then
1217
If Clients(i).hThread <> 0 Then
1218
Engine_Send("", MSG_TYPE_EXIT, Clients(i).hClient)
1219
NetClose Clients(i).hClient
1221
ThreadWait(Clients(i).hThread)
1226
Engine_Send("", MSG_TYPE_EXIT, hEngineConn)
1229
NetClose hEngineConn
1230
' bNetConnState = NETCONN_CLOSE
968
1235
' (<b>Dev API</b>) Joins a server.
970
' @return Returns <b>True</b> if successfully joined a game, and <b>False</b>, otherwise.
1237
' @return Returns <b>1</b> if successfully joined a game, and <b>0</b>, otherwise.
971
1238
' @remarks This is called by engine through <b>Net:Join</b>.
972
1239
Private Function Engine_Join(serverName As String, port As Integer) As Byte
1240
kseNet.Connected = 0
1243
If Engine_InitConnection() = 0 Then Return 0
973
1245
Dim serverIP As Integer
974
1246
serverIP = Engine_ParseIP(serverName)
1247
Engine_Log "serverIP " & serverIP,1
975
1248
If serverIP = 0 Then
976
1249
'is it the server's computer name?
977
If kseNet.sockMain.UDP_client(serverName, port) <> chi.SOCKET_OK Then
980
'TODO: register client to host then get host info
1251
' If kseNet.sockMain.UDP_client(serverName, port) <> chi.SOCKET_OK Then Return 0
984
If kseNet.sockMain.UDP_client(serverIP, port) <> chi.SOCKET_OK Then
987
'TODO: register client to host then get host info
1255
' If kseNet.sockMain.UDP_client(serverIP, port) <> chi.SOCKET_OK Then Return 0
1257
Server.sin_addr = inet_addr(serverName)
1260
g_ret = NetConnect(hEngineConn, @Server, SizeOf(SOCKADDR_IN))
1263
NetClose hEngineConn
1264
Engine_Log "Socket Connect Error",1
1265
bNetConnState = NETCONN_CLOSE
1269
Dim As Any Ptr threadMain = ThreadCreate(@Engine_ClientStart, 0)
1271
While bNetConnState = NETCONN_INIT
1272
Sleep 1 'wait for engine to fully open or close-due-to-error
1275
If bNetConnState = NETCONN_CLOSE Then
1279
Engine_Log " Connected",1
1280
kseNet.Connected = 1
1281
'TODO: register client to host then get host info
994
1284
'------------- DX7 implementation from FreeKE sources
995
' Engine_InitConnectionList
1285
Engine_InitConnectionList()
996
1286
' Engine_ListSessions
997
1287
' Dim oSessData As DirectPlaySessionData 'How is the session described?
998
1288
' On Error GoTo ptrErr