2 * Copyright (C) 2005-2013 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "Database/DatabaseEnv.h"
28 #include "Config/Config.h"
30 #include "AccountMgr.h"
32 #include "ObjectMgr.h"
34 /// RASocket constructor
37 pendingCommands(0, USYNC_THREAD
, "pendingCommands"),
43 ///- Get the config parameters
44 bSecure
= sConfig
.GetBoolDefault("RA.Secure", true);
45 bStricted
= sConfig
.GetBoolDefault("RA.Stricted", false);
46 iMinLevel
= AccountTypes(sConfig
.GetIntDefault("RA.MinLevel", SEC_ADMINISTRATOR
));
47 reference_counting_policy().value(ACE_Event_Handler::Reference_Counting_Policy::ENABLED
);
50 /// RASocket destructor
54 sLog
.outRALog("Connection was closed.");
57 /// Accept an incoming connection
58 int RASocket::open(void*)
60 if (reactor()->register_handler(this, ACE_Event_Handler::READ_MASK
| ACE_Event_Handler::WRITE_MASK
) == -1)
62 sLog
.outError("RASocket::open: unable to register client handler errno = %s", ACE_OS::strerror(errno
));
66 ACE_INET_Addr remote_addr
;
68 if (peer().get_remote_addr(remote_addr
) == -1)
70 sLog
.outError("RASocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror(errno
));
75 sLog
.outRALog("Incoming connection from %s.", remote_addr
.get_host_addr());
78 sendf(sWorld
.GetMotd());
80 sendf(sObjectMgr
.GetMangosStringForDBCLocale(LANG_RA_USER
));
85 int RASocket::close(int)
89 DEBUG_LOG("RASocket::close");
98 int RASocket::handle_close(ACE_HANDLE h
, ACE_Reactor_Mask
)
102 DEBUG_LOG("RASocket::handle_close");
103 ACE_GUARD_RETURN(ACE_Thread_Mutex
, Guard
, outBufferLock
, -1);
107 if (h
== ACE_INVALID_HANDLE
)
108 peer().close_writer();
113 int RASocket::handle_output(ACE_HANDLE
)
115 ACE_GUARD_RETURN(ACE_Thread_Mutex
, Guard
, outBufferLock
, -1);
120 if (!outputBufferLen
)
122 if (reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK
) == -1)
124 sLog
.outError("RASocket::handle_output: error while cancel_wakeup");
131 ssize_t n
= peer().send(outputBuffer
, outputBufferLen
, MSG_NOSIGNAL
);
133 ssize_t n
= peer().send(outputBuffer
, outputBufferLen
);
134 #endif // MSG_NOSIGNAL
139 ACE_OS::memmove(outputBuffer
, outputBuffer
+ n
, outputBufferLen
- n
);
141 outputBufferLen
-= n
;
146 /// Read data from the network
147 int RASocket::handle_input(ACE_HANDLE
)
149 DEBUG_LOG("RASocket::handle_input");
152 sLog
.outError("Called RASocket::handle_input with closing_ = true");
156 size_t readBytes
= peer().recv(inputBuffer
+ inputBufferLen
, RA_BUFF_SIZE
- inputBufferLen
- 1);
160 DEBUG_LOG("read " SIZEFMTD
" bytes in RASocket::handle_input", readBytes
);
164 ///- Discard data after line break or line feed
165 bool gotenter
= false;
166 for (; readBytes
> 0 ; --readBytes
)
168 char c
= inputBuffer
[inputBufferLen
];
169 if (c
== '\r' || c
== '\n')
179 inputBuffer
[inputBufferLen
] = 0;
183 /// <ul> <li> If the input is '<username>'
186 std::string szLogin
= inputBuffer
;
188 accId
= sAccountMgr
.GetId(szLogin
);
190 ///- If the user is not found, deny access
193 sendf("-No such user.\r\n");
194 sLog
.outRALog("User %s does not exist.", szLogin
.c_str());
201 sendf(sObjectMgr
.GetMangosStringForDBCLocale(LANG_RA_USER
));
205 accAccessLevel
= sAccountMgr
.GetSecurity(accId
);
207 ///- if gmlevel is too low, deny access
208 if (accAccessLevel
< iMinLevel
)
210 sendf("-Not enough privileges.\r\n");
211 sLog
.outRALog("User %s has no privilege.", szLogin
.c_str());
218 sendf(sObjectMgr
.GetMangosStringForDBCLocale(LANG_RA_USER
));
222 ///- allow by remotely connected admin use console level commands dependent from config setting
223 if (accAccessLevel
>= SEC_ADMINISTRATOR
&& !bStricted
)
224 accAccessLevel
= SEC_CONSOLE
;
227 sendf(sObjectMgr
.GetMangosStringForDBCLocale(LANG_RA_PASS
));
230 ///<li> If the input is '<password>' (and the user already gave his username)
234 std::string pw
= inputBuffer
;
236 if (sAccountMgr
.CheckPassword(accId
, pw
))
240 sendf("+Logged in.\r\n");
241 sLog
.outRALog("User account %u has logged in.", accId
);
246 ///- Else deny access
247 sendf("-Wrong pass.\r\n");
248 sLog
.outRALog("User account %u has failed to log in.", accId
);
255 sendf(sObjectMgr
.GetMangosStringForDBCLocale(LANG_RA_PASS
));
259 ///<li> If user is logged, parse and execute the command
261 if (strlen(inputBuffer
))
263 sLog
.outRALog("Got '%s' cmd.", inputBuffer
);
264 if (strncmp(inputBuffer
, "quit", 4) == 0)
268 CliCommandHolder
* cmd
= new CliCommandHolder(accId
, accAccessLevel
, this, inputBuffer
, &RASocket::zprint
, &RASocket::commandFinished
);
269 sWorld
.QueueCliCommand(cmd
);
270 pendingCommands
.acquire();
280 // no enter yet? wait for next input...
285 void RASocket::zprint(void* callbackArg
, const char* szText
)
290 ((RASocket
*)callbackArg
)->sendf(szText
);
293 void RASocket::commandFinished(void* callbackArg
, bool success
)
295 RASocket
* raSocket
= (RASocket
*)callbackArg
;
296 raSocket
->sendf("mangos>");
297 raSocket
->pendingCommands
.release();
300 int RASocket::sendf(const char* msg
)
302 ACE_GUARD_RETURN(ACE_Thread_Mutex
, Guard
, outBufferLock
, -1);
307 int msgLen
= strlen(msg
);
309 if (msgLen
+ outputBufferLen
> RA_BUFF_SIZE
)
312 ACE_OS::memcpy(outputBuffer
+ outputBufferLen
, msg
, msgLen
);
313 outputBufferLen
+= msgLen
;
317 if (reactor()->schedule_wakeup
318 (this, ACE_Event_Handler::WRITE_MASK
) == -1)
320 sLog
.outError("RASocket::sendf error while schedule_wakeup");