1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
31 #include <sys/types.h>
34 #include <vogl_core.h>
35 #include <vogl_json.h>
42 #include "../common/SimpleOpt.h"
44 #include "../common/vogllogging.h"
45 #include "../common/channel.h"
47 #include "../common/commands.h"
48 #include "../common/launchsteamgame.h"
49 #include "../common/toclientmsg.h"
50 #include "../common/listfiles.h"
59 CSimpleOpt::SOption g_rgOptions[] =
61 // Prints out help for these command line parameters.
62 { OPT_HELP, "-?", SO_NONE },
63 { OPT_HELP, "-h", SO_NONE },
64 { OPT_HELP, "-help", SO_NONE },
65 { OPT_HELP, "--help", SO_NONE },
67 // The network port the server should listen to.
68 { OPT_PORT, "-p", SO_REQ_SEP },
69 { OPT_PORT, "-port", SO_REQ_SEP },
70 { OPT_PORT, "--port", SO_REQ_SEP },
75 bool g_KeepRunning = true;
76 char *g_processName = NULL;
77 network::channelmgr *g_clientChannelMgr = NULL;
78 network::channelmgr *g_gameChannelMgr = NULL;
79 bool g_fAttemptingGameConnection = false;
81 void ShowUsage(char *szAppName);
82 static const char *GetLastErrorText(int a_nError);
84 void send_status_to_client(const char *message);
86 void ProcessCommand(void *callbackParam, unsigned int cbData, char *pbData);
88 int main(int argc, char *argv[])
90 int port = DEFAULT_PORT;
91 network::CHEC ec = network::EC_NONE;
93 CSimpleOpt args(argc, argv, g_rgOptions);
96 if (args.LastError() != SO_SUCCESS)
98 printf("%s: '%s' (use --help to get command line help)\n",
99 GetLastErrorText(args.LastError()), args.OptionText());
104 switch (args.OptionId())
115 sscanf(args.OptionArg(), "%d", &port); //or atoi()
116 printf("Server configured to bind to port %d\n", port);
122 if (args.OptionArg())
124 printf("option: %2d, text: '%s', arg: '%s'\n",
125 args.OptionId(), args.OptionText(), args.OptionArg());
129 printf("option: %2d, text: '%s'\n",
130 args.OptionId(), args.OptionText());
137 g_processName = argv[0];
140 g_clientChannelMgr = new network::channelmgr();
141 if (NULL == g_clientChannelMgr)
143 syslog(VOGL_ERROR, "%s:%d %s Unable to allocation networking channelmgr. OOM?\n", __FILE__, __LINE__, __func__);
147 // Create a client channel
148 ec = g_clientChannelMgr->Accept( port, (RECVASYNC|SENDASYNC), false, ProcessCommand, NULL, NULL, NULL );
149 if (network::EC_NONE != ec)
151 syslog(VOGL_ERROR, "%s:%d %s Unable to listen on port %d\nExiting.\n", __FILE__, __LINE__, __func__, port);
158 while (g_KeepRunning)
164 send_status_to_client("Server is still alive.");
172 void ShowUsage(char *szAppName)
174 printf("Usage: %s [Options]\n\n", szAppName);
175 printf("Where Options are:\n\n");
177 printf("Setting Ports:\n");
178 printf("[Optional] Specifies the port that this server should listen to for connections. The default value is %d.\n", DEFAULT_PORT);
179 printf("-p <portNumber>\n");
180 printf("-port <portNumber>\n");
181 printf("--port <portNumber>\n\n");
183 printf("Help message:\n");
184 printf("Gives this useful help message again.\n");
188 printf("--help\n\n");
192 GetLastErrorText(int a_nError)
199 return ("Unrecognized option");
200 case SO_OPT_MULTIPLE:
201 return ("Option matched multiple strings");
203 return ("Option does not accept argument");
204 case SO_ARG_INVALID_TYPE:
205 return ("Invalid argument format");
207 return ("Required argument is missing");
208 case SO_ARG_INVALID_DATA:
209 return ("Invalid argument data");
211 return ("Unknown error");
217 void *connect_to_launched_game(void *arg);
219 int g_gameport = TRACE_PORT;
220 void ProcessCommand(void * /*callbackParam*/, unsigned int buffer_size, char *buffer)
223 int32_t command = -1;
224 pthread_t threadGameConnect = 0;
228 command = *(int32_t *)buffer;
230 unsigned int buffer_size_temp = buffer_size - sizeof(int32_t);
231 char *buffer_temp = buffer + sizeof(int32_t);
235 case LAUNCHSTEAMGAME:
238 //send_status_to_client("Attempting to launch game.");
239 ec = LaunchSteamGame(buffer_size_temp, buffer_temp);
243 syslog(VOGL_ERROR, "%s:%d %s Unable to parse LaunchSteamGame json\n", __FILE__, __LINE__, __func__);
244 send_status_to_client("Failed to launch game. OOM.");
251 send_status_to_client("Connecting to game.");
253 if (NULL == g_gameChannelMgr && !g_fAttemptingGameConnection)
255 g_fAttemptingGameConnection = true;
256 ec = pthread_create(&threadGameConnect, NULL, connect_to_launched_game, NULL);
258 g_fAttemptingGameConnection = false;
263 case TRACE_LIST_TRACES:
265 network::CHEC chec = network::EC_NONE;
266 unsigned int buffer_size_list = 0;
267 char *buffer_list = NULL;
268 // The command just is. We simply send back the list of files.
270 ec = ListTraceFiles(&buffer_size_list, &buffer_list);
272 syslog(VOGL_ERROR, "%s:%d %s Unable to create trace list message (%d)\n", __FILE__, __LINE__, __func__, command);
274 chec = g_clientChannelMgr->SendData(buffer_size_list, buffer_list);
275 if (network::EC_NONE != chec)
277 syslog(VOGL_ERROR, "%s:%d %s Unable to send trace list message (%d)\n", __FILE__, __LINE__, __func__, chec);
280 if (NULL != buffer_list)
288 // Don't know what this is, so just forwarding on the original buffer to the game.
289 if (NULL != g_gameChannelMgr)
291 network::CHEC chec = network::EC_NONE;
293 //syslog(VOGL_INFO, "%s:%d %s Sending message (%d) on to game\n", __FILE__, __LINE__, __func__, command);
295 chec = g_gameChannelMgr->SendData(buffer_size, buffer);
296 if (network::EC_NONE != chec)
298 syslog(VOGL_ERROR, "%s:%d %s Unable to send message (%d) on to game\n", __FILE__, __LINE__, __func__, command);
310 void send_status_to_client(const char *message)
313 unsigned int buffer_size = 0;
316 // Prepare message to send
318 ec = ToClientMsgReq(g_processName, 0, message, &buffer_size, &buffer);
320 (void)g_clientChannelMgr->SendData(buffer_size, buffer);
328 void process_command_from_game(void * /*callbackParam*/, unsigned int buffer_size, char *buffer);
330 void *connect_to_launched_game(void * /*arg*/)
333 network::channelmgr *gameChannelMgr = NULL;
334 network::CHEC ec = network::EC_NONE;
335 pthread_t thisThread = pthread_self();
338 err = pthread_setname_np(thisThread, "cnt2game");
341 syslog(VOGL_ERROR, "%s:%d %s Unable to set the name of the thread. returned %d, errno %d\n", __FILE__, __LINE__, __func__, err, errno);
344 gameChannelMgr = new network::channelmgr();
345 if (NULL == gameChannelMgr)
348 //ec = gameChannelMgr->Connect( const_cast<char *>("localhost"), g_gameport, (SENDASYNC|RECVASYNC), process_command_from_game, NULL );
349 ec = gameChannelMgr->Accept( g_gameport, (RECVASYNC|SENDASYNC), true, process_command_from_game, NULL, NULL, NULL );
350 if (network::EC_NONE != ec)
352 delete gameChannelMgr;
353 syslog(VOGL_ERROR, "%s:%d %s Unable to listen to game on port %d\n", __FILE__, __LINE__, __func__, g_gameport);
358 if (NULL != g_gameChannelMgr)
360 delete g_gameChannelMgr;
361 g_gameChannelMgr = NULL;
365 g_gameChannelMgr = gameChannelMgr;
367 g_fAttemptingGameConnection = false;
372 void process_command_from_game(void * /*callbackParam*/, unsigned int buffer_size, char *buffer)
374 network::CHEC chec = network::EC_NONE;
376 //syslog(VOGL_INFO, "%s:%d %s Sending message on to client\n", __FILE__, __LINE__, __func__);
378 chec = g_clientChannelMgr->SendData(buffer_size, buffer);
379 if (network::EC_NONE != chec)
381 syslog(VOGL_ERROR, "%s:%d %s Unable to send message on to client\n", __FILE__, __LINE__, __func__);