/**************************************************************************/ /* */ /* Copyright (c) 2000-2005 by Alexandr V. Shutko, Khabarovsk, Russia */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in */ /* the documentation and/or other materials provided with the */ /* distribution. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND */ /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS */ /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, */ /* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT */ /* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */ /* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */ /* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE */ /* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* */ /* This unit implements functions that used to gather fregmented packets */ /* into big one (it use special database large objects - LO) */ /* */ /* $Id: defrag_db.cpp,v 1.10 2005/02/26 05:03:00 regress Exp $ */ /**************************************************************************/ #include "includes.h" /**************************************************************************/ /* This func add message to database (if user is not online) */ /**************************************************************************/ int db_defrag_addpart(unsigned long from_uin, int seq, int part_num, int part_cnt, int len, char *buffer) { PGresult *res; unsigned long oid; cstring dbcomm_str; int lo_fd; int nRet; DEBUG(50, ("Incoming fragmented packet... part %d of %d\n", part_num, part_cnt)); PQclear(PQexec(users_dbconn, "BEGIN")); /* first of all we should create large object and write data in it */ oid = lo_creat(users_dbconn, INV_READ|INV_WRITE); lo_fd = lo_open(users_dbconn, oid, INV_READ|INV_WRITE); (void *)lo_write(users_dbconn, lo_fd, buffer, len); (void *)lo_close(users_dbconn, lo_fd); /* then we create record with created oid int Fragment_Storage tbl */ slprintf(dbcomm_str, sizeof(dbcomm_str)-1, "INSERT INTO Fragment_Storage values (%lu, %d, %d, %d, %d, %lu, %lu)", from_uin, seq, part_num, part_cnt, len, oid, time(NULL)); res = PQexec(users_dbconn, dbcomm_str); if (PQresultStatus(res) != PGRES_COMMAND_OK) { handle_database_error(res, "[INSERT FRAGMENT]"); nRet = -1; } else if (strcmp(PQcmdTuples(res), "") != 0) { /* insert completed successfully */ nRet = 0; } else { /* command ok, but insert failed */ nRet = -1; } PQclear(res); PQclear(PQexec(users_dbconn, "END")); return(nRet); } /**************************************************************************/ /* This func delete all non-merged parts of the specified user */ /**************************************************************************/ int db_defrag_delete(unsigned long from_uin) { PGresult *res; unsigned long oid; cstring dbcomm_str; unsigned short frag_cnt; PQclear(PQexec(users_dbconn, "BEGIN")); slprintf(dbcomm_str, sizeof(dbcomm_str)-1, "SELECT frg FROM Fragment_Storage WHERE uin=%u", from_uin); res = PQexec(users_dbconn, dbcomm_str); if (PQresultStatus(res) != PGRES_TUPLES_OK) { handle_database_error(res, "[SELECT FRAGMENTS]"); PQclear(PQexec(users_dbconn, "END")); return(-1); } frag_cnt = PQntuples(res); if (frag_cnt > 0) { char **valid = NULL; for (int i=0;i 0) { char **valid = NULL; for (int i=0;i MAX_PACKET_SIZE) { /* alarm to console */ LOG_ALARM(0, ("WARNING: User %lu sent in fragments too big packet (%d bytes)\n", from_uin, pack_lenght)); LOG_ALARM(0, ("Making dump of first 50 packet bytes to debug log file...\n")); Packet pack; /* reading packet from large object */ lo_fd = lo_open(users_dbconn, atol(PQgetvalue(res, 0, 0)), INV_READ); pack.sizeVal = lo_read(users_dbconn, lo_fd, pack.buff, 50); lo_close(users_dbconn, lo_fd); /* dump it to log file */ log_alarm_packet(0, pack); PQclear(res); PQclear(PQexec(users_dbconn, "END")); /* delete packet fragments from database */ db_defrag_delete(from_uin, seq); return(0); } /* Now we have all parts we need and result packet not too big */ /* We should merge all parts and send result packet to pipe */ if (db_online_lookup(from_uin, user) == 0) { Packet inject_pack; inject_pack.from_ip = user.ip; inject_pack.from_port = user.udp_port; inject_pack.sizeVal = pack_lenght; inject_pack.reset(); for (i=0; i %d", time(NULL), lp_v3_pingtime()*10); res = PQexec(users_dbconn, dbcomm_str); if (PQresultStatus(res) != PGRES_TUPLES_OK) { handle_database_error(res, "[TEST EXPIRED FRAGS]"); PQclear(PQexec(users_dbconn, "END")); return(-1); } frag_cnt = PQntuples(res); if (frag_cnt > 0) { LOG_SYS(0, ("Fragment_storage cleanup has detected %lu expired records\n", frag_cnt)); } PQclear(res); PQclear(PQexec(users_dbconn, "END")); db_defrag_delete(); return (0); } /**************************************************************************/ /* This func delete all expired packet fragments from fragment_storage */ /**************************************************************************/ int db_defrag_delete() { PGresult *res; unsigned long oid; cstring dbcomm_str; unsigned short frag_cnt; PQclear(PQexec(users_dbconn, "BEGIN")); slprintf(dbcomm_str, sizeof(dbcomm_str)-1, "SELECT frg FROM Fragment_Storage WHERE %lu - frgtime > %d", time(NULL), lp_v3_pingtime()*10); res = PQexec(users_dbconn, dbcomm_str); if (PQresultStatus(res) != PGRES_TUPLES_OK) { handle_database_error(res, "[DELETE EXPIRED FRAGS]"); PQclear(PQexec(users_dbconn, "END")); return(-1); } frag_cnt = PQntuples(res); if (frag_cnt > 0) { char **valid = NULL; for (int i=0;i %d", time(NULL), lp_v3_pingtime()*10); res = PQexec(users_dbconn, dbcomm_str); PQclear(res); PQclear(PQexec(users_dbconn, "END")); return(0); } else { PQclear(res); PQclear(PQexec(users_dbconn, "END")); return(-1); } }