MockNamedValue MockActualFunctionCall::returnValue() { checkExpectations(); if (_fulfilledExpectation) return _fulfilledExpectation->returnValue(); return MockNamedValue("no return value"); }
bool NavKeyedDataHandler:: handleGetKeyedData( LangTypes::language_t language, NavRequestPacket* pack, NavReplyPacket* reply ) try { if ( !checkExpectations( pack->getParamBlock(), reply ) ) { return false; } MC2String key; uint32 crc; bool sentCRC; getParameters( pack->getParamBlock(), key, crc, sentCRC ); logParameters( key, language, crc, sentCRC); vector<byte> data; getDataForKey( key, language, data ); uint32 newCrc = MC2CRC32::crc32( &data.front(), data.size() ); if ( !sentCRC || crc != newCrc ) { NParamBlock& rparams = reply->getParamBlock(); rparams.addParam( NParam( 6101, newCrc ) ); addDataAsParams( rparams, data ); } return true; } catch ( const MC2Exception& e ) { mc2log << warn << "handleGetKeyedData: " << e.what() << endl; reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); return false; }
MockNamedValue MockCheckedActualCall::returnValue() { checkExpectations(); if (fulfilledExpectation_) return fulfilledExpectation_->returnValue(); return MockNamedValue("no return value"); }
bool NavVerifyThirdPartyTransactionHandler::handleVerifyThirdPartyTransaction( NavRequestData& rd ) { if ( !checkExpectations( rd.params, rd.reply ) ) { return false; } bool ok = true; // Start parameter printing mc2log << info << "handleVerifyThirdPartyTransaction:"; stringstream inputData; // Verification String MC2String verifyString; if ( getParam( 6400, verifyString, rd.params ) ) { inputData << " " << verifyString; } // Error Data Selection String MC2String selectionString; if ( getParam( 6401, selectionString, rd.params ) ) { inputData << " " << selectionString; } mc2log << inputData.str(); // End parameter printing mc2log << endl; // Split selectionString on ; vector<MC2String> selectionArray = STLStringUtility::explode( ";", selectionString ); if ( selectionArray.size() == 2 ) { if ( selectionArray[ 0 ] == "iPhoneAppStore" ) { // verifyString to AppStoreHandler bool verified = m_thread->getAppStore().verifyReceipt( verifyString ); if ( ! verified ) { rd.reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); } mc2log << info << "handleVerifyThirdPartyTransaction: Verify " << (verified ? "Successful" : "Failed" ) << endl; } else { mc2log << "handleVerifyThirdPartyTransaction: unknown error data " << "type : " << MC2CITE( selectionArray[ 0 ] ) << endl; rd.reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); } } else { mc2log << "handleVerifyThirdPartyTransaction: bad format on " << "Selection String: " << MC2CITE( selectionString ) << endl; rd.reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); } return ok; }
bool NavMapHandler::handleMap( UserItem* userItem, NavRequestPacket* req, NavReplyPacket* reply ) { if ( !checkExpectations( req->getParamBlock(), reply ) ) { return false; } bool ok = true; // The params const NParamBlock& params = req->getParamBlock(); NParamBlock& rparams = reply->getParamBlock(); // The user UserUser* user = userItem->getUser(); uint32 startTime = TimeUtility::getCurrentTime(); // Start parameter printing mc2log << info << "handleMap:"; StringTable::languageCode language = user->getLanguage(); if ( params.getParam( 6 ) ) { language = NavUtil::mc2LanguageCode( params.getParam( 6 )->getUint16() ); mc2log << " Lang " << StringTable::getString( StringTable::getLanguageAsStringCode( language ), StringTable::ENGLISH ); } // MapBoundingbox MC2BoundingBox mapBbox; if ( params.getParam( 1600 ) ) { MC2Coordinate topLeft( Nav2Coordinate( params.getParam( 1600 )->getInt32Array( 0 ), params.getParam( 1600 )->getInt32Array( 1 ) ) ); MC2Coordinate bottomRight( Nav2Coordinate( params.getParam( 1600 )->getInt32Array( 2 ), params.getParam( 1600 )->getInt32Array( 3 ) ) ); mapBbox.setMaxLat( topLeft.lat ); mapBbox.setMinLon( topLeft.lon ); mapBbox.setMinLat( bottomRight.lat ); mapBbox.setMaxLon( bottomRight.lon ); mc2log << " MapBoundingbox " << mapBbox; } MC2Coordinate mapPos; if ( params.getParam( 1601 ) ) { mapPos = MC2Coordinate( Nav2Coordinate( params.getParam( 1601 )->getInt32Array( 0 ), params.getParam( 1601 )->getInt32Array( 1 ) ) ); mc2log << " MapPosition " << mapPos; } float32 speed = 666.999; if ( params.getParam( 1602 ) ) { if ( params.getParam( 1602 )->getUint16() < MAX_INT16 ) { speed = float32(params.getParam( 1602 )->getUint16())/32; mc2log << " speed " << speed; } else { mc2log << " speed N/A"; } } uint16 heading = MAX_UINT16; if ( params.getParam( 1603 ) ) { if ( params.getParam( 1603 )->getUint16() < 256 ) { heading = uint16( rint( params.getParam( 1603 )->getUint16() * 360.0 / 256.0 ) ); mc2log << " heading " << heading << "°"; } else { mc2log << " heading N/A"; } } uint32 mapRadius = MAX_UINT32; if ( params.getParam( 1604 ) ) { mapRadius = params.getParam( 1604 )->getUint32(); mc2log << " Map radius " << mapRadius; } MC2String routeIDStr; RouteID routeID( 0, 0 ); if ( params.getParam( 1605 ) ) { routeIDStr = params.getParam( 1605 )->getString( m_thread->clientUsesLatin1()); routeID = RouteID( routeIDStr.c_str() ); mc2log << " routeID " << routeIDStr; if ( routeID.isValid() == 0 ) { mc2log << " INVALID"; } } uint16 imageWidth = 160; uint16 imageHeight = 120; if ( params.getParam( 1606 ) ) { imageWidth = params.getParam( 1606 )->getUint16Array( 0 ); imageHeight = params.getParam( 1606 )->getUint16Array( 1 ); mc2log << " imageSize " << imageWidth << "," << imageHeight; } if ( params.getParam( 1607 ) ) { mc2log << " imageVbox " << params.getParam( 1607 )->getUint16Array( 0 ) << "," << params.getParam( 1607 )->getUint16Array( 1 ); } ImageDrawConfig::imageFormat imageFormat = ImageDrawConfig::GIF; if ( params.getParam( 1608 ) ) { // Image Format imageFormat = navImgFmtToMC2( params.getParam( 1608 )->getByte() ); mc2log << " imageFormat " << ImageDrawConfig::getImageFormatAsString( imageFormat); } vector< pair<MC2Coordinate, uint16 > > mapItems; if ( params.getParam( 1609 ) ) { vector< const NParam* > pmapItems; params.getAllParams( 1609, pmapItems ); for ( uint32 i = 0 ; i < pmapItems.size() ; ++i ) { mapItems.push_back( make_pair( MC2Coordinate( Nav2Coordinate( pmapItems[ i ]->getInt32( 2 ), pmapItems[ i ]->getInt32( 6 ) ) ), pmapItems[ i ]->getUint16( 0 ) ) ); mc2log << " MapItem " << mapItems[ i ].first << "," << mapItems[ i ].second; } } MapSettings mapSettings; uint16 angle = 0; bool showMap = mapSettings.getShowMap(); bool showTopographMap = mapSettings.getShowTopographMap(); bool showPOI = mapSettings.getShowPOI(); bool showRoute = mapSettings.getShowRoute(); if ( params.getParam( 1610 ) ) { vector< const NParam* > pmapInfos; params.getAllParams( 1610, pmapInfos ); for ( uint32 i = 0 ; i < pmapInfos.size() ; ++i ) { uint16 type = pmapInfos[ i ]->getUint16( 0 ); uint32 value = pmapInfos[ i ]->getUint32( 2 ); mc2log << " mapInfo "; switch ( type ) { case 0 : mc2log << "Invalid " << value; break; case 1 : mc2log << "Category " << value; break; case 2 : mapSettings.setShowTraffic( value != 0 ); mc2log << "TrafficInformation " << BP(value); break; case 3 : mapSettings.setDrawScale( value != 0 ); mc2log << "Scale " << BP(value); break; case 4 : showTopographMap = value != 0; mc2log << "Topographic " << BP(value); break; case 5 : mc2log << "MapFormat " << value; break; case 6 : angle = uint16( rint( 360.0 / 256.0 * value ) ); mc2log << "Rotate " << angle; break; } } mapSettings.setMapContent( showMap, showTopographMap, showPOI, showRoute ); } const ClientSetting* clientSetting = m_thread->getClientSetting(); if ( clientSetting != NULL ) { mapSettings.setImageSet( clientSetting->getImageSet() ); } mc2log << endl; // Get AURA set< uint32 >* allowedMaps = NULL; if ( ok ) { if ( !m_thread->getMapIdsForUserRegionAccess( user, allowedMaps ) ) { ok = false; mc2log << warn << "handleMap: getMapIdsForUserRegionAccess" << " failed. Error: "; if ( TimeUtility::getCurrentTime() - startTime > 3000 ) { reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); mc2log << "Timeout"; } else { reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); mc2log << "Error"; } mc2log << endl; } } // Store user position?? (mapPos) // Get Route ExpandRouteRequest* expReq = NULL; PacketContainer* expandRouteCont = NULL; RouteReplyPacket* routePack = NULL; if ( ok && routeID.isValid() != 0 ) { uint32 expandType = (ROUTE_TYPE_STRING | ROUTE_TYPE_NAVIGATOR | ROUTE_TYPE_ITEM_STRING | ROUTE_TYPE_GFX); routePack = m_thread->getStoredRouteAndExpand( routeID, expandType, language, false/*abbreviate*/, false/*landmarks*/, true/*removeAheadIfDiff*/, false/*nameChangeAsWP*/, expReq, expandRouteCont ); if ( routePack == NULL || expReq == NULL || expandRouteCont == NULL ) { mc2log << warn << "handleMap: getStoredRouteAndExpand failed "; if ( TimeUtility::getCurrentTime() - startTime > 3000 ) { mc2log << "Timeout"; } else { // No such route? mc2log << "Error"; } mc2log << endl; } } // End if ok to get stored route // Make Map bbox MC2BoundingBox bbox; MC2String inputDebitStr; char tmpStr[ 256 ]; if ( ok ) { // Boundingbox -- A complete bounding box. if ( mapBbox.isValid() ) { bbox = mapBbox; inputDebitStr = "BoundingBox [("; sprintf( tmpStr, "%d", mapBbox.getMaxLat() ); inputDebitStr.append( tmpStr ); inputDebitStr.append( "," ); sprintf( tmpStr, "%d", mapBbox.getMinLon() ); inputDebitStr.append( tmpStr ); inputDebitStr.append( "),(" ); sprintf( tmpStr, "%d", mapBbox.getMinLat() ); inputDebitStr.append( tmpStr ); inputDebitStr.append( "," ); sprintf( tmpStr, "%d", mapBbox.getMaxLon() ); inputDebitStr.append( tmpStr ); inputDebitStr.append( ")]" ); mc2log << info << "handleMap: Boundingbox " << bbox << endl; } // VectorBox -- The bounding box will be calculated from the // current position, heading, speed and Route ID. else if ( mapPos.isValid() && speed < 500 && heading != MAX_UINT16 ) { bbox = m_mapHelp->handleNavMapVectorBox( mapRadius, uint16(rint(speed*32)), mapPos, heading, expandRouteCont ); inputDebitStr = "VectorBox Coord ("; sprintf( tmpStr, "%d", mapPos.lat ); inputDebitStr.append( tmpStr ); inputDebitStr.append( "," ); sprintf( tmpStr, "%d", mapPos.lon ); inputDebitStr.append( tmpStr ); inputDebitStr.append( ") speed " ); sprintf( tmpStr, "%hu", uint16(rint(speed*32)) ); inputDebitStr.append( tmpStr ); inputDebitStr.append( " hdg " ); sprintf( tmpStr, "%hu", heading ); inputDebitStr.append( tmpStr ); inputDebitStr.append( " radius " ); sprintf( tmpStr, "%hu", mapRadius ); inputDebitStr.append( tmpStr ); mc2log << info << "handleMap: VectorBox " << bbox << endl; } // RadiusBox -- The bounding box will contain a circle // centered on the current position and with the // specified map radius. else if ( mapPos.isValid() ) { uint32 posSize = 60000; if ( mapRadius != 0 && mapRadius < 100000000 ) { // Not less than 100m posSize = uint32( rint( GfxConstants::METER_TO_MC2SCALE * MAX( 100, mapRadius ) ) ); } bbox.setMaxLat( mapPos.lat + posSize ); bbox.setMinLon( mapPos.lon - posSize ); bbox.setMinLat( mapPos.lat - posSize ); bbox.setMaxLon( mapPos.lon + posSize ); inputDebitStr = "RadiusBox Coord (" ; sprintf( tmpStr, "%d", mapPos.lat ); inputDebitStr.append( tmpStr ); inputDebitStr.append( "," ); sprintf( tmpStr, "%d", mapPos.lon ); inputDebitStr.append( tmpStr ); inputDebitStr.append( ") radius " ); sprintf( tmpStr, "%hu", mapRadius ); inputDebitStr.append( tmpStr ); mc2log << info << "handleMap: RadiusBox " << bbox << endl; } // RouteBox -- The bounding box will contain the entire route // specified by the Route ID. else if ( routeID.isValid() != 0 ) { if ( expandRouteCont != NULL && static_cast<ReplyPacket*>(expandRouteCont->getPacket() ) ->getStatus() == StringTable::OK ) { ExpandRouteReplyPacket* expand = static_cast< ExpandRouteReplyPacket* > ( expandRouteCont->getPacket() ); ExpandItemID* exp = expand->getItemID(); ExpandStringItem** stringItems = expand->getStringDataItem(); uint32 numStringItems = expand->getNumStringData(); int32 minLat = 0; int32 maxLat = 0; int32 minLon = 0; int32 maxLon = 0; // uint16 angle = 0; // FullRoute HttpUtility::getRouteMC2BoundingBox( expand, exp, 0, numStringItems - 1, minLat, maxLat, minLon, maxLon ); // Set bbox bbox.setMaxLat( maxLat ); bbox.setMinLon( minLon ); bbox.setMinLat( minLat ); bbox.setMaxLon( maxLon ); inputDebitStr = "RouteBox "; sprintf( tmpStr, "%u", routeID.getRouteIDNbr() ); inputDebitStr.append( tmpStr ); inputDebitStr.append( "," ); sprintf( tmpStr, "%u", routeID.getCreationTime() ); inputDebitStr.append( tmpStr ); mc2log << info << "handleMap: RouteBox " << bbox << endl; delete exp; for ( uint32 i = 0 ; i < numStringItems ; ++i ) { delete stringItems[ i ]; } delete [] stringItems; } else { // Error route specified but now available. ok = false; mc2log << warn << "handleMap: Have routeID but not route: "; if ( TimeUtility::getCurrentTime() - startTime > 3000 ) { reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); mc2log << "Timeout"; } else { if ( routePack != NULL ) { // Expansion failed reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); mc2log << "Expansion failed"; } else { // No such route reply->setStatusCode( NavReplyPacket::NAV_STATUS_PARAMETER_INVALID ); reply->setStatusMessage( "RouteID not valid" ); mc2log << "RouteID not valid"; } } mc2log << endl; } } // Nothing to make map with, send error else { mc2log << warn << "handleMap: Nothing to make map with." << endl; reply->setStatusCode( NavReplyPacket::NAV_STATUS_MISSING_PARAMETER ); reply->setStatusMessage( "Nothing to make map with" ); ok = false; } if ( ok && bbox.isValid() ) { // Make sure that the bbox is proportional with the width, height int32 lla = bbox.getMinLat(); int32 llo = bbox.getMinLon(); int32 ula = bbox.getMaxLat(); int32 ulo = bbox.getMaxLon(); uint16 w = imageWidth; uint16 h = imageHeight; GfxUtility::getDisplaySizeFromBoundingbox( lla, llo, ula, ulo, w, h ); // Set bbox bbox.setMaxLat( ula ); bbox.setMinLon( llo ); bbox.setMinLat( lla ); bbox.setMaxLon( ulo ); // This is nessesary! bbox.updateCosLat(); // Make real request! uint32 size = imageWidth * imageHeight / 8 + 4096; MC2BoundingBox ccBBox; GfxFeatureMapImageRequest* gfxReq = new GfxFeatureMapImageRequest( m_thread->getNextRequestID(), &bbox, imageWidth, imageHeight, ItemTypes::getLanguageCodeAsLanguageType( language ), routePack, true, true, true,/*drawCopyRight*/ imageFormat, size, &mapSettings, m_thread->getTopRegionRequest(), ccBBox ); for ( uint32 i = 0 ; i < mapItems.size() ; ++i ) { const char* symbolImage = ""; GfxSymbolFeature::symbols symbolType = GfxSymbolFeature::PIN; gfxReq->addSymbolToMap( mapItems[ i ].first.lat, mapItems[ i ].first.lon, "", symbolType, symbolImage ); } gfxReq->setMapRotation( angle ); // Limit map area gfxReq->setAllowedMaps( allowedMaps ); // Wait for the answer m_thread->putRequest( gfxReq ); PacketContainer* gfxReqAnswer = gfxReq->getAnswer(); if ( gfxReqAnswer == NULL || StringTable::stringCode( static_cast<ReplyPacket*>( gfxReqAnswer->getPacket() )->getStatus() ) != StringTable::OK ) { // Error if ( gfxReqAnswer == NULL ) { mc2log << warn << "handleMap: " << " gfxReq NULL answer: "; if ( TimeUtility::getCurrentTime() - startTime > 3000 ) { reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); mc2log << "Timeout"; } else { reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); mc2log << "Error"; } mc2log << endl; } else { if ( StringTable::stringCode( static_cast<ReplyPacket*>( gfxReqAnswer ->getPacket() )->getStatus() ) == StringTable::TIMEOUT_ERROR ) { mc2log << warn << "handleMap: " << " gfxReq timed out status." << endl; reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); } else { StringTable::stringCode errCode = StringTable::stringCode( static_cast<ReplyPacket*>( gfxReqAnswer->getPacket() ) ->getStatus() ); mc2log << warn << "handleMap: " << " gfxReq not ok \"" << StringTable::getString( errCode, StringTable::ENGLISH ) << "\" (" << int(errCode) << ")" << endl; reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); } } } else { uint32 size = static_cast< GfxFeatureMapImageReplyPacket* >( gfxReqAnswer->getPacket() )->getSize(); byte* imageBuff = static_cast< GfxFeatureMapImageReplyPacket* > ( gfxReqAnswer->getPacket() )->getImageData(); mc2log << info << "handleMap: " << "reply: map size " << size << " bytes Boundingbox: " << bbox << endl; // Set reply data // MapBoundingbox NParam& pbbox = rparams.addParam( NParam( 1700 ) ); Nav2Coordinate topLeft( MC2Coordinate( bbox.getMaxLat(), bbox.getMinLon() ) ); Nav2Coordinate bottomRight( MC2Coordinate( bbox.getMinLat(), bbox.getMaxLon() ) ); pbbox.addInt32( topLeft.nav2lat ); pbbox.addInt32( topLeft.nav2lon ); pbbox.addInt32( bottomRight.nav2lat ); pbbox.addInt32( bottomRight.nav2lon ); // Image size NParam& piwh = rparams.addParam( NParam( 1701 ) ); piwh.addUint16( imageWidth ); piwh.addUint16( imageHeight ); // Real world size uint32 widthInMeters = uint32( rint( GfxConstants::MC2SCALE_TO_METER * ( bbox.getMaxLon() - bbox.getMinLon() ) * GfxUtility::getCoslat( bbox.getMinLat(), bbox.getMaxLat() ) ) ); uint32 heightInMeters = uint32( rint( GfxConstants::MC2SCALE_TO_METER * ( bbox.getMaxLat() - bbox.getMinLat() ) ) ); NParam& prwh = rparams.addParam( NParam( 1702 ) ); prwh.addUint32( widthInMeters ); prwh.addUint32( heightInMeters ); // Image Format rparams.addParam( NParam( 1703, mc2ImgFmtToNav( imageFormat ) ) ); // Image NParam& pimage = rparams.addParam( NParam( 1704 ) ); pimage.addByteArray( imageBuff, size ); // Checkpoint for VectorMap with route following // 1705 // Debit MC2Coordinate posCoord = MC2Coordinate::invalidCoordinate; if ( mapItems.size() > 0 ) { posCoord = mapItems[ 0 ].first; } MC2String extraInfo = m_userHelp->makeExtraUserInfoStr( params ); // Set debitamount here untill module sets it ok uint32 debitAmount = TimeUtility::getCurrentTime() - startTime; if ( !m_thread->getDebitHandler()->makeMapDebit( userItem, extraInfo.c_str(), size, debitAmount, bbox, inputDebitStr.c_str(), imageWidth, imageHeight, true, imageFormat, routeID.getRouteIDNbr(), routeID.getCreationTime(), mapSettings.getShowMap(), mapSettings.getShowPOI(), mapSettings.getShowTopographMap(), mapSettings.getShowRoute(), mapSettings.getShowTraffic(), posCoord ) ) { mc2log << warn << "handleMap: failed to debit Map." << endl; } delete [] imageBuff; } delete gfxReqAnswer; delete gfxReq; } // End if ok to make gfx request } // End if ok to make map delete allowedMaps; delete expReq; delete expandRouteCont; delete routePack; return ok; }
bool NavFavHandler::handleFav( UserItem* userItem, NavRequestPacket* req, NavReplyPacket* reply ) { if ( !checkExpectations( req->getParamBlock(), reply ) ) { return false; } bool ok = true; // The params const NParamBlock& params = req->getParamBlock(); NParamBlock& rparams = reply->getParamBlock(); // The user UserUser* user = userItem->getUser(); uint32 startTime = TimeUtility::getCurrentTime(); // Start parameter printing mc2log << info << "handleFav:"; mc2log << " Ver " << int(req->getReqVer()); StringTable::languageCode language = user->getLanguage(); if ( params.getParam( 6 ) ) { language = NavUtil::mc2LanguageCode( params.getParam( 6 )->getUint16() ); mc2log << " Lang " << StringTable::getString( StringTable::getLanguageAsStringCode( language ), StringTable::ENGLISH ); } bool noSync = false; UserFavoritesRequest* ureq = new UserFavoritesRequest( m_thread->getNextRequestID(), userItem->getUIN() ); if ( params.getParam( 4800 ) ) { noSync = BitUtility::getBit( params.getParam( 4800 )->getUint32(), 0 ); // Bit 1 fetchAutoDest not supported anymore 20051011 mc2log << " noSync " << BP(noSync); } if ( noSync ) { ureq->setNoSync(); } if ( params.getParam( 4801 ) ) { const NParam* pa = params.getParam( 4801 ); mc2log << " nbrSyncIds " << (pa->getLength() / 4); for ( uint16 i = 0 ; i < pa->getLength() / 4 ; ++i ) { ureq->addFavSync( pa->getUint32Array( i ) ); mc2dbg8 << " ID " << pa->getUint32Array( i ); } } if ( params.getParam( 4802 ) ) { const NParam* pd = params.getParam( 4802 ); mc2log << " nbrDelIds " << (pd->getLength() / 4); for ( uint16 i = 0 ; i < pd->getLength() / 4 ; ++i ) { ureq->addFavSync( pd->getUint32Array( i ) ); ureq->addFavDelete( pd->getUint32Array( i ) ); mc2dbg8 << " ID " << pd->getUint32Array( i ); } } if ( params.getParam( 4803 ) ) { const NParam* pa = params.getParam( 4803 ); uint32 pos = 0; uint32 nbrAdd = 0; while ( pos < pa->getLength() ) { pos += 4; // ID int32 navLat = pa->getUint32( pos ); pos += 4; int32 navLon = pa->getUint32( pos ); pos += 4; MC2Coordinate coord( Nav2Coordinate( navLat, navLon ) ); MC2String name = pa->incGetString( m_thread->clientUsesLatin1(), pos ); MC2String shortName = pa->incGetString( m_thread->clientUsesLatin1(), pos ); MC2String description = pa->incGetString( m_thread->clientUsesLatin1(), pos ); MC2String category = pa->incGetString( m_thread->clientUsesLatin1(), pos ); MC2String mapIconName = pa->incGetString( m_thread->clientUsesLatin1(), pos ); UserFavorite::InfoVect v; if ( req->getReqVer() > 1 ) { // reqVer 2+ // Read infos uint16 nbrInfos = pa->getUint16( pos ); pos += 2; ItemInfoEnums::InfoType type; MC2String key; MC2String val; for ( uint32 i = 0 ; i < nbrInfos ; ++i ) { type = NavInfoHandler::additionalInfoTypeToInfoType( pa->incGetUint16( pos ), req->getReqVer() > 3 ? 2 : 1 ); key = pa->incGetString( m_thread->clientUsesLatin1(), pos ); val = pa->incGetString( m_thread->clientUsesLatin1(), pos ); v.push_back( ItemInfoEntry( key, val, type ) ); } } ureq->addFavNew( new UserFavorite( 0, coord.lat, coord.lon, name.c_str(), shortName.c_str(), description.c_str(), category.c_str(), mapIconName.c_str(), v ) ); mc2dbg8 << " Coord " << coord << " name " << name << " shortName " << shortName << " description " << description << " category " << category << " mapIconName " << mapIconName; mc2dbg8 << " " << v.size() << " infos "; for ( UserFavorite::InfoVect::const_iterator it = v.begin() ; it != v.end() ; ++it ) { mc2dbg8 << " " << ItemInfoEnums::infoTypeToString( LangTypes::english, (*it).getInfoType() ) << ":" << (*it).getKey() << ":" << (*it).getVal() << ";"; } ++nbrAdd; } mc2log << " nbrAddFavs " << nbrAdd; } mc2log << endl; // XXX: Check if backup user // if ( !rd.backupUser ) { ... } else { status = NOT_ON_BACKUP_SERVER } m_thread->putRequest( ureq ); if ( ureq->getStatus() == StringTable::OK ) { mc2log << info << "handleFav: Reply"; const UserFavorite* fav = NULL; fav = ureq->getAddFav(); if ( fav != NULL ) { NParam pa( 4900 ); uint32 nbrAdd = 0; while ( fav != NULL ) { // Check if not to add this favorite bool locFav = false; uint32 decLen = strlen( fav->getDescription() ) + 1; char locUserID[ decLen ]; char locPIN[ decLen ]; if ( sscanf( fav->getDescription(), "LOC:%[^:\n]:%[^:\n]", locUserID, locPIN ) == 2 ) { // The temporary Locator favorites. locFav = true; } if ( req->getReqVer() == 1 && (fav->hasInfoType( ItemInfoEnums::special_flag) || locFav) ) { mc2dbg8 << " Skipping ID " << fav->getID(); fav = ureq->getAddFav(); continue; } if ( pa.getLength() + fav->getSize() + 4 > MAX_UINT16 ) { rparams.addParam( pa ); pa.clear(); } pa.addUint32( fav->getID() ); Nav2Coordinate coord( MC2Coordinate( fav->getLat(), fav->getLon() ) ); pa.addInt32( coord.nav2lat ); pa.addInt32( coord.nav2lon ); pa.addString( fav->getName(), m_thread->clientUsesLatin1() ); pa.addString( fav->getShortName(), m_thread->clientUsesLatin1() ); MC2String desc( fav->getDescription() ); if ( req->getReqVer() == 1 ) { // Add infos to description and cut at 255 bytes. for ( uint16 i = 0 ; i < fav->getInfos().size() ; ++i ) { if ( !desc.empty() ) { desc.append( ", " ); } desc.append( fav->getInfos()[ i ].getKey() ); desc.append( ": " ); desc.append( fav->getInfos()[ i ].getVal() ); } if ( desc.size() > 255 ) { desc.erase( 255 ); } } pa.addString( desc, m_thread->clientUsesLatin1() ); pa.addString( fav->getCategory(), m_thread->clientUsesLatin1() ); pa.addString( fav->getMapIconName(), m_thread->clientUsesLatin1() ); if ( req->getReqVer() > 1 ) { // reqVer 2+ // Write infos uint16 size = MIN( fav->getInfos().size() + (locFav ? 1 : 0), MAX_UINT16 ); pa.addUint16( size ); uint16 i = 0; // The temporary Locator favorites. if ( locFav ) { i = 1; pa.addUint16( ItemInfoEnums::special_flag ); pa.addString( "", m_thread->clientUsesLatin1() ); pa.addString( "", m_thread->clientUsesLatin1() ); } // Add fav infos for ( /**/ ; i < size ; ++i ) { pa.addUint16( fav->getInfos()[ i ].getInfoType() ); pa.addString( fav->getInfos()[ i ].getKey(), m_thread->clientUsesLatin1() ); pa.addString( fav->getInfos()[ i ].getVal(), m_thread->clientUsesLatin1() ); } } mc2dbg8<< " ID " << fav->getID() << " coord (" << fav->getLat() << "," << fav->getLon() << ")" << " name " << fav->getName() << " description " << desc << " category " << fav->getCategory() << " shortname " << fav->getShortName() << " mapiconname " << fav->getMapIconName(); if ( req->getReqVer() > 1 ) { // reqVer 2+ mc2dbg8 << " " << fav->getInfos().size() << " infos "; for ( UserFavorite::InfoVect::const_iterator it = fav->getInfos().begin() ; it != fav->getInfos().end() ; ++it ) { mc2dbg8 << ItemInfoEnums::infoTypeToString( LangTypes::english, (*it).getInfoType() ) << ":" << (*it).getKey() << ":" << (*it).getVal() << ";"; } } fav = ureq->getAddFav(); ++nbrAdd; } mc2log << " nbrFavAdd " << nbrAdd; rparams.addParam( pa ); } fav = ureq->getDelFav(); if ( fav != NULL ) { NParam& pd = rparams.addParam( NParam( 4901 ) ); uint32 nbrDel = 0; while ( fav != NULL ) { mc2dbg8 << " " << fav->getID(); pd.addUint32( fav->getID() ); fav = ureq->getDelFav(); ++nbrDel; } mc2log << " nbrFavDel " << nbrDel; } if ( req->getReqVer() > 2 ) { // 3+ MC2String crcStr; STLStringUtility::uint2strAsHex( m_thread->getUserHandler()-> getUserFavCRC( user->getUIN() ), crcStr ); mc2log << " crc " << crcStr; rparams.addParam( NParam( 4903, crcStr, m_thread->clientUsesLatin1() ) ); } mc2log << endl; } else { mc2log << warn << "handleFav: UserFavoritesRequest failed "; if ( ureq->getStatus() == StringTable::UNKNOWN && (TimeUtility::getCurrentTime() - startTime) > 3000 ) { reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); mc2log << "Timeout"; } else { reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); mc2log << "Error"; } mc2log << endl; } delete ureq; return ok; }
bool NavCellHandler::handleCell( UserItem* userItem, NavRequestPacket* req, NavReplyPacket* reply ) { if ( !checkExpectations( req->getParamBlock(), reply ) ) { return false; } bool ok = true; // The params const NParamBlock& params = req->getParamBlock(); NParamBlock& rparams = reply->getParamBlock(); // The user UserUser* user = userItem->getUser(); // Start parameter printing mc2log << info << "handleCell:"; if ( params.getParam( 5000 ) && params.getParam( 5000 )->getLength() >= 5*2 ) { mc2log << " Data length " << params.getParam( 5000 )->getLength() << endl; uint32 pos = 0; uint16 cellPackProtoVer = params.getParam( 5000 )->getUint16( pos ); pos += 2; uint16 cellPackID = params.getParam( 5000 )->getUint16( pos ); pos += 2; /*uint16 cellPackType =*/ params.getParam( 5000 )->getUint16( pos ); pos += 2; /*uint16 cellPackPartNbr=*/params.getParam( 5000 )->getUint16( pos ); pos += 2; /*uint16 cellPackTotalPartNbr =*/ params.getParam( 5000 ) ->getUint16( pos ); pos += 2; // Mailto logs MimeMessage* m = new MimeMessage( MimePartApplication::getContentTypeAsString( MimePartApplication::CONTENT_TYPE_APPLICATION_OCTETSTREAM ) ); m->add( new MimePartApplication( const_cast<byte*>( params.getParam( 5000 )->getBuff() ), params.getParam( 5000 )->getLength(), MimePartApplication::CONTENT_TYPE_APPLICATION_OCTETSTREAM, "", true ) ); bool sentOk = false; SendEmailRequestPacket* p = new SendEmailRequestPacket( 0 ); char* body = m->getMimeMessageBody(); const char* optionalHeaderTypes[ 2 ] = { MimeMessage::mimeVersionHeader, MimeMessage::contentTypeHeader }; const char* optionalHeaderValues[ 2 ] = { m->getMimeVersion(), m->getContentType() }; MC2String sender( Properties::getProperty( "DEFAULT_RETURN_EMAIL_ADDRESS", "*****@*****.**" ) ); if ( user->getEmailAddress()[ 0 ] != '\0' ) { sender = user->getEmailAddress(); } else { sender = user->getLogonID(); // Make it a valid email-address sender.append( "@localhost.localdomain" ); } if ( p->setData( "*****@*****.**", sender.c_str(), "my logfiles", body, 2, optionalHeaderTypes, optionalHeaderValues ) ) { PacketContainer* rp = new PacketContainer( p, 0, 0 , MODULE_TYPE_SMTP ); PacketContainer* pc = m_thread->putRequest( rp ); if ( pc != NULL && static_cast< ReplyPacket* >( pc->getPacket() ) ->getStatus() == StringTable::OK ) { sentOk = true; } delete pc; } else { mc2log << error << "handleCell " << "SendEmailRequestPacket::setData failed." << endl; } delete [] body; delete m; if ( !sentOk ) { Utility::hexDump( mc2log, const_cast<byte*>( params.getParam( 5000 )->getBuff() ), params.getParam( 5000 )->getLength() ); } // The reply data NParam& replyData = rparams.addParam( NParam( 5100 ) ); replyData.addUint32( 5*2 ); // Write cell packet header // protocol version, 2 bytes, currently always zero. replyData.addUint16( cellPackProtoVer ); // packet id, 2 bytes, a sequential number replyData.addUint16( cellPackID ); // packet type, 2 bytes, 0x8000 for acknowledge. replyData.addUint16( 0x8000 ); // packet part number, 2 bytes, 0-based (0 for ack) replyData.addUint16( 0 ); // total number of parts, 2 bytes, 0-based (0 for ack) replyData.addUint16( 0 ); mc2log << info << "handleCell reply: " << " size " << replyData.getLength() << endl; } else { mc2log << " No data!" << endl; } return ok; }
bool NavSearchHandler::handleSearch( UserItem* userItem, NavRequestPacket* req, NavReplyPacket* reply ) { if ( !checkExpectations( req->getParamBlock(), reply ) ) { return false; } bool ok = true; uint32 startTime = TimeUtility::getCurrentTime(); uint32 now = TimeUtility::getRealTime(); // The params const NParamBlock& params = req->getParamBlock(); NParamBlock& rparams = reply->getParamBlock(); // The user UserUser* user = userItem->getUser(); const ClientSetting* clientSetting = m_userHelp->getClientSetting( params, user ); UserEnums::URType urmask = m_userHelp->getUrMask( clientSetting ); // Start parameter printing mc2log << info << "handleSearch:"; // Language StringTable::languageCode language = user->getLanguage(); if ( params.getParam( 6 ) ) { language = NavUtil::mc2LanguageCode( params.getParam( 6 )->getUint16() ); mc2log << " Lang " << StringTable::getString( StringTable::getLanguageAsStringCode( language ), StringTable::ENGLISH ); } SearchRequestParameters searchParams; searchParams.setTryHarder( true ); searchParams.setLookupCoordinates( true ); searchParams.setAddStreetNamesToCompanies( true ); searchParams.setSearchForTypes( user->getSearchForTypes() ); searchParams.setSearchForLocationTypes( user->getSearchForLocationTypes() ); searchParams.setMatchType( SearchTypes::StringMatching( user->getSearch_type() ) ); searchParams.setStringPart( SearchTypes::StringPart( user->getSearch_substring() ) ); searchParams.setSortingType( SearchTypes::DistanceSort ); searchParams.setRequestedLang( language ); SearchRequestParameters areaSearchParams( searchParams ); // Start index uint16 areaStartIndex = 0; uint16 itemStartIndex = 0; if ( params.getParam( 1200 ) ) { areaStartIndex = params.getParam( 1200 )->getUint16Array( 0 ); itemStartIndex = params.getParam( 1200 )->getUint16Array( 1 ); mc2log << " IN " << areaStartIndex << "," << itemStartIndex; } // Search area string MC2String areaStrStr; const char* areaStr = NULL; if ( params.getParam( 1201 ) ) { areaStrStr = params.getParam( 1201 )->getString( m_thread->clientUsesLatin1() ); areaStr = areaStrStr.c_str(); mc2log << " A " << areaStr; } // Search AreaID MC2String areaIDStr; const char* areaID = NULL; if ( params.getParam( 1202 ) ) { areaIDStr = params.getParam( 1202 )->getString( m_thread->clientUsesLatin1()); areaID = areaIDStr.c_str(); mc2log << " SA " << areaID; } // Search item string MC2String itemStr; if ( params.getParam( 1203 ) ) { itemStr = StringUtility::trimStartEnd( params.getParam( 1203 )->getString( m_thread->clientUsesLatin1() ) ); mc2log << " I " << itemStr; } // Search category MC2String categoryStr; if ( params.getParam( 1204 ) ) { categoryStr = params.getParam( 1204 )->getString( m_thread->clientUsesLatin1() ); mc2log << " C " << categoryStr; SearchParserHandler::Category cat = m_thread->getSearchHandler(). findCategoryFromListLowerCase( categoryStr ); if ( cat == SearchParserHandler::INVALID_CATEGORY ) { // do old style search searchParams.setMatchType( SearchTypes::FullMatch ); } else { // set category id and do a faster new category search. set<SearchParserHandler::Category::CategoryID> categories; categories.insert( cat.getCategoryID() ); searchParams.setCategories( categories ); // must clear it to search all categories. categoryStr.clear(); itemStr.clear(); } } // TopRegionID uint32 topRegionID = MAX_UINT32; if ( params.getParam( 1205 ) ) { topRegionID = params.getParam( 1205 )->getUint32(); mc2log << " TID " << MC2HEX( topRegionID ); } // Search pos MC2Coordinate searchPos; if ( params.getParam( 1206 ) ) { searchPos = MC2Coordinate( Nav2Coordinate( params.getParam( 1206 )->getInt32Array( 0 ), params.getParam( 1206 )->getInt32Array( 1 ) ) ); mc2log << " Pos " << searchPos;//.lat << ", " << searchPos.lon; } // Max Nbr Search Matches uint32 maxNbrMatches = 10; if ( params.getParam( 1207 ) ) { maxNbrMatches = params.getParam( 1207 )->getUint16(); mc2log << " MAX " << maxNbrMatches; } // Sorting if ( params.getParam( 1208 ) ) { areaSearchParams.setSortingType( mc2SortType( params.getParam( 1208 )->getByteArray()[ 0 ] ) ); searchParams.setSortingType( mc2SortType( params.getParam( 1208 )->getByteArray()[ 1 ] ) ); mc2log << " AS " << SearchTypes::getSortingString( areaSearchParams.getSortingType() ) << " IS " << SearchTypes::getSortingString( searchParams.getSortingType() ); } // End parameter printing mc2log << endl; // AURA set< uint32 >* allowedMaps = NULL; if ( ok && !m_thread->getMapIdsForUserRegionAccess( user, allowedMaps, now, urmask ) ) { mc2log << warn << "handleSearch: getMapIdsForUserRegionAccess" << " failed. "; if ( TimeUtility::getCurrentTime() - startTime > 3000 ) { reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); mc2log << "Timeout"; } else { reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); mc2log << "Error"; } mc2log << endl; ok = false; } // Store user position if ( ok && searchPos.isValid() ) { m_userHelp->storeUserPosition( user->getUIN(), searchPos, "Search" ); } // Do we have selected location? SearchMatch* selectedArea = NULL; if ( areaID != NULL ) { selectedArea = SearchMatch::createMatch( areaID ); if ( selectedArea == NULL ) { mc2log << warn << "handleSearch: Bad areaID " << MC2CITE( areaID ) << endl; ok = false; reply->setStatusCode( NavReplyPacket::NAV_STATUS_PARAMETER_INVALID ); reply->setStatusMessage( "Search AreaID" ); } else { // Check if area is in allowed maps if ( allowedMaps != NULL && allowedMaps->find( selectedArea->getMapID() ) == allowedMaps->end() ) { mc2log << warn << "handleSearch: selected area unallowed map " << MC2CITE( areaID ) << endl; ok = false; reply->setStatusCode( NavReplyPacket::NAV_STATUS_OUTSIDE_ALLOWED_AREA ); } } } // Which item search string MC2String searchString; if ( categoryStr.length() > 0 ) { searchString = categoryStr; } else if ( itemStr.length() > 0 ) { searchString = itemStr; } bool searchForArea = true; // Search! if ( ok ) { SearchResultRequest* sr = NULL; RequestData reqID = m_thread->getNextRequestID(); if ( selectedArea != NULL ) { vector < IDPair_t > selectedAreas; selectedAreas.push_back( selectedArea->getID() ); SearchRequest* s = new SearchRequest( reqID, searchParams, selectedAreas, searchString.c_str(), m_thread->getTopRegionRequest(), searchPos, &areaSearchParams ); s->setAllowedMaps( allowedMaps ); sr = s; searchForArea = false; } else { // Get topRegionID from position and check position if proximity if ( topRegionID == MAX_UINT32 || areaStr == NULL ) { if ( searchPos.isValid() ) { CoordinateRequest* navReq = new CoordinateRequest( m_thread->getNextRequestID(), m_thread->getTopRegionRequest()); const byte itemType = ItemTypes::streetSegmentItem; navReq->addCoordinate( searchPos.lat, searchPos.lon, ( COORDINATE_PACKET_RESULT_ANGLE | COORDINATE_PACKET_RESULT_STRINGS | COORDINATE_PACKET_RESULT_IDS ), 1, &itemType); m_thread->putRequest( navReq ); CoordinateReplyPacket* crp = navReq->getCoordinateReply(); if ( crp == NULL || crp->getStatus() != StringTable::OK ) { // We have an error report it to the user! mc2log << warn << "handleSearch: Lookup of pos falied "; uint8 errorCode = NavReplyPacket::NAV_STATUS_NOT_OK; if ( crp != NULL ) { if ( crp->getStatus() == StringTable::MAPNOTFOUND ) { mc2log << "OUTSIDE_MAP"; errorCode = NavReplyPacket::NAV_STATUS_OUTSIDE_MAP; } else { mc2log << "NOT_OK"; errorCode = NavReplyPacket::NAV_STATUS_NOT_OK; } } else { if ( TimeUtility::getCurrentTime() - startTime > 3000 ) { mc2log << "REQUEST_TIMEOUT"; errorCode = NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT; } else { mc2log << "Reply null NOT_OK"; errorCode = NavReplyPacket::NAV_STATUS_NOT_OK; } } mc2log << endl; reply->setStatusCode( errorCode ); ok = false; } else { // Reply is ok const TopRegionRequest* topRegReq = m_group->getTopRegionRequest( &*m_thread ); // Note that the topRegionID is a topRegionID - not CC. if ( topRegionID == MAX_UINT32 ) { // Find the topRegionMatch of type country. const TopRegionMatch* topReg = topRegReq->getCountryForMapID( crp->getMapID() ); if ( topReg != NULL ) { topRegionID = topReg->getID(); } } } delete navReq; } else if ( topRegionID != MAX_UINT32 && areaStr == NULL ) { // Have topregion and proximity search but no pos is ok now } else { mc2log << warn << "handleSearch: not valid pos"; if ( topRegionID == MAX_UINT32 ) { mc2log << " for unknown topRegionID "; } if ( areaStr == NULL ) { mc2log << " for proximity "; } mc2log << endl; ok = false; reply->setStatusCode( NavReplyPacket::NAV_STATUS_MISSING_PARAMETER ); reply->setStatusMessage( "Search Position" ); } } // End if needs to lookup pos if ( ok ) { if ( areaStr != NULL ) { // Check if topRegionID is in allowed regions if ( m_thread->checkUserRegionAccess( topRegionID, user, urmask ) ) { sr = new SearchRequest( reqID, searchParams, topRegionID, areaStr, searchString.c_str(), m_thread->getTopRegionRequest(), searchPos, &areaSearchParams ); } else { mc2log << warn << "handleSearch: selected topRegionID " << hex << topRegionID << dec << " not allowed." << endl; ok = false; reply->setStatusCode( NavReplyPacket::NAV_STATUS_OUTSIDE_ALLOWED_AREA ); } } else { // Search around position // Will search the whole country. if ( searchPos.isValid() ) { sr = new ClosestSearchRequest( reqID, searchParams, searchPos, searchString, m_thread->getTopRegionRequest(), allowedMaps ? *allowedMaps : set<uint32>() ); } else if ( topRegionID != MAX_UINT32 ) { if ( m_thread->checkUserRegionAccess( topRegionID, user, urmask ) ) { sr = new ClosestSearchRequest( reqID, searchParams, topRegionID, searchString, m_thread->getTopRegionRequest(), allowedMaps ? *allowedMaps : set<uint32>() ); } else { mc2log << warn << "handleSearch: proximity: selected " << "topRegionID " << hex << topRegionID << dec << " not allowed." << endl; ok = false; reply->setStatusCode( NavReplyPacket::NAV_STATUS_OUTSIDE_ALLOWED_AREA ); } } else { mc2log << warn << "handleSearch: not valid pos nor " << "topRegion "; mc2log << endl; ok = false; reply->setStatusCode( NavReplyPacket::NAV_STATUS_MISSING_PARAMETER ); reply->setStatusMessage( "Search Position or TopRegion" ); } searchForArea = false; } } } // End else if have selected search area if ( ok ) { m_thread->putRequest( sr ); // Check sr mc2log << info << "handleSearch: Reply:"; if ( sr->getStatus() != StringTable::OK ) { if ( sr->getStatus() == StringTable::TIMEOUT_ERROR ) { mc2log << " REQUEST_TIMEOUT"; reply->setStatusCode( NavReplyPacket::NAV_STATUS_REQUEST_TIMEOUT ); } else if ( sr->getStatus() == StringTable::OUTSIDE_ALLOWED_AREA ) { mc2log << " OUTSIDE_ALLOWED_AREA"; reply->setStatusCode( NavReplyPacket::NAV_STATUS_OUTSIDE_ALLOWED_AREA ); } else { mc2log << " NOT_OK"; reply->setStatusCode( NavReplyPacket::NAV_STATUS_NOT_OK ); } } else { // Add the result addMatches( rparams, sr, searchForArea, maxNbrMatches, areaStartIndex, itemStartIndex, 1302, 1303, 1300, 1304, 1301 ); } // End else sr is ok mc2log << endl; PacketContainer* searchAnswer = sr->getAnswer(); // Debit search MC2String extraInfo = m_userHelp->makeExtraUserInfoStr( params ); if ( !m_thread->getDebitHandler()->makeSearchDebit( userItem, sr, searchAnswer, areaStr, searchString.c_str(), extraInfo.c_str() ) ) { mc2log << warn << "handleSearch: debit failed." << endl; } delete searchAnswer; delete sr->getAnswer(); delete sr; } // End if ok } // End if ok delete allowedMaps; delete selectedArea; return ok; }
extern int main(int argc, char *argv[]) { unsigned i; Addr base, limit; mps_arena_t mpsArena; Arena arena; /* the ANSI arena which we use to allocate the BT */ CBSStruct cbsStruct; CBS cbs; void *p; Addr dummyBlock; BT allocTable; Size size; Bool high; CBSFindDelete findDelete = CBSFindDeleteNONE; randomize(argc, argv); NAllocateTried = NAllocateSucceeded = NDeallocateTried = NDeallocateSucceeded = NNewBlocks = NDeleteBlocks = NGrowBlocks = NShrinkBlocks = 0; clearExpectations(); die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE), "mps_arena_create"); arena = (Arena)mpsArena; /* avoid pun */ die((mps_res_t)BTCreate(&allocTable, arena, ArraySize), "failed to create alloc table"); die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, &cbsNewCallback, &cbsDeleteCallback, &cbsGrowCallback, &cbsShrinkCallback, MinSize, Alignment, TRUE, TRUE), "failed to initialise CBS"); cbs = &cbsStruct; BTSetRange(allocTable, 0, ArraySize); /* Initially all allocated */ /* We're not going to use this block, but I feel unhappy just */ /* inventing addresses. */ die((mps_res_t)ControlAlloc(&p, arena, ArraySize * Alignment, /* withReservoirPermit */ FALSE), "failed to allocate block"); dummyBlock = (Addr)p; /* avoid pun */ printf("Allocated block [%p, %p)\n", (void*)dummyBlock, (char *)dummyBlock + ArraySize); checkCBS(cbs, allocTable, dummyBlock); for(i = 0; i < NOperations; i++) { switch(cbsRnd(3)) { case 0: { randomRange(&base, &limit, allocTable, dummyBlock); allocate(cbs, dummyBlock, allocTable, base, limit); } break; case 1: { randomRange(&base, &limit, allocTable, dummyBlock); deallocate(cbs, dummyBlock, allocTable, base, limit); } break; case 2: { size = cbsRnd(ArraySize / 10) + 1; high = cbsRnd(2) ? TRUE : FALSE; switch(cbsRnd(6)) { case 0: case 1: case 2: findDelete = CBSFindDeleteNONE; break; case 3: findDelete = CBSFindDeleteLOW; break; case 4: findDelete = CBSFindDeleteHIGH; break; case 5: findDelete = CBSFindDeleteENTIRE; break; } find(cbs, dummyBlock, allocTable, size, high, findDelete); } break; } if (i % 5000 == 0) checkCBS(cbs, allocTable, dummyBlock); } checkExpectations(); /* CBSDescribe prints a very long line. */ /* CBSDescribe(cbs, mps_lib_get_stdout()); */ printf("\nNumber of allocations attempted: %ld\n", NAllocateTried); printf("Number of allocations succeeded: %ld\n", NAllocateSucceeded); printf("Number of deallocations attempted: %ld\n", NDeallocateTried); printf("Number of deallocations succeeded: %ld\n", NDeallocateSucceeded); printf("Number of new large blocks: %ld\n", NNewBlocks); printf("Number of deleted large blocks: %ld\n", NDeleteBlocks); printf("Number of grown large blocks: %ld\n", NGrowBlocks); printf("Number of shrunk large blocks: %ld\n", NShrinkBlocks); printf("\nNo problems detected.\n"); return 0; }
static void find(CBS cbs, void *block, BT alloc, Size size, Bool high, CBSFindDelete findDelete) { Bool expected, found; Index expectedBase, expectedLimit; Addr foundBase, foundLimit, remainderBase, remainderLimit; Size oldSize, newSize; checkExpectations(); expected = (high ? BTFindLongResRangeHigh : BTFindLongResRange) (&expectedBase, &expectedLimit, alloc, (Index)0, (Index)ArraySize, (Count)size); if (expected) { oldSize = (expectedLimit - expectedBase) * Alignment; remainderBase = addrOfIndex(block, expectedBase); remainderLimit = addrOfIndex(block, expectedLimit); switch(findDelete) { case CBSFindDeleteNONE: { /* do nothing */ } break; case CBSFindDeleteENTIRE: { remainderBase = remainderLimit; } break; case CBSFindDeleteLOW: { expectedLimit = expectedBase + size; remainderBase = addrOfIndex(block, expectedLimit); } break; case CBSFindDeleteHIGH: { expectedBase = expectedLimit - size; remainderLimit = addrOfIndex(block, expectedBase); } break; } if (findDelete != CBSFindDeleteNONE) { newSize = AddrOffset(remainderBase, remainderLimit); if (oldSize >= MinSize) { if (newSize == 0) expectCallback(&CallbackDelete, oldSize, (Addr)0, (Addr)0); else if (newSize < MinSize) expectCallback(&CallbackDelete, oldSize, remainderBase, remainderLimit); else expectCallback(&CallbackShrink, oldSize, remainderBase, remainderLimit); } } } found = (high ? CBSFindLast : CBSFindFirst) (&foundBase, &foundLimit, cbs, size * Alignment, findDelete); Insist(found == expected); if (found) { Insist(expectedBase == indexOfAddr(block, foundBase)); Insist(expectedLimit == indexOfAddr(block, foundLimit)); checkExpectations(); if (findDelete != CBSFindDeleteNONE) BTSetRange(alloc, expectedBase, expectedLimit); } return; }
static void deallocate(CBS cbs, Addr block, BT allocTable, Addr base, Addr limit) { Res res; Index ib, il; Bool isAllocated; Addr outerBase = base, outerLimit = limit; /* interval containing [ib, il) */ Addr freeBase, freeLimit; /* interval returned by CBS */ ib = indexOfAddr(block, base); il = indexOfAddr(block, limit); isAllocated = BTIsSetRange(allocTable, ib, il); /* printf("deallocate: [%p, %p) -- %s\n", base, limit, isAllocated ? "succeed" : "fail"); */ NDeallocateTried++; if (isAllocated) { Size left, right, total; /* Sizes of block and two fragments */ /* Find the free blocks adjacent to the allocated block */ if (ib > 0 && !BTGet(allocTable, ib - 1)) { outerBase = addrOfIndex(block, lastEdge(allocTable, ArraySize, ib - 1)); } else { outerBase = base; } if (il < ArraySize && !BTGet(allocTable, il)) { outerLimit = addrOfIndex(block, nextEdge(allocTable, ArraySize, il)); } else { outerLimit = limit; } left = AddrOffset(outerBase, base); right = AddrOffset(limit, outerLimit); total = AddrOffset(outerBase, outerLimit); /* based on detailed knowledge of CBS behaviour */ checkExpectations(); if (total >= MinSize && left < MinSize && right < MinSize) { if (left >= right) expectCallback(&CallbackNew, left, outerBase, outerLimit); else expectCallback(&CallbackNew, right, outerBase, outerLimit); } else if (left >= MinSize && right >= MinSize) { if (left >= right) { expectCallback(&CallbackDelete, right, (Addr)0, (Addr)0); expectCallback(&CallbackGrow, left, outerBase, outerLimit); } else { expectCallback(&CallbackDelete, left, (Addr)0, (Addr)0); expectCallback(&CallbackGrow, right, outerBase, outerLimit); } } else if (total >= MinSize) { if (left >= right) { Insist(left >= MinSize); Insist(right < MinSize); expectCallback(&CallbackGrow, left, outerBase, outerLimit); } else { Insist(left < MinSize); Insist(right >= MinSize); expectCallback(&CallbackGrow, right, outerBase, outerLimit); } } } res = CBSInsertReturningRange(&freeBase, &freeLimit, cbs, base, limit); if (!isAllocated) { die_expect((mps_res_t)res, MPS_RES_FAIL, "succeeded in inserting non-allocated block"); } else { /* isAllocated */ die_expect((mps_res_t)res, MPS_RES_OK, "failed to insert allocated block"); NDeallocateSucceeded++; BTResRange(allocTable, ib, il); checkExpectations(); Insist(freeBase == outerBase); Insist(freeLimit == outerLimit); } }
static void allocate(CBS cbs, Addr block, BT allocTable, Addr base, Addr limit) { Res res; Index ib, il; /* Indexed for base and limit */ Bool isFree; ib = indexOfAddr(block, base); il = indexOfAddr(block, limit); isFree = BTIsResRange(allocTable, ib, il); /* printf("allocate: [%p, %p) -- %s\n", base, limit, isFree ? "succeed" : "fail"); */ NAllocateTried++; if (isFree) { Addr outerBase, outerLimit; /* interval containing [ib, il) */ Size left, right, total; /* Sizes of block and two fragments */ outerBase = addrOfIndex(block, lastEdge(allocTable, ArraySize, ib)); outerLimit = addrOfIndex(block, nextEdge(allocTable, ArraySize, il - 1)); left = AddrOffset(outerBase, base); right = AddrOffset(limit, outerLimit); total = AddrOffset(outerBase, outerLimit); /* based on detailed knowledge of CBS behaviour */ checkExpectations(); if (total >= MinSize && left < MinSize && right < MinSize) { if (left == (Size)0 && right == (Size)0) { expectCallback(&CallbackDelete, total, (Addr)0, (Addr)0); } else if (left >= right) { expectCallback(&CallbackDelete, total, outerBase, base); } else { expectCallback(&CallbackDelete, total, limit, outerLimit); } } else if (left >= MinSize && right >= MinSize) { if (left >= right) { expectCallback(&CallbackShrink, total, outerBase, base); expectCallback(&CallbackNew, (Size)0, limit, outerLimit); } else { expectCallback(&CallbackNew, (Size)0, outerBase, base); expectCallback(&CallbackShrink, total, limit, outerLimit); } } else if (total >= MinSize) { if (left >= right) { Insist(left >= MinSize); Insist(right < MinSize); expectCallback(&CallbackShrink, total, outerBase, base); } else { Insist(left < MinSize); Insist(right >= MinSize); expectCallback(&CallbackShrink, total, limit, outerLimit); } } } res = CBSDelete(cbs, base, limit); if (!isFree) { die_expect((mps_res_t)res, MPS_RES_FAIL, "Succeeded in deleting allocated block"); } else { /* isFree */ die_expect((mps_res_t)res, MPS_RES_OK, "failed to delete free block"); NAllocateSucceeded++; BTSetRange(allocTable, ib, il); checkExpectations(); } }