/* museekd - The Museek daemon * * Copyright (C) 2003-2004 Hyriand * * 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 */ #include #include #include #include #include #include #include #include #include #define MULOG_DOMAIN "museekd.IL" #include #ifdef PARSE # undef PARSE #endif #define PARSE(mtype) mtype s; s.parse_network_packet(message); #define CPARSE(mtype) mtype s(&mContext); s.parse_network_packet(message); using std::string; using std::map; using std::vector; IfaceListener::IfaceListener(Museekd *_museekd, const string& _path) : ListenConnection(), mMuseekd(_museekd) { if(_path.size() == 0) { error = ERR_LOOKUP_FAILED; return; } if(_path[0] == '/') { #ifdef HAVE_SYS_UN_H listen_unix(_path.c_str()); #else DEBUG("no unix socket support"); #endif } else { int ix = _path.find(":"), port = atoi(_path.substr(ix+1).c_str()); string host = _path.substr(0, ix); if(port != 0) listen(host, port); else { DEBUG("invalid tcp host: %s", _path.c_str()); error = ERR_LOOKUP_FAILED; } } } bool IfaceListener::accept() { DEBUG("IFACELISTENER::accept"); int sock = simple_accept(); if(sock == -1) return false; new IfaceConnection(mMuseekd, sock); return true; } #undef MULOG_DOMAIN #define MULOG_DOMAIN "museekd.IC" IfaceConnection::IfaceConnection(Museekd *museekd, int sock) : MessageConnection(4), mMuseekd(museekd), mAuthenticated(false) { CT("IfaceConnection %i", sock); set_socket(sock); mMuseekd->new_iface(this); } void IfaceConnection::disconnected() { CT("disconnected"); mMuseekd->remove_iface(this); } void IfaceConnection::process_message(uint32 code) { CT("process_message"); if(! mAuthenticated && code != 0x0002) { DEBUG("attempted message while not authenticated"); disconnect(); return; } switch(code) { case 0x0000: { PARSE(IPing) DEBUG("got ping request %u", s.id); mMuseekd->cb_iface_ping(this, s.id); break; } case 0x0002: { PARSE(ILogin) DEBUG("got login attempted %s, %s, %08x", s.algorithm.c_str(), s.chresponse.c_str(), s.mask); mMask = s.mask; mMuseekd->cb_iface_login(this, s.algorithm, s.chresponse); break; } case 0x0004: { DEBUG("got check privileges"); mMuseekd->cb_iface_check_privileges(this); break; } case 0x0005: { PARSE(ISetStatus) DEBUG("got set status %u", s.status); mMuseekd->cb_iface_set_status(this, s.status); break; } case 0x0101: { CPARSE(IConfigSet) DEBUG("got config set %s, %s, %s", s.domain.c_str(), s.key.c_str(), s.value.c_str()); mMuseekd->cb_iface_config_set(this, s.domain, s.key, s.value); break; } case 0x0102: { CPARSE(IConfigRemove) DEBUG("got config remove key %s, %s", s.domain.c_str(), s.key.c_str()); mMuseekd->cb_iface_config_remove(this, s.domain, s.key); break; } case 0x0103: { PARSE(IConfigSetUserImage) DEBUG("got user image <...> (%d)", s.mData.size()); mMuseekd->cb_iface_config_set_user_image(this, s.mData); break; } case 0x0201: { PARSE(IPeerExists) DEBUG("got get peer exists %s", s.user.c_str()); mMuseekd->cb_iface_peer_exists(this, s.user); break; } case 0x0202: { PARSE(IPeerStatus) DEBUG("got get peer status %s", s.user.c_str()); mMuseekd->cb_iface_peer_status(this, s.user); break; } case 0x0203: { PARSE(IPeerStats) DEBUG("got get user stats %s", s.user.c_str()); mMuseekd->cb_iface_peer_stats(this, s.user); break; } case 0x0204: { PARSE(IUserInfo) DEBUG("got get user info %s", s.user.c_str()); mMuseekd->cb_iface_info(this, s.user); break; } case 0x0205: { PARSE(IUserShares) DEBUG("got get user shares %s", s.user.c_str()); mMuseekd->cb_iface_shares(this, s.user); break; } case 0x0206: { PARSE(IPeerAddress) DEBUG("got get user address %s", s.user.c_str()); mMuseekd->cb_iface_peer_address(this, s.user); break; } case 0x0207: { PARSE(IGivePrivileges) DEBUG("got give privileges %s. %i", s.user.c_str(), s.days); mMuseekd->cb_iface_give_privileges(this, s.user, s.days); break; } case 0x0301: { DEBUG("got update room list"); mMuseekd->cb_iface_room_list(this); break; } case 0x0302: { PARSE(IPrivateMessage) DEBUG("got private message %s, %s", s.user.c_str(), s.msg.c_str()); mMuseekd->cb_iface_private(this, s.user, s.msg); break; } case 0x0303: { PARSE(IJoinRoom) DEBUG("got join room %s", s.room.c_str()); mMuseekd->cb_iface_join_room(this, s.room); break; } case 0x0304: { PARSE(ILeaveRoom) DEBUG("got leave room %s", s.room.c_str()); mMuseekd->cb_iface_leave_room(this, s.room); break; } case 0x0307: { PARSE(ISayRoom) DEBUG("got say room %s, %s", s.room.c_str(), s.line.c_str()); mMuseekd->cb_iface_say_room(this, s.room, s.line); break; } case 0x0309: { PARSE(IRoomTickerSet) DEBUG("got set room ticker %s, %s", s.room.c_str(), s.message.c_str()); mMuseekd->cb_iface_room_ticker_set(this, s.room, s.message); break; } case 0x0401: { PARSE(ISearch) DEBUG("got search request %u, %s", s.type, s.query.c_str()); mMuseekd->cb_iface_search(this, s.type, s.query); break; } case 0x0402: { PARSE(ISearchReply) DEBUG("got terminate search request %u", s.ticket); mMuseekd->cb_iface_terminate(this, s.ticket); break; } case 0x0403: { PARSE(IUserSearch) DEBUG("got user search request %s, %s", s.user.c_str(), s.query.c_str()); mMuseekd->cb_iface_user_search(this, s.user, s.query); break; } case 0x0405: { PARSE(IWishListSearch) DEBUG("got wishlist search request %s", s.query.c_str()); mMuseekd->cb_iface_wishlist_search(this, s.query); break; } case 0x501: { PARSE(ITransferUpdate) DEBUG("got update transfer %s, %s", s.user.c_str(), s.path.c_str()); mMuseekd->cb_iface_transfer_update(this, s.user, s.path); break; } case 0x0502: { PARSE(ITransferRemove); DEBUG("got remove transfer %i, %s, %s", s.upload, s.user.c_str(), s.path.c_str()); mMuseekd->cb_iface_transfer_delete(this, s.upload, s.user, s.path); break; } case 0x0503: { PARSE(IDownloadFile) DEBUG("got download file from %s. %s", s.user.c_str(), s.path.c_str()); mMuseekd->cb_iface_download_file(this, s.user, s.path); break; } case 0x0507: { PARSE(IDownloadFileTo) DEBUG("got download file from %s. %s to %s", s.user.c_str(), s.path.c_str(), s.localpath.c_str()); mMuseekd->cb_iface_download_file_to(this, s.user, s.path, s.localpath); break; } case 0x0504: { PARSE(IDownloadFolder) DEBUG("got get folder contents %s, %s", s.user.c_str(), s.folder.c_str()); mMuseekd->cb_iface_download_folder(this, s.user, s.folder); break; } case 0x0505: { PARSE(ITransferAbort) DEBUG("got abort transfer %d, %s, %s", s.upload, s.user.c_str(), s.path.c_str()); mMuseekd->cb_iface_transfer_abort(this, s.upload, s.user, s.path); break; } case 0x0506: { PARSE(IUploadFile) DEBUG("got upload file %s, %s", s.user.c_str(), s.path.c_str()); mMuseekd->cb_iface_upload_file(this, s.user, s.path); break; } case 0x0600: { DEBUG("get update recommendations " ); mMuseekd->cb_iface_get_recommendations(this); break; } case 0x0601: { DEBUG("get update global recommendations"); mMuseekd->cb_iface_get_global_recommendations(this); break; } case 0x0602: { DEBUG("get similar users " ); mMuseekd->cb_iface_get_similar_users(this); break; } case 0x0603: { PARSE(IGetItemRecommendations) DEBUG("get item recommendations %s ", s.item.c_str() ); mMuseekd->cb_iface_get_item_recommendations(this, s.item); break; } case 0x0604: { PARSE(IGetItemSimilarUsers) DEBUG("get item similar users %s ", s.item.c_str() ); mMuseekd->cb_iface_get_item_similar_users(this, s.item); break; } case 0x0610: { PARSE(IAddInterest) DEBUG("get add liked interest: %s", s.interest.c_str()); mMuseekd->cb_iface_add_interest(this, s.interest); break; } case 0x0611: { PARSE(IRemoveInterest) DEBUG("remove liked interest: %s", s.interest.c_str()); mMuseekd->cb_iface_remove_interest(this, s.interest); break; } case 0x0612: { PARSE(IAddHatedInterest) DEBUG("add hated interest: %s", s.interest.c_str()); mMuseekd->cb_iface_add_hated_interest(this, s.interest); break; } case 0x0613: { PARSE(IRemoveHatedInterest) DEBUG("remove hated interest: %s", s.interest.c_str()); mMuseekd->cb_iface_remove_hated_interest(this, s.interest); break; } case 0x0700: { DEBUG("got do connect server"); mMuseekd->cb_iface_connect_server(this); break; } case 0x0701: { DEBUG("got do disconnect server"); mMuseekd->cb_iface_disconnect_server(this); break; } case 0x0703: { DEBUG("got reload shares"); mMuseekd->cb_iface_reload_shares(this); break; } default: DEBUG("received invalid message code %u", code); disconnect(); } } void IfaceConnection::ping(uint32 id) { CT("ping"); if(mAuthenticated) { IPing s(id); send(s); } } void IfaceConnection::challenge(uint32 version, const std::string& challenge) { CT("challenge"); mChallenge = challenge; IChallenge s(version, challenge); send(s); } void IfaceConnection::login_reply(bool ok, const std::string& message, const std::string& new_challenge) { CT("login_reply %i, %s, %s", ok, message.c_str(), new_challenge.c_str()); ILogin s; mAuthenticated = ok; if(! ok) { mChallenge = new_challenge; s = ILogin(ok, message, new_challenge); } else { cipherKeySHA256(&mContext, (char*)new_challenge.data(), new_challenge.size()); s = ILogin(ok, string(), string()); } send(s); } void IfaceConnection::server_state(bool logged_in, const std::string& username) { CT("server_state %i, %s", logged_in, username.c_str()); if(mAuthenticated) { IServerState s(logged_in, username); send(s); } } void IfaceConnection::status_message(bool type, const std::string& message) { CT("status_message %i, %s", type, message.c_str()); if(mAuthenticated) { IStatusMessage s(type, message); send(s); } } void IfaceConnection::room_state(const RoomList& roomlist, const map& rooms, const map& tickers) { CT("send_room_state %i, %i", roomlist.size(), rooms.size()); if(mAuthenticated && mMask & EM_CHAT) { IRoomState cs = IRoomState(roomlist, rooms, tickers); send(cs); } } void IfaceConnection::config_state(const map& _n) { CT("config_state <...> (%d)", _n.size()); if(mAuthenticated && mMask & EM_CONFIG) { IConfigState s(&mContext, _n); send(s); } } void IfaceConnection::config_set(const string& domain, const string& key, const string& value) { CT("config_set %s, %s, %s", domain.c_str(), key.c_str(), value.c_str()); if(mAuthenticated && mMask & EM_CONFIG) { IConfigSet s(&mContext, domain, key, value); send(s); } } void IfaceConnection::config_remove(const string& domain, const string& key) { CT("config_remove %s, %s", domain.c_str(), key.c_str()); if(mAuthenticated && mMask & EM_CONFIG) { IConfigRemove s(&mContext, domain, key); send(s); } } void IfaceConnection::search(const string& query, uint32 ticket) { CT("search %s, %u", query.c_str(), ticket); if(mAuthenticated) { ISearch s(query, ticket); send(s); } } void IfaceConnection::results(uint32 ticket, const string& user, const Folder& results, uint32 avgspeed, uint32 queuelen, bool slotfree) { CT("results %u, %s, %i, %i, %i, %i", ticket, user.c_str(), results.size(), avgspeed, queuelen, slotfree); if(mAuthenticated) { ISearchReply s(ticket, user, slotfree, avgspeed, queuelen, results); send(s); } } void IfaceConnection::room_list(const RoomList& rooms) { CT("room_list <...> (%i)", rooms.size()); if(mAuthenticated && mMask & EM_CHAT) { IRoomList s(rooms); send(s); } } void IfaceConnection::get_recommendations(const Recommendations& recommendations) { CT("get_recommendations <...> (%i)", recommendations.size()); if(mAuthenticated && mMask & EM_INTERESTS) { IGetRecommendations s(recommendations); send(s); } } void IfaceConnection::get_global_recommendations(const Recommendations& recommendations) { CT("get_global_recommendations <...> (%i)", recommendations.size()); if(mAuthenticated && mMask & EM_INTERESTS) { IGetGlobalRecommendations s(recommendations); send(s); } } void IfaceConnection::get_similar_users(const SimilarUsers& similarusers) { CT("get_similar_users <...> (%i)", similarusers.size()); if(mAuthenticated && mMask & EM_INTERESTS) { IGetSimilarUsers s(similarusers); send(s); } } void IfaceConnection::get_item_similar_users(const string& item, const SimilarUsers& similarusers) { CT("get_item_similar_users for %s <...> (%i)", item.c_str(), similarusers.size()); if(mAuthenticated && mMask & EM_INTERESTS) { IGetItemSimilarUsers s(item, similarusers); send(s); } } void IfaceConnection::get_item_recommendations(const string& item, const Recommendations& recommendations) { CT("get_item_recommendations for %s <...> (%i)", item.c_str(), recommendations.size()); if(mAuthenticated && mMask & EM_INTERESTS) { IGetItemRecommendations s(item, recommendations); send(s); } } void IfaceConnection::add_interest(const string& interest) { CT("add_interest (%s)", interest.c_str()); if(mAuthenticated && mMask & EM_INTERESTS) { IAddInterest s(interest); send(s); } } void IfaceConnection::add_hated_interest(const string& interest) { CT("add_hated_interest (%s)", interest.c_str()); if(mAuthenticated && mMask & EM_INTERESTS) { IAddHatedInterest s(interest); send(s); } } void IfaceConnection::remove_interest(const string& interest) { CT("remove_interest (%s)", interest.c_str()); if(mAuthenticated && mMask & EM_INTERESTS) { IRemoveInterest s(interest); send(s); } } void IfaceConnection::remove_hated_interest(const string& interest) { CT("remove_hated_interest (%s)", interest.c_str()); if(mAuthenticated && mMask & EM_INTERESTS) { IRemoveHatedInterest s(interest); send(s); } } void IfaceConnection::say_room(const string& room, const string& user, const string& line) { CT("say_room %s, %s, %s", room.c_str(), user.c_str(), line.c_str()); if(mAuthenticated && mMask & EM_CHAT) { ISayRoom s(room, user, line); send(s); } } void IfaceConnection::joined_room(const string& room, const RoomData& users) { CT("joined_room %s, <...> (%d)", room.c_str(), users.size()); if(mAuthenticated && mMask & EM_CHAT) { IJoinRoom s(room, users); send(s); } } void IfaceConnection::left_room(const string& room) { CT("left_room %s", room.c_str()); if(mAuthenticated && mMask & EM_CHAT) { ILeaveRoom s(room); send(s); } } void IfaceConnection::user_joined_room(const string& room, const string& user, const UserData& data) { CT("user_joined_room %s, %s, <...>", room.c_str(), user.c_str()); if(mAuthenticated && mMask & EM_CHAT) { IUserJoinedRoom s(room, user, data); send(s); } } void IfaceConnection::user_left_room(const string& room, const string& user) { CT("user_left_room %s, %s", room.c_str(), user.c_str()); if(mAuthenticated && mMask & EM_CHAT) { IUserLeftRoom s(room, user); send(s); } } void IfaceConnection::private_message(uint32 direction, uint32 timestamp, const string& user, const string& message) { CT("private %u, %u, %s, %s", direction, timestamp, user.c_str(), message.c_str()); if(mAuthenticated && mMask & EM_PRIVATE) { IPrivateMessage s(direction, timestamp, user, message); send(s); } } void IfaceConnection::info(const string& user, const string& info, const vector& picture, uint32 avgspeed, uint32 queuelen, bool slotfree) { CT("info %s, %s, <...> (%d), %u, %u, %d", user.c_str(), info.c_str(), picture.size(), avgspeed, queuelen, slotfree); if(mAuthenticated && mMask & EM_USERINFO) { IUserInfo s(user, info, picture, avgspeed, queuelen, slotfree); send(s); } } void IfaceConnection::shares(const string& user, const Shares& shares) { CT("shares %s, <...> (%d)", user.c_str(), shares.size()); if (mAuthenticated && mMask & EM_USERSHARES) { IUserShares s(user, shares); send(s); } } void IfaceConnection::transfer_state(const vector& uploads, const vector& downloads) { CT("transfer_state"); if(mAuthenticated && mMask & EM_TRANSFERS) { ITransferState s(uploads, downloads); send(s); } } void IfaceConnection::transfer_update(const Transfer* transfer) { CT("transfer_update <...>"); if(mAuthenticated && mMask & EM_TRANSFERS) { ITransferUpdate s(transfer); send(s); } } void IfaceConnection::transfer_delete(const Transfer* transfer) { CT("transfer_remove <...>"); if(mAuthenticated && mMask & EM_TRANSFERS) { ITransferRemove s(transfer); send(s); } } void IfaceConnection::peer_exists(const string& user, bool exists) { CT("peer_exists %s, %d", user.c_str(), exists); if(mAuthenticated) { IPeerExists s(user, exists); send(s); } } void IfaceConnection::peer_status(const string& user, uint32 status) { CT("peer_status %s, %d", user.c_str(), status); if(mAuthenticated) { IPeerStatus s(user, status); send(s); } } void IfaceConnection::peer_stats(const string& user, uint32 avgspeed, uint32 numdownloads, uint32 files, uint32 dirs) { CT("peer_stats %s %u %u %u %u", user.c_str(), avgspeed, numdownloads, files, dirs); if(mAuthenticated) { IPeerStats s(user, avgspeed, numdownloads, files, dirs); send(s); } } void IfaceConnection::room_tickers(const string& room, const Tickers& tickers) { CT("room_tickers %s <...> (%d)", room.c_str(), tickers.size()); if(mAuthenticated && mMask & EM_CHAT) { IRoomTickers s(room, tickers); send(s); } } void IfaceConnection::room_ticker_set(const string& room, const string& user, const string& message) { CT("room_ticker_set %s, %s, %s", room.c_str(), user.c_str(), message.c_str()); if(mAuthenticated && mMask & EM_CHAT) { IRoomTickerSet s(room, user, message); send(s); } } void IfaceConnection::privileges_left(uint32 time_left) { CT("privileges_left %u", time_left); if(mAuthenticated) { ICheckPrivileges s(time_left); send(s); } } void IfaceConnection::peer_address(const std::string& user, const std::string& ip, uint32 port) { CT("peer_address %s, %s, %u", user.c_str(), ip.c_str(), port); if(mAuthenticated) { IPeerAddress s(user, ip, port); send(s); } } void IfaceConnection::status_set(uint32 status) { CT("status_set %u", status); if(mAuthenticated) { ISetStatus s(status); send(s); } }