/** * @param socket Socket to communicate over * @param type Command ID * @param source Source ID * @param len Data length * @param content Payload * @return 0 on success */ int SendMessage(SWInetSocket *socket, int type, int source, unsigned int streamid, unsigned int len, const char *content) { assert(socket != nullptr); SWBaseSocket::SWBaseError error; RoRnet::Header head; const int msgsize = sizeof(RoRnet::Header) + len; if (msgsize >= RORNET_MAX_MESSAGE_LENGTH) { Logger::Log(LOG_ERROR, "UID: %d - attempt to send too long message", source); return -4; } char buffer[RORNET_MAX_MESSAGE_LENGTH]; memset(&head, 0, sizeof(RoRnet::Header)); head.command = type; head.source = source; head.size = len; head.streamid = streamid; // construct buffer memset(buffer, 0, RORNET_MAX_MESSAGE_LENGTH); memcpy(buffer, (char *) &head, sizeof(RoRnet::Header)); memcpy(buffer + sizeof(RoRnet::Header), content, len); if (socket->fsend(buffer, msgsize, &error) < msgsize) { Logger::Log(LOG_ERROR, "send error -1: %s", error.get_error().c_str()); return -1; } StatsAddOutgoing(msgsize); return 0; }
/** * @param socket socket to communicate over * @param type a type... dunno * @param source who is sending the message * @param len length of the content being sent * @param content message to send * @return dunno */ int Messaging::sendmessage(SWInetSocket *socket, int type, int source, unsigned int streamid, unsigned int len, const char* content) { STACKLOG; if( NULL == socket ) { Logger::log( LOG_ERROR, "UID: %d - attempt to send a messaage over a" "null socket.", source ); return -3; } //SWInetSocket* socket = Sequencer::getSocket(source) SWBaseSocket::SWBaseError error; header_t head; const int msgsize = sizeof(header_t) + len; if(msgsize >= MAX_MESSAGE_LENGTH) { Logger::log( LOG_ERROR, "UID: %d - attempt to send too long message", source); return -4; } char buffer[MAX_MESSAGE_LENGTH]; int rlen = 0; memset(&head, 0, sizeof(header_t)); head.command = type; head.source = source; head.size = len; head.streamid = streamid; // construct buffer memset(buffer, 0, MAX_MESSAGE_LENGTH); memcpy(buffer, (char *)&head, sizeof(header_t)); memcpy(buffer + sizeof(header_t), content, len); #if 0 // comment out since this severly bloats the server log char body[len*2+1]; memset( body, 0,len*2+1); bodyblockashex(body, content, len); Logger::log( LOG_DEBUG, "sending message: \t%d\t%d\t%d", type, source, len); Logger::log( LOG_DEBUG, "%s", body); #endif while (rlen < msgsize) { int sendnum = socket->send( buffer + rlen, msgsize - rlen, &error ); if (sendnum < 0 || error != SWBaseSocket::ok) { Logger::log(LOG_ERROR, "send error -1: %s", error.get_error().c_str()); return -1; } rlen += sendnum; } //Logger::log(LOG_DEBUG, "message of size %d sent to uid %d.", rlen, source); traffic.bandwidthOutgoing += msgsize; return 0; }
int Notifier::HTTPPOST(const char* URL, const char* data) { STACKLOG; int res=0; SWBaseSocket::SWBaseError error; SWInetSocket mySocket; if (mySocket.connect(80, REPO_SERVER, &error)) { char query[2048]; int len = (int)strnlen(data, 16000); sprintf(query, "POST %s HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Content-Type: application/octet-stream\r\n" \ "Content-Length: %d\r\n" "\r\n" \ "%s", \ URL, REPO_SERVER, len, data); Logger::log(LOG_DEBUG,"Query to Master server: %s", query); if (mySocket.sendmsg(query, &error)<0) { Logger::log(LOG_ERROR,"Notifier: could not send request (%s)", error.get_error().c_str()); res=-1; } int rlen=mySocket.recv(httpresp, 65536, &error); if (rlen>0 && rlen<65535) httpresp[rlen]=0; else { Logger::log(LOG_ERROR,"Notifier: could not get a valid response (%s)", error.get_error().c_str()); res=-1; } Logger::log(LOG_DEBUG,"Response from Master server:'%s'", httpresp); try { resp = HttpMsg(httpresp); } catch( std::runtime_error e) { Logger::log(LOG_ERROR, e.what() ); res = -1; } // disconnect mySocket.disconnect(); } else { Logger::log(LOG_ERROR,"Notifier: could not connect to the Master server (%s)", error.get_error().c_str()); res=-1; } return res; }
int UserAuth::HTTPGET(const char* URL, HttpMsg &resp) { STACKLOG; if(trustlevel<=1) { // If this happens, then you did something wrong in the server code Logger::log(LOG_ERROR, "userauth: tried to contact master server without permission. URL: %s", URL); return 0; } char httpresp[65536]; //!< http response from the master server int res=0; SWBaseSocket::SWBaseError error; SWInetSocket mySocket; if (mySocket.connect(80, REPO_SERVER, &error)) { char query[2048]; sprintf(query, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", URL, REPO_SERVER); Logger::log(LOG_DEBUG,"Query to Master server: %s", query); if (mySocket.sendmsg(query, &error)<0) { Logger::log(LOG_ERROR,"Notifier: could not send request (%s)", error.get_error().c_str()); res=-1; } int rlen=mySocket.recv(httpresp, 65536, &error); if (rlen>0 && rlen<65535) httpresp[rlen]=0; else { Logger::log(LOG_ERROR,"Notifier: could not get a valid response (%s)", error.get_error().c_str()); res=-1; } Logger::log(LOG_DEBUG,"Response from Master server:'%s'", httpresp); try { resp = HttpMsg(httpresp); } catch( std::runtime_error e) { Logger::log(LOG_ERROR, e.what() ); res = -1; } // disconnect mySocket.disconnect(); } else { Logger::log(LOG_ERROR,"Notifier: could not connect to the Master server (%s)", error.get_error().c_str()); res=-1; } return res; }
int Notifier::HTTPGET(const char* URL) { STACKLOG; int res=0; SWBaseSocket::SWBaseError error; SWInetSocket mySocket; if (mySocket.connect(80, REPO_SERVER, &error)) { char query[2048]; sprintf(query, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", URL, REPO_SERVER); Logger::log(LOG_DEBUG,"Query to Master server: %s", query); if (mySocket.sendmsg(query, &error)<0) { Logger::log(LOG_ERROR,"Notifier: could not send request (%s)", error.get_error().c_str()); res=-1; } int rlen=mySocket.recv(httpresp, 65536, &error); if (rlen>0 && rlen<65535) httpresp[rlen]=0; else { Logger::log(LOG_ERROR,"Notifier: could not get a valid response (%s)", error.get_error().c_str()); res=-1; } Logger::log(LOG_DEBUG,"Response from Master server:'%s'", httpresp); try { resp = HttpMsg(httpresp); } catch( std::runtime_error e) { Logger::log(LOG_ERROR, e.what() ); res = -1; } // disconnect mySocket.disconnect(); } else { Logger::log(LOG_ERROR,"Notifier: could not connect to the Master server (%s)", error.get_error().c_str()); res=-1; } return res; }
void Listener::threadstart() { Logger::Log(LOG_DEBUG, "Listerer thread starting"); //here we start SWBaseSocket::SWBaseError error; //manage the listening socket m_listen_socket.bind(m_listen_port, &error); if (error != SWBaseSocket::ok) { //this is an error! Logger::Log(LOG_ERROR, "FATAL Listerer: %s", error.get_error().c_str()); //there is nothing we can do here return; // exit(1); } m_listen_socket.listen(); Logger::Log(LOG_VERBOSE, "Listener ready"); m_ready_cond.Signal(1); //await connections while (!m_thread_shutdown) { Logger::Log(LOG_VERBOSE, "Listener awaiting connections"); SWInetSocket *ts = (SWInetSocket *) m_listen_socket.accept(&error); if (error != SWBaseSocket::ok) { if (m_thread_shutdown) { Logger::Log(LOG_ERROR, "INFO Listener shutting down"); } else { Logger::Log(LOG_ERROR, "ERROR Listener: %s", error.get_error().c_str()); } } Logger::Log(LOG_VERBOSE, "Listener got a new connection"); ts->set_timeout(5, 0); //receive a magic int type; int source; unsigned int len; unsigned int streamid; char buffer[RORNET_MAX_MESSAGE_LENGTH]; try { // this is the start of it all, it all starts with a simple hello if (Messaging::ReceiveMessage(ts, &type, &source, &streamid, &len, buffer, RORNET_MAX_MESSAGE_LENGTH)) throw std::runtime_error("ERROR Listener: receiving first message"); // make sure our first message is a hello message if (type != RoRnet::MSG2_HELLO) { Messaging::SendMessage(ts, RoRnet::MSG2_WRONG_VER, 0, 0, 0, 0); throw std::runtime_error("ERROR Listener: protocol error"); } // check client version if (source == 5000 && (std::string(buffer) == "MasterServer")) { Logger::Log(LOG_VERBOSE, "Master Server knocked ..."); // send back some information, then close socket char tmp[2048] = ""; sprintf(tmp, "protocol:%s\nrev:%s\nbuild_on:%s_%s\n", RORNET_VERSION, VERSION, __DATE__, __TIME__); if (Messaging::SendMessage(ts, RoRnet::MSG2_MASTERINFO, 0, 0, (unsigned int) strlen(tmp), tmp)) { throw std::runtime_error("ERROR Listener: sending master info"); } // close socket ts->disconnect(&error); delete ts; continue; } // compare the versions if they are compatible if (strncmp(buffer, RORNET_VERSION, strlen(RORNET_VERSION))) { // not compatible Messaging::SendMessage(ts, RoRnet::MSG2_WRONG_VER, 0, 0, 0, 0); throw std::runtime_error("ERROR Listener: bad version: " + std::string(buffer) + ". rejecting ..."); } // compatible version, continue to send server settings std::string motd_str; { std::vector<std::string> lines; if (!Utils::ReadLinesFromFile(Config::getMOTDFile(), lines)) { for (const auto& line : lines) motd_str += line + "\n"; } } Logger::Log(LOG_DEBUG, "Listener sending server settings"); RoRnet::ServerInfo settings; memset(&settings, 0, sizeof(RoRnet::ServerInfo)); settings.has_password = !Config::getPublicPassword().empty(); strncpy(settings.info, motd_str.c_str(), motd_str.size()); strncpy(settings.protocolversion, RORNET_VERSION, strlen(RORNET_VERSION)); strncpy(settings.servername, Config::getServerName().c_str(), Config::getServerName().size()); strncpy(settings.terrain, Config::getTerrainName().c_str(), Config::getTerrainName().size()); if (Messaging::SendMessage(ts, RoRnet::MSG2_HELLO, 0, 0, (unsigned int) sizeof(RoRnet::ServerInfo), (char *) &settings)) throw std::runtime_error("ERROR Listener: sending version"); //receive user infos if (Messaging::ReceiveMessage(ts, &type, &source, &streamid, &len, buffer, RORNET_MAX_MESSAGE_LENGTH)) { std::stringstream error_msg; error_msg << "ERROR Listener: receiving user infos\n" << "ERROR Listener: got that: " << type; throw std::runtime_error(error_msg.str()); } if (type != RoRnet::MSG2_USER_INFO) throw std::runtime_error("Warning Listener: no user name"); if (len > sizeof(RoRnet::UserInfo)) throw std::runtime_error("Error: did not receive proper user credentials"); Logger::Log(LOG_INFO, "Listener creating a new client..."); RoRnet::UserInfo *user = (RoRnet::UserInfo *) buffer; user->authstatus = RoRnet::AUTH_NONE; // authenticate user->username[RORNET_MAX_USERNAME_LEN - 1] = 0; std::string nickname = Str::SanitizeUtf8(user->username); user->authstatus = m_sequencer->AuthorizeNick(std::string(user->usertoken, 40), nickname); strncpy(user->username, nickname.c_str(), RORNET_MAX_USERNAME_LEN - 1); if (Config::isPublic()) { Logger::Log(LOG_DEBUG, "password login: %s == %s?", Config::getPublicPassword().c_str(), std::string(user->serverpassword, 40).c_str()); if (strncmp(Config::getPublicPassword().c_str(), user->serverpassword, 40)) { Messaging::SendMessage(ts, RoRnet::MSG2_WRONG_PW, 0, 0, 0, 0); throw std::runtime_error("ERROR Listener: wrong password"); } Logger::Log(LOG_DEBUG, "user used the correct password, " "creating client!"); } else { Logger::Log(LOG_DEBUG, "no password protection, creating client"); } //create a new client m_sequencer->createClient(ts, *user); // copy the user info, since the buffer will be cleared soon Logger::Log(LOG_DEBUG, "listener returned!"); } catch (std::runtime_error &e) { Logger::Log(LOG_ERROR, e.what()); ts->disconnect(&error); delete ts; } } }
/** * @param out_type Message type, see MSG2_* macros in rornet.h * @param out_source Magic. Value 5000 used by serverlist to check this server. * @return 0 on success, negative number on error. */ int Messaging::receivemessage( SWInetSocket *socket, int* out_type, int* out_source, unsigned int* out_stream_id, unsigned int* out_payload_len, char* out_payload, unsigned int payload_buf_len) { STACKLOG; assert(socket != nullptr); assert(out_type != nullptr); assert(out_source != nullptr); assert(out_stream_id != nullptr); assert(out_payload != nullptr); char buffer[MAX_MESSAGE_LENGTH] = {}; int hlen=0; SWBaseSocket::SWBaseError error; while (hlen<(int)sizeof(header_t)) { int recvnum=socket->recv(buffer+hlen, sizeof(header_t)-hlen, &error); if (recvnum < 0 || error!=SWBaseSocket::ok) { Logger::log(LOG_ERROR, "receive error -2: %s", error.get_error().c_str()); // this also happens when the connection is canceled return -2; } hlen+=recvnum; } header_t head; memcpy(&head, buffer, sizeof(header_t)); *out_type = head.command; *out_source = head.source; *out_payload_len = head.size; *out_stream_id = head.streamid; if((int)head.size >= MAX_MESSAGE_LENGTH) { Logger::log(LOG_ERROR, "receivemessage(): payload too long: %d b (max. is %d b)", head.size, MAX_MESSAGE_LENGTH); return -3; } if( head.size > 0) { //read the rest while (hlen < (int)sizeof(header_t) + (int)head.size) { int recvnum = socket->recv(buffer + hlen, (head.size+sizeof(header_t)) - hlen, &error); if (recvnum<0 || error!=SWBaseSocket::ok) { Logger::log(LOG_ERROR, "receive error -1: %s", error.get_error().c_str()); return -1; } hlen += recvnum; } } traffic.bandwidthIncoming += (int)sizeof(header_t)+(int)head.size; memcpy(out_payload, buffer+sizeof(header_t), payload_buf_len); return 0; }