int32 do_sockets(fd_set* rfd, int32 next) { struct timeval timeout; int32 ret; memcpy(rfd, &readfds, sizeof(*rfd)); timeout.tv_sec = next / 1000; timeout.tv_usec = next % 1000 * 1000; ret = sSelect(fd_max, rfd, nullptr, nullptr, &timeout); if (ret == SOCKET_ERROR) { if (sErrno != S_EINTR) { ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno); do_final(EXIT_FAILURE); } return 0; // interrupted by a signal, just loop and try again } last_tick = time(nullptr); if (sFD_ISSET(map_fd, rfd)) { struct sockaddr_in from; socklen_t fromlen = sizeof(from); int32 ret = recvudp(map_fd, g_PBuff, map_config.buffer_size, 0, (struct sockaddr*)&from, &fromlen); if (ret != -1) { // find player char # ifdef WIN32 uint32 ip = ntohl(from.sin_addr.S_un.S_addr); # else uint32 ip = ntohl(from.sin_addr.s_addr); # endif uint64 port = ntohs(from.sin_port); uint64 ipp = ip; ipp |= port << 32; map_session_data_t* map_session_data = mapsession_getbyipp(ipp); if (map_session_data == nullptr) { map_session_data = mapsession_createsession(ip, ntohs(from.sin_port)); if (map_session_data == nullptr) { map_session_list.erase(ipp); return -1; } } map_session_data->last_update = time(nullptr); size_t size = ret; if (recv_parse(g_PBuff, &size, &from, map_session_data) != -1) { // если предыдущий пакет был потерян, то мы не собираем новый, // а отправляем предыдущий пакет повторно if (!parse(g_PBuff, &size, &from, map_session_data)) { send_parse(g_PBuff, &size, &from, map_session_data); } ret = sendudp(map_fd, g_PBuff, size, 0, (const struct sockaddr*)&from, fromlen); int8* data = g_PBuff; g_PBuff = map_session_data->server_packet_data; map_session_data->server_packet_data = data; map_session_data->server_packet_size = size; } if (map_session_data->shuttingDown > 0) { map_close_session(gettick(), map_session_data); } } } return 0; }
int32 send_parse(int8 *buff, size_t* buffsize, sockaddr_in* from, map_session_data_t* map_session_data) { // Модификация заголовка исходящего пакета // Суть преобразований: // - отправить клиенту номер последнего полученного от него пакета // - присвоить исходящему пакету номер последнего отправленного клиенту пакета +1 // - записать текущее время отправки пакета WBUFW(buff, 0) = map_session_data->server_packet_id; WBUFW(buff, 2) = map_session_data->client_packet_id; // сохранение текущего времени (32 BIT!) WBUFL(buff, 8) = (uint32)time(nullptr); // собираем большой пакет, состоящий из нескольких маленьких CCharEntity *PChar = map_session_data->PChar; CBasicPacket* PSmallPacket; uint32 PacketSize = UINT32_MAX; uint32 PacketCount = PChar->getPacketCount(); uint8 packets = 0; while (PacketSize > 1300 - FFXI_HEADER_SIZE - 16) //max size for client to accept { *buffsize = FFXI_HEADER_SIZE; PacketList_t packetList = PChar->getPacketList(); packets = 0; while (!packetList.empty() && *buffsize + packetList.front()->length() < map_config.buffer_size && packets < PacketCount) { PSmallPacket = packetList.front(); PSmallPacket->sequence(map_session_data->server_packet_id); memcpy(buff + *buffsize, *PSmallPacket, PSmallPacket->length()); *buffsize += PSmallPacket->length(); packetList.pop_front(); packets++; } //Сжимаем данные без учета заголовка //Возвращаемый размер в 8 раз больше реальных данных PacketSize = zlib_compress(buff + FFXI_HEADER_SIZE, *buffsize - FFXI_HEADER_SIZE, PTempBuff, *buffsize, zlib_compress_table); WBUFL(PTempBuff, (PacketSize + 7) / 8) = PacketSize; PacketSize = (PacketSize + 7) / 8 + 4; PacketCount /= 2; } PChar->erasePackets(packets); //Запись размера данных без учета заголовка uint8 hash[16]; md5((uint8*)PTempBuff, hash, PacketSize); memcpy(PTempBuff + PacketSize, hash, 16); PacketSize += 16; if (PacketSize > map_config.buffer_size + 20) { ShowFatalError(CL_RED"%Memory manager: PTempBuff is overflowed (%u)\n" CL_RESET, PacketSize); } //making total packet memcpy(buff + FFXI_HEADER_SIZE, PTempBuff, PacketSize); uint32 CypherSize = (PacketSize / 4)&-2; blowfish_t* pbfkey = &map_session_data->blowfish; for (uint32 j = 0; j < CypherSize; j += 2) { blowfish_encipher((uint32*)(buff)+j + 7, (uint32*)(buff)+j + 8, pbfkey->P, pbfkey->S[0]); } // контролируем размер отправляемого пакета. в случае, // если его размер превышает 1400 байт (размер данных + 42 байта IP заголовок), // то клиент игнорирует пакет и возвращает сообщение о его потере // в случае возникновения подобной ситуации выводим предупреждующее сообщение и // уменьшаем размер BuffMaxSize с шагом в 4 байта до ее устранения (вручную) *buffsize = PacketSize + FFXI_HEADER_SIZE; return 0; }
//--------------------------------------------------------- // 倉庫データを読み込む int inter_storage_init() { char line[65536]; int c = 0; FILE *fp; storage_db = idb_alloc(DB_OPT_RELEASE_DATA); fp=fopen(storage_txt,"r"); if(fp==NULL){ ShowError("can't read : %s\n",storage_txt); return 1; } while( fgets(line, sizeof(line), fp) ) { int account_id; struct storage_data *s; s = (struct storage_data*)aCalloc(sizeof(struct storage_data), 1); if( s == NULL ) { ShowFatalError("int_storage: out of memory!\n"); exit(EXIT_FAILURE); } if( storage_fromstr(line,&account_id,s) ) { idb_put(storage_db,account_id,s); } else{ ShowError("int_storage: broken data in [%s] line %d\n",storage_txt,c); aFree(s); } c++; } fclose(fp); c = 0; guild_storage_db = idb_alloc(DB_OPT_RELEASE_DATA); fp=fopen(guild_storage_txt,"r"); if(fp==NULL){ ShowError("can't read : %s\n",guild_storage_txt); return 1; } while(fgets(line, sizeof(line), fp)) { int tmp_int; struct guild_storage *gs; sscanf(line,"%d",&tmp_int); gs = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1); if(gs==NULL){ ShowFatalError("int_storage: out of memory!\n"); exit(EXIT_FAILURE); } // memset(gs,0,sizeof(struct guild_storage)); aCalloc... gs->guild_id=tmp_int; if(gs->guild_id > 0 && guild_storage_fromstr(line,gs) == 0) { idb_put(guild_storage_db,gs->guild_id,gs); } else{ ShowError("int_storage: broken data [%s] line %d\n",guild_storage_txt,c); aFree(gs); } c++; } fclose(fp); return 0; }
mempool mempool_create(const char *name, uint64 elem_size, uint64 initial_count, uint64 realloc_count, memPoolOnNodeAllocationProc onNodeAlloc, memPoolOnNodeDeallocationProc onNodeDealloc){ //.. uint64 realloc_thresh; mempool pool; pool = (mempool)aCalloc( 1, sizeof(struct mempool) ); if(pool == NULL){ ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool) ); exit(EXIT_FAILURE); } // Check minimum initial count / realloc count requirements. if(initial_count < 50) initial_count = 50; if(realloc_count < 50) realloc_count = 50; // Set Reallocation threshold to 5% of realloc_count, at least 10. realloc_thresh = (realloc_count/100)*5; // if(realloc_thresh < 10) realloc_thresh = 10; // Initialize members.. pool->name = aStrdup(name); pool->elem_size = ALIGN_TO_16(elem_size); pool->elem_realloc_step = realloc_count; pool->elem_realloc_thresh = realloc_thresh; pool->onalloc = onNodeAlloc; pool->ondealloc = onNodeDealloc; InitializeSpinLock(&pool->segmentLock); InitializeSpinLock(&pool->nodeLock); // Initial Statistic values: pool->num_nodes_total = 0; pool->num_nodes_free = 0; pool->num_segments = 0; pool->num_bytes_total = 0; pool->peak_nodes_used = 0; pool->num_realloc_events = 0; // #ifdef MEMPOOL_DEBUG ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step); #endif // Allocate first segment directly :) segment_allocate_add(pool, initial_count); // Add Pool to the global pool list EnterSpinLock(&l_mempoolListLock); pool->next = l_mempoolList; l_mempoolList = pool; LeaveSpinLock(&l_mempoolListLock); return pool; }//end: mempool_create()
static struct conf_value *makeValue(const char *key, char *val, size_t val_len){ struct conf_value *v; /* size_t sz; sz = sizeof(struct conf_value); if(val_len >= sizeof(v->strval)) sz += (val_len - sizeof(v->strval) + 1);*/ v = (struct conf_value*)aCalloc(1, sizeof(struct conf_value)); if(v == NULL){ ShowFatalError("raconf: makeValue => Out of Memory while allocating new node.\n"); return NULL; } memcpy(v->strval, val, val_len); v->strval[val_len+1] = '\0'; v->strval_len = val_len; // Parse boolean value: if((val_len == 4) && (strncmpi("true", val, 4) == 0)) v->bval = true; else if((val_len == 3) && (strncmpi("yes", val, 3) == 0)) v->bval = true; else if((val_len == 3) && (strncmpi("oui", val, 3) == 0)) v->bval = true; else if((val_len == 2) && (strncmpi("si", val, 2) == 0)) v->bval = true; else if((val_len == 2) && (strncmpi("ja", val, 2) == 0)) v->bval = true; else if((val_len == 1) && (*val == '1')) v->bval = true; else if((val_len == 5) && (strncmpi("false", val, 5) == 0)) v->bval = false; else if((val_len == 2) && (strncmpi("no", val, 2) == 0)) v->bval = false; else if((val_len == 3) && (strncmpi("non", val, 3) == 0)) v->bval = false; else if((val_len == 2) && (strncmpi("no", val, 2) == 0)) v->bval = false; else if((val_len == 4) && (strncmpi("nein", val, 4) == 0)) v->bval = false; else if((val_len == 1) && (*val == '0')) v->bval = false; else v->bval = false; // assume false. // Parse number // Supported formats: // prefix: 0x hex . // postix: h for hex // b for bin (dual) if( (val_len >= 1 && (val[val_len] == 'h')) || (val_len >= 2 && (val[0] == '0' && val[1] == 'x')) ){//HEX! if(val[val_len] == 'h'){ val[val_len]= '\0'; v->intval = strtoull(val, NULL, 16); val[val_len] = 'h'; }else v->intval = strtoull(&val[2], NULL, 16); }else if( val_len >= 1 && (val[val_len] == 'b') ){ //BIN val[val_len] = '\0'; v->intval = strtoull(val, NULL, 2); val[val_len] = 'b'; }else if( *val >='0' && *val <= '9'){ // begins with normal digit, so assume its dec. // is it float? bool is_float = false; char *p; for(p = val; *p != '\0'; p++){ if(*p == '.'){ v->floatval = strtod(val, NULL); v->intval = (int64) v->floatval; is_float = true; break; } } if(is_float == false){ v->intval = strtoull(val, NULL, 10); v->floatval = (double) v->intval; } }else{ // Everything else: lets use boolean for fallback if(v->bval == true) v->intval = 1; else v->intval = 0; } return v; }//end: makeValue()
// initialize int inter_init(const char *file) { //int i; ShowInfo ("interserver initialize...\n"); inter_config_read(file); //DB connection initialized mysql_init(&mysql_handle); ShowInfo("Connect Character DB server.... (Character Server)\n"); if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw, char_server_db ,char_server_port, (char *)NULL, 0)) { //pointer check ShowFatalError("%s\n",mysql_error(&mysql_handle)); exit(1); } else if (inter_sql_test()) { ShowStatus("Connect Success! (Character Server)\n"); } if(char_gm_read) { mysql_init(&lmysql_handle); ShowInfo("Connect Character DB server.... (login server)\n"); if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, login_server_db ,login_server_port, (char *)NULL, 0)) { //pointer check ShowFatalError("%s\n",mysql_error(&lmysql_handle)); exit(1); } else { ShowStatus ("Connect Success! (Login Server)\n"); } } if(strlen(default_codepage) > 0 ) { sprintf( tmp_sql, "SET NAMES %s", default_codepage ); if (mysql_query(&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } if(char_gm_read) if (mysql_query(&lmysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } } wis_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); inter_guild_sql_init(); inter_storage_sql_init(); inter_party_sql_init(); inter_pet_sql_init(); inter_accreg_sql_init(); //printf ("interserver timer initializing : %d sec...\n",autosave_interval); //i=add_timer_interval(gettick()+autosave_interval,inter_save_timer,0,0,autosave_interval); if (connection_ping_interval) { add_timer_func_list(inter_sql_ping, "inter_sql_ping"); add_timer_interval(gettick()+connection_ping_interval*60*60*1000, inter_sql_ping, 0, 0, connection_ping_interval*60*60*1000); } return 0; }
QM_Model QM_ReadFile( const char *filename ) // Read model from input file. // The output QM_Model has only QM_OrigQuad. // The axis-aligned bounding box is computed. { char badFile[] = "Invalid input model file"; char badEOF[] = "Unexpected end of file"; char lineBuf[ MAX_LINE_LEN + 1 ]; // Open input file FILE *fp = fopen( filename, "r" ); if ( fp == NULL ) ShowFatalError( __FILE__, __LINE__, "Cannot open input model file \"%s\"", filename ); int lineNum = 0; //=== VERTICES === int numVertices = 0; float *vertexTable = NULL; // An array of 3D vertices. // Read number of vertices. if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%d", &numVertices ) != 1 || numVertices < 0 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); vertexTable = (float *) CheckedMalloc( sizeof(float) * 3 * numVertices ); // Read the vertices. for ( int v = 0; v < numVertices; v++ ) { float x, y, z; if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%f %f %f", &x, &y, &z ) != 3 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); vertexTable[ 3 * v + 0 ] = x; vertexTable[ 3 * v + 1 ] = y; vertexTable[ 3 * v + 2 ] = z; } //=== MATERIALS === int numMaterials = 0; float *reflectivityTable = NULL; // An array of RGB reflectivity values. float *emissionTable = NULL; // An array of RGB emission values. // Read number of materials. if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%d", &numMaterials ) != 1 || numMaterials < 0 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); reflectivityTable = (float *) CheckedMalloc( sizeof(float) * 3 * numMaterials ); emissionTable = (float *) CheckedMalloc( sizeof(float) * 3 * numMaterials ); // Read the materials. for ( int m = 0; m < numMaterials; m++ ) { float r, g, b; if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%f %f %f", &r, &g, &b ) != 3 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); reflectivityTable[ 3 * m + 0 ] = r; reflectivityTable[ 3 * m + 1 ] = g; reflectivityTable[ 3 * m + 2 ] = b; if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%f %f %f", &r, &g, &b ) != 3 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); emissionTable[ 3 * m + 0 ] = r; emissionTable[ 3 * m + 1 ] = g; emissionTable[ 3 * m + 2 ] = b; } //=== SURFACES === int numSurfaces = 0; QM_Surface *surfaceTable = NULL; // An array of surfaces. // Read number of surfaces. if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%d", &numSurfaces ) != 1 || numSurfaces < 0 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); surfaceTable = (QM_Surface *) CheckedMalloc( sizeof(QM_Surface) * numSurfaces ); // Read the surfaces. for ( int s = 0; s < numSurfaces; s++ ) { QM_SurfaceInit( &surfaceTable[s] ); int matID, numQuads; // Read material index. if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%d", &matID ) != 1 || matID < 0 || matID >= numMaterials ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); CopyArray3( surfaceTable[s].reflectivity, &reflectivityTable[3*matID] ); CopyArray3( surfaceTable[s].emission, &emissionTable[3*matID] ); // Read number of quadrilaterals in the surface. if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%d", &numQuads ) != 1 || numQuads < 0 ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); surfaceTable[s].numOrigQuads = numQuads; surfaceTable[s].origQuads = (QM_OrigQuad *) CheckedMalloc( sizeof(QM_OrigQuad) * numQuads ); // Read vertex indices for each quadrilateral. for ( int q = 0; q < numQuads; q++ ) { int vertID[4]; if ( !ReadDataLine( lineBuf, &lineNum, filename, fp ) ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\"", badEOF, filename ); if ( sscanf( lineBuf, "%d %d %d %d", &vertID[0], &vertID[1], &vertID[2], &vertID[3] ) != 4 || vertID[0] < 0 || vertID[0] >= numVertices || vertID[1] < 0 || vertID[1] >= numVertices || vertID[2] < 0 || vertID[2] >= numVertices || vertID[3] < 0 || vertID[3] >= numVertices ) ShowFatalError( __FILE__, __LINE__, "%s \"%s\" at line %d", badFile, filename, lineNum ); CopyArray3( surfaceTable[s].origQuads[q].v[0], &vertexTable[ 3*vertID[0] ] ); CopyArray3( surfaceTable[s].origQuads[q].v[1], &vertexTable[ 3*vertID[1] ] ); CopyArray3( surfaceTable[s].origQuads[q].v[2], &vertexTable[ 3*vertID[2] ] ); CopyArray3( surfaceTable[s].origQuads[q].v[3], &vertexTable[ 3*vertID[3] ] ); // Compute normal vector to the quadrilateral. VecTriNormal( surfaceTable[s].origQuads[q].normal, surfaceTable[s].origQuads[q].v[0], surfaceTable[s].origQuads[q].v[1], surfaceTable[s].origQuads[q].v[2] ); VecNormalize( surfaceTable[s].origQuads[q].normal, surfaceTable[s].origQuads[q].normal ); } } QM_Model model = QM_ModelInit(); model.numSurfaces = numSurfaces; model.surfaces = surfaceTable; ComputeBoundingBox( &model ); fclose( fp ); free( vertexTable ); free( reflectivityTable ); free( emissionTable ); return model; }
void CZone::LoadZoneSettings() { static const int8* Query = "SELECT " "zone.name," "zone.zoneip," "zone.zoneport," "zone.music_day," "zone.music_night," "zone.battlesolo," "zone.battlemulti," "zone.tax," "zone.misc," "zone.navmesh," "zone.zonetype," "bcnm.name," "zone.eventtype " "FROM zone_settings AS zone " "LEFT JOIN bcnm_info AS bcnm " "USING (zoneid) " "WHERE zoneid = %u " "LIMIT 1"; if (Sql_Query(SqlHandle, Query, m_zoneID) != SQL_ERROR && Sql_NumRows(SqlHandle) != 0 && Sql_NextRow(SqlHandle) == SQL_SUCCESS) { m_zoneName.insert(0, Sql_GetData(SqlHandle,0)); m_zoneIP = inet_addr(Sql_GetData(SqlHandle,1)); m_zonePort = (uint16)Sql_GetUIntData(SqlHandle,2); m_zoneMusic.m_songDay = (uint8)Sql_GetUIntData(SqlHandle, 3); // background music (day) m_zoneMusic.m_songNight = (uint8)Sql_GetUIntData(SqlHandle, 4); // background music (night) m_zoneMusic.m_bSongS = (uint8)Sql_GetUIntData(SqlHandle,5); // solo battle music m_zoneMusic.m_bSongM = (uint8)Sql_GetUIntData(SqlHandle,6); // party battle music m_tax = (uint16)(Sql_GetFloatData(SqlHandle,7) * 100); // tax for bazaar m_miscMask = (uint16)Sql_GetUIntData(SqlHandle,8); m_useNavMesh = (bool)Sql_GetIntData(SqlHandle,9); m_eventType = (EVENTTYPE)Sql_GetUIntData(SqlHandle, 12); if (luautils::IsSummerfestYearRound()) { if ((EVENTTYPE)Sql_GetUIntData(SqlHandle, 12) >= 3) { m_zoneMusic.m_songNight = 227; // background music (night) } } m_zoneType = (ZONETYPE)Sql_GetUIntData(SqlHandle, 10); //luautils::OnZoneWeatherChange(GetID(), Weather); if (Sql_GetData(SqlHandle,11) != nullptr) // сейчас нельзя использовать bcnmid, т.к. они начинаются с нуля { m_BattlefieldHandler = new CBattlefieldHandler(m_zoneID); } if (m_miscMask & MISC_TREASURE) { m_TreasurePool = new CTreasurePool(TREASUREPOOL_ZONE); } } else { ShowFatalError(CL_RED"CZone::LoadZoneSettings: Cannot load zone settings (%u)\n" CL_RESET, m_zoneID); } }
void* _mmalloc(size_t size, const char *file, int line, const char *func ) { struct block *block; short size_hash = size2hash( size ); struct unit_head *head; if (((long) size) < 0) { ShowError("_mmalloc: %d\n", size); return NULL; } if(size == 0) { return NULL; } memmgr_usage_bytes += size; /* To ensure the area that exceeds the length of the block, using malloc () to */ /* At that time, the distinction by assigning NULL to unit_head.block */ if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); if(p != NULL) { p->size = size; p->unit_head.block = NULL; p->unit_head.size = 0; p->unit_head.file = file; p->unit_head.line = line; p->prev = NULL; if (unit_head_large_first == NULL) p->next = NULL; else { unit_head_large_first->prev = p; p->next = unit_head_large_first; } unit_head_large_first = p; *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; return (char *)p + sizeof(struct unit_head_large) - sizeof(long); } else { ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); exit(EXIT_FAILURE); } } /* When a block of the same size is not ensured, to ensure a new */ if(hash_unfill[size_hash]) { block = hash_unfill[size_hash]; } else { block = block_malloc(size_hash); } if( block->unit_unfill == 0xFFFF ) { // there are no more free space that memmgr_assert(block->unit_used < block->unit_count); memmgr_assert(block->unit_used == block->unit_maxused); head = block2unit(block, block->unit_maxused); block->unit_used++; block->unit_maxused++; } else { head = block2unit(block, block->unit_unfill); block->unit_unfill = head->size; block->unit_used++; } if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { // Since I ran out of the unit, removed from the list unfill if( block->unfill_prev == &block_head) { hash_unfill[ size_hash ] = block->unfill_next; } else { block->unfill_prev->unfill_next = block->unfill_next; } if( block->unfill_next ) { block->unfill_next->unfill_prev = block->unfill_prev; } block->unfill_prev = NULL; } #ifdef DEBUG_MEMMGR { size_t i, sz = hash2size( size_hash ); for( i=0; i<sz; i++ ) { if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd ) { if( head->line != 0xfdfd ) { ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); } else { ShowError("Memory manager: not-allocated-data is changed.\n"); } break; } } memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); } #endif head->block = block; head->file = file; head->line = line; head->size = (unsigned short)size; *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; return (char *)head + sizeof(struct unit_head) - sizeof(long); }
/*========================================== * アイテムデータベースの読み込み *------------------------------------------ */ static int itemdb_readdb(void) { FILE *fp; char line[1024]; int ln=0,lines=0; int nameid,j; char *str[32],*p,*np; struct item_data *id; int i=0; char *filename[]={ "item_db.txt","item_db2.txt" }; for(i=0;i<2;i++){ sprintf(line, "%s/%s", db_path, filename[i]); fp=fopen(line,"r"); if(fp==NULL){ if(i>0) continue; ShowFatalError("can't read %s\n",line); exit(1); } lines=0; while(fgets(line,1020,fp)){ lines++; if(line[0]=='/' && line[1]=='/') continue; memset(str,0,sizeof(str)); for(j=0,np=p=line;j<19 && p;j++){ str[j]=p; p=strchr(p,','); if(p){ *p++=0; np=p; } } if(str[0]==NULL) continue; nameid=atoi(str[0]); if(nameid<=0 || nameid>=20000) continue; if (j < 19) { //Crash-fix on broken item lines. [Skotlex] ShowWarning("Reading %s: Insufficient fields for item with id %d, skipping.\n", filename[i], nameid); continue; } ln++; //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View id=itemdb_search(nameid); memcpy(id->name, str[1], ITEM_NAME_LENGTH-1); memcpy(id->jname, str[2], ITEM_NAME_LENGTH-1); id->type=atoi(str[3]); if (id->type == 11) { //Items that are consumed upon target confirmation //(yggdrasil leaf, spells & pet lures) [Skotlex] id->type = 2; id->flag.delay_consume=1; } { int buy = atoi(str[4]), sell = atoi(str[5]); // if buying price > selling price * 2 consider it valid and don't change it [celest] if (buy && sell && buy > sell*2){ id->value_buy = buy; id->value_sell = sell; } else { // buy≠sell*2 は item_value_db.txt で指定してください。 if (sell) { // sell値を優先とする id->value_buy = sell*2; id->value_sell = sell; } else { id->value_buy = buy; id->value_sell = buy/2; } } // check for bad prices that can possibly cause exploits if (id->value_buy*75/100 < id->value_sell*124/100) { ShowWarning ("Item %s [%d] buying:%d < selling:%d\n", id->name, id->nameid, id->value_buy*75/100, id->value_sell*124/100); } } id->weight=atoi(str[6]); id->atk=atoi(str[7]); id->def=atoi(str[8]); id->range=atoi(str[9]); id->slot=atoi(str[10]); if (id->slot > MAX_SLOTS) { ShowWarning("itemdb_readdb: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS); id->slot = MAX_SLOTS; } itemdb_jobid2mapid(id->class_base, atoi(str[11])); id->class_upper = atoi(str[12]); id->sex = atoi(str[13]); if(id->equip != atoi(str[14])){ id->equip=atoi(str[14]); } id->wlv=atoi(str[15]); id->elv=atoi(str[16]); id->flag.no_refine = atoi(str[17])?0:1; //If the refine column is 1, no_refine is 0 id->look=atoi(str[18]); id->flag.available=1; id->flag.value_notdc=0; id->flag.value_notoc=0; id->view_id=0; id->sex = itemdb_gendercheck(id); //Apply gender filtering. if (id->script) { aFree(id->script); id->script=NULL; } if((p=strchr(np,'{'))==NULL) continue; id->script = parse_script((unsigned char *) p,lines); } fclose(fp); if (ln > 0) { ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); } ln=0; // reset to 0 } return 0; }
void netbuffer_init() { char localsection[32]; raconf conf; sysint i; // Initialize Statistic counters: l_nEmergencyAllocations = 0; // Set localsection name according to running serverype. switch(SERVER_TYPE) { case ATHENA_SERVER_LOGIN: strcpy(localsection, "login-netbuffer"); break; case ATHENA_SERVER_CHAR: strcpy(localsection, "char-netbuffer"); break; case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break; case ATHENA_SERVER_MAP: strcpy(localsection, "map-netbuffer"); break; default: strcpy(localsection, "unsupported_type"); break; } conf = raconf_parse("conf/network.conf"); if(conf == NULL) { ShowFatalError(read_message("Source.common.net_buffer_init")); exit(EXIT_FAILURE); } // Get Values from config file l_nPools = (sysint)raconf_getintEx(conf, localsection, "netbuffer", "num", 0); if(l_nPools == 0) { ShowFatalError(read_message("Source.common.net_buffer_init2")); exit(EXIT_FAILURE); } // Allocate arrays. l_poolElemSize = (sysint *)aCalloc(l_nPools, sizeof(sysint)); l_pool = (mempool *)aCalloc(l_nPools, sizeof(mempool)); for(i = 0; i < l_nPools; i++) { int64 num_prealloc, num_realloc; char key[32]; sprintf(key, "pool_%u_size", (uint32)i+1); l_poolElemSize[i] = (sysint)raconf_getintEx(conf, localsection, "netbuffer", key, 4096); if(l_poolElemSize[i] < 32) { ShowWarning(read_message("Source.common.net_buffer_init3")); l_poolElemSize[i] = 32; } sprintf(key, "pool_%u_prealloc", (uint32)i+1); num_prealloc = raconf_getintEx(conf, localsection, "netbuffer", key, 150); sprintf(key, "pool_%u_realloc_step", (uint32)i+1); num_realloc = raconf_getintEx(conf, localsection, "netbuffer", key, 100); // Create Pool! sprintf(key, "Netbuffer %u", (uint32)l_poolElemSize[i]); // name. // Info ShowInfo(read_message("Source.net_buffer_init4"), l_poolElemSize[i], num_prealloc, num_realloc, (float)((sizeof(struct netbuf) + l_poolElemSize[i] - 32)* num_prealloc)/1024.0f/1024.0f); // // Size Calculation: // struct netbuf + requested buffer size - 32 (because the struct already contains 32 byte buffer space at the end of struct) l_pool[i] = mempool_create(key, (sizeof(struct netbuf) + l_poolElemSize[i] - 32), num_prealloc, num_realloc, NULL, NULL); if(l_pool[i] == NULL) { ShowFatalError(read_message("Source.net_buffer_init5"), l_poolElemSize[i]); // @leak: clean everything :D exit(EXIT_FAILURE); } }// raconf_destroy(conf); }//end: netbuffer_init()
/* ブロックを確保する */ static struct block* block_malloc(void) { if(block_unused != NULL) { /* ブロック用の領域は確保済み */ struct block* ret = block_unused; do { block_unused = block_unused->block_next; } while(block_unused != NULL && block_unused->unit_size != 0); return ret; } else { /* ブロック用の領域を新たに確保する */ int i; int block_no; struct block* p; struct chunk* chunk; char *pb = (char *) CALLOC (sizeof(struct block),BLOCK_ALLOC + 1); if(pb == NULL) { ShowFatalError("Administrador de memoria::block_alloc falhou.\n"); exit(1); } // store original block address in chunk chunk = (struct chunk *) MALLOC (sizeof(struct chunk)); if (chunk == NULL) { ShowFatalError("Administrador de Memoria::block_alloc falhou.\n"); exit(1); } chunk->block = pb; chunk->next = (chunk_first) ? chunk_first : NULL; chunk_first = chunk; // ブロックのポインタの先頭をsizeof(block) アライメントに揃える // このアドレスをfree() することはないので、直接ポインタを変更している。 pb += sizeof(struct block) - ((unsigned long)pb % sizeof(struct block)); p = (struct block*)pb; if(block_first == NULL) { /* 初回確保 */ block_no = 0; block_first = p; } else { block_no = block_last->block_no + 1; block_last->block_next = p; p->block_prev = block_last; } block_last = &p[BLOCK_ALLOC - 1]; /* ブロックを連結させる */ for(i=0;i<BLOCK_ALLOC;i++) { if(i != 0) { p[i].block_prev = &p[i-1]; } if(i != BLOCK_ALLOC -1) { p[i].block_next = &p[i+1]; } p[i].block_no = block_no + i; } /* 未使用ブロックへのポインタを更新 */ block_unused = &p[1]; p->unit_size = 1; return p; } }
/*==============================================================* * Function: Auth::Run * * Author: GreenBox * * Date: 08/12/11 * * Description: Start Auth-Server and load configurations * **==============================================================*/ void AuthServer::run() { boost::asio::io_service io_service; // Read Config Files try { auth_config = new config_file("./Config/authserver.conf"); { config.network_bindip = auth_config->read<string>("network.bindip", "0.0.0.0"); config.network_bindport = auth_config->read<unsigned short>("network.bindport", 6900); config.auth_use_md5 = auth_config->read<bool>("auth.use_md5", false); } ShowStatus("Finished reading authserver.conf.\n"); } catch (config_file::file_not_found *fnf) { ShowFatalError("Config file not found: %s.\n", fnf->filename); return; } TimerManager::Initialize(&io_service); // Initialize Database System { ShowInfo("Opening connection to database...\n"); try { database = database_helper::get_session(auth_config); } catch (soci::soci_error err) { ShowFatalError("Error opening database connection: %s\n", err.what()); return; } accounts = new AccountDB(database); ShowSQL("Successfully opened database connection.\n"); } // Initialize Network System { boost::system::error_code err; address_v4 bindip = address_v4::from_string(config.network_bindip, err); if (err) { ShowFatalError("%s\n", err.message().c_str()); return; } server = new tcp_server(io_service, (address)bindip, config.network_bindport); server->set_default_parser(AuthServer::parse_from_client); ShowStatus("AuthServer is ready and listening on %s:%d.\n", config.network_bindip.c_str(), config.network_bindport); } // Run IO service service and start pooling events io_service.run(); }
int do_sockets(fd_set* rfd,int next) { struct timeval timeout; int ret,i; // can timeout until the next tick timeout.tv_sec = next/1000; timeout.tv_usec = next%1000*1000; memcpy(rfd, &readfds, sizeof(*rfd)); ret = sSelect(fd_max, rfd, NULL, NULL, &timeout); if( ret == SOCKET_ERROR ) { if( sErrno != S_EINTR ) { ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno); exit(EXIT_FAILURE); } return 0; // interrupted by a signal, just loop and try again } last_tick = time(NULL); #if defined(WIN32) // on windows, enumerating all members of the fd_set is way faster if we access the internals for( i = 0; i < (int)rfd->fd_count; ++i ) { int fd = sock2fd(rfd->fd_array[i]); if( session[fd] ) { session[fd]->func_recv(fd); if( fd != login_fd && fd != login_lobbydata_fd && fd != login_lobbyview_fd ) { session[fd]->func_parse(fd); if(!session[fd]) continue; // RFIFOFLUSH(fd); } } } #else // otherwise assume that the fd_set is a bit-array and enumerate it in a standard way for( i = 1; ret && i < fd_max; ++i ) { if(sFD_ISSET(i,rfd) && session[i]) { session[i]->func_recv(i); if( session[i] ) { if( i != login_fd && i != login_lobbydata_fd && i != login_lobbyview_fd ) { session[i]->func_parse(i); if(!session[i]) continue; // RFIFOFLUSH(fd); } --ret; } } } #endif /* // parse input data on each socket for(i = 1; i < fd_max; i++) { if(!session[i]) continue; if (session[i]->rdata_tick && DIFF_TICK(last_tick, session[i]->rdata_tick) > stall_time) { ShowInfo("Session #%d timed out\n", i); set_eof(i); } session[i]->func_parse(i); if(!session[i]) continue; // after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed) if (session[i]->rdata_size == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) { set_eof(i); continue; } RFIFOFLUSH(i); }*/ for (i = 1; i < fd_max; i++) { if(!session[i]) continue; if(session[i]->wdata_size) session[i]->func_send(i); } return 0; }
/*! * \brief Start Char Server * \details Start the char-server and load the confs * \author Fimbulwinter Development Team * \author GreenBox * \date 08/12/11 * **/ void CharServer::run() { io_service = new boost::asio::io_service(); // Read Config Files try { char_config = new config_file("./Config/charserver.conf"); { config.server_name = char_config->read<string>("server.name", "Cronus++"); config.network_bindip = char_config->read<string>("network.bindip", "0.0.0.0"); config.network_bindport = char_config->read<unsigned short>("network.bindport", 6121); config.network_charip = char_config->read<string>("network.charip", ""); config.inter_login_ip = char_config->read<string>("inter.login.ip", "127.0.0.1"); config.inter_login_port = char_config->read<unsigned short>("inter.login.port", 6900); config.inter_login_user = char_config->read<string>("inter.login.user", "s1"); config.inter_login_pass = char_config->read<string>("inter.login.pass", "p1"); if (config.network_charip == "") { ShowInfo("Auto-detecting my IP Address...\n"); tcp::resolver resolver(*io_service); tcp::resolver::query query(boost::asio::ip::host_name(), ""); tcp::resolver::iterator iter = resolver.resolve(query); tcp::resolver::iterator end; while (iter != end) { tcp::endpoint ep = *iter++; if (!ep.address().is_v4()) continue; config.network_charip = ep.address().to_string(); break; } ShowStatus("Defaulting our IP Address to %s...\n", config.network_charip.c_str()); } } ShowStatus("Finished reading charserver.conf.\n"); } catch (config_file::file_not_found *fnf) { ShowFatalError("Config file not found: %s.\n", fnf->filename); return; } TimerManager::Initialize(io_service); if (!maps.load("./Data/map_index")) { getchar(); abort(); } // Initialize Database System { ShowInfo("Opening connection to database...\n"); try { database = database_helper::get_session(char_config); } catch (soci::soci_error err) { ShowFatalError("Error opening database connection: %s\n", err.what()); return; } chars = new CharDB(database); ShowSQL("Successfully opened database connection.\n"); } connect_to_auth(); // Initialize Network System { boost::system::error_code err; address_v4 bindip = address_v4::from_string(config.network_bindip, err); if (err) { ShowFatalError("%s\n", err.message().c_str()); return; } server = new tcp_server(*io_service, (address)bindip, config.network_bindport); server->set_default_parser(CharServer::parse_from_client); ShowStatus("CharServer is ready and listening on %s:%d.\n", config.network_bindip.c_str(), config.network_bindport); } // Run IO service service and start pooling events io_service->run(); }
void *_mmalloc (size_t size, const char *file, int line, const char *func) { struct block *block; short size_hash = size2hash (size); struct unit_head *head; if ( ( (long) size) < 0) { ShowError ("_mmalloc: %d\n", size); return NULL; } if (size == 0) { return NULL; } memmgr_usage_bytes += size; /* ブロック長を超える領域の確保には、malloc() を用いる */ /* その際、unit_head.block に NULL を代入して区別する */ if (hash2size (size_hash) > BLOCK_DATA_SIZE - sizeof (struct unit_head)) { struct unit_head_large *p = (struct unit_head_large *) MALLOC (sizeof (struct unit_head_large) + size, file, line, func); if (p != NULL) { p->size = size; p->unit_head.block = NULL; p->unit_head.size = 0; p->unit_head.file = file; p->unit_head.line = line; p->prev = NULL; if (unit_head_large_first == NULL) p->next = NULL; else { unit_head_large_first->prev = p; p->next = unit_head_large_first; } unit_head_large_first = p; * (long *) ( (char *) p + sizeof (struct unit_head_large) - sizeof (long) + size) = 0xdeadbeaf; return (char *) p + sizeof (struct unit_head_large) - sizeof (long); } else { ShowFatalError ("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof (struct unit_head_large), size, file, line); exit (EXIT_FAILURE); } } /* 同一サイズのブロックが確保されていない時、新たに確保する */ if (hash_unfill[size_hash]) { block = hash_unfill[size_hash]; } else { block = block_malloc (size_hash); } if (block->unit_unfill == 0xFFFF) { // free済み領域が残っていない memmgr_assert (block->unit_used < block->unit_count); memmgr_assert (block->unit_used == block->unit_maxused); head = block2unit (block, block->unit_maxused); block->unit_used++; block->unit_maxused++; } else { head = block2unit (block, block->unit_unfill); block->unit_unfill = head->size; block->unit_used++; } if (block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { // ユニットを使い果たしたので、unfillリストから削除 if (block->unfill_prev == &block_head) { hash_unfill[ size_hash ] = block->unfill_next; } else { block->unfill_prev->unfill_next = block->unfill_next; } if (block->unfill_next) { block->unfill_next->unfill_prev = block->unfill_prev; } block->unfill_prev = NULL; } #ifdef DEBUG_MEMMGR { size_t i, sz = hash2size (size_hash); for (i = 0; i < sz; i++) { if ( ( (unsigned char *) head) [ sizeof (struct unit_head) - sizeof (long) + i] != 0xfd) { if (head->line != 0xfdfd) { ShowError ("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file, head->line); } else { ShowError ("Memory manager: not-allocated-data is changed.\n"); } break; } } memset ( (char *) head + sizeof (struct unit_head) - sizeof (long), 0xcd, sz); } #endif head->block = block; head->file = file; head->line = line; head->size = (unsigned short) size; * (long *) ( (char *) head + sizeof (struct unit_head) - sizeof (long) + size) = 0xdeadbeaf; return (char *) head + sizeof (struct unit_head) - sizeof (long); }
//--------------------------------------------------------- // 倉庫データを読み込む int inter_storage_init() { char line[65536]; int c=0,tmp_int; struct storage *s; struct guild_storage *gs; FILE *fp; storage_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); fp=fopen(storage_txt,"r"); if(fp==NULL){ ShowError("can't read : %s\n",storage_txt); return 1; } while(fgets(line,65535,fp)){ sscanf(line,"%d",&tmp_int); s = (struct storage*)aCalloc(sizeof(struct storage), 1); if(s==NULL){ ShowFatalError("int_storage: out of memory!\n"); exit(0); } // memset(s,0,sizeof(struct storage)); aCalloc does this... s->account_id=tmp_int; if(s->account_id > 0 && storage_fromstr(line,s) == 0) { idb_put(storage_db,s->account_id,s); } else{ ShowError("int_storage: broken data [%s] line %d\n",storage_txt,c); aFree(s); } c++; } fclose(fp); c = 0; guild_storage_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); fp=fopen(guild_storage_txt,"r"); if(fp==NULL){ ShowError("can't read : %s\n",guild_storage_txt); return 1; } while(fgets(line,65535,fp)){ sscanf(line,"%d",&tmp_int); gs = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1); if(gs==NULL){ ShowFatalError("int_storage: out of memory!\n"); exit(0); } // memset(gs,0,sizeof(struct guild_storage)); aCalloc... gs->guild_id=tmp_int; if(gs->guild_id > 0 && guild_storage_fromstr(line,gs) == 0) { idb_put(guild_storage_db,gs->guild_id,gs); } else{ ShowError("int_storage: broken data [%s] line %d\n",guild_storage_txt,c); aFree(gs); } c++; } fclose(fp); return 0; }
void* _mmalloc(size_t size, const char *file, int line, const char *func ) { int i; struct block *block; size_t size_hash; if (((long) size) < 0) { printf("_mmalloc: %d\n", size); return 0; } size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT; if(size == 0) { return NULL; } memmgr_usage_bytes += size; /* ブロック長を超える領域の確保には、malloc() を用いる */ /* その際、unit_head.block に NULL を代入して区別する */ if(size_hash * BLOCK_ALIGNMENT > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); if(p != NULL) { p->unit_head.block = NULL; p->unit_head.size = size; p->unit_head.file = file; p->unit_head.line = line; p->prev = NULL; if (unit_head_large_first == NULL) p->next = NULL; else { unit_head_large_first->prev = p; p->next = unit_head_large_first; } unit_head_large_first = p; *(int*)((char*)p + sizeof(struct unit_head_large) - sizeof(int) + size) = 0xdeadbeaf; return (char *)p + sizeof(struct unit_head_large) - sizeof(int); } else { ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); exit(1); } } /* 同一サイズのブロックが確保されていない時、新たに確保する */ if(unit_unfill[size_hash] == NULL) { block = block_malloc(); if(unit_first[size_hash] == NULL) { /* 初回確保 */ unit_first[size_hash] = block; unit_last[size_hash] = block; block->samesize_no = 0; block->samesize_prev = NULL; block->samesize_next = NULL; } else { /* 連結作業 */ unit_last[size_hash]->samesize_next = block; block->samesize_no = unit_last[size_hash]->samesize_no + 1; block->samesize_prev = unit_last[size_hash]; block->samesize_next = NULL; unit_last[size_hash] = block; } unit_unfill[size_hash] = block; block->unit_size = size_hash * BLOCK_ALIGNMENT + sizeof(struct unit_head); block->unit_count = (int)(BLOCK_DATA_SIZE / block->unit_size); block->unit_used = 0; block->unit_hash = size_hash; /* 未使用Flagを立てる */ for(i=0;i<block->unit_count;i++) { ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL; } } /* ユニット使用個数加算 */ block = unit_unfill[size_hash]; block->unit_used++; /* ユニット内を全て使い果たした */ if(block->unit_count == block->unit_used) { do { unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next; } while( unit_unfill[size_hash] != NULL && unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used ); } /* ブロックの中の空きユニット捜索 */ for(i=0;i<block->unit_count;i++) { struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); if(head->block == NULL) { head->block = block; head->size = size; head->line = line; head->file = file; *(int*)((char*)head + sizeof(struct unit_head) - sizeof(int) + size) = 0xdeadbeaf; return (char *)head + sizeof(struct unit_head) - sizeof(int); } } // ここに来てはいけない。 ShowFatalError("Memory manager::memmgr_malloc() serious error (allocating %d+%d bytes at %s:%d)\n", sizeof(struct unit_head_large), size, file, line); memmgr_info(); exit(1); return NULL; };
// パーティ脱退要求 int mapif_parse_PartyLeave(int fd,int party_id,int account_id) { char t_member[2*NAME_LENGTH]; struct party *p = party_pt; if (p == NULL) { ShowFatalError("int_party: out of memory !\n"); return 0; } inter_party_fromsql(party_id, p); if (p->party_id >= 0) { int i; for (i = 0; i < MAX_PARTY; i++) { if (p->member[i].account_id == account_id) { mapif_party_leaved(party_id, account_id, p->member[i].name); // Update char information, does the name need encoding? sprintf (tmp_sql, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `name`='%s'", char_db, party_id, jstrescapecpy(t_member,p->member[i].name)); if (mysql_query (&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } if (p->member[i].leader == 1){ int j; for (j = 0; j < MAX_PARTY; j++) { if (p->member[j].account_id > 0 && j != i) { mapif_party_leaved(party_id, p->member[j].account_id, p->member[j].name); } } // we'll skip name-checking and just reset everyone with the same party id [celest] // -- if anything goes wrong just uncomment the section above ^^; sprintf (tmp_sql, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id); if (mysql_query(&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } // Delete the party, if has no member. sprintf(tmp_sql, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id); if (mysql_query(&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } memset(p, 0, sizeof(struct party)); } else memset(&p->member[i], 0, sizeof(struct party_member)); break; } } if (party_check_empty(p) == 0) mapif_party_info(-1,p);// まだ人がいるのでデータ送信 //else // inter_party_tosql(party_id,p); // Break the party if no member } else { sprintf(tmp_sql, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `online`='1'", char_db, party_id, account_id); if (mysql_query(&mysql_handle, tmp_sql)) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } } return 0; }