interface.cpp 241 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871
  1. /*
  2. * PROGRAM: JRD Remote Interface
  3. * MODULE: interface.cpp
  4. * DESCRIPTION: User visible entrypoints remote interface
  5. *
  6. * The contents of this file are subject to the Interbase Public
  7. * License Version 1.0 (the "License"); you may not use this file
  8. * except in compliance with the License. You may obtain a copy
  9. * of the License at http://www.Inprise.com/IPL.html
  10. *
  11. * Software distributed under the License is distributed on an
  12. * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  13. * or implied. See the License for the specific language governing
  14. * rights and limitations under the License.
  15. *
  16. * The Original Code was created by Inprise Corporation
  17. * and its predecessors. Portions created by Inprise Corporation are
  18. * Copyright (C) Inprise Corporation.
  19. *
  20. * All Rights Reserved.
  21. * Contributor(s): ______________________________________.
  22. *
  23. * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "Ultrix" port
  24. *
  25. * 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "MPEXL" port
  26. * 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "DecOSF" port
  27. *
  28. * 2002.10.29 Sean Leyne - Removed support for obsolete IPX/SPX Protocol
  29. * 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
  30. *
  31. */
  32. #include "firebird.h"
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include "../remote/remote.h"
  37. #include "../common/gdsassert.h"
  38. #include "../common/isc_proto.h"
  39. #include <stdarg.h>
  40. #ifndef NO_NFS
  41. #include <sys/param.h>
  42. #endif
  43. #include "ibase.h"
  44. #include "../common/ThreadStart.h"
  45. #include "../jrd/license.h"
  46. #include "../remote/inet_proto.h"
  47. #include "../remote/merge_proto.h"
  48. #include "../remote/parse_proto.h"
  49. #include "../remote/remot_proto.h"
  50. #include "../remote/proto_proto.h"
  51. #include "../common/cvt.h"
  52. #include "../yvalve/gds_proto.h"
  53. #include "../common/isc_f_proto.h"
  54. #include "../common/classes/ClumpletWriter.h"
  55. #include "../common/classes/BatchCompletionState.h"
  56. #include "../common/config/config.h"
  57. #include "../common/utils_proto.h"
  58. #include "../common/classes/DbImplementation.h"
  59. #include "../common/Auth.h"
  60. #include "../common/classes/GetPlugins.h"
  61. #include "firebird/Interface.h"
  62. #include "../common/StatementMetadata.h"
  63. #include "../common/IntlParametersBlock.h"
  64. #include "../common/status.h"
  65. #include "../common/db_alias.h"
  66. #include "../common/classes/auto.h"
  67. #include "../auth/SecurityDatabase/LegacyClient.h"
  68. #include "../auth/SecureRemotePassword/client/SrpClient.h"
  69. #include "../auth/trusted/AuthSspi.h"
  70. #include "../plugins/crypt/arc4/Arc4.h"
  71. #include "BlrFromMessage.h"
  72. #include "../dsql/DsqlBatch.h"
  73. #ifdef HAVE_UNISTD_H
  74. #include <unistd.h>
  75. #endif
  76. #ifdef WIN_NT
  77. #include <process.h>
  78. #endif
  79. #if defined(WIN_NT)
  80. #include "../common/isc_proto.h"
  81. #include "../remote/os/win32/xnet_proto.h"
  82. #endif
  83. const char* const PROTOCOL_INET = "inet";
  84. const char* const PROTOCOL_INET4 = "inet4";
  85. const char* const PROTOCOL_INET6 = "inet6";
  86. #ifdef WIN_NT
  87. const char* const PROTOCOL_XNET = "xnet";
  88. #endif
  89. const char* const INET_SEPARATOR = "/";
  90. const char* const INET_LOCALHOST = "localhost";
  91. using namespace Firebird;
  92. namespace {
  93. void handle_error(ISC_STATUS code)
  94. {
  95. Arg::Gds(code).raise();
  96. }
  97. template <typename T>
  98. inline void CHECK_HANDLE(T* blk, ISC_STATUS error)
  99. {
  100. if (!blk || !blk->checkHandle())
  101. {
  102. handle_error(error);
  103. }
  104. }
  105. inline void CHECK_LENGTH(rem_port* port, size_t length)
  106. {
  107. if (length > MAX_USHORT && port->port_protocol < PROTOCOL_VERSION13)
  108. status_exception::raise(Arg::Gds(isc_imp_exc) << Arg::Gds(isc_blktoobig));
  109. }
  110. class SaveString
  111. {
  112. public:
  113. SaveString(cstring& toSave, ULONG newLength, UCHAR* newBuffer)
  114. : ptr(&toSave),
  115. oldValue(*ptr)
  116. {
  117. ptr->cstr_address = newBuffer;
  118. ptr->cstr_allocated = newLength;
  119. }
  120. ~SaveString()
  121. {
  122. *ptr = oldValue;
  123. }
  124. private:
  125. cstring* ptr;
  126. cstring oldValue;
  127. };
  128. class ClientPortsCleanup : public PortsCleanup
  129. {
  130. public:
  131. ClientPortsCleanup() :
  132. PortsCleanup()
  133. {}
  134. explicit ClientPortsCleanup(MemoryPool& p) :
  135. PortsCleanup(p)
  136. {}
  137. void closePort(rem_port* port) override;
  138. void delay() override
  139. {
  140. Thread::sleep(50);
  141. }
  142. };
  143. GlobalPtr<ClientPortsCleanup> outPorts;
  144. }
  145. namespace Remote {
  146. // Provider stuff
  147. class Attachment;
  148. class Statement;
  149. class Blob final : public RefCntIface<IBlobImpl<Blob, CheckStatusWrapper> >
  150. {
  151. public:
  152. // IBlob implementation
  153. int release() override;
  154. void getInfo(CheckStatusWrapper* status,
  155. unsigned int itemsLength, const unsigned char* items,
  156. unsigned int bufferLength, unsigned char* buffer) override;
  157. int getSegment(CheckStatusWrapper* status, unsigned int bufferLength,
  158. void* buffer, unsigned int* segmentLength) override;
  159. void putSegment(CheckStatusWrapper* status, unsigned int length, const void* buffer) override;
  160. void cancel(CheckStatusWrapper* status) override;
  161. void close(CheckStatusWrapper* status) override;
  162. int seek(CheckStatusWrapper* status, int mode, int offset) override; // returns position
  163. void deprecatedCancel(Firebird::CheckStatusWrapper* status) override;
  164. void deprecatedClose(Firebird::CheckStatusWrapper* status) override;
  165. public:
  166. explicit Blob(Rbl* handle)
  167. : blob(handle)
  168. {
  169. blob->rbl_self = &blob;
  170. }
  171. private:
  172. void freeClientData(CheckStatusWrapper* status, bool force = false);
  173. void internalCancel(Firebird::CheckStatusWrapper* status);
  174. void internalClose(Firebird::CheckStatusWrapper* status);
  175. Rbl* blob;
  176. };
  177. int Blob::release()
  178. {
  179. if (--refCounter != 0)
  180. {
  181. return 1;
  182. }
  183. if (blob)
  184. {
  185. LocalStatus ls;
  186. CheckStatusWrapper status(&ls);
  187. freeClientData(&status, true);
  188. }
  189. delete this;
  190. return 0;
  191. }
  192. class Transaction final : public RefCntIface<ITransactionImpl<Transaction, CheckStatusWrapper> >
  193. {
  194. public:
  195. // ITransaction implementation
  196. int release() override;
  197. void getInfo(CheckStatusWrapper* status,
  198. unsigned int itemsLength, const unsigned char* items,
  199. unsigned int bufferLength, unsigned char* buffer) override;
  200. void prepare(CheckStatusWrapper* status,
  201. unsigned int msg_length = 0, const unsigned char* message = 0) override;
  202. void commit(CheckStatusWrapper* status) override;
  203. void commitRetaining(CheckStatusWrapper* status) override;
  204. void rollback(CheckStatusWrapper* status) override;
  205. void rollbackRetaining(CheckStatusWrapper* status) override;
  206. void disconnect(CheckStatusWrapper* status) override;
  207. ITransaction* join(CheckStatusWrapper* status, ITransaction* tra) override;
  208. Transaction* validate(CheckStatusWrapper* status, IAttachment* attachment) override;
  209. Transaction* enterDtc(CheckStatusWrapper* status) override;
  210. void deprecatedCommit(Firebird::CheckStatusWrapper* status) override;
  211. void deprecatedRollback(Firebird::CheckStatusWrapper* status) override;
  212. void deprecatedDisconnect(Firebird::CheckStatusWrapper* status) override;
  213. public:
  214. Transaction(Rtr* handle, Attachment* a)
  215. : remAtt(a),
  216. transaction(handle)
  217. {
  218. transaction->rtr_self = &transaction;
  219. }
  220. Rtr* getTransaction()
  221. {
  222. return transaction;
  223. }
  224. void clear()
  225. {
  226. transaction = NULL;
  227. }
  228. private:
  229. Transaction(Transaction* from)
  230. : remAtt(from->remAtt),
  231. transaction(from->transaction)
  232. { }
  233. void freeClientData(CheckStatusWrapper* status, bool force = false);
  234. void internalCommit(Firebird::CheckStatusWrapper* status);
  235. void internalRollback(Firebird::CheckStatusWrapper* status);
  236. void internalDisconnect(Firebird::CheckStatusWrapper* status);
  237. Attachment* remAtt;
  238. Rtr* transaction;
  239. };
  240. int Transaction::release()
  241. {
  242. if (--refCounter != 0)
  243. return 1;
  244. if (transaction)
  245. {
  246. LocalStatus ls;
  247. CheckStatusWrapper status(&ls);
  248. freeClientData(&status, true); // ASF: Rollback - is this correct for reconnected transactions?
  249. }
  250. delete this;
  251. return 0;
  252. }
  253. class ResultSet final : public RefCntIface<IResultSetImpl<ResultSet, CheckStatusWrapper> >
  254. {
  255. public:
  256. // IResultSet implementation
  257. int release() override;
  258. int fetchNext(CheckStatusWrapper* status, void* message) override;
  259. int fetchPrior(CheckStatusWrapper* status, void* message) override;
  260. int fetchFirst(CheckStatusWrapper* status, void* message) override;
  261. int fetchLast(CheckStatusWrapper* status, void* message) override;
  262. int fetchAbsolute(CheckStatusWrapper* status, int position, void* message) override;
  263. int fetchRelative(CheckStatusWrapper* status, int offset, void* message) override;
  264. FB_BOOLEAN isEof(CheckStatusWrapper* status) override;
  265. FB_BOOLEAN isBof(CheckStatusWrapper* status) override;
  266. IMessageMetadata* getMetadata(CheckStatusWrapper* status) override;
  267. void close(CheckStatusWrapper* status) override;
  268. void deprecatedClose(CheckStatusWrapper* status) override;
  269. void setDelayedOutputFormat(CheckStatusWrapper* status, IMessageMetadata* format) override;
  270. void getInfo(CheckStatusWrapper* status,
  271. unsigned int itemsLength, const unsigned char* items,
  272. unsigned int bufferLength, unsigned char* buffer) override;
  273. ResultSet(Statement* s, IMessageMetadata* outFmt, unsigned f)
  274. : stmt(s), flags(f), tmpStatement(false), delayedFormat(outFmt == DELAYED_OUT_FORMAT)
  275. {
  276. if (!delayedFormat)
  277. outputFormat = outFmt;
  278. }
  279. private:
  280. bool fetch(CheckStatusWrapper* status, void* message, P_FETCH operation, int position = 0);
  281. void releaseStatement();
  282. void freeClientData(CheckStatusWrapper* status, bool force = false);
  283. void internalClose(CheckStatusWrapper* status);
  284. Statement* stmt;
  285. const unsigned flags;
  286. RefPtr<IMessageMetadata> outputFormat;
  287. public:
  288. bool tmpStatement, delayedFormat;
  289. };
  290. int ResultSet::release()
  291. {
  292. if (--refCounter != 0)
  293. return 1;
  294. if (stmt)
  295. {
  296. LocalStatus ls;
  297. CheckStatusWrapper status(&ls);
  298. freeClientData(&status, true);
  299. }
  300. delete this;
  301. return 0;
  302. }
  303. class Batch final : public RefCntIface<IBatchImpl<Batch, CheckStatusWrapper> >
  304. {
  305. public:
  306. static const ULONG DEFER_BATCH_LIMIT = 64;
  307. Batch(Statement* s, IMessageMetadata* inFmt, unsigned parLength, const unsigned char* par);
  308. // IBatch implementation
  309. int release() override;
  310. void add(Firebird::CheckStatusWrapper* status, unsigned count, const void* inBuffer) override;
  311. void addBlob(Firebird::CheckStatusWrapper* status, unsigned length, const void* inBuffer, ISC_QUAD* blobId,
  312. unsigned parLength, const unsigned char* par) override;
  313. void appendBlobData(Firebird::CheckStatusWrapper* status, unsigned length, const void* inBuffer) override;
  314. void addBlobStream(Firebird::CheckStatusWrapper* status, unsigned length, const void* inBuffer) override;
  315. void registerBlob(Firebird::CheckStatusWrapper* status, const ISC_QUAD* existingBlob, ISC_QUAD* blobId) override;
  316. Firebird::IBatchCompletionState* execute(Firebird::CheckStatusWrapper* status, Firebird::ITransaction* transaction) override;
  317. void cancel(Firebird::CheckStatusWrapper* status) override;
  318. unsigned getBlobAlignment(Firebird::CheckStatusWrapper* status) override;
  319. void setDefaultBpb(Firebird::CheckStatusWrapper* status, unsigned parLength, const unsigned char* par) override;
  320. Firebird::IMessageMetadata* getMetadata(Firebird::CheckStatusWrapper* status) override;
  321. void close(Firebird::CheckStatusWrapper* status) override;
  322. void deprecatedClose(Firebird::CheckStatusWrapper* status) override;
  323. void getInfo(CheckStatusWrapper* status,
  324. unsigned int itemsLength, const unsigned char* items,
  325. unsigned int bufferLength, unsigned char* buffer) override;
  326. private:
  327. void freeClientData(CheckStatusWrapper* status, bool force = false);
  328. void internalClose(Firebird::CheckStatusWrapper* status);
  329. void releaseStatement();
  330. void setServerInfo();
  331. void cleanup()
  332. {
  333. if (blobPolicy != BLOB_NONE)
  334. blobStream = blobStreamBuffer;
  335. sizePointer = nullptr;
  336. messageStream = 0;
  337. }
  338. void genBlobId(ISC_QUAD* blobId)
  339. {
  340. if (++genId.gds_quad_low == 0)
  341. ++genId.gds_quad_high;
  342. memcpy(blobId, &genId, sizeof(genId));
  343. }
  344. bool batchHasData()
  345. {
  346. return batchActive;
  347. }
  348. // working with message stream buffer
  349. void putMessageData(ULONG count, const void* p)
  350. {
  351. fb_assert(messageStreamBuffer);
  352. const UCHAR* ptr = reinterpret_cast<const UCHAR*>(p);
  353. while(count)
  354. {
  355. ULONG remainSpace = messageBufferSize - messageStream;
  356. ULONG step = MIN(count, remainSpace);
  357. if (step == messageBufferSize)
  358. {
  359. // direct packet sent
  360. sendMessagePacket(step, ptr, false);
  361. }
  362. else
  363. {
  364. // use buffer
  365. memcpy(&messageStreamBuffer[messageStream * alignedSize], ptr, step * alignedSize);
  366. messageStream += step;
  367. if (messageStream == messageBufferSize)
  368. {
  369. sendMessagePacket(messageBufferSize, messageStreamBuffer, false);
  370. messageStream = 0;
  371. }
  372. }
  373. count -= step;
  374. ptr += step * alignedSize;
  375. }
  376. }
  377. // working with blob stream buffer
  378. void newBlob()
  379. {
  380. setServerInfo();
  381. alignBlobBuffer(blobAlign);
  382. fb_assert(blobStream - blobStreamBuffer <= blobBufferSize);
  383. ULONG space = blobBufferSize - (blobStream - blobStreamBuffer);
  384. if (space < Rsr::BatchStream::SIZEOF_BLOB_HEAD)
  385. {
  386. sendBlobPacket(blobStream - blobStreamBuffer, blobStreamBuffer, false);
  387. blobStream = blobStreamBuffer;
  388. }
  389. }
  390. void alignBlobBuffer(unsigned alignment, ULONG* bs = NULL)
  391. {
  392. fb_assert(alignment);
  393. ULONG align = FB_ALIGN(blobStream, alignment) - blobStream;
  394. if (bs)
  395. *bs += align;
  396. FB_UINT64 zeroFill = 0;
  397. putBlobData(align, &zeroFill);
  398. }
  399. void putBlobData(ULONG size, const void* p)
  400. {
  401. fb_assert(blobStreamBuffer);
  402. const UCHAR* ptr = reinterpret_cast<const UCHAR*>(p);
  403. while(size)
  404. {
  405. ULONG space = blobBufferSize - (blobStream - blobStreamBuffer);
  406. ULONG step = MIN(size, space);
  407. if (step == blobBufferSize)
  408. {
  409. // direct packet sent
  410. sendBlobPacket(blobBufferSize, ptr, false);
  411. }
  412. else
  413. {
  414. // use buffer
  415. memcpy(blobStream, ptr, step);
  416. blobStream += step;
  417. if (blobStream - blobStreamBuffer == blobBufferSize)
  418. {
  419. sendBlobPacket(blobBufferSize, blobStreamBuffer, false);
  420. blobStream = blobStreamBuffer;
  421. sizePointer = nullptr;
  422. }
  423. }
  424. size -= step;
  425. ptr += step;
  426. }
  427. }
  428. void setSizePointer()
  429. {
  430. fb_assert(FB_ALIGN(blobStream, sizeof(*sizePointer)) == blobStream);
  431. sizePointer = reinterpret_cast<ULONG*>(blobStream);
  432. }
  433. void putSegment(ULONG size, const void* ptr)
  434. {
  435. if (!sizePointer)
  436. {
  437. newBlob();
  438. ISC_QUAD quadZero = {0, 0};
  439. putBlobData(sizeof quadZero, &quadZero);
  440. setSizePointer();
  441. ULONG longZero = 0;
  442. putBlobData(sizeof longZero, &longZero);
  443. putBlobData(sizeof longZero, &longZero);
  444. }
  445. *sizePointer += size;
  446. if (segmented)
  447. {
  448. if (size > MAX_USHORT)
  449. {
  450. (Arg::Gds(isc_imp_exc) << Arg::Gds(isc_blobtoobig)
  451. << Arg::Gds(isc_big_segment) << Arg::Num(size)).raise();
  452. }
  453. *sizePointer += sizeof(USHORT);
  454. alignBlobBuffer(BLOB_SEGHDR_ALIGN, sizePointer);
  455. USHORT segSize = size;
  456. putBlobData(sizeof segSize, &segSize);
  457. }
  458. putBlobData(size, ptr);
  459. }
  460. void flashBatch()
  461. {
  462. if (blobPolicy != BLOB_NONE)
  463. {
  464. setServerInfo();
  465. alignBlobBuffer(blobAlign);
  466. ULONG size = blobStream - blobStreamBuffer;
  467. if (size)
  468. {
  469. sendBlobPacket(size, blobStreamBuffer, messageStream == 0);
  470. blobStream = blobStreamBuffer;
  471. }
  472. }
  473. if (messageStream)
  474. {
  475. sendMessagePacket(messageStream, messageStreamBuffer, true);
  476. messageStream = 0;
  477. }
  478. batchActive = false;
  479. blobCount = messageCount = 0;
  480. }
  481. void sendBlobPacket(unsigned size, const UCHAR* ptr, bool flash);
  482. void sendMessagePacket(unsigned size, const UCHAR* ptr, bool flash);
  483. void sendDeferredPacket(IStatus* status, rem_port* port, PACKET* packet, bool flash);
  484. Firebird::AutoPtr<UCHAR, Firebird::ArrayDelete> messageStreamBuffer, blobStreamBuffer;
  485. ULONG messageStream;
  486. UCHAR* blobStream;
  487. ULONG* sizePointer;
  488. ULONG messageSize, alignedSize, blobBufferSize, messageBufferSize, flags;
  489. Statement* stmt;
  490. RefPtr<IMessageMetadata> format;
  491. ISC_QUAD genId;
  492. int blobAlign;
  493. UCHAR blobPolicy;
  494. bool segmented, defSegmented, batchActive;
  495. ULONG messageCount, blobCount, serverSize, blobHeadSize;
  496. public:
  497. bool tmpStatement;
  498. };
  499. int Batch::release()
  500. {
  501. if (--refCounter != 0)
  502. return 1;
  503. if (stmt)
  504. {
  505. LocalStatus ls;
  506. CheckStatusWrapper status(&ls);
  507. freeClientData(&status, true);
  508. }
  509. delete this;
  510. return 0;
  511. }
  512. class Replicator final : public RefCntIface<IReplicatorImpl<Replicator, CheckStatusWrapper> >
  513. {
  514. public:
  515. // IReplicator implementation
  516. int release() override;
  517. void process(CheckStatusWrapper* status, unsigned length, const unsigned char* data) override;
  518. void close(CheckStatusWrapper* status) override;
  519. void deprecatedClose(CheckStatusWrapper* status) override;
  520. explicit Replicator(Attachment* att) : attachment(att)
  521. {}
  522. private:
  523. void freeClientData(CheckStatusWrapper* status, bool force = false);
  524. void internalClose(CheckStatusWrapper* status);
  525. Attachment* attachment;
  526. };
  527. int Replicator::release()
  528. {
  529. if (--refCounter != 0)
  530. return 1;
  531. if (attachment)
  532. {
  533. LocalStatus ls;
  534. CheckStatusWrapper status(&ls);
  535. freeClientData(&status, true);
  536. }
  537. delete this;
  538. return 0;
  539. }
  540. class Statement final : public RefCntIface<IStatementImpl<Statement, CheckStatusWrapper> >
  541. {
  542. public:
  543. // IStatement implementation
  544. int release() override;
  545. void getInfo(CheckStatusWrapper* status,
  546. unsigned int itemsLength, const unsigned char* items,
  547. unsigned int bufferLength, unsigned char* buffer) override;
  548. unsigned getType(CheckStatusWrapper* status) override;
  549. const char* getPlan(CheckStatusWrapper* status, FB_BOOLEAN detailed) override;
  550. Firebird::IMessageMetadata* getInputMetadata(CheckStatusWrapper* status) override;
  551. Firebird::IMessageMetadata* getOutputMetadata(CheckStatusWrapper* status) override;
  552. ISC_UINT64 getAffectedRecords(CheckStatusWrapper* status) override;
  553. ITransaction* execute(CheckStatusWrapper* status, ITransaction* tra,
  554. IMessageMetadata* inMetadata, void* inBuffer,
  555. IMessageMetadata* outMetadata, void* outBuffer) override;
  556. ResultSet* openCursor(CheckStatusWrapper* status, ITransaction* tra,
  557. IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outFormat,
  558. unsigned int flags) override;
  559. void setCursorName(CheckStatusWrapper* status, const char* name) override;
  560. void free(CheckStatusWrapper* status) override;
  561. void deprecatedFree(CheckStatusWrapper* status) override;
  562. unsigned getFlags(CheckStatusWrapper* status) override;
  563. unsigned int getTimeout(CheckStatusWrapper* status) override
  564. {
  565. if (statement->rsr_rdb->rdb_port->port_protocol < PROTOCOL_STMT_TOUT)
  566. {
  567. status->setErrors(Arg::Gds(isc_wish_list).value());
  568. return 0;
  569. }
  570. return statement->rsr_timeout;
  571. }
  572. void setTimeout(CheckStatusWrapper* status, unsigned int timeOut) override
  573. {
  574. if (timeOut && statement->rsr_rdb->rdb_port->port_protocol < PROTOCOL_STMT_TOUT)
  575. {
  576. status->setErrors(Arg::Gds(isc_wish_list).value());
  577. return;
  578. }
  579. statement->rsr_timeout = timeOut;
  580. }
  581. Batch* createBatch(CheckStatusWrapper* status, IMessageMetadata* inMetadata,
  582. unsigned parLength, const unsigned char* par) override;
  583. public:
  584. Statement(Rsr* handle, Attachment* a, unsigned aDialect)
  585. : metadata(getPool(), this, NULL),
  586. remAtt(a),
  587. statement(handle),
  588. dialect(aDialect)
  589. {
  590. statement->rsr_self = &statement;
  591. }
  592. Rsr* getStatement()
  593. {
  594. return statement;
  595. }
  596. Attachment* getAttachment()
  597. {
  598. return remAtt;
  599. }
  600. void parseMetadata(const Array<UCHAR>& buffer)
  601. {
  602. metadata.clear();
  603. metadata.parse((ULONG) buffer.getCount(), buffer.begin());
  604. }
  605. unsigned getDialect() const
  606. {
  607. return dialect;
  608. }
  609. private:
  610. void freeClientData(CheckStatusWrapper* status, bool force = false);
  611. void internalFree(CheckStatusWrapper* status);
  612. StatementMetadata metadata;
  613. Attachment* remAtt;
  614. Rsr* statement;
  615. unsigned dialect;
  616. };
  617. int Statement::release()
  618. {
  619. if (--refCounter != 0)
  620. return 1;
  621. if (statement)
  622. {
  623. LocalStatus ls;
  624. CheckStatusWrapper status(&ls);
  625. freeClientData(&status, true);
  626. }
  627. delete this;
  628. return 0;
  629. }
  630. class Request final : public RefCntIface<IRequestImpl<Request, CheckStatusWrapper> >
  631. {
  632. public:
  633. // IRequest implementation
  634. int release() override;
  635. void receive(CheckStatusWrapper* status, int level, unsigned int msg_type,
  636. unsigned int length, void* message) override;
  637. void send(CheckStatusWrapper* status, int level, unsigned int msg_type,
  638. unsigned int length, const void* message) override;
  639. void getInfo(CheckStatusWrapper* status, int level,
  640. unsigned int itemsLength, const unsigned char* items,
  641. unsigned int bufferLength, unsigned char* buffer) override;
  642. void start(CheckStatusWrapper* status, Firebird::ITransaction* tra, int level) override;
  643. void startAndSend(CheckStatusWrapper* status, Firebird::ITransaction* tra, int level, unsigned int msg_type,
  644. unsigned int length, const void* message) override;
  645. void unwind(CheckStatusWrapper* status, int level) override;
  646. void free(CheckStatusWrapper* status) override;
  647. void deprecatedFree(CheckStatusWrapper* status) override;
  648. public:
  649. Request(Rrq* handle, Attachment* a)
  650. : remAtt(a), rq(handle)
  651. {
  652. rq->rrq_self = &rq;
  653. }
  654. private:
  655. void freeClientData(CheckStatusWrapper* status, bool force = false);
  656. void internalFree(CheckStatusWrapper* status);
  657. Attachment* remAtt;
  658. Rrq* rq;
  659. };
  660. int Request::release()
  661. {
  662. if (--refCounter != 0)
  663. return 1;
  664. if (rq)
  665. {
  666. LocalStatus ls;
  667. CheckStatusWrapper status(&ls);
  668. freeClientData(&status, true);
  669. }
  670. delete this;
  671. return 0;
  672. }
  673. class Events final : public RefCntIface<IEventsImpl<Events, CheckStatusWrapper> >
  674. {
  675. public:
  676. // IEvents implementation
  677. int release() override;
  678. void cancel(CheckStatusWrapper* status) override;
  679. void deprecatedCancel(CheckStatusWrapper* status) override;
  680. public:
  681. Events(Rvnt* handle)
  682. : rvnt(handle), rdb(rvnt->rvnt_rdb)
  683. {
  684. rvnt->rvnt_self = &rvnt;
  685. }
  686. private:
  687. void freeClientData(CheckStatusWrapper* status, bool force = false);
  688. void internalCancel(CheckStatusWrapper* status);
  689. Rvnt* rvnt;
  690. Rdb* rdb;
  691. };
  692. int Events::release()
  693. {
  694. int rc = --refCounter;
  695. if (rc != 0)
  696. {
  697. fb_assert(rc > 0);
  698. return 1;
  699. }
  700. if (rvnt)
  701. {
  702. LocalStatus ls;
  703. CheckStatusWrapper status(&ls);
  704. freeClientData(&status, true);
  705. }
  706. delete this;
  707. return 0;
  708. }
  709. class Attachment final : public RefCntIface<IAttachmentImpl<Attachment, CheckStatusWrapper> >
  710. {
  711. public:
  712. // IAttachment implementation
  713. int release() override;
  714. void getInfo(CheckStatusWrapper* status,
  715. unsigned int itemsLength, const unsigned char* items,
  716. unsigned int bufferLength, unsigned char* buffer) override;
  717. Firebird::ITransaction* startTransaction(CheckStatusWrapper* status,
  718. unsigned int tpbLength, const unsigned char* tpb) override;
  719. Firebird::ITransaction* reconnectTransaction(CheckStatusWrapper* status, unsigned int length, const unsigned char* id) override;
  720. Firebird::IRequest* compileRequest(CheckStatusWrapper* status, unsigned int blr_length, const unsigned char* blr) override;
  721. void transactRequest(CheckStatusWrapper* status, ITransaction* transaction,
  722. unsigned int blr_length, const unsigned char* blr,
  723. unsigned int in_msg_length, const unsigned char* in_msg,
  724. unsigned int out_msg_length, unsigned char* out_msg) override;
  725. Firebird::IBlob* createBlob(CheckStatusWrapper* status, ITransaction* transaction,
  726. ISC_QUAD* id, unsigned int bpbLength = 0, const unsigned char* bpb = 0) override;
  727. Firebird::IBlob* openBlob(CheckStatusWrapper* status, ITransaction* transaction,
  728. ISC_QUAD* id, unsigned int bpbLength = 0, const unsigned char* bpb = 0) override;
  729. int getSlice(CheckStatusWrapper* status, ITransaction* transaction, ISC_QUAD* id,
  730. unsigned int sdl_length, const unsigned char* sdl,
  731. unsigned int param_length, const unsigned char* param,
  732. int sliceLength, unsigned char* slice) override;
  733. void putSlice(CheckStatusWrapper* status, ITransaction* transaction, ISC_QUAD* id,
  734. unsigned int sdl_length, const unsigned char* sdl,
  735. unsigned int param_length, const unsigned char* param,
  736. int sliceLength, unsigned char* slice) override;
  737. void executeDyn(CheckStatusWrapper* status, ITransaction* transaction, unsigned int length,
  738. const unsigned char* dyn) override;
  739. Statement* prepare(CheckStatusWrapper* status, ITransaction* transaction,
  740. unsigned int stmtLength, const char* sqlStmt, unsigned dialect, unsigned int flags) override;
  741. Firebird::ITransaction* execute(CheckStatusWrapper* status, ITransaction* transaction,
  742. unsigned int stmtLength, const char* sqlStmt, unsigned dialect,
  743. IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata, void* outBuffer) override;
  744. Firebird::IResultSet* openCursor(CheckStatusWrapper* status, ITransaction* transaction,
  745. unsigned int stmtLength, const char* sqlStmt, unsigned dialect,
  746. IMessageMetadata* inMetadata, void* inBuffer, Firebird::IMessageMetadata* outMetadata,
  747. const char* cursorName, unsigned int cursorFlags) override;
  748. Firebird::IEvents* queEvents(CheckStatusWrapper* status, Firebird::IEventCallback* callback,
  749. unsigned int length, const unsigned char* events) override;
  750. void cancelOperation(CheckStatusWrapper* status, int option) override;
  751. void ping(CheckStatusWrapper* status) override;
  752. void detach(CheckStatusWrapper* status) override;
  753. void dropDatabase(CheckStatusWrapper* status) override;
  754. void deprecatedDetach(Firebird::CheckStatusWrapper* status) override;
  755. void deprecatedDropDatabase(Firebird::CheckStatusWrapper* status) override;
  756. unsigned int getIdleTimeout(CheckStatusWrapper* status) override;
  757. void setIdleTimeout(CheckStatusWrapper* status, unsigned int timeOut) override;
  758. unsigned int getStatementTimeout(CheckStatusWrapper* status) override;
  759. void setStatementTimeout(CheckStatusWrapper* status, unsigned int timeOut) override;
  760. Batch* createBatch(Firebird::CheckStatusWrapper* status, ITransaction* transaction,
  761. unsigned stmtLength, const char* sqlStmt, unsigned dialect,
  762. IMessageMetadata* inMetadata, unsigned parLength, const unsigned char* par) override;
  763. Replicator* createReplicator(Firebird::CheckStatusWrapper* status) override;
  764. public:
  765. Attachment(Rdb* handle, const PathName& path)
  766. : replicator(nullptr), rdb(handle), dbPath(getPool(), path)
  767. { }
  768. Rdb* getRdb()
  769. {
  770. return rdb;
  771. }
  772. const PathName& getDbPath()
  773. {
  774. return dbPath;
  775. }
  776. Rtr* remoteTransaction(ITransaction* apiTra);
  777. Transaction* remoteTransactionInterface(ITransaction* apiTra);
  778. Statement* createStatement(CheckStatusWrapper* status, unsigned dialect);
  779. Replicator* replicator;
  780. private:
  781. void execWithCheck(CheckStatusWrapper* status, const string& stmt);
  782. void freeClientData(CheckStatusWrapper* status, bool force = false);
  783. void internalDetach(Firebird::CheckStatusWrapper* status);
  784. void internalDropDatabase(Firebird::CheckStatusWrapper* status);
  785. SLONG getSingleInfo(CheckStatusWrapper* status, UCHAR infoItem);
  786. Rdb* rdb;
  787. const PathName dbPath;
  788. };
  789. int Attachment::release()
  790. {
  791. if (--refCounter != 0)
  792. return 1;
  793. if (rdb)
  794. {
  795. LocalStatus ls;
  796. CheckStatusWrapper status(&ls);
  797. freeClientData(&status, true);
  798. }
  799. delete this;
  800. return 0;
  801. }
  802. class Service final : public RefCntIface<IServiceImpl<Service, CheckStatusWrapper> >
  803. {
  804. public:
  805. // IService implementation
  806. int release() override;
  807. void detach(CheckStatusWrapper* status) override;
  808. void deprecatedDetach(CheckStatusWrapper* status) override;
  809. void query(CheckStatusWrapper* status,
  810. unsigned int sendLength, const unsigned char* sendItems,
  811. unsigned int receiveLength, const unsigned char* receiveItems,
  812. unsigned int bufferLength, unsigned char* buffer) override;
  813. void start(CheckStatusWrapper* status, unsigned int spbLength, const unsigned char* spb) override;
  814. void cancel(CheckStatusWrapper* status) override;
  815. public:
  816. Service(Rdb* handle) : rdb(handle) { }
  817. private:
  818. void freeClientData(CheckStatusWrapper* status, bool force = false);
  819. void internalDetach(CheckStatusWrapper* status);
  820. Rdb* rdb;
  821. };
  822. int Service::release()
  823. {
  824. if (--refCounter != 0)
  825. return 1;
  826. if (rdb)
  827. {
  828. LocalStatus ls;
  829. CheckStatusWrapper status(&ls);
  830. freeClientData(&status, true);
  831. }
  832. delete this;
  833. return 0;
  834. }
  835. class RProvider : public StdPlugin<IProviderImpl<RProvider, CheckStatusWrapper> >
  836. {
  837. public:
  838. explicit RProvider(IPluginConfig*)
  839. : cryptCallback(NULL)
  840. { }
  841. RProvider()
  842. : cryptCallback(NULL)
  843. { }
  844. // IProvider implementation
  845. IAttachment* attachDatabase(CheckStatusWrapper* status, const char* fileName,
  846. unsigned int dpbLength, const unsigned char* dpb);
  847. IAttachment* createDatabase(CheckStatusWrapper* status, const char* fileName,
  848. unsigned int dpbLength, const unsigned char* dpb);
  849. IService* attachServiceManager(CheckStatusWrapper* status, const char* service,
  850. unsigned int spbLength, const unsigned char* spb);
  851. void shutdown(CheckStatusWrapper* status, unsigned int timeout, const int reason);
  852. void setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* cryptCallback);
  853. protected:
  854. IAttachment* attach(CheckStatusWrapper* status, const char* filename, unsigned int dpb_length,
  855. const unsigned char* dpb, bool loopback);
  856. IAttachment* create(CheckStatusWrapper* status, const char* filename, unsigned int dpb_length,
  857. const unsigned char* dpb, bool loopback);
  858. IService* attachSvc(CheckStatusWrapper* status, const char* service, unsigned int spbLength,
  859. const unsigned char* spb, bool loopback);
  860. private:
  861. Firebird::ICryptKeyCallback* cryptCallback;
  862. };
  863. void RProvider::shutdown(CheckStatusWrapper* status, unsigned int /*timeout*/, const int /*reason*/)
  864. {
  865. status->init();
  866. try
  867. {
  868. outPorts->closePorts();
  869. }
  870. catch (const Exception& ex)
  871. {
  872. ex.stuffException(status);
  873. }
  874. }
  875. void RProvider::setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback)
  876. {
  877. status->init();
  878. cryptCallback = callback;
  879. }
  880. class Loopback : public IProviderBaseImpl<Loopback, CheckStatusWrapper, RProvider>
  881. {
  882. public:
  883. explicit Loopback(IPluginConfig*)
  884. { }
  885. // IProvider implementation
  886. IAttachment* attachDatabase(CheckStatusWrapper* status, const char* fileName,
  887. unsigned int dpbLength, const unsigned char* dpb);
  888. IAttachment* createDatabase(CheckStatusWrapper* status, const char* fileName,
  889. unsigned int dpbLength, const unsigned char* dpb);
  890. IService* attachServiceManager(CheckStatusWrapper* status, const char* service,
  891. unsigned int spbLength, const unsigned char* spb);
  892. };
  893. namespace {
  894. SimpleFactory<RProvider> remoteFactory;
  895. SimpleFactory<Loopback> loopbackFactory;
  896. }
  897. void registerRedirector(Firebird::IPluginManager* iPlugin)
  898. {
  899. iPlugin->registerPluginFactory(IPluginManager::TYPE_PROVIDER, "Remote", &remoteFactory);
  900. iPlugin->registerPluginFactory(IPluginManager::TYPE_PROVIDER, "Loopback", &loopbackFactory);
  901. Auth::registerLegacyClient(iPlugin);
  902. Auth::registerSrpClient(iPlugin);
  903. #ifdef TRUSTED_AUTH
  904. Auth::registerTrustedClient(iPlugin);
  905. #endif
  906. Crypt::registerArc4(iPlugin);
  907. }
  908. } // namespace Remote
  909. /*
  910. extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster* master)
  911. {
  912. IPluginManager* pi = master->getPluginManager();
  913. registerRedirector(pi);
  914. pi->release();
  915. }
  916. */
  917. namespace Remote {
  918. static Rvnt* add_event(rem_port*);
  919. static void add_other_params(rem_port*, ClumpletWriter&, const ParametersSet&);
  920. static void add_working_directory(ClumpletWriter&, const PathName&);
  921. static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags,
  922. ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name,
  923. Firebird::ICryptKeyCallback* cryptCb);
  924. static void batch_gds_receive(rem_port*, struct rmtque *, USHORT);
  925. static void batch_dsql_fetch(rem_port*, struct rmtque *, USHORT);
  926. static void clear_queue(rem_port*);
  927. static void clear_stmt_que(rem_port*, Rsr*);
  928. static void finalize(rem_port* port);
  929. static void disconnect(rem_port*, bool rmRef = true);
  930. static void enqueue_receive(rem_port*, t_rmtque_fn, Rdb*, void*, Rrq::rrq_repeat*);
  931. static void dequeue_receive(rem_port*);
  932. static THREAD_ENTRY_DECLARE event_thread(THREAD_ENTRY_PARAM);
  933. static Rvnt* find_event(rem_port*, SLONG);
  934. static bool get_new_dpb(ClumpletWriter&, const ParametersSet&, bool);
  935. static void info(CheckStatusWrapper*, Rdb*, P_OP, USHORT, USHORT, USHORT,
  936. const UCHAR*, USHORT, const UCHAR*, ULONG, UCHAR*);
  937. static bool init(CheckStatusWrapper*, ClntAuthBlock&, rem_port*, P_OP, PathName&,
  938. ClumpletWriter&, IntlParametersBlock&, ICryptKeyCallback* cryptCallback);
  939. static Rtr* make_transaction(Rdb*, USHORT);
  940. static void mov_dsql_message(const UCHAR*, const rem_fmt*, UCHAR*, const rem_fmt*);
  941. static void move_error(const Arg::StatusVector& v);
  942. static void receive_after_start(Rrq*, USHORT);
  943. static void receive_packet(rem_port*, PACKET *);
  944. static void receive_packet_noqueue(rem_port*, PACKET *);
  945. static void receive_queued_packet(rem_port*, USHORT);
  946. static void receive_response(IStatus*, Rdb*, PACKET *);
  947. static void release_blob(Rbl*);
  948. static void release_event(Rvnt*);
  949. static void release_object(IStatus*, Rdb*, P_OP, USHORT);
  950. static void release_request(Rrq*);
  951. static void release_statement(Rsr**);
  952. static void release_sql_request(Rsr*);
  953. static void release_transaction(Rtr*);
  954. static void send_and_receive(IStatus*, Rdb*, PACKET *);
  955. static void send_blob(CheckStatusWrapper*, Rbl*, USHORT, const UCHAR*);
  956. static void send_packet(rem_port*, PACKET *);
  957. static void send_partial_packet(rem_port*, PACKET *);
  958. static void server_death(rem_port*);
  959. static void svcstart(CheckStatusWrapper*, Rdb*, P_OP, USHORT, USHORT, USHORT, const UCHAR*);
  960. static void unsupported();
  961. static void zap_packet(PACKET *);
  962. static void cleanDpb(Firebird::ClumpletWriter&, const ParametersSet*);
  963. static void authFillParametersBlock(ClntAuthBlock& authItr, ClumpletWriter& dpb,
  964. const ParametersSet* tags, rem_port* port);
  965. static void authReceiveResponse(bool havePacket, ClntAuthBlock& authItr, rem_port* port,
  966. Rdb* rdb, IStatus* status, PACKET* packet, bool checkKeys);
  967. static AtomicCounter remote_event_id;
  968. static const unsigned ANALYZE_USER_VFY = 0x01;
  969. static const unsigned ANALYZE_LOOPBACK = 0x02;
  970. static const unsigned ANALYZE_MOUNTS = 0x04;
  971. static const unsigned ANALYZE_EMP_NAME = 0x08;
  972. inline static void reset(IStatus* status) throw()
  973. {
  974. status->init();
  975. }
  976. #define SET_OBJECT(rdb, object, id) rdb->rdb_port->setHandle(object, id)
  977. inline static void defer_packet(rem_port* port, PACKET* packet, bool sent = false)
  978. {
  979. fb_assert(port->port_flags & PORT_lazy);
  980. fb_assert(port->port_deferred_packets);
  981. // hvlad: passed packet often is rdb->rdb_packet and therefore can be
  982. // changed inside clear_queue. To not confuse caller we must preserve
  983. // packet content
  984. rem_que_packet p;
  985. p.packet = *packet;
  986. p.sent = sent;
  987. clear_queue(port);
  988. *packet = p.packet;
  989. // don't use string references in P_RESP structure copied from another packet
  990. memset(&p.packet.p_resp, 0, sizeof(p.packet.p_resp));
  991. port->port_deferred_packets->add(p);
  992. }
  993. IAttachment* RProvider::attach(CheckStatusWrapper* status, const char* filename, unsigned int dpb_length,
  994. const unsigned char* dpb, bool loopback)
  995. {
  996. /**************************************
  997. *
  998. * g d s _ a t t a c h _ d a t a b a s e
  999. *
  1000. **************************************
  1001. *
  1002. * Functional description
  1003. * Connect to an old, grungy database, corrupted by user data.
  1004. *
  1005. **************************************/
  1006. try
  1007. {
  1008. reset(status);
  1009. ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE, dpb, dpb_length);
  1010. unsigned flags = ANALYZE_MOUNTS;
  1011. if (get_new_dpb(newDpb, dpbParam, loopback))
  1012. flags |= ANALYZE_USER_VFY;
  1013. if (loopback)
  1014. flags |= ANALYZE_LOOPBACK;
  1015. PathName expanded_name(filename);
  1016. resolveAlias(filename, expanded_name, nullptr);
  1017. ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam);
  1018. PathName node_name;
  1019. rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL, cryptCallback);
  1020. if (!port)
  1021. {
  1022. Arg::Gds(isc_unavailable).copyTo(status);
  1023. return NULL;
  1024. }
  1025. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1026. // The client may have set a parameter for dummy_packet_interval. Add that to the
  1027. // the DPB so the server can pay attention to it.
  1028. add_other_params(port, newDpb, dpbParam);
  1029. add_working_directory(newDpb, node_name);
  1030. IntlDpb intl;
  1031. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: call init for DB='%s'\n", expanded_name.c_str()));
  1032. if (!init(status, cBlock, port, op_attach, expanded_name, newDpb, intl, cryptCallback))
  1033. return NULL;
  1034. Attachment* a = FB_NEW Attachment(port->port_context, filename);
  1035. a->addRef();
  1036. return a;
  1037. }
  1038. catch (const Exception& ex)
  1039. {
  1040. ex.stuffException(status);
  1041. return NULL;
  1042. }
  1043. }
  1044. IAttachment* RProvider::attachDatabase(CheckStatusWrapper* status, const char* filename,
  1045. unsigned int dpb_length, const unsigned char* dpb)
  1046. {
  1047. /**************************************
  1048. *
  1049. * g d s _ a t t a c h _ d a t a b a s e
  1050. *
  1051. **************************************
  1052. *
  1053. * Functional description
  1054. * Connect to an old, grungy database, corrupted by user data.
  1055. *
  1056. **************************************/
  1057. return attach(status, filename, dpb_length, dpb, false);
  1058. }
  1059. IAttachment* Loopback::attachDatabase(CheckStatusWrapper* status, const char* filename,
  1060. unsigned int dpb_length, const unsigned char* dpb)
  1061. {
  1062. /**************************************
  1063. *
  1064. * g d s _ a t t a c h _ d a t a b a s e
  1065. *
  1066. **************************************
  1067. *
  1068. * Functional description
  1069. * Connect to an old, grungy database, corrupted by user data.
  1070. *
  1071. **************************************/
  1072. return attach(status, filename, dpb_length, dpb, true);
  1073. }
  1074. void Blob::getInfo(CheckStatusWrapper* status,
  1075. unsigned int itemsLength, const unsigned char* items,
  1076. unsigned int bufferLength, unsigned char* buffer)
  1077. {
  1078. /**************************************
  1079. *
  1080. * g d s _ b l o b _ i n f o
  1081. *
  1082. **************************************
  1083. *
  1084. * Functional description
  1085. * Provide information on blob object.
  1086. *
  1087. **************************************/
  1088. try
  1089. {
  1090. reset(status);
  1091. CHECK_HANDLE(blob, isc_bad_segstr_handle);
  1092. Rdb* rdb = blob->rbl_rdb;
  1093. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1094. rem_port* port = rdb->rdb_port;
  1095. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1096. info(status, rdb, op_info_blob, blob->rbl_id, 0,
  1097. itemsLength, items, 0, 0, bufferLength, buffer);
  1098. }
  1099. catch (const Exception& ex)
  1100. {
  1101. ex.stuffException(status);
  1102. }
  1103. }
  1104. void Blob::freeClientData(CheckStatusWrapper* status, bool force)
  1105. {
  1106. /**************************************
  1107. *
  1108. * g d s _ c a n c e l _ b l o b
  1109. *
  1110. **************************************
  1111. *
  1112. * Functional description
  1113. * Abort a partially completed blob.
  1114. *
  1115. **************************************/
  1116. try
  1117. {
  1118. if (!blob)
  1119. {
  1120. return;
  1121. }
  1122. CHECK_HANDLE(blob, isc_bad_segstr_handle);
  1123. Rdb* rdb = blob->rbl_rdb;
  1124. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1125. rem_port* port = rdb->rdb_port;
  1126. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1127. try
  1128. {
  1129. release_object(status, rdb, op_cancel_blob, blob->rbl_id);
  1130. }
  1131. catch (const Exception&)
  1132. {
  1133. if (!force)
  1134. throw;
  1135. }
  1136. release_blob(blob);
  1137. blob = NULL;
  1138. }
  1139. catch (const Exception& ex)
  1140. {
  1141. ex.stuffException(status);
  1142. }
  1143. }
  1144. void Blob::internalCancel(CheckStatusWrapper* status)
  1145. {
  1146. /**************************************
  1147. *
  1148. * g d s _ c a n c e l _ b l o b
  1149. *
  1150. **************************************
  1151. *
  1152. * Functional description
  1153. * Abort a partially completed blob.
  1154. *
  1155. **************************************/
  1156. reset(status);
  1157. freeClientData(status);
  1158. }
  1159. void Blob::cancel(CheckStatusWrapper* status)
  1160. {
  1161. internalCancel(status);
  1162. if (status->isEmpty())
  1163. release();
  1164. }
  1165. void Blob::deprecatedCancel(CheckStatusWrapper* status)
  1166. {
  1167. internalCancel(status);
  1168. }
  1169. void Blob::internalClose(CheckStatusWrapper* status)
  1170. {
  1171. /**************************************
  1172. *
  1173. * g d s _ c l o s e _ b l o b
  1174. *
  1175. **************************************
  1176. *
  1177. * Functional description
  1178. * Close a completed blob.
  1179. *
  1180. **************************************/
  1181. try
  1182. {
  1183. reset(status);
  1184. CHECK_HANDLE(blob, isc_bad_segstr_handle);
  1185. Rdb* rdb = blob->rbl_rdb;
  1186. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1187. rem_port* port = rdb->rdb_port;
  1188. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1189. if ((blob->rbl_flags & Rbl::CREATE) && blob->rbl_ptr != blob->rbl_buffer)
  1190. {
  1191. send_blob(status, blob, 0, NULL);
  1192. }
  1193. release_object(status, rdb, op_close_blob, blob->rbl_id);
  1194. release_blob(blob);
  1195. blob = NULL;
  1196. }
  1197. catch (const Exception& ex)
  1198. {
  1199. ex.stuffException(status);
  1200. }
  1201. }
  1202. void Blob::close(CheckStatusWrapper* status)
  1203. {
  1204. internalClose(status);
  1205. if (status->isEmpty())
  1206. release();
  1207. }
  1208. void Blob::deprecatedClose(CheckStatusWrapper* status)
  1209. {
  1210. internalClose(status);
  1211. }
  1212. void Events::freeClientData(CheckStatusWrapper* status, bool force)
  1213. {
  1214. /**************************************
  1215. *
  1216. * g d s _ $ c a n c e l _ e v e n t s
  1217. *
  1218. **************************************
  1219. *
  1220. * Functional description
  1221. * Cancel an outstanding event.
  1222. *
  1223. **************************************/
  1224. RefPtr<IEventCallback> callback;
  1225. try
  1226. {
  1227. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1228. rem_port* port = rdb->rdb_port;
  1229. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1230. if (!rvnt)
  1231. {
  1232. return;
  1233. }
  1234. CHECK_HANDLE(rvnt, isc_bad_events_handle);
  1235. try
  1236. {
  1237. // Tell the remote server to cancel it and delete it from the list
  1238. PACKET* packet = &rdb->rdb_packet;
  1239. // Set the various parameters for the packet:
  1240. // remote operation to perform, which database,
  1241. // and which event.
  1242. packet->p_operation = op_cancel_events;
  1243. packet->p_event.p_event_database = rdb->rdb_id;
  1244. const SLONG save_id = packet->p_event.p_event_rid = rvnt->rvnt_id;
  1245. // Send the packet, and if that worked, get a response
  1246. try
  1247. {
  1248. LocalStatus ls;
  1249. CheckStatusWrapper dummy(&ls);
  1250. send_packet(rdb->rdb_port, packet);
  1251. receive_response(&dummy, rdb, packet);
  1252. }
  1253. catch (const Exception&) { }
  1254. // Get ready to fire the event.
  1255. if (rvnt->rvnt_id == save_id)
  1256. {
  1257. callback = rvnt->rvnt_callback;
  1258. rvnt->rvnt_id = 0;
  1259. }
  1260. }
  1261. catch (const Exception&)
  1262. {
  1263. if (!force)
  1264. throw;
  1265. }
  1266. rvnt = NULL;
  1267. }
  1268. catch (const Exception& ex)
  1269. {
  1270. ex.stuffException(status);
  1271. }
  1272. // If the event has never been fired, fire it off with a length of 0.
  1273. // Note: it is job of person being notified to check that counts
  1274. // actually changed and that they were not woken up because of
  1275. // server death.
  1276. if (callback)
  1277. callback->eventCallbackFunction(0, NULL);
  1278. }
  1279. void Events::internalCancel(CheckStatusWrapper* status)
  1280. {
  1281. /**************************************
  1282. *
  1283. * g d s _ $ c a n c e l _ e v e n t s
  1284. *
  1285. **************************************
  1286. *
  1287. * Functional description
  1288. * Cancel an outstanding event.
  1289. *
  1290. **************************************/
  1291. reset(status);
  1292. freeClientData(status);
  1293. }
  1294. void Events::cancel(CheckStatusWrapper* status)
  1295. {
  1296. internalCancel(status);
  1297. if (status->isEmpty())
  1298. release();
  1299. }
  1300. void Events::deprecatedCancel(CheckStatusWrapper* status)
  1301. {
  1302. internalCancel(status);
  1303. }
  1304. void Transaction::internalCommit(CheckStatusWrapper* status)
  1305. {
  1306. /**************************************
  1307. *
  1308. * g d s _ c o m m i t
  1309. *
  1310. **************************************
  1311. *
  1312. * Functional description
  1313. * Commit a transaction.
  1314. *
  1315. **************************************/
  1316. try
  1317. {
  1318. reset(status);
  1319. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  1320. Rdb* rdb = transaction->rtr_rdb;
  1321. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1322. rem_port* port = rdb->rdb_port;
  1323. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1324. release_object(status, rdb, op_commit, transaction->rtr_id);
  1325. REMOTE_cleanup_transaction(transaction);
  1326. release_transaction(transaction);
  1327. transaction = NULL;
  1328. }
  1329. catch (const Exception& ex)
  1330. {
  1331. ex.stuffException(status);
  1332. }
  1333. }
  1334. void Transaction::commit(CheckStatusWrapper* status)
  1335. {
  1336. internalCommit(status);
  1337. if (status->isEmpty())
  1338. release();
  1339. }
  1340. void Transaction::deprecatedCommit(CheckStatusWrapper* status)
  1341. {
  1342. internalCommit(status);
  1343. }
  1344. void Transaction::commitRetaining(CheckStatusWrapper* status)
  1345. {
  1346. /**************************************
  1347. *
  1348. * g d s _ c o m m i t _ r e t a i n i n g
  1349. *
  1350. **************************************
  1351. *
  1352. * Functional description
  1353. *
  1354. **************************************/
  1355. try
  1356. {
  1357. reset(status);
  1358. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  1359. Rdb* rdb = transaction->rtr_rdb;
  1360. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1361. rem_port* port = rdb->rdb_port;
  1362. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1363. release_object(status, rdb, op_commit_retaining, transaction->rtr_id);
  1364. }
  1365. catch (const Exception& ex)
  1366. {
  1367. ex.stuffException(status);
  1368. }
  1369. }
  1370. ITransaction* Transaction::join(CheckStatusWrapper* status, ITransaction* tra)
  1371. {
  1372. /**************************************
  1373. *
  1374. * I T r a n s a c t i o n :: j o i n
  1375. *
  1376. **************************************
  1377. *
  1378. * Functional description
  1379. * Join this and passed transactions
  1380. * into single distributed transaction
  1381. *
  1382. **************************************/
  1383. try
  1384. {
  1385. reset(status);
  1386. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  1387. return DtcInterfacePtr()->join(status, this, tra);
  1388. }
  1389. catch (const Exception& ex)
  1390. {
  1391. ex.stuffException(status);
  1392. }
  1393. return NULL;
  1394. }
  1395. Transaction* Transaction::validate(CheckStatusWrapper* /*status*/, IAttachment* testAtt)
  1396. {
  1397. return (transaction && remAtt == testAtt) ? this : NULL;
  1398. }
  1399. Transaction* Transaction::enterDtc(CheckStatusWrapper* status)
  1400. {
  1401. try
  1402. {
  1403. Transaction* copy = FB_NEW Transaction(this);
  1404. copy->addRef();
  1405. transaction = NULL;
  1406. return copy;
  1407. }
  1408. catch (const Exception& ex)
  1409. {
  1410. ex.stuffException(status);
  1411. }
  1412. return NULL;
  1413. }
  1414. Firebird::IRequest* Attachment::compileRequest(CheckStatusWrapper* status,
  1415. unsigned int blr_length, const unsigned char* blr)
  1416. {
  1417. /**************************************
  1418. *
  1419. * g d s _ c o m p i l e
  1420. *
  1421. **************************************
  1422. *
  1423. * Functional description
  1424. *
  1425. **************************************/
  1426. try
  1427. {
  1428. reset(status);
  1429. // Check and validate handles, etc.
  1430. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1431. rem_port* port = rdb->rdb_port;
  1432. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1433. // Validate data length
  1434. CHECK_LENGTH(port, blr_length);
  1435. // Parse the request in case blr_d_float must be converted to blr_double
  1436. const UCHAR* new_blr = blr;
  1437. // Make up a packet for the remote guy
  1438. PACKET* packet = &rdb->rdb_packet;
  1439. packet->p_operation = op_compile;
  1440. P_CMPL* compile = &packet->p_cmpl;
  1441. compile->p_cmpl_database = rdb->rdb_id;
  1442. compile->p_cmpl_blr.cstr_length = blr_length;
  1443. compile->p_cmpl_blr.cstr_address = new_blr;
  1444. send_and_receive(status, rdb, packet);
  1445. // Parse the request to find the messages
  1446. RMessage* next;
  1447. RMessage* message = PARSE_messages(blr, blr_length);
  1448. USHORT max_msg = 0;
  1449. for (next = message; next; next = next->msg_next)
  1450. max_msg = MAX(max_msg, next->msg_number);
  1451. // Allocate request block
  1452. Rrq* request = FB_NEW Rrq(max_msg + 1);
  1453. request->rrq_rdb = rdb;
  1454. request->rrq_id = packet->p_resp.p_resp_object;
  1455. request->rrq_max_msg = max_msg;
  1456. SET_OBJECT(rdb, request, request->rrq_id);
  1457. request->rrq_next = rdb->rdb_requests;
  1458. rdb->rdb_requests = request;
  1459. // when the messages are parsed, they are linked together; we need
  1460. // to place the messages in the tail of the request block and create
  1461. // a queue of length 1 for each message number
  1462. for (; message; message = next)
  1463. {
  1464. next = message->msg_next;
  1465. message->msg_next = message;
  1466. Rrq::rrq_repeat * tail = &request->rrq_rpt[message->msg_number];
  1467. tail->rrq_message = message;
  1468. tail->rrq_xdr = message;
  1469. tail->rrq_format = (rem_fmt*) message->msg_address;
  1470. message->msg_address = NULL;
  1471. }
  1472. Firebird::IRequest* r = FB_NEW Request(request, this);
  1473. r->addRef();
  1474. return r;
  1475. }
  1476. catch (const Exception& ex)
  1477. {
  1478. // deallocate new_blr here???
  1479. ex.stuffException(status);
  1480. }
  1481. return NULL;
  1482. }
  1483. IBlob* Attachment::createBlob(CheckStatusWrapper* status, ITransaction* apiTra, ISC_QUAD* blob_id,
  1484. unsigned int bpb_length, const unsigned char* bpb)
  1485. {
  1486. /**************************************
  1487. *
  1488. * g d s _ c r e a t e _ b l o b 2
  1489. *
  1490. **************************************
  1491. *
  1492. * Functional description
  1493. * Open an existing blob.
  1494. *
  1495. **************************************/
  1496. try
  1497. {
  1498. reset(status);
  1499. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1500. rem_port* port = rdb->rdb_port;
  1501. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1502. Rtr* transaction = remoteTransaction(apiTra);
  1503. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  1504. // Validate data length
  1505. CHECK_LENGTH(port, bpb_length);
  1506. PACKET* packet = &rdb->rdb_packet;
  1507. packet->p_operation = op_create_blob2;
  1508. P_BLOB* p_blob = &packet->p_blob;
  1509. p_blob->p_blob_transaction = transaction->rtr_id;
  1510. p_blob->p_blob_bpb.cstr_length = bpb_length;
  1511. fb_assert(!p_blob->p_blob_bpb.cstr_allocated ||
  1512. p_blob->p_blob_bpb.cstr_allocated < p_blob->p_blob_bpb.cstr_length);
  1513. // CVC: Should we ensure here that cstr_allocated < bpb_length???
  1514. // Otherwise, xdr_cstring() calling alloc_string() to decode would
  1515. // cause memory problems on the client side for SS, as the client
  1516. // would try to write to the application's provided R/O buffer.
  1517. p_blob->p_blob_bpb.cstr_address = bpb;
  1518. try
  1519. {
  1520. send_and_receive(status, rdb, packet);
  1521. }
  1522. catch (const Exception&)
  1523. {
  1524. p_blob->p_blob_bpb.cstr_length = 0;
  1525. p_blob->p_blob_bpb.cstr_address = NULL;
  1526. throw;
  1527. }
  1528. p_blob->p_blob_bpb.cstr_length = 0;
  1529. p_blob->p_blob_bpb.cstr_address = NULL;
  1530. Rbl* blob = FB_NEW Rbl();
  1531. *blob_id = packet->p_resp.p_resp_blob_id;
  1532. blob->rbl_rdb = rdb;
  1533. blob->rbl_rtr = transaction;
  1534. blob->rbl_id = packet->p_resp.p_resp_object;
  1535. blob->rbl_flags |= Rbl::CREATE;
  1536. SET_OBJECT(rdb, blob, blob->rbl_id);
  1537. blob->rbl_next = transaction->rtr_blobs;
  1538. transaction->rtr_blobs = blob;
  1539. Firebird::IBlob* b = FB_NEW Blob(blob);
  1540. b->addRef();
  1541. return b;
  1542. }
  1543. catch (const Exception& ex)
  1544. {
  1545. ex.stuffException(status);
  1546. }
  1547. return NULL;
  1548. }
  1549. Firebird::IAttachment* RProvider::create(CheckStatusWrapper* status, const char* filename,
  1550. unsigned int dpb_length, const unsigned char* dpb, bool loopback)
  1551. {
  1552. /**************************************
  1553. *
  1554. * g d s _ c r e a t e _ d a t a b a s e
  1555. *
  1556. **************************************
  1557. *
  1558. * Functional description
  1559. * Create a nice, squeeky clean database, uncorrupted by user data.
  1560. *
  1561. **************************************/
  1562. try
  1563. {
  1564. reset(status);
  1565. ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE,
  1566. reinterpret_cast<const UCHAR*>(dpb), dpb_length);
  1567. unsigned flags = ANALYZE_MOUNTS;
  1568. if (get_new_dpb(newDpb, dpbParam, loopback))
  1569. flags |= ANALYZE_USER_VFY;
  1570. if (loopback)
  1571. flags |= ANALYZE_LOOPBACK;
  1572. PathName expanded_name(filename);
  1573. resolveAlias(filename, expanded_name, nullptr);
  1574. ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam);
  1575. PathName node_name;
  1576. rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL, cryptCallback);
  1577. if (!port)
  1578. {
  1579. Arg::Gds(isc_unavailable).copyTo(status);
  1580. return NULL;
  1581. }
  1582. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1583. Rdb* rdb = port->port_context;
  1584. // The client may have set a parameter for dummy_packet_interval. Add that to the
  1585. // the DPB so the server can pay attention to it. Note: allocation code must
  1586. // ensure sufficient space has been added.
  1587. add_other_params(port, newDpb, dpbParam);
  1588. add_working_directory(newDpb, node_name);
  1589. IntlDpb intl;
  1590. if (!init(status, cBlock, port, op_create, expanded_name, newDpb, intl, cryptCallback))
  1591. return NULL;
  1592. Firebird::IAttachment* a = FB_NEW Attachment(rdb, filename);
  1593. a->addRef();
  1594. return a;
  1595. }
  1596. catch (const Exception& ex)
  1597. {
  1598. ex.stuffException(status);
  1599. }
  1600. return NULL;
  1601. }
  1602. IAttachment* RProvider::createDatabase(CheckStatusWrapper* status, const char* fileName,
  1603. unsigned int dpbLength, const unsigned char* dpb)
  1604. {
  1605. /**************************************
  1606. *
  1607. * g d s _ c r e a t e _ d a t a b a s e
  1608. *
  1609. **************************************
  1610. *
  1611. * Functional description
  1612. * Create a nice, squeeky clean database, uncorrupted by user data.
  1613. *
  1614. **************************************/
  1615. return create(status, fileName, dpbLength, dpb, false);
  1616. }
  1617. IAttachment* Loopback::createDatabase(CheckStatusWrapper* status, const char* fileName,
  1618. unsigned int dpbLength, const unsigned char* dpb)
  1619. {
  1620. /**************************************
  1621. *
  1622. * g d s _ c r e a t e _ d a t a b a s e
  1623. *
  1624. **************************************
  1625. *
  1626. * Functional description
  1627. * Create a nice, squeeky clean database, uncorrupted by user data.
  1628. *
  1629. **************************************/
  1630. return create(status, fileName, dpbLength, dpb, true);
  1631. }
  1632. void Attachment::getInfo(CheckStatusWrapper* status,
  1633. unsigned int item_length, const unsigned char* items,
  1634. unsigned int buffer_length, unsigned char* buffer)
  1635. {
  1636. /**************************************
  1637. *
  1638. * g d s _ d a t a b a s e _ i n f o
  1639. *
  1640. **************************************
  1641. *
  1642. * Functional description
  1643. * Provide information on database object.
  1644. *
  1645. **************************************/
  1646. try
  1647. {
  1648. reset(status);
  1649. HalfStaticArray<UCHAR, 1024> temp;
  1650. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1651. rem_port* port = rdb->rdb_port;
  1652. USHORT protocol = memchr(items, fb_info_protocol_version, item_length) ? port->port_protocol : 0;
  1653. protocol &= FB_PROTOCOL_MASK;
  1654. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1655. UCHAR* temp_buffer = temp.getBuffer(buffer_length);
  1656. info(status, rdb, op_info_database, rdb->rdb_id, 0,
  1657. item_length, items, 0, 0, buffer_length, temp_buffer);
  1658. string version;
  1659. port->versionInfo(version);
  1660. MERGE_database_info(temp_buffer, buffer, buffer_length,
  1661. DbImplementation::current.backwardCompatibleImplementation(), 3, 1,
  1662. reinterpret_cast<const UCHAR*>(version.c_str()),
  1663. reinterpret_cast<const UCHAR*>(port->port_host->str_data),
  1664. protocol);
  1665. }
  1666. catch (const Exception& ex)
  1667. {
  1668. ex.stuffException(status);
  1669. }
  1670. }
  1671. void Attachment::executeDyn(CheckStatusWrapper* status, ITransaction* apiTra, unsigned int length,
  1672. const unsigned char* dyn)
  1673. {
  1674. /**************************************
  1675. *
  1676. * g d s _ d d l
  1677. *
  1678. **************************************
  1679. *
  1680. * Functional description
  1681. *
  1682. **************************************/
  1683. try
  1684. {
  1685. reset(status);
  1686. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1687. rem_port* port = rdb->rdb_port;
  1688. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1689. Rtr* transaction = remoteTransaction(apiTra);
  1690. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  1691. // Validate data length
  1692. CHECK_LENGTH(port, length);
  1693. // Make up a packet for the remote guy
  1694. PACKET* packet = &rdb->rdb_packet;
  1695. packet->p_operation = op_ddl;
  1696. P_DDL* ddl = &packet->p_ddl;
  1697. ddl->p_ddl_database = rdb->rdb_id;
  1698. ddl->p_ddl_transaction = transaction->rtr_id;
  1699. ddl->p_ddl_blr.cstr_length = length;
  1700. ddl->p_ddl_blr.cstr_address = dyn;
  1701. send_and_receive(status, rdb, packet);
  1702. }
  1703. catch (const Exception& ex)
  1704. {
  1705. ex.stuffException(status);
  1706. }
  1707. }
  1708. void Attachment::freeClientData(CheckStatusWrapper* status, bool force)
  1709. {
  1710. /**************************************
  1711. *
  1712. * g d s _ d e t a c h
  1713. *
  1714. **************************************
  1715. *
  1716. * Functional description
  1717. * Close down a database.
  1718. *
  1719. **************************************/
  1720. try
  1721. {
  1722. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1723. rem_port* port = rdb->rdb_port;
  1724. RemotePortGuard portGuard(port, FB_FUNCTION);
  1725. try
  1726. {
  1727. if (!(port->port_flags & (PORT_rdb_shutdown | PORT_detached)))
  1728. {
  1729. release_object(status, rdb, op_detach, rdb->rdb_id);
  1730. }
  1731. }
  1732. catch (const status_exception& ex)
  1733. {
  1734. // If something other than a network error occurred, just return. Otherwise
  1735. // we need to free up the associated structures, close the socket and
  1736. // scream. By the way, we should probably create an entry in the log
  1737. // telling the user that an unrecoverable network error occurred and that
  1738. // if there was any uncommitted work, its gone...... Oh well....
  1739. ex.stuffException(status);
  1740. if (!fb_utils::isNetworkError(status->getErrors()[1]) && (!force))
  1741. {
  1742. return;
  1743. }
  1744. }
  1745. while (rdb->rdb_events)
  1746. release_event(rdb->rdb_events);
  1747. while (rdb->rdb_requests)
  1748. release_request(rdb->rdb_requests);
  1749. while (rdb->rdb_sql_requests)
  1750. release_sql_request(rdb->rdb_sql_requests);
  1751. while (rdb->rdb_transactions)
  1752. release_transaction(rdb->rdb_transactions);
  1753. if (port->port_statement)
  1754. release_statement(&port->port_statement);
  1755. // If there is a network error, don't try to send another packet, just
  1756. // free the packet and disconnect the port. Put something into firebird.log
  1757. // informing the user of the following.
  1758. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  1759. {
  1760. iscLogStatus("REMOTE INTERFACE/gds__detach: Unsuccessful detach from "
  1761. "database.\n\tUncommitted work may have been lost.", status);
  1762. reset(status);
  1763. }
  1764. disconnect(port);
  1765. rdb = NULL;
  1766. }
  1767. catch (const Exception& ex)
  1768. {
  1769. ex.stuffException(status);
  1770. }
  1771. }
  1772. void Attachment::internalDetach(CheckStatusWrapper* status)
  1773. {
  1774. /**************************************
  1775. *
  1776. * g d s _ d e t a c h
  1777. *
  1778. **************************************
  1779. *
  1780. * Functional description
  1781. * Close down a database.
  1782. *
  1783. **************************************/
  1784. reset(status);
  1785. freeClientData(status);
  1786. }
  1787. void Attachment::detach(CheckStatusWrapper* status)
  1788. {
  1789. internalDetach(status);
  1790. if (status->isEmpty())
  1791. release();
  1792. }
  1793. void Attachment::deprecatedDetach(CheckStatusWrapper* status)
  1794. {
  1795. internalDetach(status);
  1796. }
  1797. void Attachment::internalDropDatabase(CheckStatusWrapper* status)
  1798. {
  1799. /**************************************
  1800. *
  1801. * i s c _ d r o p _ d a t a b a s e
  1802. *
  1803. **************************************
  1804. *
  1805. * Functional description
  1806. * Close down and purge a database.
  1807. *
  1808. **************************************/
  1809. try
  1810. {
  1811. reset(status);
  1812. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1813. rem_port* port = rdb->rdb_port;
  1814. RemotePortGuard portGuard(port, FB_FUNCTION);
  1815. try
  1816. {
  1817. release_object(status, rdb, op_drop_database, rdb->rdb_id);
  1818. }
  1819. catch (const status_exception& ex)
  1820. {
  1821. ex.stuffException(status);
  1822. if (ex.value()[1] != isc_drdb_completed_with_errs)
  1823. {
  1824. return;
  1825. }
  1826. }
  1827. while (rdb->rdb_events)
  1828. release_event(rdb->rdb_events);
  1829. while (rdb->rdb_requests)
  1830. release_request(rdb->rdb_requests);
  1831. while (rdb->rdb_sql_requests)
  1832. release_sql_request(rdb->rdb_sql_requests);
  1833. while (rdb->rdb_transactions)
  1834. release_transaction(rdb->rdb_transactions);
  1835. if (port->port_statement)
  1836. release_statement(&port->port_statement);
  1837. disconnect(port);
  1838. rdb = NULL;
  1839. }
  1840. catch (const Exception& ex)
  1841. {
  1842. ex.stuffException(status);
  1843. }
  1844. }
  1845. void Attachment::dropDatabase(CheckStatusWrapper* status)
  1846. {
  1847. internalDropDatabase(status);
  1848. if (status->isEmpty())
  1849. release();
  1850. }
  1851. void Attachment::deprecatedDropDatabase(CheckStatusWrapper* status)
  1852. {
  1853. internalDropDatabase(status);
  1854. }
  1855. SLONG Attachment::getSingleInfo(CheckStatusWrapper* status, UCHAR infoItem)
  1856. {
  1857. UCHAR buff[16];
  1858. getInfo(status, 1, &infoItem, sizeof(buff), buff);
  1859. if (status->getState() & IStatus::STATE_ERRORS)
  1860. return 0;
  1861. const UCHAR* p = buff;
  1862. const UCHAR* const end = buff + sizeof(buff);
  1863. UCHAR item;
  1864. while ((item = *p++) != isc_info_end && p < end - 1)
  1865. {
  1866. const SLONG length = gds__vax_integer(p, 2);
  1867. p += 2;
  1868. if (item == infoItem)
  1869. return gds__vax_integer(p, (SSHORT)length);
  1870. fb_assert(false);
  1871. p += length;
  1872. }
  1873. return 0;
  1874. }
  1875. void Attachment::execWithCheck(CheckStatusWrapper* status, const string& stmt)
  1876. {
  1877. /**************************************
  1878. *
  1879. * Used to execute "SET xxx TIMEOUT" statements. Checks for protocol version
  1880. * and convert expected SQL error into isc_wish_list error. The only possible
  1881. * case is when modern network server works with legacy engine.
  1882. *
  1883. **************************************/
  1884. if (rdb->rdb_port->port_protocol >= PROTOCOL_STMT_TOUT)
  1885. {
  1886. execute(status, NULL, stmt.length(), stmt.c_str(), SQL_DIALECT_CURRENT, NULL, NULL, NULL, NULL);
  1887. if (!(status->getState() & IStatus::STATE_ERRORS))
  1888. return;
  1889. // handle isc_dsql_token_unk_err
  1890. const ISC_STATUS* errs = status->getErrors();
  1891. if (!fb_utils::containsErrorCode(errs, isc_sqlerr) ||
  1892. !fb_utils::containsErrorCode(errs, isc_dsql_token_unk_err))
  1893. {
  1894. return;
  1895. }
  1896. status->init();
  1897. }
  1898. status->setErrors(Arg::Gds(isc_wish_list).value());
  1899. }
  1900. unsigned int Attachment::getIdleTimeout(CheckStatusWrapper* status)
  1901. {
  1902. if (rdb->rdb_port->port_protocol >= PROTOCOL_STMT_TOUT)
  1903. return getSingleInfo(status, fb_info_ses_idle_timeout_att);
  1904. status->setErrors(Arg::Gds(isc_wish_list).value());
  1905. return 0;
  1906. }
  1907. void Attachment::setIdleTimeout(CheckStatusWrapper* status, unsigned int timeOut)
  1908. {
  1909. string stmt;
  1910. stmt.printf("SET SESSION IDLE TIMEOUT %lu", timeOut);
  1911. execWithCheck(status, stmt);
  1912. }
  1913. unsigned int Attachment::getStatementTimeout(CheckStatusWrapper* status)
  1914. {
  1915. if (rdb->rdb_port->port_protocol >= PROTOCOL_STMT_TOUT)
  1916. return getSingleInfo(status, fb_info_statement_timeout_att);
  1917. status->setErrors(Arg::Gds(isc_wish_list).value());
  1918. return 0;
  1919. }
  1920. void Attachment::setStatementTimeout(CheckStatusWrapper* status, unsigned int timeOut)
  1921. {
  1922. string stmt;
  1923. stmt.printf("SET STATEMENT TIMEOUT %lu", timeOut);
  1924. execWithCheck(status, stmt);
  1925. }
  1926. Batch* Attachment::createBatch(CheckStatusWrapper* status, ITransaction* transaction,
  1927. unsigned stmtLength, const char* sqlStmt, unsigned dialect,
  1928. IMessageMetadata* inMetadata, unsigned parLength, const unsigned char* par)
  1929. {
  1930. /**************************************
  1931. *
  1932. * c r e a t e B a t c h
  1933. *
  1934. **************************************
  1935. *
  1936. * Functional description
  1937. * Create jdbc-style batch for SQL statement.
  1938. *
  1939. **************************************/
  1940. Statement* stmt = prepare(status, transaction, stmtLength, sqlStmt, dialect, 0);
  1941. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  1942. {
  1943. return NULL;
  1944. }
  1945. Batch* rc = stmt->createBatch(status, inMetadata, parLength, par);
  1946. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  1947. {
  1948. stmt->release();
  1949. return NULL;
  1950. }
  1951. rc->tmpStatement = true;
  1952. return rc;
  1953. }
  1954. Batch* Statement::createBatch(CheckStatusWrapper* status, IMessageMetadata* inMetadata,
  1955. unsigned parLength, const unsigned char* par)
  1956. {
  1957. /**************************************
  1958. *
  1959. * c r e a t e B a t c h
  1960. *
  1961. **************************************
  1962. *
  1963. * Functional description
  1964. * Create jdbc-style batch for prepared statement.
  1965. *
  1966. **************************************/
  1967. try
  1968. {
  1969. reset(status);
  1970. // Check and validate handles, etc.
  1971. CHECK_HANDLE(statement, isc_bad_req_handle);
  1972. Rdb* rdb = statement->rsr_rdb;
  1973. CHECK_HANDLE(rdb, isc_bad_db_handle);
  1974. rem_port* port = rdb->rdb_port;
  1975. if (port->port_protocol < PROTOCOL_VERSION16)
  1976. unsupported();
  1977. // Build input BLR
  1978. RefPtr<IMessageMetadata> meta;
  1979. if (!inMetadata)
  1980. {
  1981. meta.assignRefNoIncr(getInputMetadata(status));
  1982. check(status);
  1983. inMetadata = meta;
  1984. }
  1985. BlrFromMessage inBlr(inMetadata, dialect, port->port_protocol);
  1986. const unsigned int in_blr_length = inBlr.getLength();
  1987. const UCHAR* const in_blr = inBlr.getBytes();
  1988. // Validate data length
  1989. CHECK_LENGTH(port, in_blr_length);
  1990. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  1991. delete statement->rsr_bind_format;
  1992. statement->rsr_bind_format = NULL;
  1993. if (port->port_statement)
  1994. {
  1995. delete port->port_statement->rsr_select_format;
  1996. port->port_statement->rsr_select_format = NULL;
  1997. }
  1998. // Parse the blr describing the message, if there is any.
  1999. if (in_blr_length)
  2000. statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
  2001. RMessage* message = NULL;
  2002. if (!statement->rsr_buffer)
  2003. {
  2004. statement->rsr_buffer = message = FB_NEW RMessage(0);
  2005. statement->rsr_message = message;
  2006. message->msg_next = message;
  2007. statement->rsr_fmt_length = 0;
  2008. }
  2009. else
  2010. message = statement->rsr_message = statement->rsr_buffer;
  2011. statement->rsr_flags.clear(Rsr::FETCHED);
  2012. statement->rsr_format = statement->rsr_bind_format;
  2013. statement->rsr_batch_stream.blobRemaining = 0;
  2014. statement->clearException();
  2015. // set up the packet for the other guy...
  2016. PACKET* packet = &rdb->rdb_packet;
  2017. packet->p_operation = op_batch_create;
  2018. P_BATCH_CREATE* batch = &packet->p_batch_create;
  2019. batch->p_batch_statement = statement->rsr_id;
  2020. batch->p_batch_blr.cstr_length = in_blr_length;
  2021. batch->p_batch_blr.cstr_address = in_blr;
  2022. batch->p_batch_msglen = inMetadata->getMessageLength(status);
  2023. check(status);
  2024. batch->p_batch_pb.cstr_length = parLength;
  2025. batch->p_batch_pb.cstr_address = par;
  2026. if (port->port_flags & PORT_lazy)
  2027. {
  2028. send_partial_packet(port, packet);
  2029. defer_packet(port, packet, true);
  2030. }
  2031. else {
  2032. send_and_receive(status, rdb, packet);
  2033. }
  2034. message->msg_address = NULL;
  2035. Batch* b = FB_NEW Batch(this, inMetadata, parLength, par);
  2036. b->addRef();
  2037. return b;
  2038. }
  2039. catch (const Exception& ex)
  2040. {
  2041. ex.stuffException(status);
  2042. }
  2043. return NULL;
  2044. }
  2045. Batch::Batch(Statement* s, IMessageMetadata* inFmt, unsigned parLength, const unsigned char* par)
  2046. : messageStream(0), blobStream(nullptr), sizePointer(nullptr),
  2047. messageSize(0), alignedSize(0), blobBufferSize(0), messageBufferSize(0), flags(0),
  2048. stmt(s), format(inFmt), blobAlign(0), blobPolicy(BLOB_NONE),
  2049. segmented(false), defSegmented(false), batchActive(false),
  2050. messageCount(0), blobCount(0), serverSize(0), blobHeadSize(0),
  2051. tmpStatement(false)
  2052. {
  2053. LocalStatus ls;
  2054. CheckStatusWrapper st(&ls);
  2055. messageSize = format->getMessageLength(&st);
  2056. check(&st);
  2057. alignedSize = format->getAlignedLength(&st);
  2058. check(&st);
  2059. memset(&genId, 0, sizeof(genId));
  2060. ClumpletReader rdr(ClumpletReader::WideTagged, par, parLength);
  2061. for (rdr.rewind(); !rdr.isEof(); rdr.moveNext())
  2062. {
  2063. UCHAR t = rdr.getClumpTag();
  2064. switch (t)
  2065. {
  2066. case TAG_MULTIERROR:
  2067. case TAG_RECORD_COUNTS:
  2068. if (rdr.getInt())
  2069. flags |= (1 << t);
  2070. else
  2071. flags &= ~(1 << t);
  2072. break;
  2073. case TAG_BLOB_POLICY:
  2074. blobPolicy = rdr.getInt();
  2075. switch (blobPolicy)
  2076. {
  2077. case BLOB_ID_ENGINE:
  2078. case BLOB_ID_USER:
  2079. case BLOB_STREAM:
  2080. break;
  2081. default:
  2082. blobPolicy = BLOB_NONE;
  2083. break;
  2084. }
  2085. break;
  2086. }
  2087. }
  2088. s->getStatement()->rsr_batch_flags = flags;
  2089. // allocate buffers
  2090. Rsr* statement = stmt->getStatement();
  2091. CHECK_HANDLE(statement, isc_bad_req_handle);
  2092. Rdb* rdb = statement->rsr_rdb;
  2093. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2094. rem_port* port = rdb->rdb_port;
  2095. blobBufferSize = port->getPortConfig()->getClientBatchBuffer();
  2096. messageBufferSize = blobBufferSize / alignedSize;
  2097. if (!messageBufferSize)
  2098. messageBufferSize = 1;
  2099. messageStreamBuffer.reset(FB_NEW UCHAR[messageBufferSize * alignedSize]);
  2100. if (blobPolicy != BLOB_NONE)
  2101. {
  2102. blobStreamBuffer.reset(FB_NEW UCHAR[blobBufferSize]);
  2103. blobStream = blobStreamBuffer;
  2104. }
  2105. }
  2106. void Batch::add(CheckStatusWrapper* status, unsigned count, const void* inBuffer)
  2107. {
  2108. try
  2109. {
  2110. // Check and validate handles, etc.
  2111. if (!stmt)
  2112. {
  2113. Arg::Gds(isc_bad_req_handle).raise();
  2114. }
  2115. Rsr* statement = stmt->getStatement();
  2116. CHECK_HANDLE(statement, isc_bad_req_handle);
  2117. Rdb* rdb = statement->rsr_rdb;
  2118. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2119. rem_port* port = rdb->rdb_port;
  2120. if (count == 0)
  2121. return;
  2122. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2123. putMessageData(count, inBuffer);
  2124. batchActive = true;
  2125. }
  2126. catch (const Exception& ex)
  2127. {
  2128. ex.stuffException(status);
  2129. }
  2130. }
  2131. void Batch::sendMessagePacket(unsigned count, const UCHAR* ptr, bool flash)
  2132. {
  2133. Rsr* statement = stmt->getStatement();
  2134. CHECK_HANDLE(statement, isc_bad_req_handle);
  2135. Rdb* rdb = statement->rsr_rdb;
  2136. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2137. rem_port* port = rdb->rdb_port;
  2138. PACKET* packet = &rdb->rdb_packet;
  2139. packet->p_operation = op_batch_msg;
  2140. P_BATCH_MSG* batch = &packet->p_batch_msg;
  2141. batch->p_batch_statement = statement->rsr_id;
  2142. batch->p_batch_messages = count;
  2143. batch->p_batch_data.cstr_address = const_cast<UCHAR*>(ptr);
  2144. statement->rsr_batch_size = alignedSize;
  2145. sendDeferredPacket(nullptr, port, packet, flash);
  2146. messageCount += count;
  2147. }
  2148. void Batch::addBlob(CheckStatusWrapper* status, unsigned length, const void* inBuffer, ISC_QUAD* blobId,
  2149. unsigned parLength, const unsigned char* par)
  2150. {
  2151. try
  2152. {
  2153. // Check and validate handles, etc.
  2154. if (!stmt)
  2155. {
  2156. Arg::Gds(isc_bad_req_handle).raise();
  2157. }
  2158. Rsr* statement = stmt->getStatement();
  2159. CHECK_HANDLE(statement, isc_bad_req_handle);
  2160. Rdb* rdb = statement->rsr_rdb;
  2161. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2162. rem_port* port = rdb->rdb_port;
  2163. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2164. // Policy check
  2165. switch (blobPolicy)
  2166. {
  2167. case IBatch::BLOB_ID_ENGINE:
  2168. genBlobId(blobId);
  2169. break;
  2170. case IBatch::BLOB_ID_USER:
  2171. break;
  2172. default:
  2173. (Arg::Gds(isc_batch_policy) << "addBlob").raise();
  2174. }
  2175. // Build blob HDR in stream
  2176. newBlob();
  2177. putBlobData(sizeof *blobId, blobId);
  2178. setSizePointer();
  2179. putBlobData(sizeof parLength, &parLength);
  2180. putBlobData(sizeof parLength, &parLength);
  2181. putBlobData(parLength, par);
  2182. segmented = parLength ? fb_utils::isBpbSegmented(parLength, par) : defSegmented;
  2183. // Store blob data
  2184. putSegment(length, inBuffer);
  2185. batchActive = true;
  2186. }
  2187. catch (const Exception& ex)
  2188. {
  2189. ex.stuffException(status);
  2190. }
  2191. }
  2192. void Batch::appendBlobData(CheckStatusWrapper* status, unsigned length, const void* inBuffer)
  2193. {
  2194. try
  2195. {
  2196. // Check and validate handles, etc.
  2197. if (!stmt)
  2198. {
  2199. Arg::Gds(isc_bad_req_handle).raise();
  2200. }
  2201. // Policy check
  2202. switch (blobPolicy)
  2203. {
  2204. case IBatch::BLOB_ID_USER:
  2205. case IBatch::BLOB_ID_ENGINE:
  2206. break;
  2207. default:
  2208. (Arg::Gds(isc_batch_policy) << "appendBlobData").raise();
  2209. }
  2210. Rsr* statement = stmt->getStatement();
  2211. CHECK_HANDLE(statement, isc_bad_req_handle);
  2212. Rdb* rdb = statement->rsr_rdb;
  2213. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2214. rem_port* port = rdb->rdb_port;
  2215. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2216. // Store blob data
  2217. putSegment(length, inBuffer);
  2218. }
  2219. catch (const Exception& ex)
  2220. {
  2221. ex.stuffException(status);
  2222. }
  2223. }
  2224. void Batch::addBlobStream(CheckStatusWrapper* status, unsigned length, const void* inBuffer)
  2225. {
  2226. try
  2227. {
  2228. // Check and validate handles, etc.
  2229. if (!stmt)
  2230. {
  2231. Arg::Gds(isc_bad_req_handle).raise();
  2232. }
  2233. // Policy check
  2234. if (blobPolicy != IBatch::BLOB_STREAM)
  2235. {
  2236. (Arg::Gds(isc_batch_policy) << "addBlobStream").raise();
  2237. }
  2238. Rsr* statement = stmt->getStatement();
  2239. CHECK_HANDLE(statement, isc_bad_req_handle);
  2240. Rdb* rdb = statement->rsr_rdb;
  2241. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2242. rem_port* port = rdb->rdb_port;
  2243. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2244. // Store stream data
  2245. putBlobData(length, inBuffer);
  2246. batchActive = true;
  2247. }
  2248. catch (const Exception& ex)
  2249. {
  2250. ex.stuffException(status);
  2251. }
  2252. }
  2253. void Batch::sendBlobPacket(unsigned size, const UCHAR* ptr, bool flash)
  2254. {
  2255. Rsr* statement = stmt->getStatement();
  2256. Rdb* rdb = statement->rsr_rdb;
  2257. rem_port* port = rdb->rdb_port;
  2258. setServerInfo();
  2259. fb_assert(!(size % blobAlign));
  2260. PACKET* packet = &rdb->rdb_packet;
  2261. packet->p_operation = op_batch_blob_stream;
  2262. P_BATCH_BLOB* batch = &packet->p_batch_blob;
  2263. batch->p_batch_statement = statement->rsr_id;
  2264. batch->p_batch_blob_data.cstr_address = const_cast<UCHAR*>(ptr);
  2265. batch->p_batch_blob_data.cstr_length = size;
  2266. sendDeferredPacket(nullptr, port, packet, flash);
  2267. blobCount += size;
  2268. }
  2269. void Batch::sendDeferredPacket(IStatus* status, rem_port* port, PACKET* packet, bool flash)
  2270. {
  2271. if (port->port_flags & PORT_lazy)
  2272. {
  2273. send_partial_packet(port, packet);
  2274. defer_packet(port, packet, true);
  2275. if ((port->port_protocol >= PROTOCOL_VERSION17) &&
  2276. ((port->port_deferred_packets->getCount() >= DEFER_BATCH_LIMIT) || flash))
  2277. {
  2278. packet->p_operation = op_batch_sync;
  2279. send_packet(port, packet);
  2280. receive_packet(port, packet);
  2281. LocalStatus warning;
  2282. port->checkResponse(&warning, packet, false);
  2283. Rsr* statement = stmt->getStatement();
  2284. if (statement->haveException())
  2285. {
  2286. cleanup();
  2287. statement->raiseException();
  2288. }
  2289. }
  2290. }
  2291. else if (status)
  2292. {
  2293. send_and_receive(status, port->port_context, packet);
  2294. }
  2295. else
  2296. {
  2297. LocalStatus local;
  2298. send_and_receive(&local, port->port_context, packet);
  2299. }
  2300. }
  2301. void Batch::setDefaultBpb(CheckStatusWrapper* status, unsigned parLength, const unsigned char* par)
  2302. {
  2303. try
  2304. {
  2305. // Check and validate handles, etc.
  2306. if (!stmt)
  2307. Arg::Gds(isc_bad_req_handle).raise();
  2308. Rsr* statement = stmt->getStatement();
  2309. CHECK_HANDLE(statement, isc_bad_req_handle);
  2310. Rdb* rdb = statement->rsr_rdb;
  2311. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2312. rem_port* port = rdb->rdb_port;
  2313. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2314. // Check for presence of any data in batch buffers
  2315. if (batchHasData())
  2316. Arg::Gds(isc_batch_defbpb).raise();
  2317. // Set default segmentation flag
  2318. defSegmented = fb_utils::isBpbSegmented(parLength, par);
  2319. // Prepare and send the packet
  2320. PACKET* packet = &rdb->rdb_packet;
  2321. packet->p_operation = op_batch_set_bpb;
  2322. P_BATCH_SETBPB* batch = &packet->p_batch_setbpb;
  2323. batch->p_batch_statement = statement->rsr_id;
  2324. batch->p_batch_blob_bpb.cstr_address = par;
  2325. batch->p_batch_blob_bpb.cstr_length = parLength;
  2326. sendDeferredPacket(status, port, packet, true);
  2327. }
  2328. catch (const Exception& ex)
  2329. {
  2330. ex.stuffException(status);
  2331. }
  2332. }
  2333. unsigned Batch::getBlobAlignment(CheckStatusWrapper* status)
  2334. {
  2335. try
  2336. {
  2337. setServerInfo();
  2338. }
  2339. catch (const Exception& ex)
  2340. {
  2341. ex.stuffException(status);
  2342. }
  2343. return blobAlign;
  2344. }
  2345. void Batch::setServerInfo()
  2346. {
  2347. if (blobAlign)
  2348. return;
  2349. // Check and validate handles, etc.
  2350. if (!stmt)
  2351. {
  2352. Arg::Gds(isc_bad_req_handle).raise();
  2353. }
  2354. Rsr* statement = stmt->getStatement();
  2355. CHECK_HANDLE(statement, isc_bad_req_handle);
  2356. Rdb* rdb = statement->rsr_rdb;
  2357. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2358. rem_port* port = rdb->rdb_port;
  2359. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2360. LocalStatus ls;
  2361. CheckStatusWrapper s(&ls);
  2362. if (port->port_protocol < PROTOCOL_VERSION17)
  2363. {
  2364. UCHAR item = isc_info_sql_stmt_blob_align;
  2365. UCHAR buffer[16];
  2366. info(&s, rdb, op_info_sql, statement->rsr_id, 0,
  2367. 1, &item, 0, 0, sizeof(buffer), buffer);
  2368. check(&s);
  2369. // Extract from buffer
  2370. if (buffer[0] != item)
  2371. Arg::Gds(isc_batch_align).raise();
  2372. int len = gds__vax_integer(&buffer[1], 2);
  2373. statement->rsr_batch_stream.alignment = blobAlign = gds__vax_integer(&buffer[3], len);
  2374. if (!blobAlign)
  2375. Arg::Gds(isc_batch_align).raise();
  2376. return;
  2377. }
  2378. // Perform info call to server
  2379. UCHAR items[] = {IBatch::INF_BLOB_ALIGNMENT, IBatch::INF_BUFFER_BYTES_SIZE, IBatch::INF_BLOB_HEADER};
  2380. UCHAR buffer[64];
  2381. info(&s, rdb, op_info_batch, statement->rsr_id, 0,
  2382. sizeof(items), items, 0, 0, sizeof(buffer), buffer);
  2383. check(&s);
  2384. // Extract from buffer
  2385. ClumpletReader out(ClumpletReader::InfoResponse, buffer, sizeof(buffer));
  2386. for (out.rewind(); !out.isEof(); out.moveNext())
  2387. {
  2388. UCHAR item = out.getClumpTag();
  2389. if (item == isc_info_end)
  2390. break;
  2391. switch(item)
  2392. {
  2393. case IBatch::INF_BLOB_ALIGNMENT:
  2394. statement->rsr_batch_stream.alignment = blobAlign = out.getInt();
  2395. break;
  2396. case IBatch::INF_BUFFER_BYTES_SIZE:
  2397. serverSize = out.getInt();
  2398. break;
  2399. case IBatch::INF_BLOB_HEADER:
  2400. blobHeadSize = out.getInt();
  2401. break;
  2402. case isc_info_error:
  2403. (Arg::Gds(isc_batch_align) << Arg::Gds(out.getInt())).raise();
  2404. case isc_info_truncated:
  2405. (Arg::Gds(isc_batch_align) << Arg::Gds(isc_random) << "truncated").raise();
  2406. default:
  2407. {
  2408. string msg;
  2409. msg.printf("Wrong info item %u", item);
  2410. (Arg::Gds(isc_batch_align) << Arg::Gds(isc_random) << msg).raise();
  2411. }
  2412. }
  2413. }
  2414. if (! (blobAlign && serverSize && blobHeadSize))
  2415. Arg::Gds(isc_batch_align).raise();
  2416. }
  2417. IMessageMetadata* Batch::getMetadata(CheckStatusWrapper* status)
  2418. {
  2419. reset(status);
  2420. format->addRef();
  2421. return format;
  2422. }
  2423. void Batch::registerBlob(CheckStatusWrapper* status, const ISC_QUAD* existingBlob, ISC_QUAD* blobId)
  2424. {
  2425. try
  2426. {
  2427. // Check and validate handles, etc.
  2428. if (!stmt)
  2429. {
  2430. Arg::Gds(isc_bad_req_handle).raise();
  2431. }
  2432. Rsr* statement = stmt->getStatement();
  2433. CHECK_HANDLE(statement, isc_bad_req_handle);
  2434. Rdb* rdb = statement->rsr_rdb;
  2435. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2436. rem_port* port = rdb->rdb_port;
  2437. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2438. if (blobPolicy == IBatch::BLOB_ID_ENGINE)
  2439. genBlobId(blobId);
  2440. PACKET* packet = &rdb->rdb_packet;
  2441. packet->p_operation = op_batch_regblob;
  2442. P_BATCH_REGBLOB* batch = &packet->p_batch_regblob;
  2443. batch->p_batch_statement = statement->rsr_id;
  2444. batch->p_batch_exist_id = *existingBlob;
  2445. batch->p_batch_blob_id = *blobId;
  2446. sendDeferredPacket(status, port, packet, true);
  2447. }
  2448. catch (const Exception& ex)
  2449. {
  2450. ex.stuffException(status);
  2451. }
  2452. }
  2453. IBatchCompletionState* Batch::execute(CheckStatusWrapper* status, ITransaction* apiTra)
  2454. {
  2455. try
  2456. {
  2457. // Check and validate handles, etc.
  2458. if (!stmt)
  2459. {
  2460. Arg::Gds(isc_bad_req_handle).raise();
  2461. }
  2462. Rsr* statement = stmt->getStatement();
  2463. CHECK_HANDLE(statement, isc_bad_req_handle);
  2464. Rdb* rdb = statement->rsr_rdb;
  2465. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2466. rem_port* port = rdb->rdb_port;
  2467. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2468. Rtr* transaction = NULL;
  2469. Transaction* rt = stmt->getAttachment()->remoteTransactionInterface(apiTra);
  2470. if (rt)
  2471. {
  2472. transaction = rt->getTransaction();
  2473. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  2474. }
  2475. // Sanity checks complete - flash data in buffers
  2476. flashBatch();
  2477. // Prepare and send execute packet
  2478. PACKET* packet = &rdb->rdb_packet;
  2479. packet->p_operation = op_batch_exec;
  2480. P_BATCH_EXEC* batch = &packet->p_batch_exec;
  2481. batch->p_batch_statement = statement->rsr_id;
  2482. batch->p_batch_transaction = transaction->rtr_id;
  2483. send_packet(port, packet);
  2484. statement->rsr_batch_size = alignedSize;
  2485. AutoPtr<BatchCompletionState, SimpleDispose>
  2486. cs(FB_NEW BatchCompletionState(flags & (1 << IBatch::TAG_RECORD_COUNTS), 256));
  2487. statement->rsr_batch_cs = cs;
  2488. receive_packet(port, packet);
  2489. statement->rsr_batch_cs = nullptr;
  2490. if (packet->p_operation == op_batch_cs)
  2491. {
  2492. // when working with 4.0.0 server we could not raise it in advance...
  2493. statement->clearException();
  2494. return cs.release();
  2495. }
  2496. REMOTE_check_response(status, rdb, packet);
  2497. }
  2498. catch (const Exception& ex)
  2499. {
  2500. ex.stuffException(status);
  2501. }
  2502. return nullptr;
  2503. }
  2504. void Batch::cancel(CheckStatusWrapper* status)
  2505. {
  2506. try
  2507. {
  2508. // Check and validate handles, etc.
  2509. if (!stmt)
  2510. {
  2511. Arg::Gds(isc_dsql_cursor_err).raise();
  2512. }
  2513. Rsr* statement = stmt->getStatement();
  2514. CHECK_HANDLE(statement, isc_bad_req_handle);
  2515. Rdb* rdb = statement->rsr_rdb;
  2516. rem_port* port = rdb->rdb_port;
  2517. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2518. // Cleanup local data
  2519. cleanup();
  2520. batchActive = false;
  2521. // Prepare packet
  2522. PACKET* packet = &rdb->rdb_packet;
  2523. packet->p_operation = op_batch_cancel;
  2524. P_BATCH_FREE_CANCEL* batch = &packet->p_batch_free_cancel;
  2525. batch->p_batch_statement = statement->rsr_id;
  2526. send_and_receive(status, rdb, packet);
  2527. batchActive = false;
  2528. }
  2529. catch (const Exception& ex)
  2530. {
  2531. ex.stuffException(status);
  2532. }
  2533. }
  2534. void Batch::freeClientData(CheckStatusWrapper* status, bool force)
  2535. {
  2536. try
  2537. {
  2538. // Check and validate handles, etc.
  2539. if (!stmt)
  2540. {
  2541. Arg::Gds(isc_dsql_cursor_err).raise();
  2542. }
  2543. Rsr* statement = stmt->getStatement();
  2544. CHECK_HANDLE(statement, isc_bad_req_handle);
  2545. Rdb* rdb = statement->rsr_rdb;
  2546. rem_port* port = rdb->rdb_port;
  2547. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2548. PACKET* packet = &rdb->rdb_packet;
  2549. packet->p_operation = op_batch_rls;
  2550. P_BATCH_FREE_CANCEL* batch = &packet->p_batch_free_cancel;
  2551. batch->p_batch_statement = statement->rsr_id;
  2552. if (rdb->rdb_port->port_flags & PORT_lazy)
  2553. {
  2554. defer_packet(rdb->rdb_port, packet);
  2555. packet->p_resp.p_resp_object = statement->rsr_id;
  2556. }
  2557. else
  2558. {
  2559. try
  2560. {
  2561. send_and_receive(status, rdb, packet);
  2562. }
  2563. catch (const Exception&)
  2564. {
  2565. if (!force)
  2566. throw;
  2567. }
  2568. }
  2569. releaseStatement();
  2570. }
  2571. catch (const Exception& ex)
  2572. {
  2573. ex.stuffException(status);
  2574. }
  2575. }
  2576. void Batch::internalClose(CheckStatusWrapper* status)
  2577. {
  2578. reset(status);
  2579. freeClientData(status);
  2580. }
  2581. void Batch::close(CheckStatusWrapper* status)
  2582. {
  2583. internalClose(status);
  2584. if (status->isEmpty())
  2585. release();
  2586. }
  2587. void Batch::deprecatedClose(CheckStatusWrapper* status)
  2588. {
  2589. internalClose(status);
  2590. }
  2591. void Batch::getInfo(CheckStatusWrapper* status, unsigned int itemsLength, const unsigned char* items,
  2592. unsigned int bufferLength, unsigned char* buffer)
  2593. {
  2594. try
  2595. {
  2596. ClumpletReader it(ClumpletReader::InfoItems, items, itemsLength);
  2597. ClumpletWriter out(ClumpletReader::InfoResponse, bufferLength - 1); // place for isc_info_end / isc_info_truncated
  2598. for (it.rewind(); !it.isEof(); it.moveNext())
  2599. {
  2600. UCHAR item = it.getClumpTag();
  2601. if (item == isc_info_end)
  2602. break;
  2603. try
  2604. {
  2605. switch(item)
  2606. {
  2607. case IBatch::INF_BUFFER_BYTES_SIZE:
  2608. setServerInfo();
  2609. if (serverSize)
  2610. out.insertInt(item, serverSize);
  2611. break;
  2612. case IBatch::INF_DATA_BYTES_SIZE:
  2613. out.insertInt(item, (messageCount + messageStream) * alignedSize);
  2614. break;
  2615. case IBatch::INF_BLOBS_BYTES_SIZE:
  2616. if (blobStream)
  2617. out.insertInt(item, blobCount + (blobStream - blobStreamBuffer));
  2618. break;
  2619. case IBatch::INF_BLOB_ALIGNMENT:
  2620. setServerInfo();
  2621. out.insertInt(item, blobAlign);
  2622. break;
  2623. case IBatch::INF_BLOB_HEADER:
  2624. setServerInfo();
  2625. out.insertInt(item, blobHeadSize);
  2626. break;
  2627. default:
  2628. out.insertInt(isc_info_error, isc_infunk);
  2629. break;
  2630. }
  2631. }
  2632. catch(const fatal_exception&)
  2633. {
  2634. // here it's sooner of all caused by writer overflow but anyway check that
  2635. if (out.hasOverflow())
  2636. {
  2637. memcpy(buffer, out.getBuffer(), out.getBufferLength());
  2638. buffer += out.getBufferLength();
  2639. *buffer++ = isc_info_truncated;
  2640. if (out.getBufferLength() <= bufferLength - 2)
  2641. *buffer++ = isc_info_end;
  2642. return;
  2643. }
  2644. else
  2645. throw;
  2646. }
  2647. }
  2648. memcpy(buffer, out.getBuffer(), out.getBufferLength());
  2649. buffer += out.getBufferLength();
  2650. *buffer++ = isc_info_end;
  2651. }
  2652. catch (const Exception& ex)
  2653. {
  2654. ex.stuffException(status);
  2655. }
  2656. }
  2657. void Batch::releaseStatement()
  2658. {
  2659. if (tmpStatement)
  2660. {
  2661. stmt->release();
  2662. }
  2663. stmt = NULL;
  2664. }
  2665. Replicator* Attachment::createReplicator(CheckStatusWrapper* status)
  2666. {
  2667. /**************************************
  2668. *
  2669. * c r e a t e R e p l i c a t o r
  2670. *
  2671. **************************************
  2672. *
  2673. * Functional description
  2674. * Create data replication interface.
  2675. *
  2676. **************************************/
  2677. try
  2678. {
  2679. reset(status);
  2680. // Check and validate handles, etc.
  2681. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2682. rem_port* port = rdb->rdb_port;
  2683. if (port->port_protocol < PROTOCOL_VERSION16)
  2684. unsupported();
  2685. if (!replicator)
  2686. replicator = FB_NEW Replicator(this);
  2687. replicator->addRef();
  2688. return replicator;
  2689. }
  2690. catch (const Exception& ex)
  2691. {
  2692. ex.stuffException(status);
  2693. }
  2694. return NULL;
  2695. }
  2696. void Replicator::process(CheckStatusWrapper* status, unsigned length, const unsigned char* data)
  2697. {
  2698. try
  2699. {
  2700. reset(status);
  2701. Rdb* rdb = attachment->getRdb();
  2702. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2703. rem_port* port = rdb->rdb_port;
  2704. if (port->port_protocol < PROTOCOL_VERSION16)
  2705. unsupported();
  2706. // Validate data length
  2707. CHECK_LENGTH(port, length);
  2708. PACKET* packet = &rdb->rdb_packet;
  2709. packet->p_operation = op_repl_data;
  2710. P_REPLICATE* repl = &packet->p_replicate;
  2711. repl->p_repl_database = rdb->rdb_id;
  2712. repl->p_repl_data.cstr_length = length;
  2713. repl->p_repl_data.cstr_address = data;
  2714. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2715. send_and_receive(status, rdb, packet);
  2716. }
  2717. catch (const Exception& ex)
  2718. {
  2719. ex.stuffException(status);
  2720. }
  2721. }
  2722. void Replicator::internalClose(CheckStatusWrapper* status)
  2723. {
  2724. reset(status);
  2725. freeClientData(status);
  2726. }
  2727. void Replicator::close(CheckStatusWrapper* status)
  2728. {
  2729. internalClose(status);
  2730. if (status->isEmpty())
  2731. release();
  2732. }
  2733. void Replicator::deprecatedClose(CheckStatusWrapper* status)
  2734. {
  2735. internalClose(status);
  2736. }
  2737. void Replicator::freeClientData(CheckStatusWrapper* status, bool force)
  2738. {
  2739. try
  2740. {
  2741. reset(status);
  2742. if (attachment && attachment->replicator)
  2743. {
  2744. Rdb* rdb = attachment->getRdb();
  2745. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2746. rem_port* port = rdb->rdb_port;
  2747. if (port->port_protocol < PROTOCOL_VERSION16)
  2748. unsupported();
  2749. PACKET* packet = &rdb->rdb_packet;
  2750. packet->p_operation = op_repl_data;
  2751. P_REPLICATE* repl = &packet->p_replicate;
  2752. repl->p_repl_database = rdb->rdb_id;
  2753. repl->p_repl_data.cstr_length = 0;
  2754. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2755. try
  2756. {
  2757. send_and_receive(status, rdb, packet);
  2758. }
  2759. catch (const Exception&)
  2760. {
  2761. if (!force)
  2762. throw;
  2763. }
  2764. attachment->replicator = NULL;
  2765. }
  2766. }
  2767. catch (const Exception& ex)
  2768. {
  2769. ex.stuffException(status);
  2770. }
  2771. }
  2772. ITransaction* Statement::execute(CheckStatusWrapper* status, ITransaction* apiTra,
  2773. IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata, void* outBuffer)
  2774. {
  2775. /**************************************
  2776. *
  2777. * d s q l _ e x e c u t e 2
  2778. *
  2779. **************************************
  2780. *
  2781. * Functional description
  2782. * Execute a non-SELECT dynamic SQL statement.
  2783. *
  2784. **************************************/
  2785. try
  2786. {
  2787. reset(status);
  2788. // Check and validate handles, etc.
  2789. CHECK_HANDLE(statement, isc_bad_req_handle);
  2790. Rdb* rdb = statement->rsr_rdb;
  2791. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2792. rem_port* port = rdb->rdb_port;
  2793. BlrFromMessage inBlr(inMetadata, dialect, port->port_protocol);
  2794. const unsigned int in_blr_length = inBlr.getLength();
  2795. const UCHAR* const in_blr = inBlr.getBytes();
  2796. const unsigned int in_msg_length = inBlr.getMsgLength();
  2797. UCHAR* const in_msg = static_cast<UCHAR*>(inBuffer);
  2798. BlrFromMessage outBlr(outMetadata, dialect, port->port_protocol);
  2799. const unsigned int out_blr_length = outBlr.getLength();
  2800. const UCHAR* const out_blr = outBlr.getBytes();
  2801. const unsigned int out_msg_length = outBlr.getMsgLength();
  2802. UCHAR* const out_msg = static_cast<UCHAR*>(outBuffer);
  2803. // Validate data length
  2804. CHECK_LENGTH(port, in_blr_length);
  2805. CHECK_LENGTH(port, in_msg_length);
  2806. CHECK_LENGTH(port, out_blr_length);
  2807. CHECK_LENGTH(port, out_msg_length);
  2808. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2809. Rtr* transaction = NULL;
  2810. Transaction* rt = remAtt->remoteTransactionInterface(apiTra);
  2811. if (rt)
  2812. {
  2813. transaction = rt->getTransaction();
  2814. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  2815. }
  2816. // 24-Mar-2004 Nickolay Samofatov
  2817. // Unconditionally deallocate existing formats that are left from
  2818. // previous executions (possibly with different statement if
  2819. // isc_dsql_prepare is called multiple times).
  2820. // This should cure SF#919246
  2821. delete statement->rsr_bind_format;
  2822. statement->rsr_bind_format = NULL;
  2823. if (port->port_statement)
  2824. {
  2825. delete port->port_statement->rsr_select_format;
  2826. port->port_statement->rsr_select_format = NULL;
  2827. }
  2828. // Parse the blr describing the message, if there is any.
  2829. if (in_blr_length)
  2830. statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
  2831. // Parse the blr describing the output message. This is not the fetch
  2832. // message! That comes later.
  2833. if (out_blr_length)
  2834. {
  2835. if (!port->port_statement)
  2836. port->port_statement = FB_NEW Rsr;
  2837. port->port_statement->rsr_select_format = PARSE_msg_format(out_blr, out_blr_length);
  2838. if (!port->port_statement->rsr_buffer)
  2839. {
  2840. RMessage* message2 = FB_NEW RMessage(0);
  2841. port->port_statement->rsr_buffer = message2;
  2842. port->port_statement->rsr_message = message2;
  2843. message2->msg_next = message2;
  2844. port->port_statement->rsr_fmt_length = 0;
  2845. }
  2846. }
  2847. RMessage* message = NULL;
  2848. if (!statement->rsr_buffer)
  2849. {
  2850. statement->rsr_buffer = message = FB_NEW RMessage(0);
  2851. statement->rsr_message = message;
  2852. message->msg_next = message;
  2853. statement->rsr_fmt_length = 0;
  2854. }
  2855. else {
  2856. message = statement->rsr_message = statement->rsr_buffer;
  2857. }
  2858. message->msg_address = const_cast<UCHAR*>(in_msg);
  2859. statement->rsr_flags.clear(Rsr::FETCHED);
  2860. statement->rsr_format = statement->rsr_bind_format;
  2861. statement->clearException();
  2862. // set up the packet for the other guy...
  2863. PACKET* packet = &rdb->rdb_packet;
  2864. packet->p_operation = out_msg_length ? op_execute2 : op_execute;
  2865. P_SQLDATA* sqldata = &packet->p_sqldata;
  2866. sqldata->p_sqldata_statement = statement->rsr_id;
  2867. sqldata->p_sqldata_transaction = transaction ? transaction->rtr_id : 0;
  2868. sqldata->p_sqldata_blr.cstr_length = in_blr_length;
  2869. sqldata->p_sqldata_blr.cstr_address = const_cast<UCHAR*>(in_blr); // safe, see protocol.cpp and server.cpp
  2870. sqldata->p_sqldata_message_number = 0;
  2871. sqldata->p_sqldata_messages = (statement->rsr_bind_format) ? 1 : 0;
  2872. sqldata->p_sqldata_out_blr.cstr_length = out_blr_length;
  2873. sqldata->p_sqldata_out_blr.cstr_address = const_cast<UCHAR*>(out_blr);
  2874. sqldata->p_sqldata_out_message_number = 0; // out_msg_type
  2875. sqldata->p_sqldata_timeout = statement->rsr_timeout;
  2876. sqldata->p_sqldata_cursor_flags = 0;
  2877. send_packet(port, packet);
  2878. // Set up the response packet. We may receive an SQL response followed
  2879. // by a normal response packet or simply a response packet.
  2880. message->msg_address = NULL;
  2881. if (out_msg_length)
  2882. port->port_statement->rsr_message->msg_address = out_msg;
  2883. receive_packet(port, packet);
  2884. if (packet->p_operation != op_sql_response)
  2885. REMOTE_check_response(status, rdb, packet);
  2886. else
  2887. {
  2888. port->port_statement->rsr_message->msg_address = NULL;
  2889. receive_response(status, rdb, packet);
  2890. }
  2891. if (transaction && !packet->p_resp.p_resp_object)
  2892. {
  2893. REMOTE_cleanup_transaction(transaction);
  2894. release_transaction(transaction);
  2895. transaction = NULL;
  2896. rt->clear();
  2897. statement->rsr_rtr = NULL;
  2898. return NULL;
  2899. }
  2900. else if (!transaction && packet->p_resp.p_resp_object)
  2901. {
  2902. transaction = make_transaction(rdb, packet->p_resp.p_resp_object);
  2903. statement->rsr_rtr = transaction;
  2904. Transaction* newTrans = FB_NEW Transaction(transaction, remAtt);
  2905. newTrans->addRef();
  2906. return newTrans;
  2907. }
  2908. }
  2909. catch (const Exception& ex)
  2910. {
  2911. ex.stuffException(status);
  2912. }
  2913. return apiTra;
  2914. }
  2915. ResultSet* Statement::openCursor(CheckStatusWrapper* status, Firebird::ITransaction* apiTra,
  2916. IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outFormat, unsigned int flags)
  2917. {
  2918. /**************************************
  2919. *
  2920. * d s q l _ e x e c u t e 2
  2921. *
  2922. **************************************
  2923. *
  2924. * Functional description
  2925. * Execute a non-SELECT dynamic SQL statement.
  2926. *
  2927. **************************************/
  2928. try
  2929. {
  2930. reset(status);
  2931. // Check and validate handles, etc.
  2932. CHECK_HANDLE(statement, isc_bad_req_handle);
  2933. Rdb* rdb = statement->rsr_rdb;
  2934. CHECK_HANDLE(rdb, isc_bad_db_handle);
  2935. rem_port* port = rdb->rdb_port;
  2936. BlrFromMessage inBlr(inMetadata, dialect, port->port_protocol);
  2937. const unsigned int in_blr_length = inBlr.getLength();
  2938. const UCHAR* const in_blr = inBlr.getBytes();
  2939. const unsigned int in_msg_length = inBlr.getMsgLength();
  2940. UCHAR* const in_msg = static_cast<UCHAR*>(inBuffer);
  2941. RefPtr<IMessageMetadata> defaultOutputFormat;
  2942. if (!outFormat)
  2943. {
  2944. defaultOutputFormat.assignRefNoIncr(this->getOutputMetadata(status));
  2945. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  2946. {
  2947. return NULL;
  2948. }
  2949. if (defaultOutputFormat)
  2950. {
  2951. outFormat = defaultOutputFormat;
  2952. }
  2953. }
  2954. BlrFromMessage outBlr((outFormat == DELAYED_OUT_FORMAT ? NULL : outFormat), dialect, port->port_protocol);
  2955. const unsigned int out_blr_length = outBlr.getLength();
  2956. const UCHAR* const out_blr = outBlr.getBytes();
  2957. // Validate data length
  2958. CHECK_LENGTH(port, in_blr_length);
  2959. CHECK_LENGTH(port, in_msg_length);
  2960. CHECK_LENGTH(port, out_blr_length);
  2961. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  2962. Rtr* transaction = NULL;
  2963. Transaction* rt = remAtt->remoteTransactionInterface(apiTra);
  2964. if (rt)
  2965. {
  2966. transaction = rt->getTransaction();
  2967. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  2968. }
  2969. // 24-Mar-2004 Nickolay Samofatov
  2970. // Unconditionally deallocate existing formats that are left from
  2971. // previous executions (possibly with different statement if
  2972. // isc_dsql_prepare is called multiple times).
  2973. // This should cure SF#919246
  2974. delete statement->rsr_bind_format;
  2975. statement->rsr_bind_format = NULL;
  2976. if (port->port_statement)
  2977. {
  2978. delete port->port_statement->rsr_select_format;
  2979. port->port_statement->rsr_select_format = NULL;
  2980. }
  2981. // Parse the blr describing the message, if there is any.
  2982. if (in_blr_length)
  2983. statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
  2984. RMessage* message = NULL;
  2985. if (!statement->rsr_buffer)
  2986. {
  2987. statement->rsr_buffer = message = FB_NEW RMessage(0);
  2988. statement->rsr_message = message;
  2989. message->msg_next = message;
  2990. statement->rsr_fmt_length = 0;
  2991. }
  2992. else {
  2993. message = statement->rsr_message = statement->rsr_buffer;
  2994. }
  2995. message->msg_address = const_cast<UCHAR*>(in_msg);
  2996. statement->rsr_flags.clear(Rsr::FETCHED);
  2997. statement->rsr_format = statement->rsr_bind_format;
  2998. statement->clearException();
  2999. // set up the packet for the other guy...
  3000. PACKET* packet = &rdb->rdb_packet;
  3001. packet->p_operation = op_execute;
  3002. P_SQLDATA* sqldata = &packet->p_sqldata;
  3003. sqldata->p_sqldata_statement = statement->rsr_id;
  3004. sqldata->p_sqldata_transaction = transaction ? transaction->rtr_id : 0;
  3005. sqldata->p_sqldata_blr.cstr_length = in_blr_length;
  3006. sqldata->p_sqldata_blr.cstr_address = const_cast<UCHAR*>(in_blr); // safe, see protocol.cpp and server.cpp
  3007. sqldata->p_sqldata_message_number = 0;
  3008. sqldata->p_sqldata_messages = (statement->rsr_bind_format) ? 1 : 0;
  3009. sqldata->p_sqldata_out_blr.cstr_length = out_blr_length;
  3010. sqldata->p_sqldata_out_blr.cstr_address = const_cast<UCHAR*>(out_blr);
  3011. sqldata->p_sqldata_out_message_number = 0; // out_msg_type
  3012. sqldata->p_sqldata_timeout = statement->rsr_timeout;
  3013. sqldata->p_sqldata_cursor_flags = flags;
  3014. {
  3015. Firebird::Cleanup msgClean([&message] {
  3016. message->msg_address = NULL;
  3017. });
  3018. if (statement->rsr_flags.test(Rsr::DEFER_EXECUTE))
  3019. {
  3020. send_partial_packet(port, packet);
  3021. defer_packet(port, packet, true);
  3022. }
  3023. else
  3024. {
  3025. send_and_receive(status, rdb, packet);
  3026. }
  3027. }
  3028. ResultSet* rs = FB_NEW ResultSet(this, outFormat, flags);
  3029. rs->addRef();
  3030. return rs;
  3031. }
  3032. catch (const Exception& ex)
  3033. {
  3034. ex.stuffException(status);
  3035. }
  3036. return NULL;
  3037. }
  3038. IResultSet* Attachment::openCursor(CheckStatusWrapper* status, ITransaction* transaction,
  3039. unsigned int stmtLength, const char* sqlStmt, unsigned dialect,
  3040. IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata,
  3041. const char* cursorName, unsigned int cursorFlags)
  3042. {
  3043. Statement* stmt = prepare(status, transaction, stmtLength, sqlStmt, dialect,
  3044. (outMetadata ? 0 : IStatement::PREPARE_PREFETCH_OUTPUT_PARAMETERS));
  3045. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  3046. {
  3047. return NULL;
  3048. }
  3049. ResultSet* rc = stmt->openCursor(status, transaction, inMetadata, inBuffer, outMetadata, cursorFlags);
  3050. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  3051. {
  3052. stmt->release();
  3053. return NULL;
  3054. }
  3055. if (cursorName)
  3056. {
  3057. stmt->setCursorName(status, cursorName);
  3058. if (status->getState() & Firebird::IStatus::STATE_ERRORS)
  3059. {
  3060. rc->release();
  3061. stmt->release();
  3062. return NULL;
  3063. }
  3064. }
  3065. rc->tmpStatement = true;
  3066. return rc;
  3067. }
  3068. ITransaction* Attachment::execute(CheckStatusWrapper* status, ITransaction* apiTra,
  3069. unsigned int stmtLength, const char* sqlStmt, unsigned int dialect,
  3070. IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata, void* outBuffer)
  3071. {
  3072. /**************************************
  3073. *
  3074. * d s q l _ e x e c u t e _ i m m e d i a t e 2
  3075. *
  3076. **************************************
  3077. *
  3078. * Functional description
  3079. * Prepare and execute a statement.
  3080. *
  3081. **************************************/
  3082. try
  3083. {
  3084. // Check and validate handles, etc.
  3085. CHECK_HANDLE(rdb, isc_bad_db_handle);
  3086. rem_port* port = rdb->rdb_port;
  3087. BlrFromMessage inBlr(inMetadata, dialect, port->port_protocol);
  3088. const unsigned int in_blr_length = inBlr.getLength();
  3089. const UCHAR* const in_blr = inBlr.getBytes();
  3090. const unsigned int in_msg_length = inBlr.getMsgLength();
  3091. UCHAR* const in_msg = static_cast<UCHAR*>(inBuffer);
  3092. BlrFromMessage outBlr(outMetadata, dialect, port->port_protocol);
  3093. const unsigned int out_blr_length = outBlr.getLength();
  3094. const UCHAR* const out_blr = outBlr.getBytes();
  3095. const unsigned int out_msg_length = outBlr.getMsgLength();
  3096. UCHAR* const out_msg = static_cast<UCHAR*>(outBuffer);
  3097. // Validate data length
  3098. CHECK_LENGTH(port, in_blr_length);
  3099. CHECK_LENGTH(port, in_msg_length);
  3100. CHECK_LENGTH(port, out_blr_length);
  3101. CHECK_LENGTH(port, out_msg_length);
  3102. if (sqlStmt && !stmtLength)
  3103. stmtLength = static_cast<ULONG>(strlen(sqlStmt));
  3104. // Validate string length
  3105. CHECK_LENGTH(port, stmtLength);
  3106. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3107. Rtr* transaction = NULL;
  3108. Transaction* rt = remoteTransactionInterface(apiTra);
  3109. if (rt)
  3110. {
  3111. transaction = rt->getTransaction();
  3112. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  3113. }
  3114. if (dialect > 10)
  3115. {
  3116. // dimitr: adjust dialect received after
  3117. // a multi-hop transmission to be
  3118. // redirected in its original value.
  3119. dialect /= 10;
  3120. }
  3121. reset(status);
  3122. Rsr* statement = port->port_statement;
  3123. if (!statement) {
  3124. statement = port->port_statement = FB_NEW Rsr;
  3125. }
  3126. // reset statement buffers
  3127. clear_queue(rdb->rdb_port);
  3128. REMOTE_reset_statement(statement);
  3129. delete statement->rsr_bind_format;
  3130. statement->rsr_bind_format = NULL;
  3131. delete statement->rsr_select_format;
  3132. statement->rsr_select_format = NULL;
  3133. if (in_msg_length || out_msg_length)
  3134. {
  3135. if (in_blr_length)
  3136. statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
  3137. if (out_blr_length)
  3138. statement->rsr_select_format = PARSE_msg_format(out_blr, out_blr_length);
  3139. }
  3140. RMessage* message = 0;
  3141. if (!statement->rsr_buffer)
  3142. {
  3143. statement->rsr_buffer = message = FB_NEW RMessage(0);
  3144. statement->rsr_message = message;
  3145. message->msg_next = message;
  3146. statement->rsr_fmt_length = 0;
  3147. }
  3148. else {
  3149. message = statement->rsr_message = statement->rsr_buffer;
  3150. }
  3151. message->msg_address = const_cast<UCHAR*>(in_msg);
  3152. statement->clearException();
  3153. // set up the packet for the other guy...
  3154. PACKET* packet = &rdb->rdb_packet;
  3155. packet->p_operation = (in_msg_length || out_msg_length) ?
  3156. op_exec_immediate2 : op_exec_immediate;
  3157. P_SQLST* ex_now = &packet->p_sqlst;
  3158. ex_now->p_sqlst_transaction = transaction ? transaction->rtr_id : 0;
  3159. ex_now->p_sqlst_SQL_dialect = dialect;
  3160. ex_now->p_sqlst_SQL_str.cstr_length = stmtLength;
  3161. ex_now->p_sqlst_SQL_str.cstr_address = reinterpret_cast<const UCHAR*>(sqlStmt);
  3162. ex_now->p_sqlst_items.cstr_length = 0;
  3163. ex_now->p_sqlst_buffer_length = 0;
  3164. ex_now->p_sqlst_blr.cstr_length = in_blr_length;
  3165. ex_now->p_sqlst_blr.cstr_address = const_cast<UCHAR*>(in_blr);
  3166. ex_now->p_sqlst_message_number = 0;
  3167. ex_now->p_sqlst_messages = (in_msg_length && statement->rsr_bind_format) ? 1 : 0;
  3168. ex_now->p_sqlst_out_blr.cstr_length = out_blr_length;
  3169. ex_now->p_sqlst_out_blr.cstr_address = const_cast<unsigned char*>(out_blr);
  3170. ex_now->p_sqlst_out_message_number = 0; // out_msg_type
  3171. send_packet(port, packet);
  3172. // SEND could have changed the message
  3173. message = statement->rsr_message;
  3174. // Set up the response packet. We may receive an SQL response followed
  3175. // by a normal response packet or simply a response packet.
  3176. if (in_msg_length || out_msg_length)
  3177. port->port_statement->rsr_message->msg_address = out_msg;
  3178. receive_packet(rdb->rdb_port, packet);
  3179. if (packet->p_operation != op_sql_response)
  3180. REMOTE_check_response(status, rdb, packet);
  3181. else
  3182. {
  3183. message->msg_address = NULL;
  3184. receive_response(status, rdb, packet);
  3185. }
  3186. if (transaction && !packet->p_resp.p_resp_object)
  3187. {
  3188. REMOTE_cleanup_transaction(transaction);
  3189. release_transaction(transaction);
  3190. transaction = NULL;
  3191. rt->clear();
  3192. return NULL;
  3193. }
  3194. else if (!transaction && packet->p_resp.p_resp_object)
  3195. {
  3196. transaction = make_transaction(rdb, packet->p_resp.p_resp_object);
  3197. Firebird::ITransaction* newTrans = FB_NEW Transaction(transaction, this);
  3198. newTrans->addRef();
  3199. return newTrans;
  3200. }
  3201. }
  3202. catch (const Exception& ex)
  3203. {
  3204. ex.stuffException(status);
  3205. }
  3206. return apiTra;
  3207. }
  3208. void Statement::freeClientData(CheckStatusWrapper* status, bool force)
  3209. {
  3210. /**************************************
  3211. *
  3212. * d s q l _ f r e e _ s t a t e m e n t
  3213. *
  3214. **************************************
  3215. *
  3216. * Functional description
  3217. * Release request for a Dynamic SQL statement
  3218. *
  3219. **************************************/
  3220. try
  3221. {
  3222. // Check and validate handles, etc.
  3223. if (!statement)
  3224. {
  3225. return;
  3226. }
  3227. CHECK_HANDLE(statement, isc_bad_req_handle);
  3228. Rdb* rdb = statement->rsr_rdb;
  3229. CHECK_HANDLE(rdb, isc_bad_db_handle);
  3230. rem_port* port = rdb->rdb_port;
  3231. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3232. fb_assert(statement->haveException() == 0);
  3233. statement->clearException();
  3234. if (statement->rsr_flags.test(Rsr::LAZY))
  3235. {
  3236. release_sql_request(statement);
  3237. statement = NULL;
  3238. return;
  3239. }
  3240. PACKET* packet = &rdb->rdb_packet;
  3241. packet->p_operation = op_free_statement;
  3242. P_SQLFREE* free_stmt = &packet->p_sqlfree;
  3243. free_stmt->p_sqlfree_statement = statement->rsr_id;
  3244. free_stmt->p_sqlfree_option = DSQL_drop;
  3245. if (rdb->rdb_port->port_flags & PORT_lazy)
  3246. {
  3247. send_packet(rdb->rdb_port, packet);
  3248. defer_packet(rdb->rdb_port, packet, true);
  3249. packet->p_resp.p_resp_object = statement->rsr_id;
  3250. }
  3251. else
  3252. {
  3253. try
  3254. {
  3255. send_and_receive(status, rdb, packet);
  3256. }
  3257. catch (const Exception&)
  3258. {
  3259. if (!force)
  3260. throw;
  3261. }
  3262. }
  3263. if (packet->p_resp.p_resp_object == INVALID_OBJECT)
  3264. {
  3265. release_sql_request(statement);
  3266. }
  3267. else
  3268. {
  3269. statement->rsr_flags.clear(Rsr::FETCHED);
  3270. statement->rsr_rtr = NULL;
  3271. clear_queue(rdb->rdb_port);
  3272. REMOTE_reset_statement(statement);
  3273. }
  3274. statement = NULL;
  3275. }
  3276. catch (const Exception& ex)
  3277. {
  3278. ex.stuffException(status);
  3279. }
  3280. }
  3281. void Statement::internalFree(CheckStatusWrapper* status)
  3282. {
  3283. /**************************************
  3284. *
  3285. * d s q l _ f r e e _ s t a t e m e n t
  3286. *
  3287. **************************************
  3288. *
  3289. * Functional description
  3290. * Release request for a Dynamic SQL statement
  3291. *
  3292. **************************************/
  3293. reset(status);
  3294. freeClientData(status);
  3295. }
  3296. void Statement::free(CheckStatusWrapper* status)
  3297. {
  3298. internalFree(status);
  3299. if (status->isEmpty())
  3300. release();
  3301. }
  3302. void Statement::deprecatedFree(CheckStatusWrapper* status)
  3303. {
  3304. internalFree(status);
  3305. }
  3306. Statement* Attachment::createStatement(CheckStatusWrapper* status, unsigned dialect)
  3307. {
  3308. reset(status);
  3309. Rsr* statement = NULL;
  3310. if (rdb->rdb_port->port_flags & PORT_lazy)
  3311. {
  3312. statement = FB_NEW Rsr;
  3313. statement->rsr_rdb = rdb;
  3314. statement->rsr_id = INVALID_OBJECT;
  3315. statement->rsr_flags.set(Rsr::LAZY);
  3316. }
  3317. else
  3318. {
  3319. PACKET* packet = &rdb->rdb_packet;
  3320. packet->p_operation = op_allocate_statement;
  3321. packet->p_rlse.p_rlse_object = rdb->rdb_id;
  3322. send_and_receive(status, rdb, packet);
  3323. // Allocate SQL request block
  3324. statement = FB_NEW Rsr;
  3325. statement->rsr_rdb = rdb;
  3326. statement->rsr_id = packet->p_resp.p_resp_object;
  3327. // register the object
  3328. SET_OBJECT(rdb, statement, statement->rsr_id);
  3329. }
  3330. statement->rsr_next = rdb->rdb_sql_requests;
  3331. rdb->rdb_sql_requests = statement;
  3332. Statement* s = FB_NEW Statement(statement, this, dialect);
  3333. s->addRef();
  3334. return s;
  3335. }
  3336. Statement* Attachment::prepare(CheckStatusWrapper* status, ITransaction* apiTra,
  3337. unsigned int stmtLength, const char* sqlStmt, unsigned int dialect, unsigned int flags)
  3338. {
  3339. /**************************************
  3340. *
  3341. * d s q l _ p r e p a r e
  3342. *
  3343. **************************************
  3344. *
  3345. * Functional description
  3346. * Prepare a dynamic SQL statement for execution.
  3347. *
  3348. **************************************/
  3349. Statement* stmt = NULL;
  3350. try
  3351. {
  3352. reset(status);
  3353. // Check and validate handles, etc.
  3354. CHECK_HANDLE(rdb, isc_bad_db_handle);
  3355. rem_port* port = rdb->rdb_port;
  3356. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3357. Rtr* transaction = NULL;
  3358. if (apiTra)
  3359. {
  3360. transaction = remoteTransaction(apiTra);
  3361. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  3362. }
  3363. if (sqlStmt && !stmtLength)
  3364. stmtLength = static_cast<ULONG>(strlen(sqlStmt));
  3365. // Validate string length
  3366. CHECK_LENGTH(port, stmtLength);
  3367. if (dialect > 10)
  3368. {
  3369. // dimitr: adjust dialect received after
  3370. // a multi-hop transmission to be
  3371. // redirected in its original value.
  3372. dialect /= 10;
  3373. }
  3374. // create new statement
  3375. stmt = createStatement(status, dialect);
  3376. Rsr* statement = stmt->getStatement();
  3377. // reset current statement
  3378. clear_queue(rdb->rdb_port);
  3379. REMOTE_reset_statement(statement);
  3380. // set up the packet for the other guy...
  3381. PACKET* packet = &rdb->rdb_packet;
  3382. if (statement->rsr_flags.test(Rsr::LAZY))
  3383. {
  3384. packet->p_operation = op_allocate_statement;
  3385. packet->p_rlse.p_rlse_object = rdb->rdb_id;
  3386. send_partial_packet(rdb->rdb_port, packet);
  3387. }
  3388. Array<UCHAR> items, buffer;
  3389. buffer.resize(StatementMetadata::buildInfoItems(items, flags));
  3390. // Validate data length
  3391. CHECK_LENGTH(port, items.getCount());
  3392. CHECK_LENGTH(port, buffer.getCount());
  3393. packet->p_operation = op_prepare_statement;
  3394. P_SQLST* prepare = &packet->p_sqlst;
  3395. prepare->p_sqlst_transaction = transaction ? transaction->rtr_id : 0;
  3396. prepare->p_sqlst_statement = statement->rsr_id;
  3397. prepare->p_sqlst_SQL_dialect = dialect;
  3398. prepare->p_sqlst_SQL_str.cstr_length = stmtLength;
  3399. prepare->p_sqlst_SQL_str.cstr_address = reinterpret_cast<const UCHAR*>(sqlStmt);
  3400. prepare->p_sqlst_items.cstr_length = (ULONG) items.getCount();
  3401. prepare->p_sqlst_items.cstr_address = items.begin();
  3402. prepare->p_sqlst_buffer_length = (ULONG) buffer.getCount();
  3403. send_packet(rdb->rdb_port, packet);
  3404. statement->rsr_flags.clear(Rsr::DEFER_EXECUTE);
  3405. // Set up for the response packet.
  3406. if (statement->rsr_flags.test(Rsr::LAZY))
  3407. {
  3408. receive_response(status, rdb, packet);
  3409. statement->rsr_id = packet->p_resp.p_resp_object;
  3410. SET_OBJECT(rdb, statement, statement->rsr_id);
  3411. statement->rsr_flags.clear(Rsr::LAZY);
  3412. }
  3413. P_RESP* response = &packet->p_resp;
  3414. SaveString temp(response->p_resp_data, buffer.getCount(), buffer.begin());
  3415. try
  3416. {
  3417. receive_response(status, rdb, packet);
  3418. stmt->parseMetadata(buffer);
  3419. }
  3420. catch (const Exception& ex)
  3421. {
  3422. ex.stuffException(status);
  3423. }
  3424. if (rdb->rdb_port->port_flags & PORT_lazy)
  3425. {
  3426. if (response->p_resp_object & STMT_DEFER_EXECUTE) {
  3427. statement->rsr_flags.set(Rsr::DEFER_EXECUTE);
  3428. }
  3429. }
  3430. else
  3431. {
  3432. fb_assert(!response->p_resp_object);
  3433. response->p_resp_object = 0;
  3434. }
  3435. if (!(status->getState() & Firebird::IStatus::STATE_ERRORS))
  3436. {
  3437. return stmt;
  3438. }
  3439. }
  3440. catch (const Exception& ex)
  3441. {
  3442. ex.stuffException(status);
  3443. }
  3444. // free statement in case of error
  3445. if (stmt)
  3446. {
  3447. stmt->release();
  3448. }
  3449. return NULL;
  3450. }
  3451. void Statement::getInfo(CheckStatusWrapper* status,
  3452. unsigned int itemsLength, const unsigned char* items,
  3453. unsigned int bufferLength, unsigned char* buffer)
  3454. {
  3455. /**************************************
  3456. *
  3457. * d s q l _ s q l _ i n f o
  3458. *
  3459. **************************************
  3460. *
  3461. * Functional description
  3462. * Provide information on sql object.
  3463. *
  3464. **************************************/
  3465. try
  3466. {
  3467. reset(status);
  3468. // Check and validate handles, etc.
  3469. CHECK_HANDLE(statement, isc_bad_req_handle);
  3470. Rdb* rdb = statement->rsr_rdb;
  3471. rem_port* port = rdb->rdb_port;
  3472. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3473. statement->raiseException();
  3474. if (!metadata.fillFromCache(itemsLength, items, bufferLength, buffer))
  3475. {
  3476. info(status, rdb, op_info_sql, statement->rsr_id, 0,
  3477. itemsLength, items, 0, 0, bufferLength, buffer);
  3478. metadata.parse(bufferLength, buffer);
  3479. }
  3480. statement->raiseException();
  3481. }
  3482. catch (const Exception& ex)
  3483. {
  3484. ex.stuffException(status);
  3485. }
  3486. }
  3487. unsigned Statement::getType(CheckStatusWrapper* status)
  3488. {
  3489. try
  3490. {
  3491. reset(status);
  3492. // Check and validate handles, etc.
  3493. CHECK_HANDLE(statement, isc_bad_req_handle);
  3494. Rdb* rdb = statement->rsr_rdb;
  3495. rem_port* port = rdb->rdb_port;
  3496. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3497. statement->raiseException();
  3498. return metadata.getType();
  3499. }
  3500. catch (const Exception& ex)
  3501. {
  3502. ex.stuffException(status);
  3503. }
  3504. return 0;
  3505. }
  3506. unsigned Statement::getFlags(CheckStatusWrapper* status)
  3507. {
  3508. try
  3509. {
  3510. reset(status);
  3511. // Check and validate handles, etc.
  3512. CHECK_HANDLE(statement, isc_bad_req_handle);
  3513. Rdb* rdb = statement->rsr_rdb;
  3514. rem_port* port = rdb->rdb_port;
  3515. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3516. statement->raiseException();
  3517. if (port->port_protocol >= PROTOCOL_VERSION13)
  3518. {
  3519. // we are in luck - use flags from server
  3520. return metadata.getFlags();
  3521. }
  3522. // Need to guess flags based on statement type
  3523. unsigned value = IStatement::FLAG_REPEAT_EXECUTE;
  3524. switch (metadata.getType())
  3525. {
  3526. case isc_info_sql_stmt_ddl:
  3527. value &= ~IStatement::FLAG_REPEAT_EXECUTE;
  3528. break;
  3529. case isc_info_sql_stmt_select:
  3530. case isc_info_sql_stmt_select_for_upd:
  3531. value |= IStatement::FLAG_HAS_CURSOR;
  3532. break;
  3533. }
  3534. return value;
  3535. }
  3536. catch (const Exception& ex)
  3537. {
  3538. ex.stuffException(status);
  3539. }
  3540. return 0;
  3541. }
  3542. const char* Statement::getPlan(CheckStatusWrapper* status, FB_BOOLEAN detailed)
  3543. {
  3544. try
  3545. {
  3546. reset(status);
  3547. // Check and validate handles, etc.
  3548. CHECK_HANDLE(statement, isc_bad_req_handle);
  3549. Rdb* rdb = statement->rsr_rdb;
  3550. rem_port* port = rdb->rdb_port;
  3551. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3552. statement->raiseException();
  3553. return metadata.getPlan(detailed);
  3554. }
  3555. catch (const Exception& ex)
  3556. {
  3557. ex.stuffException(status);
  3558. }
  3559. return NULL;
  3560. }
  3561. IMessageMetadata* Statement::getInputMetadata(CheckStatusWrapper* status)
  3562. {
  3563. try
  3564. {
  3565. reset(status);
  3566. // Check and validate handles, etc.
  3567. CHECK_HANDLE(statement, isc_bad_req_handle);
  3568. Rdb* rdb = statement->rsr_rdb;
  3569. rem_port* port = rdb->rdb_port;
  3570. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3571. statement->raiseException();
  3572. return metadata.getInputMetadata();
  3573. }
  3574. catch (const Exception& ex)
  3575. {
  3576. ex.stuffException(status);
  3577. }
  3578. return NULL;
  3579. }
  3580. IMessageMetadata* Statement::getOutputMetadata(CheckStatusWrapper* status)
  3581. {
  3582. try
  3583. {
  3584. reset(status);
  3585. // Check and validate handles, etc.
  3586. CHECK_HANDLE(statement, isc_bad_req_handle);
  3587. Rdb* rdb = statement->rsr_rdb;
  3588. rem_port* port = rdb->rdb_port;
  3589. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3590. statement->raiseException();
  3591. return metadata.getOutputMetadata();
  3592. }
  3593. catch (const Exception& ex)
  3594. {
  3595. ex.stuffException(status);
  3596. }
  3597. return NULL;
  3598. }
  3599. ISC_UINT64 Statement::getAffectedRecords(CheckStatusWrapper* status)
  3600. {
  3601. try
  3602. {
  3603. reset(status);
  3604. // Check and validate handles, etc.
  3605. CHECK_HANDLE(statement, isc_bad_req_handle);
  3606. Rdb* rdb = statement->rsr_rdb;
  3607. rem_port* port = rdb->rdb_port;
  3608. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3609. statement->raiseException();
  3610. return metadata.getAffectedRecords();
  3611. }
  3612. catch (const Exception& ex)
  3613. {
  3614. ex.stuffException(status);
  3615. }
  3616. return 0;
  3617. }
  3618. void Statement::setCursorName(CheckStatusWrapper* status, const char* cursor)
  3619. {
  3620. /*****************************************
  3621. *
  3622. * d s q l _ s e t _ c u r s o r
  3623. *
  3624. *****************************************
  3625. *
  3626. * Functional Description
  3627. * Declare a cursor for a dynamic request.
  3628. *
  3629. * Note: prior to version 6.0, this function terminated the
  3630. * cursor name at the first blank. With delimited cursor
  3631. * name support that is no longer sufficient. We now pass
  3632. * the entire NULL-Terminated cursor name to the server, and let
  3633. * the server deal with blank termination or not.
  3634. * NOTE: THIS NOW MEANS THAT IF CURSOR is NOT null terminated
  3635. * we will have inconsistant results with version 5.x. The only
  3636. * "normal" way this happens is if this API is called from a
  3637. * non-C host language. If that results in a later problem we
  3638. * must provide a new API that takes a "cursor_name_length"
  3639. * parameter.
  3640. *
  3641. *****************************************/
  3642. try
  3643. {
  3644. reset(status);
  3645. // Check and validate handles, etc.
  3646. Rsr* statement = getStatement();
  3647. CHECK_HANDLE(statement, isc_bad_req_handle);
  3648. Rdb* rdb = statement->rsr_rdb;
  3649. rem_port* port = rdb->rdb_port;
  3650. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3651. statement->raiseException();
  3652. // set up the packet for the other guy...
  3653. PACKET* packet = &rdb->rdb_packet;
  3654. if (statement->rsr_flags.test(Rsr::LAZY))
  3655. {
  3656. packet->p_operation = op_allocate_statement;
  3657. packet->p_rlse.p_rlse_object = rdb->rdb_id;
  3658. send_partial_packet(rdb->rdb_port, packet);
  3659. }
  3660. packet->p_operation = op_set_cursor;
  3661. P_SQLCUR* sqlcur = &packet->p_sqlcur;
  3662. sqlcur->p_sqlcur_statement = statement->rsr_id;
  3663. const ULONG name_l = static_cast<ULONG>(strlen(cursor));
  3664. sqlcur->p_sqlcur_cursor_name.cstr_length = name_l + 1;
  3665. sqlcur->p_sqlcur_cursor_name.cstr_address = reinterpret_cast<const UCHAR*>(cursor);
  3666. sqlcur->p_sqlcur_type = 0; // type
  3667. send_packet(port, packet);
  3668. if (statement->rsr_flags.test(Rsr::LAZY))
  3669. {
  3670. receive_response(status, rdb, packet);
  3671. statement->rsr_id = packet->p_resp.p_resp_object;
  3672. SET_OBJECT(rdb, statement, statement->rsr_id);
  3673. statement->rsr_flags.clear(Rsr::LAZY);
  3674. }
  3675. receive_response(status, rdb, packet);
  3676. statement->raiseException();
  3677. }
  3678. catch (const Exception& ex)
  3679. {
  3680. ex.stuffException(status);
  3681. }
  3682. }
  3683. void ResultSet::setDelayedOutputFormat(CheckStatusWrapper* status, IMessageMetadata* format)
  3684. {
  3685. try
  3686. {
  3687. reset(status);
  3688. // Check and validate handles, etc.
  3689. if (!delayedFormat)
  3690. {
  3691. (Arg::Gds(isc_dsql_cursor_err) << Arg::Gds(isc_bad_req_handle)).raise();
  3692. }
  3693. outputFormat = format;
  3694. delayedFormat = false;
  3695. }
  3696. catch (const Exception& ex)
  3697. {
  3698. ex.stuffException(status);
  3699. }
  3700. }
  3701. bool ResultSet::fetch(CheckStatusWrapper* status, void* buffer, P_FETCH operation, int position)
  3702. {
  3703. /**************************************
  3704. *
  3705. * d s q l _ f e t c h
  3706. *
  3707. **************************************
  3708. *
  3709. * Functional description
  3710. * Fetch next record from a dynamic SQL cursor.
  3711. *
  3712. **************************************/
  3713. reset(status);
  3714. // Check and validate handles, etc.
  3715. if (delayedFormat || !stmt)
  3716. {
  3717. (Arg::Gds(isc_dsql_cursor_err) << Arg::Gds(isc_bad_req_handle)).raise();
  3718. }
  3719. Rsr* const statement = stmt->getStatement();
  3720. CHECK_HANDLE(statement, isc_bad_req_handle);
  3721. Rdb* const rdb = statement->rsr_rdb;
  3722. CHECK_HANDLE(rdb, isc_bad_db_handle);
  3723. rem_port* const port = rdb->rdb_port;
  3724. // Scrolling is not available in older protocols
  3725. if (operation != fetch_next && port->port_protocol < PROTOCOL_FETCH_SCROLL)
  3726. unsupported();
  3727. // Whether we're fetching relatively to the current position
  3728. const bool relative =
  3729. (operation == fetch_next || operation == fetch_prior || operation == fetch_relative);
  3730. BlrFromMessage outBlr(outputFormat, stmt->getDialect(), port->port_protocol);
  3731. unsigned int blr_length = outBlr.getLength();
  3732. const UCHAR* blr = outBlr.getBytes();
  3733. const unsigned int msg_length = outBlr.getMsgLength();
  3734. UCHAR* msg = static_cast<UCHAR*>(buffer);
  3735. // Validate data length
  3736. CHECK_LENGTH(port, blr_length);
  3737. CHECK_LENGTH(port, msg_length);
  3738. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  3739. if (!statement->rsr_flags.test(Rsr::FETCHED))
  3740. {
  3741. // On first fetch, clear the end-of-stream flag & reset the message buffers
  3742. statement->raiseException();
  3743. statement->rsr_flags.clear(Rsr::STREAM_END | Rsr::PAST_END | Rsr::STREAM_ERR);
  3744. statement->rsr_rows_pending = 0;
  3745. statement->rsr_fetch_operation = operation;
  3746. statement->rsr_fetch_position = position;
  3747. statement->clearException();
  3748. RMessage* message = statement->rsr_message;
  3749. if (message)
  3750. {
  3751. statement->rsr_buffer = message;
  3752. while (true)
  3753. {
  3754. message->msg_address = NULL;
  3755. message = message->msg_next;
  3756. if (message == statement->rsr_message)
  3757. break;
  3758. }
  3759. }
  3760. }
  3761. else if (!relative)
  3762. {
  3763. // Clear the end-of-stream flag if the fetch is positioned absolutely
  3764. statement->rsr_flags.clear(Rsr::STREAM_END | Rsr::PAST_END);
  3765. }
  3766. else if (statement->rsr_flags.test(Rsr::PAST_END))
  3767. {
  3768. // If we're already at BOF/EOF and the requested fetch operation
  3769. // cannot change our position, just do nothing
  3770. if (operation == fetch_relative && position == 0)
  3771. return false;
  3772. if ((operation == fetch_next || (operation == fetch_relative && position > 0)) &&
  3773. statement->rsr_flags.test(Rsr::PAST_EOF))
  3774. {
  3775. return false;
  3776. }
  3777. if ((operation == fetch_prior || (operation == fetch_relative && position < 0)) &&
  3778. statement->rsr_flags.test(Rsr::PAST_BOF))
  3779. {
  3780. return false;
  3781. }
  3782. }
  3783. // Parse the blr describing the message, if there is any.
  3784. if (blr_length)
  3785. {
  3786. if (statement->rsr_user_select_format &&
  3787. statement->rsr_user_select_format != statement->rsr_select_format)
  3788. {
  3789. delete statement->rsr_user_select_format;
  3790. }
  3791. statement->rsr_user_select_format = PARSE_msg_format(blr, blr_length);
  3792. if (statement->rsr_flags.test(Rsr::FETCHED))
  3793. blr_length = 0;
  3794. else
  3795. {
  3796. delete statement->rsr_select_format;
  3797. statement->rsr_select_format = statement->rsr_user_select_format;
  3798. }
  3799. }
  3800. if (!statement->rsr_buffer)
  3801. {
  3802. statement->rsr_buffer = FB_NEW RMessage(0);
  3803. statement->rsr_message = statement->rsr_buffer;
  3804. statement->rsr_message->msg_next = statement->rsr_message;
  3805. statement->rsr_fmt_length = 0;
  3806. }
  3807. RMessage* message = statement->rsr_message;
  3808. #ifdef DEBUG
  3809. fprintf(stdout, "Rows Pending in REM_fetch=%lu\n", statement->rsr_rows_pending);
  3810. #endif
  3811. // If the fetch direction was changed, we don't need the batched rows anymore.
  3812. // Swallow them and reset the stream for subsequent fetches.
  3813. if (operation != statement->rsr_fetch_operation ||
  3814. position != statement->rsr_fetch_position)
  3815. {
  3816. while (statement->rsr_rows_pending)
  3817. receive_queued_packet(port, statement->rsr_id);
  3818. if (statement->rsr_flags.test(Rsr::STREAM_ERR))
  3819. {
  3820. statement->rsr_flags.clear(Rsr::STREAM_ERR);
  3821. // hvlad: prevent subsequent fetches
  3822. statement->rsr_flags.set(Rsr::STREAM_END);
  3823. statement->raiseException();
  3824. }
  3825. const SLONG adjustment = statement->getCursorAdjustment();
  3826. statement->rsr_flags.clear(Rsr::STREAM_END | Rsr::PAST_END);
  3827. // We have some messages in the queue. Reset them for reuse.
  3828. if (statement->rsr_msgs_waiting)
  3829. {
  3830. fb_assert(statement->rsr_fetch_operation == fetch_next ||
  3831. statement->rsr_fetch_operation == fetch_prior);
  3832. RMessage* message = statement->rsr_message;
  3833. if (message)
  3834. {
  3835. statement->rsr_buffer = message;
  3836. while (true)
  3837. {
  3838. message->msg_address = NULL;
  3839. message = message->msg_next;
  3840. if (message == statement->rsr_message)
  3841. break;
  3842. }
  3843. }
  3844. statement->rsr_msgs_waiting = 0;
  3845. }
  3846. // If we had some rows batched and the requested scrolling is relative,
  3847. // then move the server cursor to the actual client's position before proceeding.
  3848. // We don't know the absolute client's position, but it's not really necessary.
  3849. // rsr_msgs_waiting shows how much we're ahead the server, so we may re-position
  3850. // the cursor relatively.
  3851. if (relative && adjustment)
  3852. {
  3853. const bool isAhead = (statement->rsr_fetch_operation == fetch_next);
  3854. PACKET* packet = &rdb->rdb_packet;
  3855. packet->p_operation = op_fetch_scroll;
  3856. P_SQLDATA* sqldata = &packet->p_sqldata;
  3857. sqldata->p_sqldata_statement = statement->rsr_id;
  3858. sqldata->p_sqldata_blr.cstr_length = 0;
  3859. sqldata->p_sqldata_blr.cstr_address = nullptr;
  3860. sqldata->p_sqldata_message_number = 0; // msg_type
  3861. sqldata->p_sqldata_messages = statement->rsr_select_format ? 1 : 0;
  3862. sqldata->p_sqldata_fetch_op = fetch_relative;
  3863. sqldata->p_sqldata_fetch_pos = adjustment;
  3864. send_packet(port, packet);
  3865. // Receive response packets. If everything is OK, there should be two of them:
  3866. // first with packet->p_sqldata.p_sqldata_messages == 1 and second with
  3867. // packet->p_sqldata.p_sqldata_messages == 0 (end-of-batch).
  3868. do
  3869. {
  3870. receive_packet(rdb->rdb_port, packet);
  3871. // If we get an error, handle it
  3872. if (packet->p_operation != op_fetch_response)
  3873. {
  3874. statement->rsr_flags.set(Rsr::STREAM_ERR);
  3875. REMOTE_check_response(status, rdb, packet);
  3876. break;
  3877. }
  3878. // If we get end-of-stream, something went seriously wrong, thus punt
  3879. if (packet->p_sqldata.p_sqldata_status == 100)
  3880. Arg::Gds(isc_req_sync).raise();
  3881. // We should get either the requested row or the end-of-batch marker
  3882. fb_assert(packet->p_sqldata.p_sqldata_messages == 0 ||
  3883. packet->p_sqldata.p_sqldata_messages == 1);
  3884. // Release the received message, we don't need it
  3885. const auto message = statement->rsr_message;
  3886. if (message && message->msg_address)
  3887. {
  3888. statement->rsr_message = message->msg_next;
  3889. message->msg_address = NULL;
  3890. }
  3891. }
  3892. while (packet->p_sqldata.p_sqldata_messages);
  3893. }
  3894. // These are the necessary conditions to continue fetching (see below)
  3895. fb_assert(!statement->rsr_flags.test(Rsr::STREAM_END | Rsr::STREAM_ERR));
  3896. fb_assert(!statement->rsr_message->msg_address);
  3897. fb_assert(!statement->rsr_rows_pending);
  3898. }
  3899. // Check to see if data is waiting. If not, solicite data.
  3900. if ((!statement->rsr_flags.test(Rsr::STREAM_END | Rsr::STREAM_ERR) &&
  3901. !statement->rsr_message->msg_address && !statement->rsr_rows_pending) ||
  3902. ( // Low in inventory
  3903. (statement->rsr_rows_pending <= statement->rsr_reorder_level) &&
  3904. (statement->rsr_msgs_waiting <= statement->rsr_reorder_level) &&
  3905. // Pipelining causes both server & client to
  3906. // write at the same time. In XNET, writes
  3907. // block for the other end to read - and so when both
  3908. // attempt to write simultaneously, they end up
  3909. // waiting indefinitely for the other end to read.
  3910. (port->port_type != rem_port::XNET) &&
  3911. // We're fetching either forward or backward
  3912. (operation == fetch_next || operation == fetch_prior) &&
  3913. // We've reached end-of-stream or there was an error
  3914. !statement->rsr_flags.test(Rsr::STREAM_END | Rsr::STREAM_ERR) &&
  3915. // No error pending
  3916. !statement->haveException() ))
  3917. {
  3918. // set up the packet for the other guy...
  3919. PACKET* packet = &rdb->rdb_packet;
  3920. packet->p_operation = (operation == fetch_next) ? op_fetch : op_fetch_scroll;
  3921. P_SQLDATA* sqldata = &packet->p_sqldata;
  3922. sqldata->p_sqldata_statement = statement->rsr_id;
  3923. sqldata->p_sqldata_blr.cstr_length = blr_length;
  3924. sqldata->p_sqldata_blr.cstr_address = const_cast<unsigned char*>(blr);
  3925. sqldata->p_sqldata_message_number = 0; // msg_type
  3926. sqldata->p_sqldata_messages = statement->rsr_select_format ? 1 : 0;
  3927. sqldata->p_sqldata_fetch_op = operation;
  3928. sqldata->p_sqldata_fetch_pos = position;
  3929. if (statement->rsr_select_format)
  3930. {
  3931. if (operation == fetch_next || operation == fetch_prior)
  3932. {
  3933. sqldata->p_sqldata_messages = REMOTE_compute_batch_size(
  3934. port, 0, op_fetch_response, statement->rsr_select_format);
  3935. }
  3936. // Reorder data when the local buffer is half empty
  3937. statement->rsr_reorder_level = sqldata->p_sqldata_messages / 2;
  3938. #ifdef DEBUG
  3939. fprintf(stdout, "Recalculating Rows Pending in REM_fetch=%lu\n",
  3940. statement->rsr_rows_pending);
  3941. #endif
  3942. }
  3943. statement->rsr_rows_pending += sqldata->p_sqldata_messages;
  3944. // We've either got data, or some is on the way, or we have an error, or we have EOF
  3945. if (!(statement->rsr_msgs_waiting ||
  3946. statement->rsr_rows_pending ||
  3947. statement->haveException() ||
  3948. statement->rsr_flags.test(Rsr::STREAM_END)))
  3949. {
  3950. // We were asked to fetch from the statement, not ready for it.
  3951. // Give up before sending something to the server.
  3952. Arg::Gds(isc_req_sync).raise();
  3953. }
  3954. // Make the batch request - and force the packet over the wire
  3955. send_packet(port, packet);
  3956. statement->rsr_batch_count++;
  3957. statement->rsr_fetch_operation = operation;
  3958. statement->rsr_fetch_position = position;
  3959. // Queue up receipt of the pending data
  3960. enqueue_receive(port, batch_dsql_fetch, rdb, statement, NULL);
  3961. fb_assert(statement->rsr_rows_pending || !statement->rsr_select_format);
  3962. }
  3963. // Receive queued responses until we have some data for this cursor
  3964. // or an error status has been received.
  3965. // We've either got data, or some is on the way, or we have an error, or we have EOF
  3966. fb_assert(statement->rsr_msgs_waiting || statement->rsr_rows_pending ||
  3967. statement->haveException() || statement->rsr_flags.test(Rsr::STREAM_END));
  3968. while (!statement->haveException() && // received a database error
  3969. !statement->rsr_flags.test(Rsr::STREAM_END) && // reached end of stream
  3970. statement->rsr_msgs_waiting < 2 && // Have looked ahead for end of batch
  3971. statement->rsr_rows_pending)
  3972. {
  3973. // Hit end of batch
  3974. receive_queued_packet(port, statement->rsr_id);
  3975. }
  3976. if (!statement->rsr_msgs_waiting)
  3977. {
  3978. if (statement->rsr_flags.test(Rsr::STREAM_END))
  3979. {
  3980. // hvlad: we may have queued fetch packet but received end-of-stream before start
  3981. // handling of this packet. Handle it now.
  3982. clear_stmt_que(port, statement);
  3983. // hvlad: as we processed all queued packets at code above we can leave Rsr::EOF_SET flag.
  3984. // It allows us to return EOF for all subsequent isc_dsql_fetch calls until statement
  3985. // will be re-executed (and without roundtrip to remote server).
  3986. //statement->rsr_flags.clear(Rsr::STREAM_END);
  3987. if (statement->rsr_flags.test(Rsr::BOF_SET))
  3988. statement->rsr_flags.set(Rsr::PAST_BOF);
  3989. if (statement->rsr_flags.test(Rsr::EOF_SET))
  3990. statement->rsr_flags.set(Rsr::PAST_EOF);
  3991. return false;
  3992. }
  3993. if (statement->rsr_flags.test(Rsr::STREAM_ERR))
  3994. {
  3995. // The previous batch of receives ended with an error status.
  3996. // We're all done returning data in the local queue.
  3997. // Return that error status vector to the user.
  3998. // Stuff in the error result to the user's vector
  3999. statement->rsr_flags.clear(Rsr::STREAM_ERR);
  4000. // hvlad: prevent subsequent fetches
  4001. statement->rsr_flags.set(Rsr::STREAM_END);
  4002. statement->raiseException();
  4003. }
  4004. }
  4005. statement->rsr_msgs_waiting--;
  4006. message = statement->rsr_message;
  4007. statement->rsr_message = message->msg_next;
  4008. if (statement->rsr_user_select_format->fmt_length != msg_length)
  4009. {
  4010. status_exception::raise(Arg::Gds(isc_port_len) <<
  4011. Arg::Num(msg_length) << Arg::Num(statement->rsr_user_select_format->fmt_length));
  4012. }
  4013. if (statement->rsr_user_select_format == statement->rsr_select_format)
  4014. {
  4015. if (!msg || !message->msg_address)
  4016. {
  4017. move_error(Arg::Gds(isc_dsql_sqlda_err));
  4018. // Msg 263 SQLDA missing or wrong number of variables
  4019. }
  4020. memcpy(msg, message->msg_address, msg_length);
  4021. }
  4022. else
  4023. {
  4024. mov_dsql_message(message->msg_address, statement->rsr_select_format, msg,
  4025. statement->rsr_user_select_format);
  4026. }
  4027. message->msg_address = NULL;
  4028. return true;
  4029. }
  4030. int ResultSet::fetchNext(CheckStatusWrapper* user_status, void* buffer)
  4031. {
  4032. try
  4033. {
  4034. return fetch(user_status, buffer, fetch_next) ?
  4035. IStatus::RESULT_OK : IStatus::RESULT_NO_DATA;
  4036. }
  4037. catch (const Exception& ex)
  4038. {
  4039. ex.stuffException(user_status);
  4040. }
  4041. return IStatus::RESULT_ERROR;
  4042. }
  4043. int ResultSet::fetchPrior(CheckStatusWrapper* user_status, void* buffer)
  4044. {
  4045. try
  4046. {
  4047. if (!(flags & IStatement::CURSOR_TYPE_SCROLLABLE))
  4048. (Arg::Gds(isc_invalid_fetch_option) << Arg::Str("PRIOR")).raise();
  4049. return fetch(user_status, buffer, fetch_prior) ?
  4050. IStatus::RESULT_OK : IStatus::RESULT_NO_DATA;
  4051. }
  4052. catch (const Exception& ex)
  4053. {
  4054. ex.stuffException(user_status);
  4055. }
  4056. return IStatus::RESULT_ERROR;
  4057. }
  4058. int ResultSet::fetchFirst(CheckStatusWrapper* user_status, void* buffer)
  4059. {
  4060. try
  4061. {
  4062. if (!(flags & IStatement::CURSOR_TYPE_SCROLLABLE))
  4063. (Arg::Gds(isc_invalid_fetch_option) << Arg::Str("FIRST")).raise();
  4064. return fetch(user_status, buffer, fetch_first) ?
  4065. IStatus::RESULT_OK : IStatus::RESULT_NO_DATA;
  4066. }
  4067. catch (const Exception& ex)
  4068. {
  4069. ex.stuffException(user_status);
  4070. }
  4071. return IStatus::RESULT_ERROR;
  4072. }
  4073. int ResultSet::fetchLast(CheckStatusWrapper* user_status, void* buffer)
  4074. {
  4075. try
  4076. {
  4077. if (!(flags & IStatement::CURSOR_TYPE_SCROLLABLE))
  4078. (Arg::Gds(isc_invalid_fetch_option) << Arg::Str("LAST")).raise();
  4079. return fetch(user_status, buffer, fetch_last) ?
  4080. IStatus::RESULT_OK : IStatus::RESULT_NO_DATA;
  4081. }
  4082. catch (const Exception& ex)
  4083. {
  4084. ex.stuffException(user_status);
  4085. }
  4086. return IStatus::RESULT_ERROR;
  4087. }
  4088. int ResultSet::fetchAbsolute(CheckStatusWrapper* user_status, int position, void* buffer)
  4089. {
  4090. try
  4091. {
  4092. if (!(flags & IStatement::CURSOR_TYPE_SCROLLABLE))
  4093. (Arg::Gds(isc_invalid_fetch_option) << Arg::Str("ABSOLUTE")).raise();
  4094. return fetch(user_status, buffer, fetch_absolute, position) ?
  4095. IStatus::RESULT_OK : IStatus::RESULT_NO_DATA;
  4096. }
  4097. catch (const Exception& ex)
  4098. {
  4099. ex.stuffException(user_status);
  4100. }
  4101. return IStatus::RESULT_ERROR;
  4102. }
  4103. int ResultSet::fetchRelative(CheckStatusWrapper* user_status, int offset, void* buffer)
  4104. {
  4105. try
  4106. {
  4107. if (!(flags & IStatement::CURSOR_TYPE_SCROLLABLE))
  4108. (Arg::Gds(isc_invalid_fetch_option) << Arg::Str("RELATIVE")).raise();
  4109. return fetch(user_status, buffer, fetch_relative, offset) ?
  4110. IStatus::RESULT_OK : IStatus::RESULT_NO_DATA;
  4111. }
  4112. catch (const Exception& ex)
  4113. {
  4114. ex.stuffException(user_status);
  4115. }
  4116. return IStatus::RESULT_ERROR;
  4117. }
  4118. FB_BOOLEAN ResultSet::isEof(CheckStatusWrapper* status)
  4119. {
  4120. try
  4121. {
  4122. reset(status);
  4123. // Check and validate handles, etc.
  4124. if (!stmt)
  4125. {
  4126. Arg::Gds(isc_dsql_cursor_err).raise();
  4127. }
  4128. Rsr* statement = stmt->getStatement();
  4129. CHECK_HANDLE(statement, isc_bad_req_handle);
  4130. if (!statement->rsr_flags.test(Rsr::FETCHED))
  4131. return FB_FALSE;
  4132. return statement->rsr_flags.test(Rsr::PAST_EOF) ? FB_TRUE : FB_FALSE;
  4133. }
  4134. catch (const Exception& ex)
  4135. {
  4136. ex.stuffException(status);
  4137. }
  4138. return FB_FALSE;
  4139. }
  4140. FB_BOOLEAN ResultSet::isBof(CheckStatusWrapper* status)
  4141. {
  4142. try
  4143. {
  4144. reset(status);
  4145. // Check and validate handles, etc.
  4146. if (!stmt)
  4147. {
  4148. Arg::Gds(isc_dsql_cursor_err).raise();
  4149. }
  4150. Rsr* statement = stmt->getStatement();
  4151. CHECK_HANDLE(statement, isc_bad_req_handle);
  4152. if (!statement->rsr_flags.test(Rsr::FETCHED))
  4153. return FB_TRUE;
  4154. return statement->rsr_flags.test(Rsr::PAST_BOF) ? FB_TRUE : FB_FALSE;
  4155. }
  4156. catch (const Exception& ex)
  4157. {
  4158. ex.stuffException(status);
  4159. }
  4160. return FB_FALSE;
  4161. }
  4162. IMessageMetadata* ResultSet::getMetadata(CheckStatusWrapper* status)
  4163. {
  4164. if (!outputFormat)
  4165. {
  4166. status->setErrors(Arg::Gds(isc_no_output_format).value());
  4167. return NULL;
  4168. }
  4169. reset(status);
  4170. outputFormat->addRef();
  4171. return outputFormat;
  4172. }
  4173. void ResultSet::getInfo(CheckStatusWrapper* status,
  4174. unsigned int itemsLength, const unsigned char* items,
  4175. unsigned int bufferLength, unsigned char* buffer)
  4176. {
  4177. try
  4178. {
  4179. reset(status);
  4180. // Check and validate handles, etc.
  4181. if (!stmt)
  4182. Arg::Gds(isc_dsql_cursor_err).raise();
  4183. const auto statement = stmt->getStatement();
  4184. CHECK_HANDLE(statement, isc_bad_req_handle);
  4185. const auto rdb = statement->rsr_rdb;
  4186. const auto port = rdb->rdb_port;
  4187. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4188. if (port->port_protocol < PROTOCOL_FETCH_SCROLL)
  4189. unsupported();
  4190. info(status, rdb, op_info_cursor, statement->rsr_id, 0,
  4191. itemsLength, items, 0, 0, bufferLength, buffer);
  4192. }
  4193. catch (const Exception& ex)
  4194. {
  4195. ex.stuffException(status);
  4196. }
  4197. }
  4198. void ResultSet::freeClientData(CheckStatusWrapper* status, bool force)
  4199. {
  4200. /**************************************
  4201. *
  4202. * d s q l _ f r e e _ s t a t e m e n t
  4203. *
  4204. **************************************
  4205. *
  4206. * Functional description
  4207. * Close SQL cursor
  4208. *
  4209. **************************************/
  4210. try
  4211. {
  4212. // Check and validate handles, etc.
  4213. if (!stmt)
  4214. {
  4215. Arg::Gds(isc_dsql_cursor_err).raise();
  4216. }
  4217. Rsr* statement = stmt->getStatement();
  4218. CHECK_HANDLE(statement, isc_bad_req_handle);
  4219. Rdb* rdb = statement->rsr_rdb;
  4220. rem_port* port = rdb->rdb_port;
  4221. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4222. statement->clearException();
  4223. if (statement->rsr_flags.test(Rsr::LAZY))
  4224. {
  4225. statement->rsr_flags.clear(Rsr::FETCHED);
  4226. statement->rsr_rtr = NULL;
  4227. clear_queue(rdb->rdb_port);
  4228. REMOTE_reset_statement(statement);
  4229. releaseStatement();
  4230. return;
  4231. }
  4232. PACKET* packet = &rdb->rdb_packet;
  4233. packet->p_operation = op_free_statement;
  4234. P_SQLFREE* free_stmt = &packet->p_sqlfree;
  4235. free_stmt->p_sqlfree_statement = statement->rsr_id;
  4236. free_stmt->p_sqlfree_option = DSQL_close;
  4237. if (rdb->rdb_port->port_flags & PORT_lazy)
  4238. {
  4239. defer_packet(rdb->rdb_port, packet);
  4240. packet->p_resp.p_resp_object = statement->rsr_id;
  4241. statement->clearException();
  4242. }
  4243. else
  4244. {
  4245. try
  4246. {
  4247. send_and_receive(status, rdb, packet);
  4248. }
  4249. catch (const Exception&)
  4250. {
  4251. if (!force)
  4252. throw;
  4253. }
  4254. }
  4255. statement->rsr_flags.clear(Rsr::FETCHED);
  4256. statement->rsr_rtr = NULL;
  4257. clear_queue(rdb->rdb_port);
  4258. REMOTE_reset_statement(statement);
  4259. releaseStatement();
  4260. }
  4261. catch (const Exception& ex)
  4262. {
  4263. ex.stuffException(status);
  4264. }
  4265. }
  4266. void ResultSet::internalClose(CheckStatusWrapper* status)
  4267. {
  4268. /**************************************
  4269. *
  4270. * d s q l _ f r e e _ s t a t e m e n t
  4271. *
  4272. **************************************
  4273. *
  4274. * Functional description
  4275. * Close SQL cursor
  4276. *
  4277. **************************************/
  4278. reset(status);
  4279. freeClientData(status);
  4280. }
  4281. void ResultSet::close(CheckStatusWrapper* status)
  4282. {
  4283. internalClose(status);
  4284. if (status->isEmpty())
  4285. release();
  4286. }
  4287. void ResultSet::deprecatedClose(CheckStatusWrapper* status)
  4288. {
  4289. internalClose(status);
  4290. }
  4291. void ResultSet::releaseStatement()
  4292. {
  4293. if (tmpStatement)
  4294. {
  4295. stmt->release();
  4296. }
  4297. stmt = NULL;
  4298. }
  4299. int Blob::getSegment(CheckStatusWrapper* status, unsigned int bufferLength, void* buffer,
  4300. unsigned int* segmentLength)
  4301. {
  4302. /**************************************
  4303. *
  4304. * g d s _ g e t _ s e g m e n t
  4305. *
  4306. **************************************
  4307. *
  4308. * Functional description
  4309. * Buffer segments of a blob and pass
  4310. * them one by one to the caller.
  4311. *
  4312. **************************************/
  4313. try
  4314. {
  4315. reset(status);
  4316. UCHAR* bufferPtr = static_cast<UCHAR*>(buffer);
  4317. // Sniff out handles, etc, and find the various blocks.
  4318. CHECK_HANDLE(blob, isc_bad_segstr_handle);
  4319. Rdb* rdb = blob->rbl_rdb;
  4320. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4321. rem_port* port = rdb->rdb_port;
  4322. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4323. // Build the primary packet to get the operation started.
  4324. PACKET* packet = &rdb->rdb_packet;
  4325. P_SGMT* segment = &packet->p_sgmt;
  4326. P_RESP* response = &packet->p_resp;
  4327. SaveString temp(response->p_resp_data, bufferLength, bufferPtr);
  4328. // Handle a blob that has been created rather than opened (this should yield an error)
  4329. if (blob->rbl_flags & Rbl::CREATE)
  4330. {
  4331. packet->p_operation = op_get_segment;
  4332. segment->p_sgmt_length = bufferLength;
  4333. segment->p_sgmt_blob = blob->rbl_id;
  4334. segment->p_sgmt_segment.cstr_length = 0;
  4335. send_packet(port, packet);
  4336. receive_response(status, rdb, packet);
  4337. if (segmentLength)
  4338. *segmentLength = response->p_resp_data.cstr_length;
  4339. return IStatus::RESULT_OK;
  4340. }
  4341. // New protocol -- ask for a 1K chunk of blob and
  4342. // fill segment requests from it until its time to
  4343. // get the next section. In other words, get a bunch,
  4344. // pass it out piece by piece, then when there isn't
  4345. // enough left, ask for more.
  4346. unsigned int length = 0;
  4347. // if we're already done, stop now
  4348. if (blob->rbl_flags & Rbl::EOF_SET)
  4349. {
  4350. if (segmentLength)
  4351. *segmentLength = length;
  4352. return IStatus::RESULT_NO_DATA;
  4353. }
  4354. // Here's the loop, passing out data from our basket & refilling it.
  4355. // Our buffer (described by the structure blob) is counted strings
  4356. // <count word> <string> <count word> <string>...
  4357. int code = IStatus::RESULT_OK;
  4358. while (true)
  4359. {
  4360. // If there's data to be given away, give some away (p points to the local data)
  4361. if (blob->rbl_length)
  4362. {
  4363. UCHAR* p = blob->rbl_ptr;
  4364. // If there was a fragment left over last time use it
  4365. USHORT l = blob->rbl_fragment_length;
  4366. if (l) {
  4367. blob->rbl_fragment_length = 0;
  4368. }
  4369. else
  4370. {
  4371. // otherwise pick up the count word as the length, & decrement the local length
  4372. l = *p++;
  4373. l += *p++ << 8;
  4374. blob->rbl_length -= 2;
  4375. }
  4376. // Now check that what we've got fits.
  4377. // If not, set up the fragment pointer and set the status vector
  4378. if (l > bufferLength)
  4379. {
  4380. blob->rbl_fragment_length = l - bufferLength;
  4381. l = bufferLength;
  4382. code = IStatus::RESULT_SEGMENT;
  4383. }
  4384. // and, just for yucks, see if we're exactly using up the fragment
  4385. // part of a previous incomplete read - if so mark this as an
  4386. // incomplete read
  4387. if (l == bufferLength && l == blob->rbl_length && (blob->rbl_flags & Rbl::SEGMENT))
  4388. {
  4389. code = IStatus::RESULT_SEGMENT;
  4390. }
  4391. // finally set up the return length, decrement the current length,
  4392. // copy the data, and indicate where to start next time.
  4393. length += l;
  4394. blob->rbl_length -= l;
  4395. blob->rbl_offset += l;
  4396. bufferLength -= l;
  4397. if (l) {
  4398. memcpy(bufferPtr, p, l);
  4399. }
  4400. bufferPtr += l;
  4401. p += l;
  4402. blob->rbl_ptr = p;
  4403. // return if we've filled up the caller's buffer, or completed a segment
  4404. if (!bufferLength || blob->rbl_length || !(blob->rbl_flags & Rbl::SEGMENT))
  4405. {
  4406. break;
  4407. }
  4408. }
  4409. // We're done with buffer. If this was the last, we're done
  4410. if (blob->rbl_flags & Rbl::EOF_PENDING)
  4411. {
  4412. blob->rbl_flags |= Rbl::EOF_SET;
  4413. code = IStatus::RESULT_NO_DATA;
  4414. break;
  4415. }
  4416. // Preparatory to asking for more data, use input buffer length
  4417. // to cue more efficient blob buffering.
  4418. // Allocate 2 extra bytes to handle the special case where the
  4419. // segment size of blob in the database is equal to the buffer
  4420. // size that the user has passed.
  4421. // Do not go into this loop if we already have a buffer
  4422. // of size 65535 or 65534.
  4423. if (bufferLength > blob->rbl_buffer_length - sizeof(USHORT) &&
  4424. blob->rbl_buffer_length <= MAX_USHORT - sizeof(USHORT))
  4425. {
  4426. ULONG new_size = bufferLength + sizeof(USHORT);
  4427. if (new_size > MAX_USHORT) // Check if we've overflown
  4428. new_size = bufferLength;
  4429. blob->rbl_ptr = blob->rbl_buffer = blob->rbl_data.getBuffer(new_size);
  4430. blob->rbl_buffer_length = (USHORT) new_size;
  4431. }
  4432. // We need more data. Ask for it politely
  4433. packet->p_operation = op_get_segment;
  4434. segment->p_sgmt_length = blob->rbl_buffer_length;
  4435. segment->p_sgmt_blob = blob->rbl_id;
  4436. segment->p_sgmt_segment.cstr_length = 0;
  4437. send_packet(rdb->rdb_port, packet);
  4438. response->p_resp_data.cstr_allocated = blob->rbl_buffer_length;
  4439. response->p_resp_data.cstr_address = blob->rbl_buffer;
  4440. receive_response(status, rdb, packet);
  4441. blob->rbl_length = (USHORT) response->p_resp_data.cstr_length;
  4442. blob->rbl_ptr = blob->rbl_buffer;
  4443. blob->rbl_flags &= ~Rbl::SEGMENT;
  4444. if (response->p_resp_object == 1)
  4445. blob->rbl_flags |= Rbl::SEGMENT;
  4446. else if (response->p_resp_object == 2)
  4447. blob->rbl_flags |= Rbl::EOF_PENDING;
  4448. }
  4449. if (segmentLength)
  4450. *segmentLength = length;
  4451. return code;
  4452. }
  4453. catch (const Exception& ex)
  4454. {
  4455. ex.stuffException(status);
  4456. }
  4457. return IStatus::RESULT_ERROR;
  4458. }
  4459. int Attachment::getSlice(CheckStatusWrapper* status, ITransaction* apiTra, ISC_QUAD* array_id,
  4460. unsigned int sdl_length, const unsigned char* sdl,
  4461. unsigned int param_length, const unsigned char* param,
  4462. int slice_length, unsigned char* slice)
  4463. {
  4464. /**************************************
  4465. *
  4466. * g d s _ g e t _ s l i c e
  4467. *
  4468. **************************************
  4469. *
  4470. * Functional description
  4471. * Snatch a slice of an array.
  4472. *
  4473. **************************************/
  4474. try
  4475. {
  4476. reset(status);
  4477. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4478. rem_port* port = rdb->rdb_port;
  4479. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4480. Rtr* transaction = remoteTransaction(apiTra);
  4481. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  4482. // Validate data length
  4483. CHECK_LENGTH(port, sdl_length);
  4484. CHECK_LENGTH(port, param_length);
  4485. // Parse the sdl in case blr_d_float must be converted to blr_double
  4486. const UCHAR* new_sdl = sdl;
  4487. // CVC: Modified this horrible idea: don't touch input parameters!
  4488. // The modified (perhaps) sdl is send to the remote connection. The
  4489. // original sdl is used to process the slice data when it is received.
  4490. // (This is why both 'new_sdl' and 'sdl' are saved in the packet.)
  4491. HalfStaticArray<UCHAR, 128> sdl_buffer;
  4492. UCHAR* old_sdl = sdl_buffer.getBuffer(sdl_length);
  4493. memcpy(old_sdl, sdl, sdl_length);
  4494. PACKET* packet = &rdb->rdb_packet;
  4495. packet->p_operation = op_get_slice;
  4496. P_SLC* data = &packet->p_slc;
  4497. data->p_slc_transaction = transaction->rtr_id;
  4498. data->p_slc_id = *array_id;
  4499. data->p_slc_length = slice_length;
  4500. data->p_slc_sdl.cstr_length = sdl_length;
  4501. data->p_slc_sdl.cstr_address = const_cast<UCHAR*>(new_sdl);
  4502. data->p_slc_parameters.cstr_length = param_length;
  4503. data->p_slc_parameters.cstr_address = const_cast<UCHAR*>(param);
  4504. data->p_slc_slice.lstr_length = 0;
  4505. data->p_slc_slice.lstr_address = slice;
  4506. P_SLR* response = &packet->p_slr;
  4507. response->p_slr_sdl = old_sdl; //const_cast<UCHAR*>(sdl);
  4508. response->p_slr_sdl_length = sdl_length;
  4509. response->p_slr_slice.lstr_address = slice;
  4510. response->p_slr_slice.lstr_length = slice_length;
  4511. send_packet(rdb->rdb_port, packet);
  4512. receive_packet(rdb->rdb_port, packet);
  4513. if (packet->p_operation != op_slice)
  4514. {
  4515. REMOTE_check_response(status, rdb, packet);
  4516. }
  4517. return response->p_slr_length;
  4518. }
  4519. catch (const Exception& ex)
  4520. {
  4521. ex.stuffException(status);
  4522. }
  4523. return 0;
  4524. }
  4525. IBlob* Attachment::openBlob(CheckStatusWrapper* status, ITransaction* apiTra, ISC_QUAD* id,
  4526. unsigned int bpb_length, const unsigned char* bpb)
  4527. {
  4528. /**************************************
  4529. *
  4530. * g d s _ o p e n _ b l o b 2
  4531. *
  4532. **************************************
  4533. *
  4534. * Functional description
  4535. * Open an existing blob.
  4536. *
  4537. **************************************/
  4538. try
  4539. {
  4540. reset(status);
  4541. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4542. rem_port* port = rdb->rdb_port;
  4543. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4544. Rtr* transaction = remoteTransaction(apiTra);
  4545. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  4546. // Validate data length
  4547. CHECK_LENGTH(port, bpb_length);
  4548. PACKET* packet = &rdb->rdb_packet;
  4549. packet->p_operation = op_open_blob2;
  4550. P_BLOB* p_blob = &packet->p_blob;
  4551. p_blob->p_blob_transaction = transaction->rtr_id;
  4552. p_blob->p_blob_id = *id;
  4553. p_blob->p_blob_bpb.cstr_length = bpb_length;
  4554. fb_assert(!p_blob->p_blob_bpb.cstr_allocated ||
  4555. p_blob->p_blob_bpb.cstr_allocated < p_blob->p_blob_bpb.cstr_length);
  4556. // CVC: Should we ensure here that cstr_allocated < bpb_length???
  4557. // Otherwise, xdr_cstring() calling alloc_string() to decode would
  4558. // cause memory problems on the client side for SS, as the client
  4559. // would try to write to the application's provided R/O buffer.
  4560. p_blob->p_blob_bpb.cstr_address = bpb;
  4561. send_and_receive(status, rdb, packet);
  4562. // CVC: It's not evident to me why these two lines that I've copied
  4563. // here as comments are only found in create_blob calls.
  4564. // I think they should be enabled to avoid whatever buffer corruption.
  4565. //p_blob->p_blob_bpb.cstr_length = 0;
  4566. //p_blob->p_blob_bpb.cstr_address = NULL;
  4567. Rbl* blob = FB_NEW Rbl;
  4568. blob->rbl_rdb = rdb;
  4569. blob->rbl_rtr = transaction;
  4570. blob->rbl_id = packet->p_resp.p_resp_object;
  4571. SET_OBJECT(rdb, blob, blob->rbl_id);
  4572. blob->rbl_next = transaction->rtr_blobs;
  4573. transaction->rtr_blobs = blob;
  4574. Firebird::IBlob* b = FB_NEW Blob(blob);
  4575. b->addRef();
  4576. return b;
  4577. }
  4578. catch (const Exception& ex)
  4579. {
  4580. ex.stuffException(status);
  4581. }
  4582. return NULL;
  4583. }
  4584. void Transaction::prepare(CheckStatusWrapper* status, unsigned int msg_length, const unsigned char* msg)
  4585. {
  4586. /**************************************
  4587. *
  4588. * g d s _ p r e p a r e
  4589. *
  4590. **************************************
  4591. *
  4592. * Functional description
  4593. * Prepare a transaction for commit. First phase of a two
  4594. * phase commit.
  4595. *
  4596. **************************************/
  4597. try
  4598. {
  4599. reset(status);
  4600. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  4601. Rdb* rdb = transaction->rtr_rdb;
  4602. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4603. rem_port* port = rdb->rdb_port;
  4604. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4605. // Validate data length
  4606. CHECK_LENGTH(port, msg_length);
  4607. PACKET* packet = &rdb->rdb_packet;
  4608. packet->p_operation = op_prepare2;
  4609. packet->p_prep.p_prep_transaction = transaction->rtr_id;
  4610. packet->p_prep.p_prep_data.cstr_length = msg_length;
  4611. packet->p_prep.p_prep_data.cstr_address = msg;
  4612. send_packet(rdb->rdb_port, packet);
  4613. receive_response(status, rdb, packet);
  4614. }
  4615. catch (const Exception& ex)
  4616. {
  4617. ex.stuffException(status);
  4618. }
  4619. }
  4620. void Blob::putSegment(CheckStatusWrapper* status, unsigned int segment_length, const void* segment)
  4621. {
  4622. /**************************************
  4623. *
  4624. * g d s _ p u t _ s e g m e n t
  4625. *
  4626. **************************************
  4627. *
  4628. * Functional description
  4629. * Emit a blob segment. If the protocol allows,
  4630. * the segment is buffered locally for a later
  4631. * batch put.
  4632. *
  4633. **************************************/
  4634. try
  4635. {
  4636. reset(status);
  4637. const UCHAR* segmentPtr = static_cast<const UCHAR*>(segment);
  4638. // Sniff out handles, etc, and find the various blocks.
  4639. CHECK_HANDLE(blob, isc_bad_segstr_handle);
  4640. Rdb* rdb = blob->rbl_rdb;
  4641. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4642. rem_port* port = rdb->rdb_port;
  4643. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4644. // Handle a blob that has been opened rather than created (this should yield an error)
  4645. if (!(blob->rbl_flags & Rbl::CREATE))
  4646. {
  4647. send_blob(status, blob, segment_length, segmentPtr);
  4648. fb_assert(false);
  4649. }
  4650. // If the buffer can't hold the complete incoming segment, flush out the
  4651. // buffer. If the incoming segment is too large to fit into the blob
  4652. // buffer, just send it as a single segment.
  4653. UCHAR* p = blob->rbl_ptr;
  4654. const unsigned int l = blob->rbl_buffer_length - (p - blob->rbl_buffer);
  4655. if (segment_length + 2 > l)
  4656. {
  4657. if (blob->rbl_ptr > blob->rbl_buffer)
  4658. {
  4659. send_blob(status, blob, 0, NULL);
  4660. }
  4661. if ((ULONG) segment_length + 2 > blob->rbl_buffer_length)
  4662. {
  4663. send_blob(status, blob, segment_length, segmentPtr);
  4664. return;
  4665. }
  4666. p = blob->rbl_buffer;
  4667. }
  4668. // Move segment length and data into blob buffer
  4669. *p++ = (UCHAR) segment_length;
  4670. *p++ = segment_length >> 8;
  4671. if (segment_length) {
  4672. memcpy(p, segmentPtr, segment_length);
  4673. }
  4674. blob->rbl_ptr = p + segment_length;
  4675. }
  4676. catch (const Exception& ex)
  4677. {
  4678. ex.stuffException(status);
  4679. }
  4680. }
  4681. void Attachment::putSlice(CheckStatusWrapper* status, ITransaction* apiTra, ISC_QUAD* id,
  4682. unsigned int sdl_length, const unsigned char* sdl,
  4683. unsigned int param_length, const unsigned char* param,
  4684. int sliceLength, unsigned char* slice)
  4685. {
  4686. /**************************************
  4687. *
  4688. * g d s _ p u t _ s l i c e
  4689. *
  4690. **************************************
  4691. *
  4692. * Functional description
  4693. * Store a slice of an array.
  4694. *
  4695. **************************************/
  4696. try
  4697. {
  4698. reset(status);
  4699. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4700. rem_port* port = rdb->rdb_port;
  4701. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4702. Rtr* transaction = remoteTransaction(apiTra);
  4703. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  4704. // Validate data length
  4705. CHECK_LENGTH(port, sdl_length);
  4706. CHECK_LENGTH(port, param_length);
  4707. // Parse the sdl in case blr_d_float must be converted to blr_double
  4708. const UCHAR* new_sdl = sdl;
  4709. // CVC: Modified this horrible idea: don't touch input parameters!
  4710. // The modified (perhaps) sdl is sent to the remote connection. The
  4711. // original sdl is used to process the slice data before it is sent.
  4712. // (This is why both 'new_sdl' and 'sdl' are saved in the packet.)
  4713. HalfStaticArray<UCHAR, 128> sdl_buffer;
  4714. UCHAR* old_sdl = sdl_buffer.getBuffer(sdl_length);
  4715. memcpy(old_sdl, sdl, sdl_length);
  4716. PACKET* packet = &rdb->rdb_packet;
  4717. packet->p_operation = op_put_slice;
  4718. P_SLC* data = &packet->p_slc;
  4719. data->p_slc_transaction = transaction->rtr_id;
  4720. data->p_slc_id = *id;
  4721. data->p_slc_length = sliceLength;
  4722. data->p_slc_sdl.cstr_length = sdl_length;
  4723. data->p_slc_sdl.cstr_address = const_cast<UCHAR*>(new_sdl);
  4724. data->p_slc_parameters.cstr_length = param_length;
  4725. data->p_slc_parameters.cstr_address = const_cast<UCHAR*>(param);
  4726. data->p_slc_slice.lstr_length = sliceLength;
  4727. data->p_slc_slice.lstr_address = slice;
  4728. P_SLR* response = &packet->p_slr;
  4729. response->p_slr_sdl = old_sdl; //const_cast<UCHAR*>(sdl);
  4730. response->p_slr_sdl_length = sdl_length;
  4731. response->p_slr_slice.lstr_address = slice;
  4732. response->p_slr_slice.lstr_length = sliceLength;
  4733. send_and_receive(status, rdb, packet);
  4734. *id = packet->p_resp.p_resp_blob_id;
  4735. }
  4736. catch (const Exception& ex)
  4737. {
  4738. ex.stuffException(status);
  4739. }
  4740. }
  4741. Firebird::IEvents* Attachment::queEvents(CheckStatusWrapper* status, Firebird::IEventCallback* callback,
  4742. unsigned int length, const unsigned char* events)
  4743. {
  4744. /**************************************
  4745. *
  4746. * g d s _ $ q u e _ e v e n t s
  4747. *
  4748. **************************************
  4749. *
  4750. * Functional description
  4751. * Queue a request for event notification.
  4752. *
  4753. **************************************/
  4754. try
  4755. {
  4756. reset(status);
  4757. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4758. rem_port* port = rdb->rdb_port;
  4759. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4760. // Validate data length
  4761. CHECK_LENGTH(port, length);
  4762. PACKET* packet = &rdb->rdb_packet;
  4763. // If there isn't a auxiliary asynchronous port, make one now
  4764. if (!port->port_async)
  4765. {
  4766. packet->p_operation = op_connect_request;
  4767. P_REQ* request = &packet->p_req;
  4768. request->p_req_object = rdb->rdb_id;
  4769. request->p_req_type = P_REQ_async;
  4770. send_packet(port, packet);
  4771. receive_response(status, rdb, packet);
  4772. port->connect(packet);
  4773. rem_port* port_async = port->port_async;
  4774. port_async->port_events_threadId =
  4775. Thread::start(event_thread, port_async, THREAD_high, &port_async->port_events_thread);
  4776. port_async->port_context = rdb;
  4777. }
  4778. // Add event block to port's list of active remote events
  4779. Rvnt* rem_event = add_event(port);
  4780. rem_event->rvnt_callback = callback;
  4781. rem_event->rvnt_port = port->port_async;
  4782. rem_event->rvnt_length = length;
  4783. rem_event->rvnt_rdb = rdb;
  4784. // Build the primary packet to get the operation started.
  4785. packet = &rdb->rdb_packet;
  4786. packet->p_operation = op_que_events;
  4787. P_EVENT* event = &packet->p_event;
  4788. event->p_event_database = rdb->rdb_id;
  4789. event->p_event_items.cstr_length = length;
  4790. event->p_event_items.cstr_address = events;
  4791. event->p_event_ast = 0;
  4792. event->p_event_arg = 0;
  4793. event->p_event_rid = rem_event->rvnt_id;
  4794. send_packet(port, packet);
  4795. receive_response(status, rdb, packet);
  4796. Firebird::IEvents* rc = FB_NEW Events(rem_event);
  4797. rc->addRef();
  4798. return rc;
  4799. }
  4800. catch (const Exception& ex)
  4801. {
  4802. ex.stuffException(status);
  4803. }
  4804. return NULL;
  4805. }
  4806. void Request::receive(CheckStatusWrapper* status, int level, unsigned int msg_type,
  4807. unsigned int msg_length, void* msg)
  4808. {
  4809. /**************************************
  4810. *
  4811. * g d s _ r e c e i v e
  4812. *
  4813. **************************************
  4814. *
  4815. * Functional description
  4816. * Give a client program a record. Ask the
  4817. * Remote server to send it to us if necessary.
  4818. *
  4819. **************************************/
  4820. try
  4821. {
  4822. reset(status);
  4823. // Check handles and environment, then set up error handling
  4824. CHECK_HANDLE(rq, isc_bad_req_handle);
  4825. Rrq* request = REMOTE_find_request(rq, level);
  4826. Rdb* rdb = request->rrq_rdb;
  4827. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4828. rem_port* port = rdb->rdb_port;
  4829. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4830. Rrq::rrq_repeat* tail = &request->rrq_rpt[msg_type];
  4831. RMessage* message = tail->rrq_message;
  4832. #ifdef DEBUG
  4833. fprintf(stdout, "Rows Pending in REM_receive=%d\n", tail->rrq_rows_pending);
  4834. #endif
  4835. // Check to see if data is waiting. If not, solicit data.
  4836. // Solicit data either when we've run out, or there's a low
  4837. // inventory of messages in local buffers & no shipments on the
  4838. // ether being sent to us.
  4839. if (request->rrqStatus.isSuccess() && // No error pending
  4840. ((!message->msg_address && tail->rrq_rows_pending == 0) || // No message waiting
  4841. (tail->rrq_rows_pending <= tail->rrq_reorder_level && // Low in inventory
  4842. tail->rrq_msgs_waiting <= tail->rrq_reorder_level &&
  4843. // Pipelining causes both server & client to
  4844. // write at the same time. In XNET, writes
  4845. // block for the other end to read - and so when both
  4846. // attempt to write simultaenously, they end up
  4847. // waiting indefinetly for the other end to read.
  4848. (port->port_type != rem_port::XNET) &&
  4849. request->rrq_max_msg <= 1)))
  4850. {
  4851. // there's only one message type
  4852. #ifdef DEBUG
  4853. fprintf(stderr, "Rows Pending %d\n", tail->rrq_rows_pending);
  4854. if (!message->msg_address)
  4855. fprintf(stderr, "Out of data - reordering\n");
  4856. else
  4857. fprintf(stderr, "Low on inventory - reordering\n");
  4858. #endif
  4859. // Format a request for data
  4860. PACKET *packet = &rdb->rdb_packet;
  4861. packet->p_operation = op_receive;
  4862. P_DATA* data = &packet->p_data;
  4863. data->p_data_request = request->rrq_id;
  4864. data->p_data_message_number = msg_type;
  4865. data->p_data_incarnation = level;
  4866. // Compute how many to send in a batch. While this calculation
  4867. // is the same for each batch (June 1996), perhaps in the future it
  4868. // could dynamically adjust batching sizes based on fetch patterns
  4869. data->p_data_messages = REMOTE_compute_batch_size(port, 0, op_send, tail->rrq_format);
  4870. tail->rrq_reorder_level = data->p_data_messages / 2;
  4871. tail->rrq_rows_pending += data->p_data_messages;
  4872. #ifdef DEBUG
  4873. fprintf(stdout, "Recalculating Rows Pending in REM_receive=%d\n",
  4874. tail->rrq_rows_pending);
  4875. #endif
  4876. #ifdef DEBUG
  4877. fprintf(stderr, "port_flags %d max_msg %d\n", port->port_flags, request->rrq_max_msg);
  4878. fprintf(stderr, "Fetch: Req One batch of %d messages\n", data->p_data_messages);
  4879. #endif
  4880. send_packet(port, packet);
  4881. tail->rrq_batch_count++;
  4882. #ifdef DEBUG
  4883. fprintf(stderr, "Rows Pending %d\n", tail->rrq_rows_pending);
  4884. #endif
  4885. // Queue up receipt of the pending data
  4886. enqueue_receive(port, batch_gds_receive, rdb, request, tail);
  4887. }
  4888. // Receive queued responses until we have some data for this cursor
  4889. // or an error status has been received.
  4890. // We've either got data, or some is on the way, or we have an error
  4891. fb_assert(message->msg_address || tail->rrq_rows_pending > 0 || (!request->rrqStatus.isSuccess()));
  4892. while (!message->msg_address && request->rrqStatus.isSuccess())
  4893. {
  4894. receive_queued_packet(port, request->rrq_id);
  4895. }
  4896. if (!message->msg_address && !request->rrqStatus.isSuccess())
  4897. {
  4898. // The previous batch of receives ended with an error status.
  4899. // We're all done returning data in the local queue.
  4900. // Return that error status vector to the user.
  4901. // Stuff in the error result to the user's vector
  4902. request->rrqStatus.raise();
  4903. }
  4904. // Copy data from the message buffer to the client buffer
  4905. if (tail->rrq_format->fmt_length != msg_length)
  4906. {
  4907. status_exception::raise(Arg::Gds(isc_port_len) <<
  4908. Arg::Num(msg_length) << Arg::Num(tail->rrq_format->fmt_length));
  4909. }
  4910. message = tail->rrq_message;
  4911. memcpy(msg, message->msg_address, msg_length);
  4912. // Move the head-of-full-buffer-queue pointer forward
  4913. tail->rrq_message = message->msg_next;
  4914. // Mark the buffer the message came from as available for reuse
  4915. message->msg_address = NULL;
  4916. tail->rrq_msgs_waiting--;
  4917. }
  4918. catch (const Exception& ex)
  4919. {
  4920. ex.stuffException(status);
  4921. }
  4922. }
  4923. Firebird::ITransaction* Attachment::reconnectTransaction(CheckStatusWrapper* status,
  4924. unsigned int length, const unsigned char* id)
  4925. {
  4926. /**************************************
  4927. *
  4928. * g d s _ r e c o n n e c t
  4929. *
  4930. **************************************
  4931. *
  4932. * Functional description
  4933. *
  4934. **************************************/
  4935. try
  4936. {
  4937. reset(status);
  4938. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4939. rem_port* port = rdb->rdb_port;
  4940. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4941. // Validate data length
  4942. CHECK_LENGTH(port, length);
  4943. PACKET* packet = &rdb->rdb_packet;
  4944. packet->p_operation = op_reconnect;
  4945. P_STTR* trans = &packet->p_sttr;
  4946. trans->p_sttr_database = rdb->rdb_id;
  4947. trans->p_sttr_tpb.cstr_length = length;
  4948. trans->p_sttr_tpb.cstr_address = id;
  4949. send_and_receive(status, rdb, packet);
  4950. Firebird::ITransaction* t = FB_NEW Transaction(make_transaction(rdb, packet->p_resp.p_resp_object), this);
  4951. t->addRef();
  4952. return t;
  4953. }
  4954. catch (const Exception& ex)
  4955. {
  4956. ex.stuffException(status);
  4957. }
  4958. return NULL;
  4959. }
  4960. void Request::freeClientData(CheckStatusWrapper* status, bool force)
  4961. {
  4962. /**************************************
  4963. *
  4964. * g d s _ r e l e a s e _ r e q u e s t
  4965. *
  4966. **************************************
  4967. *
  4968. * Functional description
  4969. * Release a request.
  4970. *
  4971. **************************************/
  4972. try
  4973. {
  4974. CHECK_HANDLE(rq, isc_bad_req_handle);
  4975. Rdb* rdb = rq->rrq_rdb;
  4976. CHECK_HANDLE(rdb, isc_bad_db_handle);
  4977. rem_port* port = rdb->rdb_port;
  4978. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  4979. try
  4980. {
  4981. release_object(status, rdb, op_release, rq->rrq_id);
  4982. }
  4983. catch (const Exception&)
  4984. {
  4985. if (!force)
  4986. throw;
  4987. }
  4988. release_request(rq);
  4989. rq = NULL;
  4990. }
  4991. catch (const Exception& ex)
  4992. {
  4993. ex.stuffException(status);
  4994. }
  4995. }
  4996. void Request::internalFree(CheckStatusWrapper* status)
  4997. {
  4998. /**************************************
  4999. *
  5000. * g d s _ r e l e a s e _ r e q u e s t
  5001. *
  5002. **************************************
  5003. *
  5004. * Functional description
  5005. * Release a request.
  5006. *
  5007. **************************************/
  5008. reset(status);
  5009. freeClientData(status);
  5010. }
  5011. void Request::free(CheckStatusWrapper* status)
  5012. {
  5013. internalFree(status);
  5014. if (status->isEmpty())
  5015. release();
  5016. }
  5017. void Request::deprecatedFree(CheckStatusWrapper* status)
  5018. {
  5019. internalFree(status);
  5020. }
  5021. void Request::getInfo(CheckStatusWrapper* status, int level,
  5022. unsigned int itemsLength, const unsigned char* items,
  5023. unsigned int bufferLength, unsigned char* buffer)
  5024. {
  5025. /**************************************
  5026. *
  5027. * g d s _ r e q u e s t _ i n f o
  5028. *
  5029. **************************************
  5030. *
  5031. * Functional description
  5032. * Provide information on request object.
  5033. *
  5034. **************************************/
  5035. try
  5036. {
  5037. reset(status);
  5038. CHECK_HANDLE(rq, isc_bad_req_handle);
  5039. Rrq* request = REMOTE_find_request(rq, level);
  5040. CHECK_HANDLE(request, isc_bad_req_handle);
  5041. Rdb* rdb = request->rrq_rdb;
  5042. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5043. rem_port* port = rdb->rdb_port;
  5044. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5045. // Check for buffered message. If there is, report on it locally.
  5046. const Rrq::rrq_repeat* tail= request->rrq_rpt.begin();
  5047. for (const Rrq::rrq_repeat* const end = tail + request->rrq_max_msg; tail <= end; tail++)
  5048. {
  5049. RMessage* msg = tail->rrq_message;
  5050. if (!msg || !msg->msg_address) {
  5051. continue;
  5052. }
  5053. // We've got a pending message, respond locally
  5054. const rem_fmt* format = tail->rrq_format;
  5055. UCHAR* out = buffer;
  5056. const UCHAR* infoItems = items;
  5057. const UCHAR* const endItems = infoItems + itemsLength;
  5058. while (infoItems < endItems)
  5059. {
  5060. USHORT data = 0;
  5061. const UCHAR item = *infoItems++;
  5062. switch (item)
  5063. {
  5064. case isc_info_end:
  5065. break;
  5066. case isc_info_state:
  5067. data = isc_info_req_send;
  5068. break;
  5069. case isc_info_message_number:
  5070. data = msg->msg_number;
  5071. break;
  5072. case isc_info_message_size:
  5073. data = format->fmt_length;
  5074. break;
  5075. default:
  5076. goto punt;
  5077. }
  5078. *out++ = item;
  5079. if (item == isc_info_end)
  5080. break;
  5081. *out++ = 2;
  5082. *out++ = 2 >> 8;
  5083. *out++ = (UCHAR) data;
  5084. *out++ = data >> 8;
  5085. }
  5086. }
  5087. // No message pending, request status from other end
  5088. punt:
  5089. info(status, rdb, op_info_request, request->rrq_id, level,
  5090. itemsLength, items, 0, 0, bufferLength, buffer);
  5091. }
  5092. catch (const Exception& ex)
  5093. {
  5094. ex.stuffException(status);
  5095. }
  5096. }
  5097. void Transaction::rollbackRetaining(CheckStatusWrapper* status)
  5098. {
  5099. /**************************************
  5100. *
  5101. * i s c _ r o l l b a c k _ r e t a i n i n g
  5102. *
  5103. **************************************
  5104. *
  5105. * Functional description
  5106. * Abort a transaction but keep its environment valid
  5107. *
  5108. **************************************/
  5109. try
  5110. {
  5111. reset(status);
  5112. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5113. Rdb* rdb = transaction->rtr_rdb;
  5114. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5115. rem_port* port = rdb->rdb_port;
  5116. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5117. release_object(status, rdb, op_rollback_retaining, transaction->rtr_id);
  5118. }
  5119. catch (const Exception& ex)
  5120. {
  5121. ex.stuffException(status);
  5122. }
  5123. }
  5124. void Transaction::freeClientData(CheckStatusWrapper* status, bool force)
  5125. {
  5126. /**************************************
  5127. *
  5128. * g d s _ r o l l b a c k
  5129. *
  5130. **************************************
  5131. *
  5132. * Functional description
  5133. * Abort a transaction.
  5134. *
  5135. **************************************/
  5136. try
  5137. {
  5138. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5139. Rdb* rdb = transaction->rtr_rdb;
  5140. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5141. rem_port* port = rdb->rdb_port;
  5142. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5143. try
  5144. {
  5145. release_object(status, rdb, op_rollback, transaction->rtr_id);
  5146. }
  5147. catch (const Exception&)
  5148. {
  5149. if (!force)
  5150. throw;
  5151. }
  5152. REMOTE_cleanup_transaction(transaction);
  5153. release_transaction(transaction);
  5154. transaction = NULL;
  5155. }
  5156. catch (const Exception& ex)
  5157. {
  5158. ex.stuffException(status);
  5159. }
  5160. }
  5161. void Transaction::internalRollback(CheckStatusWrapper* status)
  5162. {
  5163. /**************************************
  5164. *
  5165. * g d s _ r o l l b a c k
  5166. *
  5167. **************************************
  5168. *
  5169. * Functional description
  5170. * Abort a transaction.
  5171. *
  5172. **************************************/
  5173. reset(status);
  5174. freeClientData(status);
  5175. }
  5176. void Transaction::rollback(CheckStatusWrapper* status)
  5177. {
  5178. internalRollback(status);
  5179. if (status->isEmpty())
  5180. release();
  5181. }
  5182. void Transaction::deprecatedRollback(CheckStatusWrapper* status)
  5183. {
  5184. internalRollback(status);
  5185. }
  5186. void Transaction::internalDisconnect(CheckStatusWrapper* status)
  5187. {
  5188. try
  5189. {
  5190. reset(status);
  5191. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5192. Rdb* rdb = transaction->rtr_rdb;
  5193. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5194. // ASF: Looks wrong that this method is ignored in the engine and remote providers.
  5195. }
  5196. catch (const Exception& ex)
  5197. {
  5198. ex.stuffException(status);
  5199. }
  5200. }
  5201. void Transaction::disconnect(CheckStatusWrapper* status)
  5202. {
  5203. internalDisconnect(status);
  5204. if (status->isEmpty())
  5205. release();
  5206. }
  5207. void Transaction::deprecatedDisconnect(CheckStatusWrapper* status)
  5208. {
  5209. internalDisconnect(status);
  5210. }
  5211. int Blob::seek(CheckStatusWrapper* status, int mode, int offset)
  5212. {
  5213. /**************************************
  5214. *
  5215. * g d s _ s e e k _ b l o b
  5216. *
  5217. **************************************
  5218. *
  5219. * Functional description
  5220. * Seek into a blob.
  5221. *
  5222. **************************************/
  5223. try
  5224. {
  5225. reset(status);
  5226. CHECK_HANDLE(blob, isc_bad_segstr_handle);
  5227. Rdb* rdb = blob->rbl_rdb;
  5228. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5229. rem_port* port = rdb->rdb_port;
  5230. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5231. PACKET* packet = &rdb->rdb_packet;
  5232. packet->p_operation = op_seek_blob;
  5233. P_SEEK* seek = &packet->p_seek;
  5234. seek->p_seek_blob = blob->rbl_id;
  5235. seek->p_seek_mode = mode;
  5236. seek->p_seek_offset = offset;
  5237. if (mode == 1)
  5238. {
  5239. seek->p_seek_mode = 0;
  5240. seek->p_seek_offset = blob->rbl_offset + offset;
  5241. }
  5242. send_and_receive(status, rdb, packet);
  5243. blob->rbl_offset = packet->p_resp.p_resp_blob_id.gds_quad_low;
  5244. blob->rbl_length = 0;
  5245. blob->rbl_fragment_length = 0;
  5246. blob->rbl_flags &= ~(Rbl::EOF_SET | Rbl::EOF_PENDING | Rbl::SEGMENT);
  5247. return blob->rbl_offset;
  5248. }
  5249. catch (const Exception& ex)
  5250. {
  5251. ex.stuffException(status);
  5252. }
  5253. return 0;
  5254. }
  5255. void Request::send(CheckStatusWrapper* status, int level, unsigned int msg_type,
  5256. unsigned int /*length*/, const void* msg)
  5257. {
  5258. /**************************************
  5259. *
  5260. * g d s _ s e n d
  5261. *
  5262. **************************************
  5263. *
  5264. * Functional description
  5265. * Send a message to the server.
  5266. *
  5267. **************************************/
  5268. try
  5269. {
  5270. reset(status);
  5271. CHECK_HANDLE(rq, isc_bad_req_handle);
  5272. Rrq* request = REMOTE_find_request(rq, level);
  5273. Rdb* rdb = request->rrq_rdb;
  5274. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5275. rem_port* port = rdb->rdb_port;
  5276. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5277. if (msg_type > request->rrq_max_msg)
  5278. {
  5279. handle_error(isc_badmsgnum);
  5280. }
  5281. RMessage* message = request->rrq_rpt[msg_type].rrq_message;
  5282. // We are lying here, but the interface shows for years this param as const
  5283. message->msg_address = const_cast<unsigned char*>(static_cast<const unsigned char*>(msg));
  5284. PACKET* packet = &rdb->rdb_packet;
  5285. packet->p_operation = op_send;
  5286. P_DATA* data = &packet->p_data;
  5287. data->p_data_request = request->rrq_id;
  5288. data->p_data_message_number = msg_type;
  5289. data->p_data_incarnation = level;
  5290. send_packet(port, packet);
  5291. // Bump up the message pointer to resync with rrq_xdr (rrq_xdr
  5292. // was incremented by xdr_request in the SEND call).
  5293. message->msg_address = NULL;
  5294. request->rrq_rpt[msg_type].rrq_message = message->msg_next;
  5295. receive_response(status, rdb, packet);
  5296. }
  5297. catch (const Exception& ex)
  5298. {
  5299. ex.stuffException(status);
  5300. }
  5301. }
  5302. Firebird::IService* RProvider::attachSvc(CheckStatusWrapper* status, const char* service,
  5303. unsigned int spbLength, const unsigned char* spb, bool loopback)
  5304. {
  5305. /**************************************
  5306. *
  5307. * g d s _ s e r v i c e _ a t t a c h
  5308. *
  5309. **************************************
  5310. *
  5311. * Functional description
  5312. * Connect to a Firebird service.
  5313. *
  5314. **************************************/
  5315. try
  5316. {
  5317. reset(status);
  5318. PathName node_name, expanded_name(service);
  5319. ClumpletWriter newSpb(ClumpletReader::spbList, MAX_DPB_SIZE, spb, spbLength);
  5320. const bool user_verification = get_new_dpb(newSpb, spbParam, loopback);
  5321. ClntAuthBlock cBlock(NULL, &newSpb, &spbParam);
  5322. unsigned flags = 0;
  5323. if (user_verification)
  5324. flags |= ANALYZE_USER_VFY;
  5325. if (loopback)
  5326. flags |= ANALYZE_LOOPBACK;
  5327. flags |= ANALYZE_EMP_NAME;
  5328. PathName refDbName;
  5329. if (newSpb.find(isc_spb_expected_db))
  5330. newSpb.getPath(refDbName);
  5331. rem_port* port = analyze(cBlock, expanded_name, flags, newSpb, spbParam, node_name, &refDbName, cryptCallback);
  5332. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5333. Rdb* rdb = port->port_context;
  5334. // The client may have set a parameter for dummy_packet_interval. Add that to the
  5335. // the SPB so the server can pay attention to it. Note: allocation code must
  5336. // ensure sufficient space has been added.
  5337. add_other_params(port, newSpb, spbParam);
  5338. IntlSpb intl;
  5339. if (!init(status, cBlock, port, op_service_attach, expanded_name, newSpb, intl, cryptCallback))
  5340. return NULL;
  5341. Firebird::IService* s = FB_NEW Service(rdb);
  5342. s->addRef();
  5343. return s;
  5344. }
  5345. catch (const Exception& ex)
  5346. {
  5347. ex.stuffException(status);
  5348. }
  5349. return NULL;
  5350. }
  5351. Firebird::IService* RProvider::attachServiceManager(CheckStatusWrapper* status, const char* service,
  5352. unsigned int spbLength, const unsigned char* spb)
  5353. {
  5354. /**************************************
  5355. *
  5356. * g d s _ s e r v i c e _ a t t a c h
  5357. *
  5358. **************************************
  5359. *
  5360. * Functional description
  5361. * Connect to a Firebird service.
  5362. *
  5363. **************************************/
  5364. return attachSvc(status, service, spbLength, spb, false);
  5365. }
  5366. Firebird::IService* Loopback::attachServiceManager(CheckStatusWrapper* status, const char* service,
  5367. unsigned int spbLength, const unsigned char* spb)
  5368. {
  5369. /**************************************
  5370. *
  5371. * g d s _ s e r v i c e _ a t t a c h
  5372. *
  5373. **************************************
  5374. *
  5375. * Functional description
  5376. * Connect to a Firebird service.
  5377. *
  5378. **************************************/
  5379. return attachSvc(status, service, spbLength, spb, true);
  5380. }
  5381. void Service::freeClientData(CheckStatusWrapper* status, bool force)
  5382. {
  5383. /**************************************
  5384. *
  5385. * g d s _ s e r v i c e _ d e t a c h
  5386. *
  5387. **************************************
  5388. *
  5389. * Functional description
  5390. * Close down a connection to a Firebird service.
  5391. *
  5392. **************************************/
  5393. try
  5394. {
  5395. reset(status);
  5396. // Check and validate handles, etc.
  5397. CHECK_HANDLE(rdb, isc_bad_svc_handle);
  5398. rem_port* port = rdb->rdb_port;
  5399. RemotePortGuard portGuard(port, FB_FUNCTION);
  5400. if (!(port->port_flags & PORT_detached))
  5401. {
  5402. try
  5403. {
  5404. release_object(status, rdb, op_service_detach, rdb->rdb_id);
  5405. }
  5406. catch (const Exception&)
  5407. {
  5408. if (!force)
  5409. throw;
  5410. }
  5411. }
  5412. disconnect(port);
  5413. rdb = NULL;
  5414. }
  5415. catch (const Exception& ex)
  5416. {
  5417. ex.stuffException(status);
  5418. }
  5419. }
  5420. void Service::internalDetach(CheckStatusWrapper* status)
  5421. {
  5422. /**************************************
  5423. *
  5424. * g d s _ s e r v i c e _ d e t a c h
  5425. *
  5426. **************************************
  5427. *
  5428. * Functional description
  5429. * Close down a connection to a Firebird service.
  5430. *
  5431. **************************************/
  5432. reset(status);
  5433. freeClientData(status);
  5434. }
  5435. void Service::detach(CheckStatusWrapper* status)
  5436. {
  5437. internalDetach(status);
  5438. if (status->isEmpty())
  5439. release();
  5440. }
  5441. void Service::deprecatedDetach(CheckStatusWrapper* status)
  5442. {
  5443. internalDetach(status);
  5444. }
  5445. void Service::query(CheckStatusWrapper* status,
  5446. unsigned int sendLength, const unsigned char* sendItems,
  5447. unsigned int receiveLength, const unsigned char* receiveItems,
  5448. unsigned int bufferLength, unsigned char* buffer)
  5449. {
  5450. /**************************************
  5451. *
  5452. * g d s _ s e r v i c e _ q u e r y
  5453. *
  5454. **************************************
  5455. *
  5456. * Functional description
  5457. * Provide information on service object.
  5458. *
  5459. **************************************/
  5460. try
  5461. {
  5462. reset(status);
  5463. // Check and validate handles, etc.
  5464. CHECK_HANDLE(rdb, isc_bad_svc_handle);
  5465. rem_port* port = rdb->rdb_port;
  5466. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5467. info(status, rdb, op_service_info, rdb->rdb_id, 0,
  5468. sendLength, sendItems, receiveLength, receiveItems,
  5469. bufferLength, buffer);
  5470. }
  5471. catch (const Exception& ex)
  5472. {
  5473. ex.stuffException(status);
  5474. }
  5475. }
  5476. void Service::cancel(CheckStatusWrapper* status)
  5477. {
  5478. try
  5479. {
  5480. reset(status);
  5481. // Check and validate handles, etc.
  5482. CHECK_HANDLE(rdb, isc_bad_svc_handle);
  5483. /*
  5484. rem_port* port = rdb->rdb_port;
  5485. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5486. */
  5487. Arg::Gds(isc_wish_list).raise();
  5488. }
  5489. catch (const Exception& ex)
  5490. {
  5491. ex.stuffException(status);
  5492. }
  5493. }
  5494. void Service::start(CheckStatusWrapper* status,
  5495. unsigned int spbLength, const unsigned char* spb)
  5496. {
  5497. /**************************************
  5498. *
  5499. * g d s _ s e r v i c e _ s t a r t
  5500. *
  5501. **************************************
  5502. *
  5503. * Functional description
  5504. * Start a Firebird service
  5505. *
  5506. **************************************/
  5507. try
  5508. {
  5509. reset(status);
  5510. // Check and validate handles, etc.
  5511. CHECK_HANDLE(rdb, isc_bad_svc_handle);
  5512. rem_port* port = rdb->rdb_port;
  5513. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5514. svcstart(status, rdb, op_service_start, rdb->rdb_id, 0, spbLength, spb);
  5515. }
  5516. catch (const Exception& ex)
  5517. {
  5518. ex.stuffException(status);
  5519. }
  5520. }
  5521. void Request::startAndSend(CheckStatusWrapper* status, Firebird::ITransaction* apiTra, int level,
  5522. unsigned int msg_type, unsigned int /*length*/, const void* msg)
  5523. {
  5524. /**************************************
  5525. *
  5526. * g d s _ s t a r t _ a n d _ s e n d
  5527. *
  5528. **************************************
  5529. *
  5530. * Functional description
  5531. * Get a record from the host program.
  5532. *
  5533. **************************************/
  5534. try
  5535. {
  5536. reset(status);
  5537. CHECK_HANDLE(rq, isc_bad_req_handle);
  5538. Rrq* request = REMOTE_find_request(rq, level);
  5539. Rtr* transaction = remAtt->remoteTransaction(apiTra);
  5540. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5541. Rdb* rdb = request->rrq_rdb;
  5542. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5543. rem_port* port = rdb->rdb_port;
  5544. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5545. if (msg_type > request->rrq_max_msg)
  5546. {
  5547. handle_error(isc_badmsgnum);
  5548. }
  5549. if (transaction->rtr_rdb != rdb)
  5550. {
  5551. Arg::Gds(isc_trareqmis).raise();
  5552. }
  5553. clear_queue(rdb->rdb_port);
  5554. REMOTE_reset_request(request, 0);
  5555. RMessage* message = request->rrq_rpt[msg_type].rrq_message;
  5556. message->msg_address = const_cast<unsigned char*>(static_cast<const unsigned char*>(msg));
  5557. PACKET* packet = &rdb->rdb_packet;
  5558. packet->p_operation = op_start_send_and_receive;
  5559. P_DATA* data = &packet->p_data;
  5560. data->p_data_request = request->rrq_id;
  5561. data->p_data_transaction = transaction->rtr_id;
  5562. data->p_data_message_number = msg_type;
  5563. data->p_data_incarnation = level;
  5564. send_packet(port, packet);
  5565. // Bump up the message pointer to resync with rrq_xdr (rrq_xdr
  5566. // was incremented by xdr_request in the SEND call).
  5567. message->msg_address = NULL;
  5568. request->rrq_rpt[msg_type].rrq_message = message->msg_next;
  5569. receive_response(status, rdb, packet);
  5570. // Save the request's transaction.
  5571. request->rrq_rtr = transaction;
  5572. if (packet->p_operation == op_response_piggyback)
  5573. {
  5574. receive_after_start(request, packet->p_resp.p_resp_object);
  5575. }
  5576. }
  5577. catch (const Exception& ex)
  5578. {
  5579. ex.stuffException(status);
  5580. }
  5581. }
  5582. void Request::start(CheckStatusWrapper* status, Firebird::ITransaction* apiTra, int level)
  5583. {
  5584. /**************************************
  5585. *
  5586. * g d s _ s t a r t
  5587. *
  5588. **************************************
  5589. *
  5590. * Functional description
  5591. * Get a record from the host program.
  5592. *
  5593. **************************************/
  5594. try
  5595. {
  5596. reset(status);
  5597. CHECK_HANDLE(rq, isc_bad_req_handle);
  5598. Rrq* request = REMOTE_find_request(rq, level);
  5599. Rtr* transaction = remAtt->remoteTransaction(apiTra);
  5600. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5601. Rdb* rdb = request->rrq_rdb;
  5602. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5603. rem_port* port = rdb->rdb_port;
  5604. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5605. if (transaction->rtr_rdb != rdb)
  5606. {
  5607. Arg::Gds(isc_trareqmis).raise();
  5608. }
  5609. clear_queue(rdb->rdb_port);
  5610. REMOTE_reset_request(request, 0);
  5611. PACKET* packet = &rdb->rdb_packet;
  5612. packet->p_operation = op_start_and_receive;
  5613. P_DATA* data = &packet->p_data;
  5614. data->p_data_request = request->rrq_id;
  5615. data->p_data_transaction = transaction->rtr_id;
  5616. data->p_data_message_number = 0;
  5617. data->p_data_incarnation = level;
  5618. send_and_receive(status, rdb, packet);
  5619. // Save the request's transaction.
  5620. request->rrq_rtr = transaction;
  5621. if (packet->p_operation == op_response_piggyback)
  5622. {
  5623. receive_after_start(request, packet->p_resp.p_resp_object);
  5624. }
  5625. }
  5626. catch (const Exception& ex)
  5627. {
  5628. ex.stuffException(status);
  5629. }
  5630. }
  5631. Firebird::ITransaction* Attachment::startTransaction(CheckStatusWrapper* status, unsigned int tpbLength,
  5632. const unsigned char* tpb)
  5633. {
  5634. /**************************************
  5635. *
  5636. * g d s _ t r a n s a c t i o n
  5637. *
  5638. **************************************
  5639. *
  5640. * Functional description
  5641. * Start a transaction.
  5642. *
  5643. **************************************/
  5644. try
  5645. {
  5646. reset(status);
  5647. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5648. rem_port* port = rdb->rdb_port;
  5649. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5650. if (/***tpbLength < 0 ||***/ (tpbLength > 0 && !tpb))
  5651. {
  5652. status_exception::raise(Arg::Gds(isc_bad_tpb_form));
  5653. }
  5654. // Validate data length
  5655. CHECK_LENGTH(port, tpbLength);
  5656. PACKET* packet = &rdb->rdb_packet;
  5657. packet->p_operation = op_transaction;
  5658. P_STTR* trans = &packet->p_sttr;
  5659. trans->p_sttr_database = rdb->rdb_id;
  5660. trans->p_sttr_tpb.cstr_length = tpbLength;
  5661. trans->p_sttr_tpb.cstr_address = tpb;
  5662. send_and_receive(status, rdb, packet);
  5663. Firebird::ITransaction* t = FB_NEW Transaction(make_transaction(rdb, packet->p_resp.p_resp_object), this);
  5664. t->addRef();
  5665. return t;
  5666. }
  5667. catch (const Exception& ex)
  5668. {
  5669. ex.stuffException(status);
  5670. }
  5671. return NULL;
  5672. }
  5673. void Attachment::transactRequest(CheckStatusWrapper* status, ITransaction* apiTra,
  5674. unsigned int blr_length, const unsigned char* blr,
  5675. unsigned int in_msg_length, const unsigned char* in_msg,
  5676. unsigned int out_msg_length, unsigned char* out_msg)
  5677. {
  5678. /**************************************
  5679. *
  5680. * i s c _ t r a n s a c t _ r e q u e s t
  5681. *
  5682. **************************************
  5683. *
  5684. * Functional description
  5685. * Execute a procedure on remote host.
  5686. *
  5687. **************************************/
  5688. try
  5689. {
  5690. reset(status);
  5691. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5692. rem_port* port = rdb->rdb_port;
  5693. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5694. Rtr* transaction = remoteTransaction(apiTra);
  5695. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5696. // Validate data length
  5697. CHECK_LENGTH(port, blr_length);
  5698. CHECK_LENGTH(port, in_msg_length);
  5699. CHECK_LENGTH(port, out_msg_length);
  5700. Rpr* procedure = port->port_rpr;
  5701. if (!procedure) {
  5702. procedure = port->port_rpr = FB_NEW Rpr;
  5703. }
  5704. // Parse the blr describing the messages
  5705. delete procedure->rpr_in_msg;
  5706. procedure->rpr_in_msg = NULL;
  5707. delete procedure->rpr_in_format;
  5708. procedure->rpr_in_format = NULL;
  5709. delete procedure->rpr_out_msg;
  5710. procedure->rpr_out_msg = NULL;
  5711. delete procedure->rpr_out_format;
  5712. procedure->rpr_out_format = NULL;
  5713. RMessage* message = PARSE_messages(blr, blr_length);
  5714. while (message)
  5715. {
  5716. switch (message->msg_number)
  5717. {
  5718. case 0:
  5719. procedure->rpr_in_msg = message;
  5720. procedure->rpr_in_format = (rem_fmt*) message->msg_address;
  5721. message->msg_address = const_cast<unsigned char*>(in_msg);
  5722. message = message->msg_next;
  5723. procedure->rpr_in_msg->msg_next = NULL;
  5724. break;
  5725. case 1:
  5726. procedure->rpr_out_msg = message;
  5727. procedure->rpr_out_format = (rem_fmt*) message->msg_address;
  5728. message->msg_address = out_msg;
  5729. message = message->msg_next;
  5730. procedure->rpr_out_msg->msg_next = NULL;
  5731. break;
  5732. default:
  5733. RMessage* temp = message;
  5734. message = message->msg_next;
  5735. delete temp;
  5736. break;
  5737. }
  5738. }
  5739. PACKET* packet = &rdb->rdb_packet;
  5740. packet->p_operation = op_transact;
  5741. P_TRRQ* trrq = &packet->p_trrq;
  5742. trrq->p_trrq_database = rdb->rdb_id;
  5743. trrq->p_trrq_transaction = transaction->rtr_id;
  5744. trrq->p_trrq_blr.cstr_length = blr_length;
  5745. trrq->p_trrq_blr.cstr_address = const_cast<unsigned char*>(blr);
  5746. trrq->p_trrq_messages = in_msg_length ? 1 : 0;
  5747. send_packet(port, packet);
  5748. // Two types of responses are possible, op_transact_response or
  5749. // op_response. When there is an error op_response packet is returned
  5750. // and it modifies the status vector to indicate the error which occurred.
  5751. // But when success occurs a packet with op_transact_response comes back
  5752. // which does not change the status vector.
  5753. receive_packet(port, packet);
  5754. if (packet->p_operation != op_transact_response)
  5755. {
  5756. REMOTE_check_response(status, rdb, packet);
  5757. }
  5758. }
  5759. catch (const Exception& ex)
  5760. {
  5761. ex.stuffException(status);
  5762. }
  5763. }
  5764. void Transaction::getInfo(CheckStatusWrapper* status,
  5765. unsigned int itemsLength, const unsigned char* items,
  5766. unsigned int bufferLength, unsigned char* buffer)
  5767. {
  5768. /**************************************
  5769. *
  5770. * g d s _ t r a n s a c t i o n _ i n f o
  5771. *
  5772. **************************************
  5773. *
  5774. * Functional description
  5775. *
  5776. **************************************/
  5777. Array<unsigned char> newItemsBuffer;
  5778. try
  5779. {
  5780. reset(status);
  5781. CHECK_HANDLE(transaction, isc_bad_trans_handle);
  5782. Rdb* rdb = transaction->rtr_rdb;
  5783. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5784. rem_port* port = rdb->rdb_port;
  5785. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5786. fb_utils::getDbPathInfo(itemsLength, items, bufferLength, buffer,
  5787. newItemsBuffer, remAtt->getDbPath());
  5788. info(status, rdb, op_info_transaction, transaction->rtr_id, 0,
  5789. itemsLength, items, 0, 0, bufferLength, buffer);
  5790. }
  5791. catch (const Exception& ex)
  5792. {
  5793. ex.stuffException(status);
  5794. }
  5795. }
  5796. void Request::unwind(CheckStatusWrapper* status, int level)
  5797. {
  5798. /**************************************
  5799. *
  5800. * g d s _ u n w i n d
  5801. *
  5802. **************************************
  5803. *
  5804. * Functional description
  5805. * Unwind a running request.
  5806. *
  5807. **************************************/
  5808. try
  5809. {
  5810. reset(status);
  5811. Rrq* request = REMOTE_find_request(rq, level);
  5812. CHECK_HANDLE(request, isc_bad_req_handle);
  5813. Rdb* rdb = request->rrq_rdb;
  5814. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5815. rem_port* port = rdb->rdb_port;
  5816. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5817. }
  5818. catch (const Exception& ex)
  5819. {
  5820. ex.stuffException(status);
  5821. }
  5822. }
  5823. void Attachment::ping(CheckStatusWrapper* status)
  5824. {
  5825. /**************************************
  5826. *
  5827. * p i n g
  5828. *
  5829. **************************************
  5830. *
  5831. * Functional description
  5832. * Check the attachment handle for persistent errors.
  5833. *
  5834. **************************************/
  5835. try
  5836. {
  5837. reset(status);
  5838. CHECK_HANDLE(rdb, isc_bad_db_handle);
  5839. rem_port* port = rdb->rdb_port;
  5840. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  5841. // Make sure protocol support action
  5842. if (rdb->rdb_port->port_protocol < PROTOCOL_VERSION13)
  5843. unsupported();
  5844. PACKET* packet = &rdb->rdb_packet;
  5845. packet->p_operation = op_ping;
  5846. send_and_receive(status, rdb, packet);
  5847. }
  5848. catch (const Exception& ex)
  5849. {
  5850. ex.stuffException(status);
  5851. }
  5852. }
  5853. static Rvnt* add_event( rem_port* port)
  5854. {
  5855. /*************************************
  5856. *
  5857. * a d d _ e v e n t
  5858. *
  5859. **************************************
  5860. *
  5861. * Functional description
  5862. * Add remote event block to active chain.
  5863. *
  5864. **************************************/
  5865. Rdb* rdb = port->port_context;
  5866. // Find unused event block or, if necessary, a new one
  5867. Rvnt* event;
  5868. for (event = rdb->rdb_events; event; event = event->rvnt_next)
  5869. {
  5870. if (!event->rvnt_id)
  5871. break;
  5872. }
  5873. if (!event)
  5874. {
  5875. event = FB_NEW Rvnt;
  5876. event->rvnt_next = rdb->rdb_events;
  5877. rdb->rdb_events = event;
  5878. }
  5879. event->rvnt_id = ++remote_event_id;
  5880. return event;
  5881. }
  5882. static void add_other_params(rem_port* port, ClumpletWriter& dpb, const ParametersSet& par)
  5883. {
  5884. /**************************************
  5885. *
  5886. * a d d _ o t h e r _ p a r a m s
  5887. *
  5888. **************************************
  5889. *
  5890. * Functional description
  5891. * Add parameters to a dpb to describe client-side
  5892. * settings that the server should know about.
  5893. *
  5894. **************************************/
  5895. if (port->port_flags & PORT_dummy_pckt_set)
  5896. {
  5897. dpb.deleteWithTag(par.dummy_packet_interval);
  5898. dpb.insertInt(par.dummy_packet_interval, port->port_dummy_packet_interval);
  5899. }
  5900. // Older version of engine not understand new tags and may process whole
  5901. // DPB incorrectly. Check for protocol version is an poor attempt to make
  5902. // guess about remote engine's version
  5903. if (port->port_protocol >= PROTOCOL_VERSION11)
  5904. {
  5905. dpb.deleteWithTag(par.process_id);
  5906. dpb.insertInt(par.process_id, getpid());
  5907. if (!dpb.find(par.process_name))
  5908. {
  5909. PathName path(fb_utils::get_process_name());
  5910. ISC_systemToUtf8(path);
  5911. ISC_escape(path);
  5912. if (!dpb.find(isc_dpb_utf8_filename))
  5913. ISC_utf8ToSystem(path);
  5914. dpb.insertString(par.process_name, path);
  5915. }
  5916. }
  5917. if (port->port_protocol >= PROTOCOL_VERSION13)
  5918. {
  5919. dpb.deleteWithTag(par.client_version);
  5920. dpb.insertString(par.client_version, FB_VERSION);
  5921. }
  5922. }
  5923. static void add_working_directory(ClumpletWriter& dpb, const PathName& node_name)
  5924. {
  5925. /************************************************
  5926. *
  5927. * a d d _ w o r k i n g _ d i r e c t o r y
  5928. *
  5929. ************************************************
  5930. *
  5931. * Functional description
  5932. * Add parameters to a dpb or spb to describe client-side
  5933. * settings that the server should know about.
  5934. *
  5935. ************************************************/
  5936. if (dpb.find(isc_dpb_working_directory))
  5937. {
  5938. return;
  5939. }
  5940. PathName cwd;
  5941. // for WNet local node_name should be compared with "\\\\." ?
  5942. if (node_name == "localhost")
  5943. {
  5944. fb_utils::getCwd(cwd);
  5945. ISC_systemToUtf8(cwd);
  5946. ISC_escape(cwd);
  5947. if (!dpb.find(isc_dpb_utf8_filename))
  5948. ISC_utf8ToSystem(cwd);
  5949. }
  5950. dpb.insertString(isc_dpb_working_directory, cwd);
  5951. }
  5952. static void authenticateStep0(ClntAuthBlock& cBlock)
  5953. {
  5954. LocalStatus ls;
  5955. CheckStatusWrapper s(&ls);
  5956. for (; cBlock.plugins.hasData(); cBlock.plugins.next())
  5957. {
  5958. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authenticateStep0(%s)\n", cBlock.plugins.name()));
  5959. switch(cBlock.plugins.plugin()->authenticate(&s, &cBlock))
  5960. {
  5961. case IAuth::AUTH_SUCCESS:
  5962. case IAuth::AUTH_MORE_DATA:
  5963. return;
  5964. case IAuth::AUTH_FAILED:
  5965. if (s.getState() & Firebird::IStatus::STATE_ERRORS)
  5966. {
  5967. iscLogStatus("Authentication, client plugin:", &s);
  5968. }
  5969. (Arg::Gds(isc_login_error)
  5970. #ifdef DEV_BUILD
  5971. << Arg::StatusVector(&s)
  5972. #endif
  5973. ).raise();
  5974. break; // compiler silencer
  5975. }
  5976. }
  5977. }
  5978. static void secureAuthentication(ClntAuthBlock& cBlock, rem_port* port)
  5979. {
  5980. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: secureAuthentication\n"));
  5981. if (!port)
  5982. return;
  5983. Rdb* rdb = port->port_context;
  5984. fb_assert(rdb);
  5985. PACKET* packet = &rdb->rdb_packet;
  5986. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: secureAuthentication: port OK, op=%d\n", packet->p_operation));
  5987. if (packet->p_operation == op_cond_accept)
  5988. {
  5989. LocalStatus ls;
  5990. CheckStatusWrapper st(&ls);
  5991. authReceiveResponse(true, cBlock, port, rdb, &st, packet, true);
  5992. if (st.getState() & Firebird::IStatus::STATE_ERRORS)
  5993. status_exception::raise(&st);
  5994. }
  5995. else
  5996. {
  5997. // try to start crypt
  5998. cBlock.tryNewKeys(port);
  5999. }
  6000. }
  6001. static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags,
  6002. ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name,
  6003. Firebird::ICryptKeyCallback* cryptCb)
  6004. {
  6005. /**************************************
  6006. *
  6007. * a n a l y z e
  6008. *
  6009. **************************************
  6010. *
  6011. * Functional description
  6012. * Analyze an attach specification and determine whether
  6013. * a remote server is required, and if so, what protocol
  6014. * to use. If the target can be accessed via the
  6015. * remote subsystem, return address of a port block
  6016. * with which to communicate with the server.
  6017. * Otherwise, return NULL.
  6018. *
  6019. * NOTE: The file name must have been expanded prior to this call.
  6020. *
  6021. **************************************/
  6022. rem_port* port = NULL;
  6023. int inet_af = AF_UNSPEC;
  6024. cBlock.loadClnt(pb, &parSet);
  6025. pb.deleteWithTag(parSet.auth_block);
  6026. authenticateStep0(cBlock);
  6027. bool needFile = !(flags & ANALYZE_EMP_NAME);
  6028. #ifdef WIN_NT
  6029. if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
  6030. port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
  6031. else
  6032. #endif
  6033. if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
  6034. inet_af = AF_INET;
  6035. else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
  6036. inet_af = AF_INET6;
  6037. if (inet_af != AF_UNSPEC ||
  6038. ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
  6039. ISC_analyze_tcp(attach_name, node_name, needFile))
  6040. {
  6041. if (node_name.isEmpty())
  6042. node_name = INET_LOCALHOST;
  6043. else
  6044. {
  6045. ISC_unescape(node_name);
  6046. ISC_utf8ToSystem(node_name);
  6047. }
  6048. port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
  6049. cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
  6050. }
  6051. // We have a local connection string. If it's a file on a network share,
  6052. // try to connect to the corresponding host remotely.
  6053. if (flags & ANALYZE_MOUNTS)
  6054. {
  6055. #ifdef WIN_NT
  6056. if (!port)
  6057. {
  6058. PathName expanded_name = attach_name;
  6059. if (ISC_analyze_pclan(expanded_name, node_name))
  6060. {
  6061. ISC_unescape(node_name);
  6062. ISC_utf8ToSystem(node_name);
  6063. port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
  6064. cBlock.getConfig(), ref_db_name, cryptCb);
  6065. }
  6066. }
  6067. #endif
  6068. #ifndef NO_NFS
  6069. if (!port)
  6070. {
  6071. PathName expanded_name = attach_name;
  6072. if (ISC_analyze_nfs(expanded_name, node_name))
  6073. {
  6074. ISC_unescape(node_name);
  6075. ISC_utf8ToSystem(node_name);
  6076. port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
  6077. cBlock.getConfig(), ref_db_name, cryptCb);
  6078. }
  6079. }
  6080. #endif
  6081. }
  6082. if ((flags & ANALYZE_LOOPBACK) && !port)
  6083. {
  6084. // We have a local connection string.
  6085. // If we are in loopback mode attempt connect to a localhost.
  6086. if (node_name.isEmpty())
  6087. {
  6088. #ifdef WIN_NT
  6089. if (!port)
  6090. {
  6091. port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
  6092. cBlock.getConfig(), ref_db_name);
  6093. }
  6094. #endif
  6095. if (!port)
  6096. {
  6097. port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
  6098. cBlock.getConfig(), ref_db_name, cryptCb);
  6099. }
  6100. }
  6101. }
  6102. if (!port)
  6103. Arg::Gds(isc_unavailable).raise();
  6104. try
  6105. {
  6106. secureAuthentication(cBlock, port);
  6107. }
  6108. catch (const Exception&)
  6109. {
  6110. disconnect(port, false);
  6111. throw;
  6112. }
  6113. outPorts->registerPort(port);
  6114. return port;
  6115. }
  6116. static void clear_stmt_que(rem_port* port, Rsr* statement)
  6117. {
  6118. /**************************************
  6119. *
  6120. * c l e a r _ s t m t _ q u e
  6121. *
  6122. **************************************
  6123. *
  6124. * Functional description
  6125. *
  6126. * Receive and handle all queued packets for a completely fetched statement.
  6127. * There must be no more than one such packet.
  6128. *
  6129. **************************************/
  6130. fb_assert(statement->rsr_batch_count <= 1);
  6131. while (statement->rsr_batch_count)
  6132. receive_queued_packet(port, statement->rsr_id);
  6133. // hvlad: clear isc_req_sync error as it is received because of our batch
  6134. // fetching code, not because of wrong client application.
  6135. // dimitr: modern engine versions do not pass isc_req_sync to the client,
  6136. // but it's possible if we're connected to the older one.
  6137. if (statement->haveException() == isc_req_sync)
  6138. statement->clearException();
  6139. }
  6140. static void batch_dsql_fetch(rem_port* port,
  6141. rmtque* que_inst,
  6142. USHORT id)
  6143. {
  6144. /**************************************
  6145. *
  6146. * b a t c h _ d s q l _ f e t c h
  6147. *
  6148. **************************************
  6149. *
  6150. * Functional description
  6151. * Receive a batch of messages that were queued
  6152. * on the wire.
  6153. *
  6154. * This function will be invoked whenever we need to wait
  6155. * for something to come over on the wire, and there are
  6156. * items in the queue for receipt.
  6157. *
  6158. * Note on error handing: Actual networking errors
  6159. * need to be reported to status - which is bubbled
  6160. * upwards to the API call which initiated this receive.
  6161. * A status vector being returned as part of the cursor
  6162. * fetch needs to be stored away for later return to the
  6163. * client in the proper place in the stream.
  6164. *
  6165. **************************************/
  6166. fb_assert(port);
  6167. fb_assert(que_inst);
  6168. fb_assert(que_inst->rmtque_function == batch_dsql_fetch);
  6169. Rdb* rdb = que_inst->rmtque_rdb;
  6170. Rsr* statement = static_cast<Rsr*>(que_inst->rmtque_parm);
  6171. PACKET* packet = &rdb->rdb_packet;
  6172. fb_assert(port == rdb->rdb_port);
  6173. // Setup the packet structures so it knows what statement we
  6174. // are trying to receive at this point in time
  6175. packet->p_sqldata.p_sqldata_statement = statement->rsr_id;
  6176. // We'll either receive the whole batch, until end-of-batch is seen,
  6177. // or we'll just fetch one. We'll fetch one when we've run out of
  6178. // local data to return to the client, so we grab one "hot off the wire"
  6179. // to handoff to them. We'll grab the whole batch when we need to
  6180. // receive a response for a DIFFERENT network request on the wire,
  6181. // so we have to clear the wire before the response can be received
  6182. // In addition to the above we grab all the records in case of XNET as
  6183. // we need to clear the queue.
  6184. const bool clear_queue = (id != statement->rsr_id || port->port_type == rem_port::XNET);
  6185. statement->rsr_flags.set(Rsr::FETCHED);
  6186. while (true)
  6187. {
  6188. LocalStatus ls;
  6189. CheckStatusWrapper status(&ls);
  6190. // Swallow up data. If a buffer isn't available, allocate another.
  6191. RMessage* message = statement->rsr_buffer;
  6192. if (message->msg_address)
  6193. {
  6194. RMessage* new_msg = FB_NEW RMessage(statement->rsr_fmt_length);
  6195. statement->rsr_buffer = new_msg;
  6196. new_msg->msg_next = message;
  6197. while (message->msg_next != new_msg->msg_next)
  6198. message = message->msg_next;
  6199. message->msg_next = new_msg;
  6200. }
  6201. try {
  6202. receive_packet_noqueue(port, packet);
  6203. }
  6204. catch (const Exception&)
  6205. {
  6206. // Must be a network error
  6207. statement->rsr_rows_pending = 0;
  6208. --statement->rsr_batch_count;
  6209. dequeue_receive(port);
  6210. throw;
  6211. }
  6212. if (packet->p_operation != op_fetch_response)
  6213. {
  6214. statement->rsr_flags.set(Rsr::STREAM_ERR);
  6215. try
  6216. {
  6217. REMOTE_check_response(&status, rdb, packet);
  6218. statement->saveException(&status, false);
  6219. }
  6220. catch (const Exception& ex)
  6221. {
  6222. // Queue errors within the batched request
  6223. statement->saveException(ex, false);
  6224. }
  6225. statement->rsr_rows_pending = 0;
  6226. --statement->rsr_batch_count;
  6227. dequeue_receive(port);
  6228. break;
  6229. }
  6230. // See if we're at end of the batch
  6231. if (packet->p_sqldata.p_sqldata_status || !packet->p_sqldata.p_sqldata_messages)
  6232. {
  6233. if (packet->p_sqldata.p_sqldata_status == 100)
  6234. {
  6235. const auto operation = statement->rsr_fetch_operation;
  6236. const auto position = statement->rsr_fetch_position;
  6237. const bool forward =
  6238. (operation == fetch_next || operation == fetch_last ||
  6239. ((operation == fetch_absolute || operation == fetch_relative) && position > 0));
  6240. if (forward)
  6241. statement->rsr_flags.set(Rsr::EOF_SET);
  6242. else
  6243. statement->rsr_flags.set(Rsr::BOF_SET);
  6244. statement->rsr_rows_pending = 0;
  6245. #ifdef DEBUG
  6246. fprintf(stdout, "Resetting Rows Pending in batch_dsql_fetch=%lu\n",
  6247. statement->rsr_rows_pending);
  6248. #endif
  6249. }
  6250. if (--statement->rsr_batch_count == 0)
  6251. statement->rsr_rows_pending = 0;
  6252. dequeue_receive(port);
  6253. // clear next queued batch(es) if present
  6254. if (packet->p_sqldata.p_sqldata_status == 100)
  6255. {
  6256. try
  6257. {
  6258. clear_stmt_que(port, statement);
  6259. }
  6260. catch (const Exception&) { }
  6261. }
  6262. break;
  6263. }
  6264. statement->rsr_msgs_waiting++;
  6265. statement->rsr_rows_pending--;
  6266. #ifdef DEBUG
  6267. fprintf(stdout, "Decrementing Rows Pending in batch_dsql_fetch=%lu\n",
  6268. statement->rsr_rows_pending);
  6269. #endif
  6270. if (!clear_queue)
  6271. break;
  6272. }
  6273. }
  6274. static void batch_gds_receive(rem_port* port,
  6275. rmtque* que_inst,
  6276. USHORT id)
  6277. {
  6278. /**************************************
  6279. *
  6280. * b a t c h _ g d s _ r e c e i v e
  6281. *
  6282. **************************************
  6283. *
  6284. * Functional description
  6285. * Receive a batch of messages that were queued
  6286. * on the wire.
  6287. *
  6288. * This function will be invoked whenever we need to wait
  6289. * for something to come over on the wire, and there are
  6290. * items in the queue for receipt.
  6291. *
  6292. * Note on error handing: Actual networking errors
  6293. * need to be reported to status - which is bubbled
  6294. * upwards to the API call which initiated this receive.
  6295. * A status vector being returned as part of the cursor
  6296. * fetch needs to be stored away for later return to the
  6297. * client in the proper place in the stream.
  6298. *
  6299. **************************************/
  6300. fb_assert(port);
  6301. fb_assert(que_inst);
  6302. fb_assert(que_inst->rmtque_function == batch_gds_receive);
  6303. Rdb* rdb = que_inst->rmtque_rdb;
  6304. Rrq* request = static_cast<Rrq*>(que_inst->rmtque_parm);
  6305. Rrq::rrq_repeat* tail = que_inst->rmtque_message;
  6306. PACKET *packet = &rdb->rdb_packet;
  6307. fb_assert(port == rdb->rdb_port);
  6308. bool clear_queue = false;
  6309. // indicates whether queue is just being emptied, not retrieved
  6310. // always clear the complete queue for XNET, as we might
  6311. // have incomplete packets
  6312. if (id != request->rrq_id || port->port_type == rem_port::XNET)
  6313. {
  6314. clear_queue = true;
  6315. }
  6316. // Receive the whole batch of records, until end-of-batch is seen
  6317. while (true)
  6318. {
  6319. RMessage* message = tail->rrq_xdr; // First free buffer
  6320. // If the buffer queue is full, allocate a new message and
  6321. // place it in the queue--if we are clearing the queue, don't
  6322. // read records into messages linked list so that we don't
  6323. // mess up the record cache for scrolling purposes.
  6324. if (message->msg_address)
  6325. {
  6326. const rem_fmt* format = tail->rrq_format;
  6327. RMessage* new_msg = FB_NEW RMessage(format->fmt_length);
  6328. tail->rrq_xdr = new_msg;
  6329. new_msg->msg_next = message;
  6330. new_msg->msg_number = message->msg_number;
  6331. // Walk the que until we find the predecessor of message
  6332. while (message->msg_next != new_msg->msg_next)
  6333. {
  6334. message = message->msg_next;
  6335. }
  6336. message->msg_next = new_msg;
  6337. }
  6338. // Note: not receive_packet
  6339. try
  6340. {
  6341. receive_packet_noqueue(rdb->rdb_port, packet);
  6342. }
  6343. catch (const Exception&)
  6344. {
  6345. // Must be a network error
  6346. tail->rrq_rows_pending = 0;
  6347. --tail->rrq_batch_count;
  6348. dequeue_receive(port);
  6349. throw;
  6350. }
  6351. if (packet->p_operation != op_send)
  6352. {
  6353. tail->rrq_rows_pending = 0;
  6354. --tail->rrq_batch_count;
  6355. try
  6356. {
  6357. LocalStatus ls;
  6358. CheckStatusWrapper status(&ls);
  6359. REMOTE_check_response(&status, rdb, packet);
  6360. #ifdef DEBUG
  6361. fprintf(stderr, "End of batch. rows pending = %d\n", tail->rrq_rows_pending);
  6362. #endif
  6363. request->saveStatus(&status);
  6364. }
  6365. catch (const Exception& ex)
  6366. {
  6367. #ifdef DEBUG
  6368. fprintf(stderr, "Got batch error %ld Max message = %d\n",
  6369. ex->value()[1], request->rrq_max_msg);
  6370. #endif
  6371. // Queue errors within the batched request
  6372. request->saveStatus(ex);
  6373. }
  6374. dequeue_receive(port);
  6375. break;
  6376. }
  6377. tail->rrq_msgs_waiting++;
  6378. tail->rrq_rows_pending--;
  6379. #ifdef DEBUG
  6380. fprintf(stdout, "Decrementing Rows Pending in batch_gds_receive=%d\n",
  6381. tail->rrq_rows_pending);
  6382. #endif
  6383. // See if we're at end of the batch
  6384. if (!packet->p_data.p_data_messages)
  6385. {
  6386. if (!(--tail->rrq_batch_count))
  6387. tail->rrq_rows_pending = 0;
  6388. #ifdef DEBUG
  6389. fprintf(stderr, "End of batch waiting %d\n", tail->rrq_rows_pending);
  6390. #endif
  6391. dequeue_receive(port);
  6392. break;
  6393. }
  6394. // one packet is enough unless we are trying to clear the queue
  6395. if (!clear_queue)
  6396. break;
  6397. }
  6398. }
  6399. static void clear_queue(rem_port* port)
  6400. {
  6401. /**************************************
  6402. *
  6403. * c l e a r _ q u e u e
  6404. *
  6405. **************************************
  6406. *
  6407. * Functional description
  6408. * Clear the queue of batched packets - in preparation
  6409. * for waiting for a specific response, or when we are
  6410. * about to reuse an internal request.
  6411. * Return codes:
  6412. * true - no errors.
  6413. * false - Network error occurred, error code in status
  6414. **************************************/
  6415. while (port->port_receive_rmtque)
  6416. {
  6417. receive_queued_packet(port, (USHORT) -1);
  6418. }
  6419. }
  6420. static void finalize(rem_port* port)
  6421. {
  6422. /**************************************
  6423. *
  6424. * f i n a l i z e
  6425. *
  6426. **************************************
  6427. *
  6428. * Functional description
  6429. * Disconnect remote port.
  6430. *
  6431. **************************************/
  6432. // no need to do something if port already detached
  6433. if (port->port_flags & PORT_detached)
  6434. return;
  6435. // Avoid async send during finalize
  6436. RefMutexGuard guard(*port->port_write_sync, FB_FUNCTION);
  6437. // recheck with mutex taken
  6438. if (port->port_flags & PORT_detached)
  6439. return;
  6440. // Send a disconnect to the server so that it
  6441. // gracefully terminates.
  6442. Rdb* rdb = port->port_context;
  6443. if (rdb)
  6444. {
  6445. PACKET* packet = &rdb->rdb_packet;
  6446. // Deliver the pending deferred packets
  6447. if (port->port_deferred_packets)
  6448. {
  6449. for (rem_que_packet* p = port->port_deferred_packets->begin();
  6450. p < port->port_deferred_packets->end();
  6451. p++)
  6452. {
  6453. if (!p->sent)
  6454. port->send(&p->packet);
  6455. }
  6456. }
  6457. packet->p_operation = op_disconnect;
  6458. port->send(packet);
  6459. REMOTE_free_packet(port, packet);
  6460. }
  6461. // Cleanup the queue
  6462. delete port->port_deferred_packets;
  6463. port->port_deferred_packets = nullptr;
  6464. port->port_flags &= ~PORT_lazy;
  6465. port->port_flags |= PORT_detached;
  6466. }
  6467. static void disconnect(rem_port* port, bool rmRef)
  6468. {
  6469. /**************************************
  6470. *
  6471. * d i s c o n n e c t
  6472. *
  6473. **************************************
  6474. *
  6475. * Functional description
  6476. * Disconnect a port and free its memory.
  6477. *
  6478. **************************************/
  6479. finalize(port);
  6480. Rdb* rdb = port->port_context;
  6481. port->port_context = nullptr;
  6482. // Clear context reference for the associated event handler
  6483. // to avoid SEGV during shutdown
  6484. if (port->port_async)
  6485. {
  6486. port->port_async->port_context = NULL;
  6487. port->port_async->port_flags |= PORT_disconnect;
  6488. }
  6489. // Perform physical network disconnect and release
  6490. // memory for remote database context.
  6491. port->port_flags |= PORT_disconnect;
  6492. port->disconnect();
  6493. delete rdb;
  6494. // Remove from active ports
  6495. if (rmRef)
  6496. outPorts->unRegisterPort(port);
  6497. }
  6498. static THREAD_ENTRY_DECLARE event_thread(THREAD_ENTRY_PARAM arg)
  6499. {
  6500. /**************************************
  6501. *
  6502. * e v e n t _ t h r e a d
  6503. *
  6504. **************************************
  6505. *
  6506. * Functional description
  6507. * Wait on auxilary mailbox for event notification.
  6508. *
  6509. **************************************/
  6510. rem_port* port = (rem_port*)arg;
  6511. // Reference portRef(*port);
  6512. PACKET packet;
  6513. while (!(port->port_flags & PORT_disconnect))
  6514. {
  6515. // zero packet
  6516. zap_packet(&packet);
  6517. // read what should be an event message
  6518. rem_port* stuff = NULL;
  6519. P_OP operation = op_void;
  6520. { // scope
  6521. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  6522. try
  6523. {
  6524. stuff = port->receive(&packet);
  6525. }
  6526. catch(status_exception&)
  6527. {
  6528. // ignore
  6529. }
  6530. operation = packet.p_operation;
  6531. if (!stuff || operation == op_exit || operation == op_disconnect)
  6532. {
  6533. // Actually, the remote server doing the watching died.
  6534. // Clean up and leave.
  6535. REMOTE_free_packet(port, &packet);
  6536. server_death(port);
  6537. break;
  6538. }
  6539. } // end scope
  6540. // If the packet was an event, we handle it
  6541. if (operation == op_event)
  6542. {
  6543. P_EVENT* pevent = &packet.p_event;
  6544. Rvnt* event = NULL;
  6545. { // scope
  6546. RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
  6547. event = find_event(port, pevent->p_event_rid);
  6548. }
  6549. if (event)
  6550. {
  6551. // Call the asynchronous event routine associated
  6552. // with this event
  6553. const ULONG length = pevent->p_event_items.cstr_length;
  6554. if (length <= event->rvnt_length)
  6555. {
  6556. event->rvnt_callback->eventCallbackFunction(length, pevent->p_event_items.cstr_address);
  6557. }
  6558. //else {....
  6559. //This is error condition, but we have absolutely no ways to report it.
  6560. //Therefore simply ignore such bad packet.
  6561. // Finished processing this event
  6562. // Callback above should release event and another thread could reuse it meanwhile.
  6563. // Make sure we don't release such reused event.
  6564. if (event->rvnt_id == pevent->p_event_rid)
  6565. event->rvnt_id = 0;
  6566. }
  6567. } // end of event handling for op_event
  6568. REMOTE_free_packet(port, &packet);
  6569. } // end of infinite for loop
  6570. // to make compilers happy
  6571. return 0;
  6572. }
  6573. static Rvnt* find_event( rem_port* port, SLONG id)
  6574. {
  6575. /*************************************
  6576. *
  6577. * f i n d _ e v e n t
  6578. *
  6579. **************************************
  6580. *
  6581. * Functional description
  6582. * Find event with specified event_id.
  6583. *
  6584. **************************************/
  6585. Rdb* rdb = port->port_context;
  6586. if (rdb && !(port->port_flags & PORT_disconnect))
  6587. {
  6588. for (Rvnt* event = rdb->rdb_events; event; event = event->rvnt_next)
  6589. {
  6590. if (event->rvnt_id == id)
  6591. return event;
  6592. }
  6593. }
  6594. return NULL;
  6595. }
  6596. static bool get_new_dpb(ClumpletWriter& dpb, const ParametersSet& par, bool loopback)
  6597. {
  6598. /**************************************
  6599. *
  6600. * g e t _ n e w _ d p b
  6601. *
  6602. **************************************
  6603. *
  6604. * Functional description
  6605. * Fetch user_string out of dpb.
  6606. * Analyze and prepare dpb for attachment to remote server.
  6607. *
  6608. **************************************/
  6609. bool redirection = Config::getRedirection();
  6610. if (((loopback || !redirection) && dpb.find(par.address_path)) || dpb.find(par.map_attach))
  6611. {
  6612. status_exception::raise(Arg::Gds(isc_unavailable));
  6613. }
  6614. return dpb.find(par.user_name);
  6615. }
  6616. static void info(CheckStatusWrapper* status,
  6617. Rdb* rdb,
  6618. P_OP operation,
  6619. USHORT object,
  6620. USHORT incarnation,
  6621. USHORT item_length,
  6622. const UCHAR* items,
  6623. USHORT recv_item_length,
  6624. const UCHAR* recv_items,
  6625. ULONG buffer_length,
  6626. UCHAR* buffer)
  6627. {
  6628. /**************************************
  6629. *
  6630. * i n f o
  6631. *
  6632. **************************************
  6633. *
  6634. * Functional description
  6635. * Solicit and receive information.
  6636. *
  6637. **************************************/
  6638. // Build the primary packet to get the operation started.
  6639. PACKET* packet = &rdb->rdb_packet;
  6640. packet->p_operation = operation;
  6641. P_INFO* information = &packet->p_info;
  6642. information->p_info_object = object;
  6643. information->p_info_incarnation = incarnation;
  6644. information->p_info_items.cstr_length = item_length;
  6645. information->p_info_items.cstr_address = items;
  6646. if (operation == op_service_info)
  6647. {
  6648. information->p_info_recv_items.cstr_length = recv_item_length;
  6649. information->p_info_recv_items.cstr_address = recv_items;
  6650. }
  6651. information->p_info_buffer_length = buffer_length;
  6652. send_packet(rdb->rdb_port, packet);
  6653. // Set up for the response packet.
  6654. P_RESP* response = &packet->p_resp;
  6655. SaveString temp(response->p_resp_data, buffer_length, buffer);
  6656. receive_response(status, rdb, packet);
  6657. }
  6658. static bool useLegacyAuth(const char* nm, int protocol, ClumpletWriter& dpb)
  6659. {
  6660. LegacyPlugin legacyAuth = REMOTE_legacy_auth(nm, protocol);
  6661. if (!legacyAuth)
  6662. return false;
  6663. int requestedAuth = dpb.find(isc_dpb_user_name) ? PLUGIN_LEGACY : PLUGIN_TRUSTED;
  6664. return legacyAuth == requestedAuth;
  6665. }
  6666. // Let plugins try to add data to DPB in order to avoid extra network roundtrip
  6667. static void authFillParametersBlock(ClntAuthBlock& cBlock, ClumpletWriter& dpb,
  6668. const ParametersSet* tags, rem_port* port)
  6669. {
  6670. if (cBlock.authComplete)
  6671. return; // Already authenticated
  6672. LocalStatus ls;
  6673. CheckStatusWrapper s(&ls);
  6674. cBlock.resetDataFromPlugin();
  6675. for (; cBlock.plugins.hasData(); cBlock.plugins.next())
  6676. {
  6677. if (port->port_protocol >= PROTOCOL_VERSION13 ||
  6678. useLegacyAuth(cBlock.plugins.name(), port->port_protocol, dpb))
  6679. {
  6680. // OK to use plugin
  6681. cBlock.resetDataFromPlugin();
  6682. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authFillParametersBlock(%s)\n", cBlock.plugins.name()));
  6683. int authRc = cBlock.plugins.plugin()->authenticate(&s, &cBlock);
  6684. switch (authRc)
  6685. {
  6686. case IAuth::AUTH_SUCCESS:
  6687. case IAuth::AUTH_MORE_DATA:
  6688. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authFillParametersBlock: plugin %s is OK\n",
  6689. cBlock.plugins.name()));
  6690. cleanDpb(dpb, tags);
  6691. cBlock.extractDataFromPluginTo(dpb, tags, port->port_protocol);
  6692. return;
  6693. case IAuth::AUTH_CONTINUE:
  6694. continue;
  6695. case IAuth::AUTH_FAILED:
  6696. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authFillParametersBlock: plugin %s FAILED\n",
  6697. cBlock.plugins.name()));
  6698. (Arg::Gds(isc_login) << Arg::StatusVector(&s)).raise();
  6699. break; // compiler silencer
  6700. }
  6701. }
  6702. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authFillParametersBlock: try next plugin, %s skipped\n",
  6703. cBlock.plugins.name()));
  6704. }
  6705. }
  6706. #ifdef NOT_USED_OR_REPLACED
  6707. static CSTRING* REMOTE_dup_string(const CSTRING* from)
  6708. {
  6709. if (from && from->cstr_length)
  6710. {
  6711. CSTRING* rc = FB_NEW_POOL(*getDefaultMemoryPool()) CSTRING;
  6712. memset(rc, 0, sizeof(CSTRING));
  6713. rc->cstr_length = from->cstr_length;
  6714. rc->cstr_allocated = rc->cstr_length;
  6715. rc->cstr_address = FB_NEW_POOL(*getDefaultMemoryPool()) UCHAR[rc->cstr_length];
  6716. memcpy(rc->cstr_address, from->cstr_address, rc->cstr_length);
  6717. return rc;
  6718. }
  6719. return NULL;
  6720. }
  6721. static void REMOTE_free_string(CSTRING* tmp)
  6722. {
  6723. if (tmp)
  6724. {
  6725. if (tmp->cstr_address)
  6726. {
  6727. fb_assert(tmp->cstr_allocated >= tmp->cstr_length);
  6728. delete[] tmp->cstr_address;
  6729. }
  6730. delete tmp;
  6731. }
  6732. }
  6733. #endif // NOT_USED_OR_REPLACED
  6734. static void authReceiveResponse(bool havePacket, ClntAuthBlock& cBlock, rem_port* port,
  6735. Rdb* rdb, IStatus* status, PACKET* packet, bool checkKeys)
  6736. {
  6737. LocalStatus ls;
  6738. CheckStatusWrapper s(&ls);
  6739. for (;;)
  6740. {
  6741. // Get response
  6742. if (!havePacket)
  6743. receive_packet(port, packet);
  6744. else
  6745. fb_assert(packet->p_operation == op_cond_accept);
  6746. havePacket = false; // havePacket means first packet is already received
  6747. // Check response
  6748. cstring* n = NULL;
  6749. cstring* d = NULL;
  6750. switch(packet->p_operation)
  6751. {
  6752. case op_trusted_auth:
  6753. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: trusted_auth\n"));
  6754. d = &packet->p_trau.p_trau_data;
  6755. break;
  6756. case op_cont_auth:
  6757. d = &packet->p_auth_cont.p_data;
  6758. n = &packet->p_auth_cont.p_name;
  6759. port->addServerKeys(&packet->p_auth_cont.p_keys);
  6760. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: cont_auth d=%d n=%d '%.*s' 0x%x\n",
  6761. d->cstr_length, n->cstr_length,
  6762. n->cstr_length, n->cstr_address, n->cstr_address ? n->cstr_address[0] : 0));
  6763. break;
  6764. case op_cond_accept:
  6765. d = &packet->p_acpd.p_acpt_data;
  6766. n = &packet->p_acpd.p_acpt_plugin;
  6767. port->addServerKeys(&packet->p_acpd.p_acpt_keys);
  6768. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: cond_accept d=%d n=%d '%.*s' 0x%x\n",
  6769. d->cstr_length, n->cstr_length,
  6770. n->cstr_length, n->cstr_address, n->cstr_address ? n->cstr_address[0] : 0));
  6771. if (packet->p_acpd.p_acpt_type & pflag_compress)
  6772. {
  6773. port->initCompression();
  6774. port->port_flags |= PORT_compressed;
  6775. }
  6776. packet->p_acpd.p_acpt_type &= ptype_MASK;
  6777. break;
  6778. default:
  6779. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: Default answer\n"));
  6780. REMOTE_check_response(status, rdb, packet, checkKeys);
  6781. // successfully attached
  6782. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: OK!\n"));
  6783. cBlock.authComplete = true;
  6784. rdb->rdb_id = packet->p_resp.p_resp_object;
  6785. // try to start crypt
  6786. cBlock.tryNewKeys(port);
  6787. return;
  6788. }
  6789. if (n && n->cstr_length && cBlock.plugins.hasData())
  6790. {
  6791. // if names match, do not change instance
  6792. if (strlen(cBlock.plugins.name()) == n->cstr_length &&
  6793. memcmp(cBlock.plugins.name(), n->cstr_address, n->cstr_length) == 0)
  6794. {
  6795. n = NULL;
  6796. }
  6797. }
  6798. if (n && n->cstr_length)
  6799. {
  6800. // switch to other plugin
  6801. PathName tmp(n->cstr_address, n->cstr_length);
  6802. if (!cBlock.checkPluginName(tmp))
  6803. {
  6804. break;
  6805. }
  6806. cBlock.plugins.set(tmp.c_str());
  6807. }
  6808. if (!cBlock.plugins.hasData())
  6809. {
  6810. break;
  6811. }
  6812. cBlock.resetDataFromPlugin();
  6813. cBlock.storeDataForPlugin(d->cstr_length, d->cstr_address);
  6814. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: receiveResponse: authenticate(%s)\n", cBlock.plugins.name()));
  6815. if (cBlock.plugins.plugin()->authenticate(&s, &cBlock) == IAuth::AUTH_FAILED)
  6816. {
  6817. break;
  6818. }
  6819. // send answer (may be empty) to server
  6820. if (port->port_protocol >= PROTOCOL_VERSION13)
  6821. {
  6822. packet->p_operation = op_cont_auth;
  6823. cBlock.extractDataFromPluginTo(&packet->p_auth_cont);
  6824. }
  6825. else
  6826. {
  6827. packet->p_operation = op_trusted_auth;
  6828. cBlock.extractDataFromPluginTo(&packet->p_trau.p_trau_data);
  6829. }
  6830. send_packet(port, packet);
  6831. REMOTE_free_packet(port, packet, true);
  6832. memset(&packet->p_auth_cont, 0, sizeof packet->p_auth_cont);
  6833. }
  6834. // If we have exited from the cycle, this mean auth failed
  6835. (Arg::Gds(isc_login) << Arg::StatusVector(&s)).raise();
  6836. }
  6837. static bool init(CheckStatusWrapper* status, ClntAuthBlock& cBlock, rem_port* port, P_OP op, PathName& file_name,
  6838. ClumpletWriter& dpb, IntlParametersBlock& intlParametersBlock, ICryptKeyCallback* cryptCallback)
  6839. {
  6840. /**************************************
  6841. *
  6842. * i n i t
  6843. *
  6844. **************************************
  6845. *
  6846. * Functional description
  6847. * Initialize for database access. First call from both CREATE and
  6848. * OPEN.
  6849. *
  6850. **************************************/
  6851. try
  6852. {
  6853. Rdb* rdb = port->port_context;
  6854. PACKET* packet = &rdb->rdb_packet;
  6855. MemoryPool& pool = *getDefaultMemoryPool();
  6856. port->port_deferred_packets = FB_NEW_POOL(pool) PacketQueue(pool);
  6857. if (port->port_protocol < PROTOCOL_VERSION12)
  6858. {
  6859. // This is FB < 2.5. Lets remove that not recognized DPB/SPB and convert the UTF8
  6860. // strings to the OS codepage.
  6861. intlParametersBlock.fromUtf8(dpb);
  6862. ISC_unescape(file_name);
  6863. ISC_utf8ToSystem(file_name);
  6864. }
  6865. const ParametersSet* const ps = (op == op_service_attach ? &spbParam : &dpbParam);
  6866. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: init calls authFillParametersBlock\n"));
  6867. authFillParametersBlock(cBlock, dpb, ps, port);
  6868. port->port_client_crypt_callback = cryptCallback;
  6869. cBlock.createCryptCallback(&port->port_client_crypt_callback);
  6870. // Make attach packet
  6871. P_ATCH* attach = &packet->p_atch;
  6872. packet->p_operation = op;
  6873. attach->p_atch_file.cstr_length = (ULONG) file_name.length();
  6874. attach->p_atch_file.cstr_address = reinterpret_cast<const UCHAR*>(file_name.c_str());
  6875. attach->p_atch_dpb.cstr_length = (ULONG) dpb.getBufferLength();
  6876. attach->p_atch_dpb.cstr_address = dpb.getBuffer();
  6877. send_packet(port, packet);
  6878. authReceiveResponse(false, cBlock, port, rdb, status, packet, true);
  6879. return true;
  6880. }
  6881. catch (const Exception& ex)
  6882. {
  6883. // report primary init error
  6884. ex.stuffException(status);
  6885. }
  6886. try
  6887. {
  6888. disconnect(port);
  6889. }
  6890. catch (const Exception&)
  6891. {
  6892. // ignore secondary error
  6893. }
  6894. return false;
  6895. }
  6896. static Rtr* make_transaction( Rdb* rdb, USHORT id)
  6897. {
  6898. /**************************************
  6899. *
  6900. * m a k e _ t r a n s a c t i o n
  6901. *
  6902. **************************************
  6903. *
  6904. * Functional description
  6905. * Create a local transaction handle.
  6906. *
  6907. **************************************/
  6908. Rtr* transaction = FB_NEW Rtr;
  6909. transaction->rtr_rdb = rdb;
  6910. transaction->rtr_id = id;
  6911. transaction->rtr_next = rdb->rdb_transactions;
  6912. rdb->rdb_transactions = transaction;
  6913. SET_OBJECT(rdb, transaction, id);
  6914. return transaction;
  6915. }
  6916. static void mov_dsql_message(const UCHAR* from_msg,
  6917. const rem_fmt* from_fmt,
  6918. UCHAR* to_msg,
  6919. const rem_fmt* to_fmt)
  6920. {
  6921. /**************************************
  6922. *
  6923. * m o v _ d s q l _ m e s s a g e
  6924. *
  6925. **************************************
  6926. *
  6927. * Functional description
  6928. * Move data using formats.
  6929. *
  6930. **************************************/
  6931. if (!from_msg || !from_fmt || !to_msg || !to_fmt ||
  6932. from_fmt->fmt_desc.getCount() != to_fmt->fmt_desc.getCount())
  6933. {
  6934. move_error(Arg::Gds(isc_dsql_sqlda_err));
  6935. // Msg 263 SQLDA missing or wrong number of variables
  6936. }
  6937. const dsc* from_desc = from_fmt->fmt_desc.begin();
  6938. const dsc* to_desc = to_fmt->fmt_desc.begin();
  6939. for (const dsc* const end_desc = to_fmt->fmt_desc.end();
  6940. to_desc < end_desc; from_desc++, to_desc++)
  6941. {
  6942. dsc from = *from_desc;
  6943. dsc to = *to_desc;
  6944. // Safe const cast, we are going to move from it to anywhere.
  6945. from.dsc_address = const_cast<UCHAR*>(from_msg) + (IPTR) from.dsc_address;
  6946. to.dsc_address = to_msg + (IPTR) to.dsc_address;
  6947. CVT_move(&from, &to, DecimalStatus(FB_DEC_Errors), move_error);
  6948. }
  6949. }
  6950. static void move_error(const Arg::StatusVector& v)
  6951. {
  6952. /**************************************
  6953. *
  6954. * m o v e _ e r r o r
  6955. *
  6956. **************************************
  6957. *
  6958. * Functional description
  6959. * A conversion error occurred. Complain.
  6960. *
  6961. **************************************/
  6962. Arg::Gds status_vector(isc_random);
  6963. status_vector << "Dynamic SQL Error" << Arg::Gds(isc_sqlerr) << Arg::Num(-303);
  6964. // append any other arguments which may have been handed to us, then post the error
  6965. status_vector.append(v);
  6966. status_exception::raise(status_vector);
  6967. }
  6968. static void receive_after_start(Rrq* request, USHORT msg_type)
  6969. {
  6970. /*****************************************
  6971. *
  6972. * r e c e i v e _ a f t e r _ s t a r t
  6973. *
  6974. *****************************************
  6975. *
  6976. * Functional Description
  6977. * Some opcodes, such as "start_and_send" automatically start the
  6978. * cursor being started, under protcol 8 we then receive the first
  6979. * batch of records without having to ask for them.
  6980. *
  6981. * Note: if a network error occurs during this receive, we do not
  6982. * recognize it in the "gds_start" API call that initiated this
  6983. * action. It will be stored with the queue of records for the
  6984. * cursor that is being fetched. This is not ideal - but compabile
  6985. * with how the code worked prior to pipelining work done
  6986. * 1996-Jul-15 David Schnepper
  6987. *
  6988. *****************************************/
  6989. // Check to see if any data is waiting to happen
  6990. Rdb* rdb = request->rrq_rdb;
  6991. PACKET* packet = &rdb->rdb_packet;
  6992. Rrq::rrq_repeat* tail = &request->rrq_rpt[msg_type];
  6993. // CVC: I commented this line because it's overwritten immediately in the loop.
  6994. // RMessage* message = tail->rrq_message;
  6995. const rem_fmt* format = tail->rrq_format;
  6996. // Swallow up data. If a buffer isn't available, allocate another
  6997. while (true)
  6998. {
  6999. RMessage* message = tail->rrq_xdr;
  7000. if (message->msg_address)
  7001. {
  7002. RMessage* new_msg = FB_NEW RMessage(format->fmt_length);
  7003. tail->rrq_xdr = new_msg;
  7004. new_msg->msg_next = message;
  7005. new_msg->msg_number = message->msg_number;
  7006. while (message->msg_next != new_msg->msg_next)
  7007. message = message->msg_next;
  7008. message->msg_next = new_msg;
  7009. }
  7010. // Note: not receive_packet
  7011. try
  7012. {
  7013. receive_packet_noqueue(rdb->rdb_port, packet);
  7014. }
  7015. catch (const Exception& ex)
  7016. {
  7017. request->saveStatus(ex);
  7018. return;
  7019. }
  7020. // Did an error response come back ?
  7021. if (packet->p_operation != op_send)
  7022. {
  7023. try
  7024. {
  7025. LocalStatus ls;
  7026. CheckStatusWrapper status(&ls);
  7027. REMOTE_check_response(&status, rdb, packet);
  7028. request->saveStatus(&status);
  7029. }
  7030. catch (const Exception& ex)
  7031. {
  7032. request->saveStatus(ex);
  7033. }
  7034. return;
  7035. }
  7036. tail->rrq_msgs_waiting++;
  7037. // Reached end of batch
  7038. if (!packet->p_data.p_data_messages)
  7039. break;
  7040. }
  7041. }
  7042. static void receive_packet(rem_port* port, PACKET* packet)
  7043. {
  7044. /**************************************
  7045. *
  7046. * r e c e i v e _ p a c k e t
  7047. *
  7048. **************************************
  7049. *
  7050. * Functional description
  7051. * Clear the queue of any pending receives, then receive the
  7052. * response to a sent request, blocking if necessary until
  7053. * the response is present.
  7054. *
  7055. * Return codes:
  7056. * true - no errors.
  7057. * false - Network error occurred, error code in status
  7058. *
  7059. **************************************/
  7060. // Must clear the wire of any queued receives before fetching
  7061. // the desired packet
  7062. clear_queue(port);
  7063. receive_packet_noqueue(port, packet);
  7064. }
  7065. static void receive_packet_with_callback(rem_port* port, PACKET* packet)
  7066. {
  7067. /**************************************
  7068. *
  7069. * r e c e i v e _ p a c k e t _ w i t h _ c a l l b a c k
  7070. *
  7071. **************************************
  7072. *
  7073. * Functional description
  7074. * If received packet is request from callback info from user,
  7075. * send requested info (or no data if callback is not set) and
  7076. * wait for next packet.
  7077. *
  7078. **************************************/
  7079. UCharBuffer buf;
  7080. for (;;)
  7081. {
  7082. if (!port->receive(packet))
  7083. {
  7084. Arg::Gds(isc_net_read_err).raise();
  7085. }
  7086. switch (packet->p_operation)
  7087. {
  7088. case op_crypt_key_callback:
  7089. {
  7090. P_CRYPT_CALLBACK* cc = &packet->p_cc;
  7091. Cleanup ccData([&cc]() {
  7092. cc->p_cc_data.cstr_length = 0;
  7093. cc->p_cc_data.cstr_address = nullptr;
  7094. });
  7095. if (port->port_client_crypt_callback)
  7096. {
  7097. if (cc->p_cc_reply <= 0)
  7098. {
  7099. cc->p_cc_reply = 1;
  7100. }
  7101. UCHAR* reply = buf.getBuffer(cc->p_cc_reply);
  7102. unsigned l = port->port_client_crypt_callback->callback(cc->p_cc_data.cstr_length,
  7103. cc->p_cc_data.cstr_address, cc->p_cc_reply, reply);
  7104. REMOTE_free_packet(port, packet, true);
  7105. cc->p_cc_data.cstr_length = l;
  7106. cc->p_cc_data.cstr_address = reply;
  7107. }
  7108. else
  7109. {
  7110. REMOTE_free_packet(port, packet, true);
  7111. cc->p_cc_data.cstr_length = 0;
  7112. }
  7113. packet->p_operation = op_crypt_key_callback;
  7114. cc->p_cc_reply = 0;
  7115. port->send(packet);
  7116. }
  7117. break;
  7118. default:
  7119. return;
  7120. }
  7121. }
  7122. }
  7123. static void receive_packet_noqueue(rem_port* port, PACKET* packet)
  7124. {
  7125. /**************************************
  7126. *
  7127. * r e c e i v e _ p a c k e t _ n o q u e u e
  7128. *
  7129. **************************************
  7130. *
  7131. * Functional description
  7132. * Receive a packet and check for a network
  7133. * error on the receive.
  7134. * Note: SOME of the network lower level protocols
  7135. * will set up a status vector when errors
  7136. * occur, but other ones won't.
  7137. * So this routine sets up an error result
  7138. * for the vector prior to going into the
  7139. * network layer. Note that we can't
  7140. * RESET the status vector as one thing
  7141. * that can be received is a new status vector
  7142. *
  7143. * See also cousin routine: send_packet, send_partial_packet
  7144. *
  7145. **************************************/
  7146. // Receive responses for all deferred packets that were already sent
  7147. if (port->port_deferred_packets)
  7148. {
  7149. while (port->port_deferred_packets->getCount())
  7150. {
  7151. rem_que_packet* const p = port->port_deferred_packets->begin();
  7152. if (!p->sent)
  7153. break;
  7154. OBJCT stmt_id = 0;
  7155. bool bCheckResponse = false, bFreeStmt = false, bAssign = false;
  7156. switch (p->packet.p_operation)
  7157. {
  7158. case op_execute:
  7159. stmt_id = p->packet.p_sqldata.p_sqldata_statement;
  7160. bCheckResponse = true;
  7161. bAssign = true;
  7162. break;
  7163. case op_batch_msg:
  7164. stmt_id = p->packet.p_batch_msg.p_batch_statement;
  7165. bCheckResponse = true;
  7166. break;
  7167. case op_batch_create:
  7168. stmt_id = p->packet.p_batch_create.p_batch_statement;
  7169. bCheckResponse = true;
  7170. break;
  7171. case op_free_statement:
  7172. stmt_id = p->packet.p_sqlfree.p_sqlfree_statement;
  7173. bFreeStmt = (p->packet.p_sqlfree.p_sqlfree_option == DSQL_drop);
  7174. break;
  7175. }
  7176. receive_packet_with_callback(port, &p->packet);
  7177. Rsr* statement = NULL;
  7178. if (bCheckResponse || bFreeStmt)
  7179. statement = port->port_objects[stmt_id];
  7180. if (bCheckResponse)
  7181. {
  7182. try
  7183. {
  7184. Rdb* rdb = port->port_context;
  7185. LocalStatus ls;
  7186. CheckStatusWrapper status(&ls);
  7187. REMOTE_check_response(&status, rdb, &p->packet);
  7188. statement->saveException(&status, false);
  7189. }
  7190. catch (const Exception& ex)
  7191. {
  7192. // save error within the corresponding statement
  7193. statement->saveException(ex, false);
  7194. bAssign = false;
  7195. }
  7196. if (bAssign)
  7197. {
  7198. // assign statement to transaction
  7199. const OBJCT tran_id = p->packet.p_sqldata.p_sqldata_transaction;
  7200. Rtr* transaction = port->port_objects[tran_id];
  7201. statement->rsr_rtr = transaction;
  7202. }
  7203. }
  7204. if (bFreeStmt && p->packet.p_resp.p_resp_object == INVALID_OBJECT)
  7205. release_sql_request(statement);
  7206. // free only part of packet we worked with
  7207. REMOTE_free_packet(port, &p->packet, true);
  7208. port->port_deferred_packets->remove(p);
  7209. }
  7210. }
  7211. receive_packet_with_callback(port, packet);
  7212. }
  7213. static void receive_queued_packet(rem_port* port, USHORT id)
  7214. {
  7215. /**************************************
  7216. *
  7217. * r e c e i v e _ q u e u e d_ p a c k e t
  7218. *
  7219. **************************************
  7220. *
  7221. * Functional description
  7222. * We're marked as having pending receives on the
  7223. * wire. Grab the first pending receive and return.
  7224. *
  7225. **************************************/
  7226. // Trivial case, nothing pending on the wire
  7227. if (!port->port_receive_rmtque)
  7228. {
  7229. return;
  7230. }
  7231. // Grab first queue entry
  7232. rmtque* que_inst = port->port_receive_rmtque;
  7233. // Receive the data
  7234. (que_inst->rmtque_function) (port, que_inst, id);
  7235. }
  7236. static void enqueue_receive(rem_port* port,
  7237. t_rmtque_fn fn,
  7238. Rdb* rdb,
  7239. void* parm,
  7240. Rrq::rrq_repeat* parm1)
  7241. {
  7242. /**************************************
  7243. *
  7244. * e n q u e u e _ r e c e i v e
  7245. *
  7246. **************************************
  7247. *
  7248. * Functional description
  7249. *
  7250. **************************************/
  7251. rmtque* const que_inst = FB_NEW rmtque;
  7252. // Prepare a queue entry
  7253. que_inst->rmtque_next = NULL;
  7254. que_inst->rmtque_function = fn;
  7255. que_inst->rmtque_parm = parm;
  7256. que_inst->rmtque_message = parm1;
  7257. que_inst->rmtque_rdb = rdb;
  7258. // Walk to the end of the current queue
  7259. rmtque** queptr = &port->port_receive_rmtque;
  7260. while (*queptr)
  7261. queptr = &(*queptr)->rmtque_next;
  7262. // Add the new entry to the end of the queue
  7263. *queptr = que_inst;
  7264. }
  7265. static void dequeue_receive( rem_port* port)
  7266. {
  7267. /**************************************
  7268. *
  7269. * d e q u e u e _ r e c e i v e
  7270. *
  7271. **************************************
  7272. *
  7273. * Functional description
  7274. *
  7275. **************************************/
  7276. // Grab first queue entry & de-queue it
  7277. rmtque* que_inst = port->port_receive_rmtque;
  7278. port->port_receive_rmtque = que_inst->rmtque_next;
  7279. que_inst->rmtque_next = NULL;
  7280. // Add queue entry onto free queue
  7281. delete que_inst;
  7282. }
  7283. static void receive_response(IStatus* status, Rdb* rdb, PACKET* packet)
  7284. {
  7285. /**************************************
  7286. *
  7287. * r e c e i v e _ r e s p o n s e
  7288. *
  7289. **************************************
  7290. *
  7291. * Functional description
  7292. * Check response to a remote call.
  7293. *
  7294. **************************************/
  7295. receive_packet(rdb->rdb_port, packet);
  7296. REMOTE_check_response(status, rdb, packet);
  7297. }
  7298. static void release_blob( Rbl* blob)
  7299. {
  7300. /**************************************
  7301. *
  7302. * r e l e a s e _ b l o b
  7303. *
  7304. **************************************
  7305. *
  7306. * Functional description
  7307. * Release a blob block and friends.
  7308. *
  7309. **************************************/
  7310. Rtr* transaction = blob->rbl_rtr;
  7311. Rdb* rdb = blob->rbl_rdb;
  7312. rdb->rdb_port->releaseObject(blob->rbl_id);
  7313. for (Rbl** p = &transaction->rtr_blobs; *p; p = &(*p)->rbl_next)
  7314. {
  7315. if (*p == blob)
  7316. {
  7317. *p = blob->rbl_next;
  7318. break;
  7319. }
  7320. }
  7321. delete blob;
  7322. }
  7323. static void release_event( Rvnt* event)
  7324. {
  7325. /**************************************
  7326. *
  7327. * r e l e a s e _ e v e n t
  7328. *
  7329. **************************************
  7330. *
  7331. * Functional description
  7332. * Release an event block.
  7333. *
  7334. **************************************/
  7335. Rdb* rdb = event->rvnt_rdb;
  7336. for (Rvnt** p = &rdb->rdb_events; *p; p = &(*p)->rvnt_next)
  7337. {
  7338. if (*p == event)
  7339. {
  7340. *p = event->rvnt_next;
  7341. break;
  7342. }
  7343. }
  7344. delete event;
  7345. }
  7346. static void release_object(IStatus* status, Rdb* rdb, P_OP op, USHORT id)
  7347. {
  7348. /**************************************
  7349. *
  7350. * r e l e a s e _ o b j e c t
  7351. *
  7352. **************************************
  7353. *
  7354. * Functional description
  7355. * Tell the server to zap an object. This doesn't necessary
  7356. * release the object, but usually does.
  7357. *
  7358. **************************************/
  7359. PACKET* packet = &rdb->rdb_packet;
  7360. packet->p_operation = op;
  7361. packet->p_rlse.p_rlse_object = id;
  7362. if (rdb->rdb_port->port_flags & PORT_lazy)
  7363. {
  7364. switch (op)
  7365. {
  7366. case op_close_blob:
  7367. case op_cancel_blob:
  7368. case op_release:
  7369. defer_packet(rdb->rdb_port, packet);
  7370. return;
  7371. default:
  7372. break;
  7373. }
  7374. }
  7375. send_packet(rdb->rdb_port, packet);
  7376. receive_response(status, rdb, packet);
  7377. }
  7378. static void release_request( Rrq* request)
  7379. {
  7380. /**************************************
  7381. *
  7382. * r e l e a s e _ r e q u e s t
  7383. *
  7384. **************************************
  7385. *
  7386. * Functional description
  7387. * Release a request block and friends.
  7388. *
  7389. **************************************/
  7390. Rdb* rdb = request->rrq_rdb;
  7391. rdb->rdb_port->releaseObject(request->rrq_id);
  7392. REMOTE_release_request(request);
  7393. }
  7394. static void release_statement( Rsr** statement)
  7395. {
  7396. /**************************************
  7397. *
  7398. * r e l e a s e _ s t a t e m e n t
  7399. *
  7400. **************************************
  7401. *
  7402. * Functional description
  7403. * Release a GDML or SQL statement block ?
  7404. *
  7405. **************************************/
  7406. delete (*statement)->rsr_bind_format;
  7407. if ((*statement)->rsr_user_select_format &&
  7408. (*statement)->rsr_user_select_format != (*statement)->rsr_select_format)
  7409. {
  7410. delete (*statement)->rsr_user_select_format;
  7411. }
  7412. delete (*statement)->rsr_select_format;
  7413. (*statement)->releaseException();
  7414. REMOTE_release_messages((*statement)->rsr_message);
  7415. delete *statement;
  7416. *statement = NULL;
  7417. }
  7418. static void release_sql_request( Rsr* statement)
  7419. {
  7420. /**************************************
  7421. *
  7422. * r e l e a s e _ s q l _ r e q u e s t
  7423. *
  7424. **************************************
  7425. *
  7426. * Functional description
  7427. * Release an SQL request block.
  7428. *
  7429. **************************************/
  7430. Rdb* rdb = statement->rsr_rdb;
  7431. rdb->rdb_port->releaseObject(statement->rsr_id);
  7432. for (Rsr** p = &rdb->rdb_sql_requests; *p; p = &(*p)->rsr_next)
  7433. {
  7434. if (*p == statement)
  7435. {
  7436. *p = statement->rsr_next;
  7437. break;
  7438. }
  7439. }
  7440. release_statement(&statement);
  7441. }
  7442. static void release_transaction( Rtr* transaction)
  7443. {
  7444. /**************************************
  7445. *
  7446. * r e l e a s e _ t r a n s a c t i o n
  7447. *
  7448. **************************************
  7449. *
  7450. * Functional description
  7451. * Release a transaction block and friends.
  7452. *
  7453. **************************************/
  7454. Rdb* rdb = transaction->rtr_rdb;
  7455. rdb->rdb_port->releaseObject(transaction->rtr_id);
  7456. while (transaction->rtr_blobs)
  7457. release_blob(transaction->rtr_blobs);
  7458. for (Rtr** p = &rdb->rdb_transactions; *p; p = &(*p)->rtr_next)
  7459. {
  7460. if (*p == transaction)
  7461. {
  7462. *p = transaction->rtr_next;
  7463. break;
  7464. }
  7465. }
  7466. delete transaction;
  7467. }
  7468. static void send_and_receive(IStatus* status, Rdb* rdb, PACKET* packet)
  7469. {
  7470. /**************************************
  7471. *
  7472. * s e n d _ a n d _ r e c e i v e
  7473. *
  7474. **************************************
  7475. *
  7476. * Functional description
  7477. * Send a packet, check status, receive a packet, and check status.
  7478. *
  7479. **************************************/
  7480. send_packet(rdb->rdb_port, packet);
  7481. receive_response(status, rdb, packet);
  7482. }
  7483. static void send_blob(CheckStatusWrapper* status,
  7484. Rbl* blob,
  7485. USHORT buffer_length,
  7486. const UCHAR* buffer)
  7487. {
  7488. /**************************************
  7489. *
  7490. * s e n d _ b l o b
  7491. *
  7492. **************************************
  7493. *
  7494. * Functional description
  7495. * Actually send blob data (which might be buffered)
  7496. *
  7497. **************************************/
  7498. Rdb* rdb = blob->rbl_rdb;
  7499. PACKET* packet = &rdb->rdb_packet;
  7500. packet->p_operation = op_put_segment;
  7501. // If we aren't passed a buffer address, this is a batch send. Pick up the
  7502. // address and length from the blob buffer and blast away
  7503. if (!buffer)
  7504. {
  7505. buffer = blob->rbl_buffer;
  7506. buffer_length = blob->rbl_ptr - buffer;
  7507. blob->rbl_ptr = blob->rbl_buffer;
  7508. packet->p_operation = op_batch_segments;
  7509. }
  7510. P_SGMT* segment = &packet->p_sgmt;
  7511. CSTRING_CONST temp = segment->p_sgmt_segment;
  7512. segment->p_sgmt_blob = blob->rbl_id;
  7513. segment->p_sgmt_segment.cstr_length = buffer_length;
  7514. segment->p_sgmt_segment.cstr_address = buffer;
  7515. segment->p_sgmt_length = buffer_length;
  7516. send_packet(rdb->rdb_port, packet);
  7517. // restore the string; "buffer" is not referenced anymore, hence no
  7518. // possibility to overwrite it accidentally.
  7519. segment->p_sgmt_segment = temp;
  7520. // Set up for the response packet.
  7521. receive_response(status, rdb, packet);
  7522. }
  7523. static void send_packet(rem_port* port, PACKET* packet)
  7524. {
  7525. /**************************************
  7526. *
  7527. * s e n d _ p a c k e t
  7528. *
  7529. **************************************
  7530. *
  7531. * Functional description
  7532. * Send a packet and check for a network error
  7533. * on the send.
  7534. * Make up a status vector for any error.
  7535. * Note: SOME of the network lower level protocols
  7536. * will set up a status vector when errors
  7537. * occur, but other ones won't.
  7538. * So this routine sets up an error result
  7539. * for the vector and resets it to true
  7540. * if the packet send occurred.
  7541. *
  7542. * See also cousin routine: receive_packet
  7543. *
  7544. **************************************/
  7545. RefMutexGuard guard(*port->port_write_sync, FB_FUNCTION);
  7546. if (port->port_flags & PORT_detached || port->port_state == rem_port::BROKEN)
  7547. {
  7548. (Arg::Gds(isc_net_write_err)
  7549. #ifdef DEV_BUILD
  7550. << Arg::Gds(isc_random) << "port detached"
  7551. #endif
  7552. ).raise();
  7553. }
  7554. // Send packets that were deferred
  7555. if (port->port_deferred_packets)
  7556. {
  7557. for (rem_que_packet* p = port->port_deferred_packets->begin();
  7558. p < port->port_deferred_packets->end();
  7559. ++p)
  7560. {
  7561. if (!p->sent)
  7562. {
  7563. if (!port->send_partial(&p->packet))
  7564. (Arg::Gds(isc_net_write_err) <<
  7565. Arg::Gds(isc_random) << "send_packet/send_partial").raise();
  7566. p->sent = true;
  7567. }
  7568. }
  7569. }
  7570. if (!port->send(packet))
  7571. {
  7572. (Arg::Gds(isc_net_write_err)<< Arg::Gds(isc_random) << "send_packet/send").raise();
  7573. }
  7574. }
  7575. static void send_partial_packet(rem_port* port, PACKET* packet)
  7576. {
  7577. /**************************************
  7578. *
  7579. * s e n d _ p a r t i a l _ p a c k e t
  7580. *
  7581. **************************************
  7582. *
  7583. * Functional description
  7584. * Send a packet and check for a network error
  7585. * on the send.
  7586. * Make up a status vector for any error.
  7587. * Note: SOME of the network lower level protocols
  7588. * will set up a status vector when errors
  7589. * occur, but other ones won't.
  7590. * So this routine sets up an error result
  7591. * for the vector and resets it to true
  7592. * if the packet send occurred.
  7593. *
  7594. * See also cousin routine: receive_packet, send_packet
  7595. *
  7596. **************************************/
  7597. RefMutexGuard guard(*port->port_write_sync, FB_FUNCTION);
  7598. if (port->port_flags & PORT_detached || port->port_state == rem_port::BROKEN)
  7599. {
  7600. (Arg::Gds(isc_net_write_err)
  7601. #ifdef DEV_BUILD
  7602. << Arg::Gds(isc_random) << "port detached"
  7603. #endif
  7604. ).raise();
  7605. }
  7606. // Send packets that were deferred
  7607. if (port->port_deferred_packets)
  7608. {
  7609. for (rem_que_packet* p = port->port_deferred_packets->begin();
  7610. p < port->port_deferred_packets->end(); p++)
  7611. {
  7612. if (!p->sent)
  7613. {
  7614. if (!port->send_partial(&p->packet))
  7615. {
  7616. (Arg::Gds(isc_net_write_err) <<
  7617. Arg::Gds(isc_random) << "send_partial_packet/send_partial").raise();
  7618. }
  7619. p->sent = true;
  7620. }
  7621. }
  7622. }
  7623. if (!port->send_partial(packet))
  7624. {
  7625. (Arg::Gds(isc_net_write_err) <<
  7626. Arg::Gds(isc_random) << "send_partial_packet/send").raise();
  7627. }
  7628. }
  7629. static void server_death(rem_port* port)
  7630. {
  7631. /**************************************
  7632. *
  7633. * s e r v e r _ d e a t h
  7634. *
  7635. **************************************
  7636. *
  7637. * Functional description
  7638. * Received "EOF" from remote server
  7639. * Cleanup events.
  7640. *
  7641. **************************************/
  7642. Rdb* rdb = port->port_context;
  7643. if (rdb && !(port->port_flags & PORT_disconnect))
  7644. {
  7645. for (Rvnt* event = rdb->rdb_events; event; event = event->rvnt_next)
  7646. {
  7647. if (event->rvnt_id)
  7648. {
  7649. event->rvnt_id = 0;
  7650. event->rvnt_callback->eventCallbackFunction(0, NULL);
  7651. }
  7652. }
  7653. }
  7654. }
  7655. static void svcstart(CheckStatusWrapper* status,
  7656. Rdb* rdb,
  7657. P_OP operation,
  7658. USHORT object,
  7659. USHORT incarnation,
  7660. USHORT item_length,
  7661. const UCHAR* items)
  7662. {
  7663. /**************************************
  7664. *
  7665. * s v c s t a r t
  7666. *
  7667. **************************************
  7668. *
  7669. * Functional description
  7670. * Instruct the server to start a service
  7671. *
  7672. **************************************/
  7673. ClumpletWriter send(ClumpletReader::SpbStart, MAX_DPB_SIZE, items, item_length);
  7674. if (rdb->rdb_port->port_protocol < PROTOCOL_VERSION13)
  7675. {
  7676. // This is FB < 3.0. Lets convert the UTF8 strings to the OS codepage.
  7677. IntlSpbStart().fromUtf8(send);
  7678. }
  7679. // Build the primary packet to get the operation started.
  7680. PACKET* packet = &rdb->rdb_packet;
  7681. packet->p_operation = operation;
  7682. P_INFO* information = &packet->p_info;
  7683. information->p_info_object = object;
  7684. information->p_info_incarnation = incarnation;
  7685. information->p_info_items.cstr_length = (ULONG) send.getBufferLength();
  7686. information->p_info_items.cstr_address = send.getBuffer();
  7687. information->p_info_buffer_length = (ULONG) send.getBufferLength();
  7688. send_packet(rdb->rdb_port, packet);
  7689. // Set up for the response packet.
  7690. P_RESP* response = &packet->p_resp;
  7691. SaveString temp(response->p_resp_data, 0, NULL);
  7692. response->p_resp_data.cstr_length = 0;
  7693. receive_response(status, rdb, packet);
  7694. }
  7695. static void unsupported()
  7696. {
  7697. /**************************************
  7698. *
  7699. * u n s u p p o r t e d
  7700. *
  7701. **************************************
  7702. *
  7703. * Functional description
  7704. * No_entrypoint is called if there is not entrypoint for a given routine.
  7705. *
  7706. **************************************/
  7707. Arg::Gds(isc_wish_list).raise();
  7708. }
  7709. static void zap_packet(PACKET* packet)
  7710. {
  7711. /**************************************
  7712. *
  7713. * z a p _ p a c k e t
  7714. *
  7715. **************************************
  7716. *
  7717. * Functional description
  7718. * Zero out a packet block.
  7719. *
  7720. **************************************/
  7721. memset(packet, 0, sizeof(struct packet));
  7722. }
  7723. void Attachment::cancelOperation(CheckStatusWrapper* status, int kind)
  7724. {
  7725. /*************************************
  7726. *
  7727. * G D S _ C A N C E L _ O P E R A T I O N
  7728. *
  7729. **************************************
  7730. *
  7731. * Functional description
  7732. * Asynchronously cancel requests, running with db_handle on remote server.
  7733. *
  7734. **************************************/
  7735. try {
  7736. reset(status);
  7737. CHECK_HANDLE(rdb, isc_bad_db_handle);
  7738. RemPortPtr port(rdb->rdb_port);
  7739. if (kind == fb_cancel_abort)
  7740. {
  7741. port->force_close();
  7742. return;
  7743. }
  7744. if (port->port_protocol < PROTOCOL_VERSION12 || port->port_type != rem_port::INET)
  7745. {
  7746. unsupported();
  7747. }
  7748. Cleanup unlockAsyncLock([this] { --(rdb->rdb_async_lock); });
  7749. if (++(rdb->rdb_async_lock) != 1)
  7750. {
  7751. // Something async already runs
  7752. Arg::Gds(isc_async_active).raise();
  7753. }
  7754. PACKET packet;
  7755. packet.p_operation = op_cancel;
  7756. P_CANCEL_OP* cancel = &packet.p_cancel_op;
  7757. cancel->p_co_kind = kind;
  7758. send_packet(rdb->rdb_port, &packet);
  7759. }
  7760. catch (const Exception& ex)
  7761. {
  7762. ex.stuffException(status);
  7763. }
  7764. }
  7765. Rtr* Attachment::remoteTransaction(ITransaction* apiTra)
  7766. {
  7767. Transaction* rt = remoteTransactionInterface(apiTra);
  7768. return rt ? rt->getTransaction() : NULL;
  7769. }
  7770. Transaction* Attachment::remoteTransactionInterface(ITransaction* apiTra)
  7771. {
  7772. if (!apiTra)
  7773. return NULL;
  7774. LocalStatus ls;
  7775. CheckStatusWrapper dummy(&ls);
  7776. ITransaction* valid = apiTra->validate(&dummy, this);
  7777. if (!valid)
  7778. return NULL;
  7779. // If validation is successfull, this means that this attachment and valid transaction
  7780. // use same provider. I.e. the following cast is safe.
  7781. return static_cast<Transaction*>(valid);
  7782. }
  7783. static void cleanDpb(Firebird::ClumpletWriter& dpb, const ParametersSet* tags)
  7784. {
  7785. dpb.deleteWithTag(tags->password);
  7786. dpb.deleteWithTag(tags->password_enc);
  7787. dpb.deleteWithTag(tags->trusted_auth);
  7788. }
  7789. } //namespace Remote
  7790. void ClientPortsCleanup::closePort(rem_port* port)
  7791. {
  7792. RefMutexEnsureUnlock guard(*port->port_sync, FB_FUNCTION);
  7793. if (port->port_flags & PORT_disconnect)
  7794. return;
  7795. if (guard.tryEnter())
  7796. Remote::finalize(port);
  7797. else
  7798. PortsCleanup::closePort(port);
  7799. }
  7800. RmtAuthBlock::RmtAuthBlock(const Firebird::AuthReader::AuthBlock& aBlock)
  7801. : buffer(*getDefaultMemoryPool(), aBlock),
  7802. rdr(*getDefaultMemoryPool(), buffer),
  7803. info(*getDefaultMemoryPool())
  7804. {
  7805. FbLocalStatus st;
  7806. first(&st);
  7807. check(&st);
  7808. }
  7809. const char* RmtAuthBlock::getType()
  7810. {
  7811. return info.type.nullStr();
  7812. }
  7813. const char* RmtAuthBlock::getName()
  7814. {
  7815. return info.name.nullStr();
  7816. }
  7817. const char* RmtAuthBlock::getPlugin()
  7818. {
  7819. return info.plugin.nullStr();
  7820. }
  7821. const char* RmtAuthBlock::getSecurityDb()
  7822. {
  7823. return info.secDb.nullStr();
  7824. }
  7825. const char* RmtAuthBlock::getOriginalPlugin()
  7826. {
  7827. return info.origPlug.nullStr();
  7828. }
  7829. FB_BOOLEAN RmtAuthBlock::next(Firebird::CheckStatusWrapper* status)
  7830. {
  7831. try
  7832. {
  7833. rdr.moveNext();
  7834. return loadInfo();
  7835. }
  7836. catch (const Exception& ex)
  7837. {
  7838. ex.stuffException(status);
  7839. }
  7840. return FB_FALSE;
  7841. }
  7842. FB_BOOLEAN RmtAuthBlock::first(Firebird::CheckStatusWrapper* status)
  7843. {
  7844. try
  7845. {
  7846. rdr.rewind();
  7847. return loadInfo();
  7848. }
  7849. catch (const Exception& ex)
  7850. {
  7851. ex.stuffException(status);
  7852. }
  7853. return FB_FALSE;
  7854. }
  7855. FB_BOOLEAN RmtAuthBlock::loadInfo()
  7856. {
  7857. if (rdr.isEof())
  7858. return FB_FALSE;
  7859. rdr.getInfo(info);
  7860. return FB_TRUE;
  7861. }
  7862. ClntAuthBlock::ClntAuthBlock(const Firebird::PathName* fileName, Firebird::ClumpletReader* dpb,
  7863. const ParametersSet* tags)
  7864. : pluginList(getPool()), serverPluginList(getPool()),
  7865. cliUserName(getPool()), cliPassword(getPool()), cliOrigUserName(getPool()),
  7866. dataForPlugin(getPool()), dataFromPlugin(getPool()),
  7867. cryptKeys(getPool()), dpbConfig(getPool()), dpbPlugins(getPool()),
  7868. createdInterface(nullptr),
  7869. plugins(IPluginManager::TYPE_AUTH_CLIENT), authComplete(false), firstTime(true)
  7870. {
  7871. if (dpb && tags)
  7872. {
  7873. if (dpb->find(tags->config_text))
  7874. dpb->getString(dpbConfig);
  7875. if (dpb->find(tags->plugin_list))
  7876. dpb->getPath(dpbPlugins);
  7877. if (dpb->find(tags->auth_block))
  7878. {
  7879. AuthReader::AuthBlock plain;
  7880. plain.add(dpb->getBytes(), dpb->getClumpLength());
  7881. remAuthBlock.reset(FB_NEW RmtAuthBlock(plain));
  7882. }
  7883. }
  7884. clntConfig = REMOTE_get_config(fileName, &dpbConfig);
  7885. resetClnt();
  7886. }
  7887. void ClntAuthBlock::resetDataFromPlugin()
  7888. {
  7889. dataFromPlugin.clear();
  7890. }
  7891. void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& dpb,
  7892. const ParametersSet* tags,
  7893. int protocol)
  7894. {
  7895. if (!dataFromPlugin.hasData())
  7896. {
  7897. return;
  7898. }
  7899. PathName pluginName = getPluginName();
  7900. if (protocol >= PROTOCOL_VERSION13)
  7901. {
  7902. if (firstTime)
  7903. {
  7904. fb_assert(tags->plugin_name && tags->plugin_list);
  7905. if (pluginName.hasData())
  7906. dpb.insertString(tags->plugin_name, pluginName);
  7907. dpb.deleteWithTag(tags->plugin_list);
  7908. dpb.insertString(tags->plugin_list, pluginList);
  7909. firstTime = false;
  7910. HANDSHAKE_DEBUG(fprintf(stderr,
  7911. "Cli: extractDataFromPluginTo: first time - added plugName & pluginList\n"));
  7912. }
  7913. fb_assert(tags->specific_data);
  7914. dpb.insertBytes(tags->specific_data, dataFromPlugin.begin(), dataFromPlugin.getCount());
  7915. HANDSHAKE_DEBUG(fprintf(stderr,
  7916. "Cli: extractDataFromPluginTo: Added %u bytes of spec data with tag %d\n",
  7917. static_cast<unsigned>(dataFromPlugin.getCount()), tags->specific_data));
  7918. return;
  7919. }
  7920. if (REMOTE_legacy_auth(pluginName.c_str(), PROTOCOL_VERSION10)) // dataFromPlugin is encrypted password
  7921. {
  7922. fb_assert(tags->password_enc);
  7923. dpb.insertBytes(tags->password_enc, dataFromPlugin.begin(), dataFromPlugin.getCount());
  7924. return;
  7925. }
  7926. fb_assert(REMOTE_legacy_auth(pluginName.c_str(), protocol)); // dataFromPlugin must be trustedAuth
  7927. fb_assert(tags->trusted_auth);
  7928. dpb.insertBytes(tags->trusted_auth, dataFromPlugin.begin(), dataFromPlugin.getCount());
  7929. }
  7930. static inline void makeUtfString(bool uft8Convert, Firebird::string& s)
  7931. {
  7932. if (uft8Convert)
  7933. {
  7934. ISC_systemToUtf8(s);
  7935. }
  7936. ISC_unescape(s);
  7937. }
  7938. void ClntAuthBlock::loadClnt(Firebird::ClumpletWriter& dpb, const ParametersSet* tags)
  7939. {
  7940. bool uft8Convert = !dpb.find(tags->utf8_filename);
  7941. for (dpb.rewind(); !dpb.isEof(); dpb.moveNext())
  7942. {
  7943. const UCHAR t = dpb.getClumpTag();
  7944. if (t == tags->user_name)
  7945. {
  7946. dpb.getString(cliUserName);
  7947. makeUtfString(uft8Convert, cliUserName);
  7948. cliOrigUserName = cliUserName;
  7949. fb_utils::dpbItemUpper(cliUserName);
  7950. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: loadClnt: Loaded from PB user = %s(was %s)\n",
  7951. cliUserName.c_str(), cliOrigUserName.c_str()));
  7952. }
  7953. else if (t == tags->password)
  7954. {
  7955. dpb.getString(cliPassword);
  7956. makeUtfString(uft8Convert, cliPassword);
  7957. HANDSHAKE_DEBUG(fprintf(stderr,
  7958. "Cli: loadClnt: Loaded from PB cliPassword = %s\n", cliPassword.c_str()));
  7959. }
  7960. else if (t == tags->encrypt_key)
  7961. {
  7962. HANDSHAKE_DEBUG(fprintf(stderr,
  7963. "Cli: loadClnt: PB contains crypt key\n"));
  7964. }
  7965. }
  7966. dpb.deleteWithTag(tags->password);
  7967. }
  7968. void ClntAuthBlock::extractDataFromPluginTo(CSTRING* to)
  7969. {
  7970. to->cstr_length = (ULONG) dataFromPlugin.getCount();
  7971. to->cstr_address = dataFromPlugin.begin();
  7972. to->cstr_allocated = 0;
  7973. }
  7974. void ClntAuthBlock::extractDataFromPluginTo(P_AUTH_CONT* to)
  7975. {
  7976. extractDataFromPluginTo(&to->p_data);
  7977. PathName pluginName = getPluginName();
  7978. to->p_name.cstr_length = (ULONG) pluginName.length();
  7979. to->p_name.cstr_address = FB_NEW_POOL(*getDefaultMemoryPool()) UCHAR[to->p_name.cstr_length];
  7980. to->p_name.cstr_allocated = to->p_name.cstr_length;
  7981. memcpy(to->p_name.cstr_address, pluginName.c_str(), to->p_name.cstr_length);
  7982. HANDSHAKE_DEBUG(fprintf(stderr, "Cli: extractDataFromPluginTo: added plugin name (%d) and data (%d)\n",
  7983. to->p_name.cstr_length, to->p_data.cstr_length));
  7984. if (firstTime)
  7985. {
  7986. to->p_list.cstr_length = (ULONG) pluginList.length();
  7987. to->p_list.cstr_address = (UCHAR*) pluginList.c_str();
  7988. to->p_list.cstr_allocated = 0;
  7989. HANDSHAKE_DEBUG(fprintf(stderr,
  7990. "Cli: extractDataFromPluginTo: added plugin list (%d len) to packet\n",
  7991. to->p_list.cstr_length));
  7992. firstTime = false;
  7993. }
  7994. else
  7995. {
  7996. to->p_list.cstr_length = 0;
  7997. }
  7998. }
  7999. const char* ClntAuthBlock::getLogin()
  8000. {
  8001. return cliUserName.nullStr();
  8002. }
  8003. const char* ClntAuthBlock::getPassword()
  8004. {
  8005. return cliPassword.nullStr();
  8006. }
  8007. IAuthBlock* ClntAuthBlock::getAuthBlock(CheckStatusWrapper* status)
  8008. {
  8009. return remAuthBlock;
  8010. }
  8011. const unsigned char* ClntAuthBlock::getData(unsigned int* length)
  8012. {
  8013. *length = (ULONG) dataForPlugin.getCount();
  8014. return *length ? dataForPlugin.begin() : NULL;
  8015. }
  8016. void ClntAuthBlock::putData(CheckStatusWrapper* status, unsigned int length, const void* data)
  8017. {
  8018. try
  8019. {
  8020. void* to = dataFromPlugin.getBuffer(length);
  8021. memcpy(to, data, length);
  8022. }
  8023. catch (const Exception& ex)
  8024. {
  8025. ex.stuffException(status);
  8026. }
  8027. }
  8028. bool ClntAuthBlock::checkPluginName(Firebird::PathName& nameToCheck)
  8029. {
  8030. Firebird::ParsedList parsed(pluginList);
  8031. for (unsigned i = 0; i < parsed.getCount(); ++i)
  8032. {
  8033. if (parsed[i] == nameToCheck)
  8034. {
  8035. return true;
  8036. }
  8037. }
  8038. return false;
  8039. }
  8040. Firebird::ICryptKey* ClntAuthBlock::newKey(CheckStatusWrapper* status)
  8041. {
  8042. status->init();
  8043. try
  8044. {
  8045. InternalCryptKey* k = FB_NEW InternalCryptKey;
  8046. fb_assert(plugins.hasData());
  8047. k->keyName = plugins.name();
  8048. WIRECRYPT_DEBUG(fprintf(stderr, "Cli: newkey %s\n", k->keyName.c_str());)
  8049. cryptKeys.add(k);
  8050. return k;
  8051. }
  8052. catch (const Exception& ex)
  8053. {
  8054. ex.stuffException(status);
  8055. }
  8056. return NULL;
  8057. }
  8058. void ClntAuthBlock::tryNewKeys(rem_port* port)
  8059. {
  8060. for (unsigned k = cryptKeys.getCount(); k--; )
  8061. {
  8062. if (port->tryNewKey(cryptKeys[k]))
  8063. {
  8064. releaseKeys(k);
  8065. cryptKeys.clear();
  8066. return;
  8067. }
  8068. }
  8069. cryptKeys.clear();
  8070. }
  8071. void ClntAuthBlock::releaseKeys(unsigned from)
  8072. {
  8073. while (from < cryptKeys.getCount())
  8074. {
  8075. delete cryptKeys[from++];
  8076. }
  8077. }
  8078. void ClntAuthBlock::createCryptCallback(Firebird::ICryptKeyCallback** callback)
  8079. {
  8080. if (*callback)
  8081. return;
  8082. *callback = clientCrypt.create(clntConfig);
  8083. if (*callback)
  8084. createdInterface = callback;
  8085. }
  8086. Firebird::ICryptKeyCallback* ClntAuthBlock::ClientCrypt::create(const Config* conf)
  8087. {
  8088. pluginItr.set(conf);
  8089. return pluginItr.hasData() ? this : nullptr;
  8090. }
  8091. unsigned ClntAuthBlock::ClientCrypt::callback(unsigned dlen, const void* data, unsigned blen, void* buffer)
  8092. {
  8093. HANDSHAKE_DEBUG(fprintf(stderr, "dlen=%d blen=%d\n", dlen, blen));
  8094. int loop = 0;
  8095. while (loop < 2)
  8096. {
  8097. for (; pluginItr.hasData(); pluginItr.next())
  8098. {
  8099. if (!currentIface)
  8100. {
  8101. LocalStatus ls;
  8102. CheckStatusWrapper st(&ls);
  8103. HANDSHAKE_DEBUG(fprintf(stderr, "Try plugin %s\n", pluginItr.name()));
  8104. currentIface = pluginItr.plugin()->chainHandle(&st);
  8105. // if plugin does not support chaining - silently ignore it
  8106. check(&st, isc_wish_list);
  8107. HANDSHAKE_DEBUG(fprintf(stderr, "Use plugin %s, ptr=%p\n", pluginItr.name(), currentIface));
  8108. }
  8109. // if we have an iface - try it
  8110. if (currentIface)
  8111. {
  8112. unsigned retlen = currentIface->callback(dlen, data, blen, buffer);
  8113. HANDSHAKE_DEBUG(fprintf(stderr, "Iface %p returned %d\n", currentIface, retlen));
  8114. if (retlen)
  8115. return retlen;
  8116. }
  8117. // no success with iface - clear it
  8118. // appropriate data structures to be released by plugin cleanup code
  8119. currentIface = nullptr;
  8120. }
  8121. ++loop;
  8122. // prepare iterator for next use
  8123. pluginItr.rewind();
  8124. }
  8125. // no luck with suggested data
  8126. return 0;
  8127. }