1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name master.cpp - The master server. */
12 //
13 // (c) Copyright 2003-2007 by Tom Zickel and Jimmy Salmon
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include <errno.h>
37 #include <stdarg.h>
38 #include <ctype.h>
39 #include <limits.h>
40
41 #include "stratagus.h"
42
43 #include "master.h"
44
45 #include "game.h"
46 #include "network/netsockets.h"
47 #include "network.h"
48 #include "net_lowlevel.h"
49 #include "parameters.h"
50 #include "script.h"
51 #include "version.h"
52
53
54 /*----------------------------------------------------------------------------
55 -- Variables
56 ----------------------------------------------------------------------------*/
57
58 CMetaClient MetaClient;
59
60 /*----------------------------------------------------------------------------
61 -- Functions
62 ----------------------------------------------------------------------------*/
63
64 /**
65 ** Set the metaserver to use for internet play.
66 **
67 ** @param host Host to connect
68 ** @param port Port to use to connect
69 */
SetMetaServer(const std::string host,const int port)70 void CMetaClient::SetMetaServer(const std::string host, const int port)
71 {
72 metaHost = host;
73 metaPort = port;
74 }
75
~CMetaClient()76 CMetaClient::~CMetaClient()
77 {
78 for (std::list<CClientLog *>::iterator it = events.begin(); it != events.end(); ++it) {
79 CClientLog *log = *it;
80 delete log;
81 }
82 events.clear();
83 this->Close();
84 }
85
86 /**
87 ** Initialize the TCP connection to the Meta Server and send test ping to it.
88 **
89 ** @return -1 fail, 0 success.
90 */
Init()91 int CMetaClient::Init()
92 {
93 if (metaPort == -1) {
94 return -1;
95 }
96
97 // Server socket
98 CHost metaServerHost(metaHost.c_str(), metaPort);
99 // Client socket
100 CHost metaClientHost(CNetworkParameter::Instance.localHost.c_str(), CNetworkParameter::Instance.localPort);
101 metaSocket.Open(metaClientHost);
102 if (metaSocket.IsValid() == false) {
103 fprintf(stderr, "METACLIENT: No free port %d available, aborting\n", metaServerHost.getPort());
104 return -1;
105 }
106 if (metaSocket.Connect(metaServerHost) == false) {
107 fprintf(stderr, "METACLIENT: Unable to connect to host %s\n", metaServerHost.toString().c_str());
108 MetaClient.Close();
109 return -1;
110 }
111
112 if (this->Send("PING") == -1) { // not sent
113 MetaClient.Close();
114 return -1;
115 }
116 if (this->Recv() == -1) { // not received
117 MetaClient.Close();
118 return -1;
119 }
120 CClientLog &log = *GetLastMessage();
121 if (log.entry.find("PING_OK") != std::string::npos) {
122 // Everything is OK
123 return 0;
124 } else {
125 fprintf(stderr, "METACLIENT: inappropriate message received from %s\n", metaServerHost.toString().c_str());
126 MetaClient.Close();
127 return -1;
128 }
129 }
130
131 /**
132 ** Close Connection to Master Server
133 **
134 ** @return nothing
135 */
Close()136 void CMetaClient::Close()
137 {
138 if (metaSocket.IsValid()) {
139 metaSocket.Close();
140 }
141 }
142
143
144 /**
145 ** Send a command to the meta server
146 **
147 ** @param cmd command to send
148 **
149 ** @returns -1 if failed, otherwise length of command
150 */
Send(const std::string cmd)151 int CMetaClient::Send(const std::string cmd)
152 {
153 int ret = -1;
154 std::string mes(cmd);
155 mes.append("\n");
156 ret = metaSocket.Send(mes.c_str(), mes.size());
157 return ret;
158 }
159
160 /**
161 ** Receive reply from Meta Server
162 **
163 ** @return error or number of bytes
164 */
Recv()165 int CMetaClient::Recv()
166 {
167 if (metaSocket.HasDataToRead(5000) == -1) {
168 return -1;
169 }
170
171 char buf[1024];
172 memset(&buf, 0, sizeof(buf));
173 int n = metaSocket.Recv(&buf, sizeof(buf));
174 if (n == -1) {
175 return n;
176 }
177 // We know we now have the whole command.
178 // Convert to standard notation
179 std::string cmd(buf, strlen(buf));
180 cmd += '\n';
181 cmd += '\0';
182 CClientLog *log = new CClientLog;
183 log->entry = cmd;
184 events.push_back(log);
185 lastRecvState = n;
186 return n;
187 }
188
189 //@}
190