-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSIMPLE_SERVER
289 lines (234 loc) · 7.28 KB
/
SIMPLE_SERVER
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
* A simple socket server that echos back
INCLUDE JBC.h
INCLUDE JBC_SOCKS.h
EQUATE CLH TO "[" : client_handle_number "R%6" : "]"
client_port = ""
mode = 0
debug = 0
ctx = ""
port = ""
threadlist = ""
args = SYSTEM(1000)
total = DCOUNT(args, @FM)
command = args<1>
client_handle_number = ""
client_handle = ""
server_handle = ""
setting = ""
DOOMSDAY = @FALSE
recieve_message = ''
thread_handle = ""
CRT CLH : "Server Startup " : "[" : @SENTENCE : "]"
FOR count = 1 TO total
current = SENTENCE(count)
name = UPCASE(FIELD(current, "=", 1))
value = FIELD(current, "=", 2)
BEGIN CASE
CASE current = SYSTEM(40)
CASE name = ""
CASE name = "-CTX"
ctx = value
CASE name = "-CLIENT"
client_handle_number = value
CASE name = "-PORT"
port = value
CASE name = "-MODE"
mode = value
CASE name = "-DEBUG"
debug = 1
CASE 1
GOTO help
END CASE
NEXT count
IF mode = 0 THEN
CRT CLH : "Running as single service"
END ELSE
CRT CLH : "Running as thread service"
END
IF port = "" THEN GOTO help
listern:
CRT CLH : "opening connections"
conDetails = ''
spawn = ""
IF ctx THEN
CRT CLH : "Passed in ctx"
mode = 1
rc = GETSERVERHANDLE(server_handle, ctx)
CRT CLH : "Getting main server handle [" : rc : "]"
IF rc = 0 THEN STOP
GOTO do_bind
END
result = SOCKSERV(port, server_handle, conDetails)
IF result NE JBASE_SOCKET_SUCCESS THEN
CRT CLH : 'Unable to establish a connection with the client - error: ':SYSTEM(0)
STOP
END
CRT CLH : 'Client connection received from [' : conDetails : "]"
multi_listern:
CRT CLH : "Call listen [" : JBASETHREADStatus( threadlist ) : "]"
rc = 1
DOOMSDAY = @FALSE
recieve_message = ''
LOOP WHILE rc NE 0
rc = SOCKACCEPT(server_handle, client_handle_number, setting)
CRT CLH : "Accept", port, client_handle_number, rc, setting
REPEAT
IF client_handle_number < 0 THEN
CRT CLH : "invalid client returned!"
GOSUB disconect
STOP
END
IF mode THEN
base_address = GETSOCKBASE(server_handle)
args = ""
args_array = ""
FOR x = 1 TO 100
a = SENTENCE(x)
IF a = "" THEN BREAK
args := " " : a
args_array<-1> = a
NEXT x
args := " -CTX=" : base_address : " -CLIENT=" : client_handle_number
args_array<-1> = "-CTX=" : base_address
args_array<-1> = "-CLIENT=" : client_handle_number
CRT CLH : "Launch thread " : SYSTEM(40) : args
rc = JBASETHREADCreate( SYSTEM(40), args_array, "", thread_handle )
CRT CLH : "Launch thread" : "rc [" : rc : "] handle [" : thread_handle :"]"
CRT CLH : "call listern"
GOTO listern
END
do_bind:
rc = SOCKBIND(server_handle, client_handle_number, client_handle, setting)
LOOP UNTIL DOOMSDAY DO
size = 0
LOOP WHILE size = 0
GOSUB recvData
REPEAT
BEGIN CASE
CASE recieve_message = 'help' ;* client is done
GOSUB send_help
CASE recieve_message = 'who' ;* client is done
command = "jwho"
GOSUB send_command
CASE recieve_message = 'diag' ;* client is done
command = "jdiag"
GOSUB send_command
CASE recieve_message = 'vwhere' ;* client is done
command = "WHERE (V"
GOSUB send_command
CASE recieve_message = 'where' ;* client is done
command = "WHERE"
GOSUB send_command
CASE recieve_message = 'close' ;* client is done
GOSUB closeConnection
CRT CLH : "end of connection"
IF mode THEN
CRT CLH : "exit server"
GOSUB disconect
STOP
END
GOTO listern
CASE recieve_message = 'stop' ;* terminate this process
CRT CLH : "exit server"
GOSUB closeConnection
GOSUB disconect
STOP
CASE recieve_message = 'status'
JBASETHREADStatus(threadlist)
this = "active threads"
FOR thread_count = 1 TO DCOUNT(threadlist, @FM)
this<-1> = "[":thread_count:"] ":threadlist<thread_count>
NEXT thread_count
GOSUB send_this
CASE recieve_message = 'mode'
IF mode = 0 THEN
this = "Running as single service"
END ELSE
this = "Running as thread service"
END
GOSUB send_this
CASE @TRUE ;* do whatever needs to be done with recieve_message; for now we will simply echo it back to the client
GOSUB sendData
END CASE
REPEAT
GOSUB closeConnection
STOP
send_command:
EXECUTE command CAPTURING this
GOSUB send_this
RETURN
send_this:
CHANGE @FM TO CHAR(10) IN this
err = SOCKSEND(client_handle, this, setting)
IF err NE JBASE_SOCKET_SUCCESS THEN
CRT CLH : 'Send failed with error: ':SYSTEM(0)
GOSUB closeConnection
STOP
END
RETURN
send_help:
this = "sample socket server 1.0"
this<-1> = ""
this<-1> = "help : this page"
this<-1> = "mode : show server mode"
this<-1> = "status : show active threads"
this<-1> = "who : run jwho on server"
this<-1> = "diag : run jdiag on server"
this<-1> = "where : run where on server"
this<-1> = "vwhere : run where (V on server"
this<-1> = "close : Close client session, but keep server running."
this<-1> = "stop : Stop server and close client"
this<-1> = ""
GOSUB send_this
RETURN
sendData:
CRT CLH : "sendData"
netstring = "OK"
err = SOCKSEND(client_handle, netstring, setting)
IF err NE JBASE_SOCKET_SUCCESS THEN
CRT CLH : 'Send failed with error: ':SYSTEM(0)
GOSUB closeConnection
STOP
END
RETURN
recvData:
IF UNASSIGNED(client_handle) THEN client_handle = ""
recieve_message = ""
setting = ""
CRT CLH : "recvData"
size = SOCKRECV(client_handle, recieve_message, setting)
recieve_message = TRIM(recieve_message)
CRT CLH : "[":size:"][":recieve_message:"][":setting:"]"
RETURN
reconnect:
CRT CLH : "reconnect"
GOSUB closeConnection
RETURN
closeConnection:
CRT CLH : "closeConnection"
SOCKCLOSE(client_handle, setting)
RETURN
disconect:
CRT CLH : "disconect"
SOCKCLOSE(client_handle, setting)
SOCKCLOSE(server_handle, setting)
RETURN
testForSocketError:
CRT CLH : "testForSocketError"
IF size < 1 THEN ;* we need to make this more generic by passing in an error type and displaying an appropriate message
CRT CLH : 'Socket failure - error: ':SYSTEM(0)
GOSUB closeConnection
END
RETURN
help:
CRT SYSTEM(40) : " server 1.0"
CRT "options"
CRT "", " -PORT=<<port>>"
CRT "", " -MODE=<<flag>>"
CRT "", "", "0 = stand alone"
CRT "", "", "1 = multi thread"
CRT "", "default mode is 0"
CRT
CRT "e.g.", SYSTEM(40) : " -port=12345 -mode=1"
CRT
STOP