/* * Copyright (C) 2005-2010 MaNGOS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** \file \ingroup mangosd */ #include "Common.h" #include "Database/DatabaseEnv.h" #include "Log.h" #include "RASocket.h" #include "World.h" #include "Config/ConfigEnv.h" #include "Util.h" #include "AccountMgr.h" #include "Language.h" #include "ObjectMgr.h" /// RASocket constructor RASocket::RASocket() :RAHandler(), pendingCommands(0, USYNC_THREAD, "pendingCommands"), outActive(false), inputBufferLen(0), outputBufferLen(0), stage(NONE) { ///- Get the config parameters bSecure = sConfig.GetBoolDefault( "RA.Secure", true ); bStricted = sConfig.GetBoolDefault( "RA.Stricted", false ); iMinLevel = AccountTypes(sConfig.GetIntDefault( "RA.MinLevel", SEC_ADMINISTRATOR )); reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); } /// RASocket destructor RASocket::~RASocket() { peer().close(); sLog.outRALog("Connection was closed."); } /// Accept an incoming connection int RASocket::open(void* ) { if (reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1) { sLog.outError ("RASocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno)); return -1; } ACE_INET_Addr remote_addr; if (peer ().get_remote_addr (remote_addr) == -1) { sLog.outError ("RASocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno)); return -1; } sLog.outRALog("Incoming connection from %s.",remote_addr.get_host_addr()); ///- print Motd sendf(sWorld.GetMotd()); sendf("\r\n"); sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_USER)); return 0; } int RASocket::close(int) { if(closing_) return -1; DEBUG_LOG("RASocket::close"); shutdown(); closing_ = true; remove_reference(); return 0; } int RASocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) { if(closing_) return -1; DEBUG_LOG("RASocket::handle_close"); ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, outBufferLock, -1); closing_ = true; if (h == ACE_INVALID_HANDLE) peer ().close_writer (); remove_reference(); return 0; } int RASocket::handle_output (ACE_HANDLE) { ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, outBufferLock, -1); if(closing_) return -1; if (!outputBufferLen) { if(reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK) == -1) { sLog.outError ("RASocket::handle_output: error while cancel_wakeup"); return -1; } outActive = false; return 0; } #ifdef MSG_NOSIGNAL ssize_t n = peer ().send (outputBuffer, outputBufferLen, MSG_NOSIGNAL); #else ssize_t n = peer ().send (outputBuffer, outputBufferLen); #endif // MSG_NOSIGNAL if(n<=0) return -1; ACE_OS::memmove(outputBuffer, outputBuffer+n, outputBufferLen-n); outputBufferLen -= n; return 0; } /// Read data from the network int RASocket::handle_input(ACE_HANDLE) { DEBUG_LOG("RASocket::handle_input"); if(closing_) { sLog.outError("Called RASocket::handle_input with closing_ = true"); return -1; } size_t readBytes = peer().recv(inputBuffer+inputBufferLen, RA_BUFF_SIZE-inputBufferLen-1); if(readBytes <= 0) { DEBUG_LOG("read %u bytes in RASocket::handle_input", readBytes); return -1; } ///- Discard data after line break or line feed bool gotenter=false; for(; readBytes > 0 ; --readBytes) { char c = inputBuffer[inputBufferLen]; if (c=='\r'|| c=='\n') { gotenter=true; break; } ++inputBufferLen; } if (gotenter) { inputBuffer[inputBufferLen]=0; inputBufferLen=0; switch(stage) { /// }; } // no enter yet? wait for next input... return 0; } /// Output function void RASocket::zprint(void* callbackArg, const char * szText ) { if( !szText ) return; ((RASocket*)callbackArg)->sendf(szText); } void RASocket::commandFinished(void* callbackArg, bool success) { RASocket* raSocket = (RASocket*)callbackArg; raSocket->sendf("mangos>"); raSocket->pendingCommands.release(); } int RASocket::sendf(const char* msg) { ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, outBufferLock, -1); if(closing_) return -1; int msgLen = strlen(msg); if(msgLen+outputBufferLen > RA_BUFF_SIZE) return -1; ACE_OS::memcpy(outputBuffer+outputBufferLen, msg, msgLen); outputBufferLen += msgLen; if(!outActive) { if (reactor ()->schedule_wakeup (this, ACE_Event_Handler::WRITE_MASK) == -1) { sLog.outError ("RASocket::sendf error while schedule_wakeup"); return -1; } outActive = true; } return 0; }