DIRECTORY Process USING [SetTimeout, MsecToTicks], ProcessorFace USING [GetClockPulses], StatsDefs USING [StatBump, StatIncr], CommFlags USING [doDebug, doStats], DriverDefs USING [MaybeGetFreePupBuffer, Glitch], PupStream USING [StreamClosing], PupPktDefs, PupPktOps, PupDefs USING [Byte, PupBuffer, DequeuePup, EnqueuePup, GetFreePupBuffer, ReturnFreePupBuffer, PupRouterSendThis], BufferDefs USING [ReturnFreeBuffer], PupTypes USING [PupAddress, maxDataBytesPerGatewayPup]; PupPktHot: MONITOR LOCKS him USING him: Instance IMPORTS Process, ProcessorFace, StatsDefs, PupStream, DriverDefs, PupPktOps, PupDefs, BufferDefs EXPORTS PupPktDefs, PupPktOps = { OPEN StatsDefs, DriverDefs, PupPktOps, PupDefs; PupPktStreamObject: PUBLIC TYPE = PupPktOps.InstanceData; NeitherDataNorMark: PUBLIC ERROR = CODE; BufferAlreadyRequeued: PUBLIC ERROR = CODE; StreamNotOpen: PUBLIC ERROR = CODE; Diff: PROC [a, b: INT] RETURNS [INTEGER] = { maxInteger: INTEGER = 77777B; temp: INT _ a - b; SELECT TRUE FROM temp > maxInteger => RETURN[maxInteger]; temp < -maxInteger => RETURN[-maxInteger]; ENDCASE => RETURN[temp]; }; Retransmitter: PUBLIC ENTRY PROC [him: Instance] = { UNTIL him.pleaseDie DO now: PupPktOps.Pulses _ ProcessorFace.GetClockPulses[]; SELECT him.state FROM open => { IF now - him.timer > pingPulses AND him.ping THEN { him.probeCounter _ pingRetransmissions; him.allocatedPups _ 0; -- will start probing }; IF now - him.timer > ctlRetransmitPulses AND (him.outEnd = 0 OR him.allocatedPups = 0) THEN ProbeForAck[him]; }; talking, finishing => { DO IF him.sentBuffer = NIL THEN him.sentBuffer _ DequeuePup[him.sentQueue]; IF him.sentBuffer = NIL THEN EXIT; IF him.ackedID - Flip[him.sentBuffer.pupID] > 0 THEN { IF (him.unackedPups _ him.unackedPups - 1) = 0 THEN { SELECT him.state FROM talking => him.state _ open; finishing => him.state _ end; ENDCASE; BROADCAST him.stateChange; }; ReturnFreePupBuffer[him.sentBuffer]; him.sentBuffer _ NIL; } ELSE EXIT; ENDLOOP; IF him.sentBuffer # NIL AND now - him.timer > him.retransmitPulses THEN { ProbeForAck[him]; IF now - him.timer > him.retransmitPulses THEN { IF him.sentBuffer.pupType = data THEN him.sentBuffer.pupType _ aData; him.timer _ ProcessorFace.GetClockPulses[]; PupRouterSendThis[him.sentBuffer]; IF CommFlags.doStats THEN StatIncr[statDataPacketsRetransmitted]; him.sentBuffer _ DequeuePup[him.sentQueue]; }; }; }; halfOpen => IF now - him.timer > ctlRetransmitPulses THEN SendRfc[him]; end => IF now - him.timer > ctlRetransmitPulses THEN SendEnd[him]; closed => { DO IF him.sentBuffer = NIL THEN him.sentBuffer _ DequeuePup[him.sentQueue]; IF him.sentBuffer = NIL THEN EXIT; him.unackedPups _ him.unackedPups - 1; ReturnFreePupBuffer[him.sentBuffer]; him.sentBuffer _ NIL; ENDLOOP; }; ENDCASE; IF him.outIntPending AND now - him.outIntTime > ctlRetransmitPulses THEN SendInt[him]; WAIT him.retransmitterReady; ENDLOOP; UNTIL him.unackedPups = 0 DO DO IF him.sentBuffer = NIL THEN him.sentBuffer _ DequeuePup[him.sentQueue]; IF him.sentBuffer = NIL THEN EXIT; him.unackedPups _ him.unackedPups - 1; ReturnFreePupBuffer[him.sentBuffer]; him.sentBuffer _ NIL; ENDLOOP; IF him.unackedPups # 0 THEN WAIT him.retransmitterReady; ENDLOOP; }; ProbeForAck: INTERNAL PROC [him: Instance] = { b: PupBuffer _ MaybeGetFreePupBuffer[]; IF b = NIL THEN RETURN; b.pupLength _ bytesPerPupHeader; b.pupType _ aData; b.pupID _ Flop[him.nextOutputID]; b.source _ him.local; b.dest _ him.remote; him.timer _ ProcessorFace.GetClockPulses[]; him.aDataOut _ FALSE; him.clumpsSinceBump _ 0; PupRouterSendThis[b]; IF CommFlags.doStats THEN StatIncr[statProbesSent]; IF (him.probeCounter _ him.probeCounter + 1) > retransmitionsBeforeAbort THEN SmashClosed[him, transmissionTimeout]; IF him.probeCounter > probesBeforePanic THEN him.retransmitPulses _ MIN[2*him.retransmitPulses, maxRetransmitPulses]; }; ThrottleForward: PROC [him: Instance] = { old: CARDINAL _ him.pathMaxAllocate; him.clumpsSinceBump _ 0; IF him.retransmitPulses = maxRetransmitPulses THEN RETURN; him.pathMaxAllocate _ MIN[him.pathMaxAllocate + 1, him.myMaxAllocate]; him.retransmitPulses _ (him.retransmitPulses*him.pathMaxAllocate)/old; }; ThrottleBack: INTERNAL PROC [him: Instance] = { IF him.pathMaxAllocate = 1 THEN { pause: CONDITION; Process.SetTimeout[@pause, Process.MsecToTicks[maxRetransmitTime]]; WAIT pause; }; UNTIL him.throttle = 0 OR him.retransmitPulses = minRetransmitPulses OR him.pathMaxAllocate = 1 DO old: CARDINAL _ him.pathMaxAllocate; him.pathMaxAllocate _ him.pathMaxAllocate - 1; him.throttle _ him.throttle - 1; ENDLOOP; him.clumpsSinceBump _ him.throttle _ 0; }; SendAck: INTERNAL PROC [him: Instance] = { b: PupBuffer _ him.c; IF b # NIL THEN him.c _ NIL ELSE IF (b _ MaybeGetFreePupBuffer[]) = NIL THEN RETURN; b.pupBody _ ack[ him.dataBytesPerPup, MAX[0, INTEGER[him.myMaxAllocate - him.inputQueue.length]], byteAllocate]; him.allocatedID _ him.nextInputID + byteAllocate; b.pupType _ ack; b.pupID _ Flop[him.nextInputID]; b.pupLength _ bytesPerAck; b.source _ him.local; b.dest _ him.remote; PupRouterSendThis[b]; IF CommFlags.doStats THEN StatIncr[statAcksSent]; IF him.state = open AND him.outEnd # 0 AND him.allocatedPups # 0 THEN him.timer _ ProcessorFace.GetClockPulses[]; -- avoid pinging him.sendAck _ FALSE; }; Get: PUBLIC ENTRY PROC [him: Instance] RETURNS [b: PupBuffer _ NIL] = { ENABLE UNWIND => NULL; IF him.inputQueue.length = 0 THEN SELECT TRUE FROM (him.state = closed) => ERROR PupStream.StreamClosing[him.whyClosed, him.text]; him.dontWait => RETURN[NIL]; ENDCASE => WAIT him.inputReady; IF him.inputQueue.length # 0 THEN b _ DequeuePup[him.inputQueue]; IF b = NIL THEN { IF him.state = closed THEN ERROR PupStream.StreamClosing[him.whyClosed, him.text]; RETURN; }; IF CommFlags.doStats THEN SELECT b.pupType FROM data, aData => { StatIncr[statDataPacketsReceived]; StatBump[statDataBytesReceived, b.pupLength - bytesPerPupHeader]; }; mark, aMark => StatIncr[statMarksReceived]; ENDCASE => Glitch[NeitherDataNorMark]; IF him.inputQueue.length = 0 AND him.sendAck THEN SendAck[him]; }; PktsAvailable: PUBLIC ENTRY PROC [him: Instance] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[ him.inputQueue.length # 0 ] }; Put: PUBLIC PROC [him: Instance, b: PupBuffer] = { IF CommFlags.doDebug AND b.requeueProcedure # BufferDefs.ReturnFreeBuffer THEN Glitch[BufferAlreadyRequeued]; SELECT him.state FROM open, talking => { IF CommFlags.doStats THEN { StatIncr[statDataPacketsSent]; StatBump[statDataBytesSent, b.pupLength - bytesPerPupHeader]; }; SendPacket[him, b]; }; idle, halfOpen => Glitch[StreamNotOpen]; ENDCASE --end, closed, finishing-- => StreamDied[him, b]; }; PutMark: PUBLIC PROC [him: Instance, byte: Byte] = { b: PupBuffer _ GetFreePupBuffer[]; b.pupBytes[0] _ byte; b.pupLength _ bytesPerPupHeader + 1; b.pupType _ aMark; SendPacket[him, b]; IF CommFlags.doStats THEN StatIncr[statMarksSent]; }; SendPacket: ENTRY PROC [him: Instance, b: PupBuffer] = { SELECT him.state FROM open, talking => { b.pupID _ Flop[him.nextOutputID]; IF b.pupLength = bytesPerPupHeader THEN him.probeCounter _ 1 ELSE { b.requeueProcedure _ LOOPHOLE[PutOnSentQueue]; b.requeueRef _ him; -- BEWARE: we rely on having another reference to the REF him.state _ talking; him.unackedPups _ him.unackedPups + 1; }; b.source _ him.local; b.dest _ him.remote; him.nextOutputID _ him.nextOutputID + (b.pupLength - bytesPerPupHeader); IF b.pupType = data AND ~((him.maxOutputID - him.nextOutputID) > 0 AND him.allocatedPups > him.unackedPups) THEN b.pupType _ aData; IF b.pupType # data THEN { him.timer _ ProcessorFace.GetClockPulses[]; him.aDataOut _ TRUE; }; PupRouterSendThis[b]; IF b.pupType # data THEN WaitToSend[him ! UNWIND => NULL]; }; idle, halfOpen => Glitch[StreamNotOpen]; ENDCASE --end, closed, finishing-- => StreamDied[him, b ! UNWIND => NULL]; }; WaitToSend: INTERNAL PROC [him: Instance] = { SELECT him.state FROM open, talking => { DO SELECT him.state FROM open => EXIT; talking => WAIT him.stateChange; ENDCASE => StreamDied[him, NIL]; ENDLOOP; UNTIL (him.maxOutputID - him.nextOutputID) > 0 AND him.allocatedPups > him.unackedPups DO SELECT him.state FROM open, talking => WAIT him.stateChange; ENDCASE => StreamDied[him, NIL]; ENDLOOP; IF him.throttle > 0 THEN ThrottleBack[him]; }; idle, halfOpen => Glitch[StreamNotOpen]; ENDCASE --end, closed, finishing-- => StreamDied[him, NIL]; }; PutOnSentQueue: PROC [b: PupBuffer] = { ReallyPutOnSentQueue[NARROW[b.requeueRef], b]; }; ReallyPutOnSentQueue: ENTRY PROC [him: Instance, b: PupBuffer] = { SELECT TRUE FROM him.ackedID > Flip[b.pupID] => { IF (him.unackedPups _ him.unackedPups - 1) = 0 THEN { SELECT him.state FROM talking => him.state _ open; finishing => him.state _ end; ENDCASE => SendAbort[him]; BROADCAST him.stateChange; }; ReturnFreePupBuffer[b]; }; him.sentBuffer = NIL => him.sentBuffer _ b; ENDCASE => EnqueuePup[him.sentQueue, b]; }; Slurp: PUBLIC PROC [him: Instance] = { UNTIL him.pleaseDie DO b: PupBuffer _ him.socket.get[]; IF b # NIL THEN InputPacket[him, b]; ENDLOOP; }; InputPacket: ENTRY PROC [him: Instance, b: PupBuffer] = { ENABLE UNWIND => NULL; thisID: INT _ Flip[b.pupID]; ackWantedBefore: BOOL = him.sendAck; him.c _ b; IF ~(b.pupType = rfc OR b.pupType = error) AND b.source.socket # him.remote.socket THEN { IF CommFlags.doStats THEN StatIncr[statPacketsRejectedBadSource]; GO TO freeC; }; SELECT b.pupType FROM data, aData, mark, aMark => SELECT him.state FROM open, talking, end => { SELECT b.pupType FROM aData, aMark => him.sendAck _ TRUE; ENDCASE; IF b.pupLength > bytesPerPupHeader THEN { offset: INTEGER _ Diff[thisID, him.nextInputID]; SELECT offset FROM 0 => { him.nextInputID _ him.nextInputID + (him.c.pupLength - bytesPerPupHeader); EnqueuePup[him.inputQueue, him.c]; NOTIFY him.inputReady; him.c _ NIL; }; ENDCASE => { IF CommFlags.doStats THEN SELECT offset FROM IN (0..duplicateWindow] => StatIncr[statDataPacketsReceivedEarly]; IN (-duplicateWindow..0) => StatIncr[statDataPacketsReceivedAgain]; ENDCASE => StatIncr[statDataPacketsReceivedVeryLate]; ReturnFreePupBuffer[him.c]; him.c _ NIL; }; } ELSE { IF CommFlags.doStats THEN IF b.pupLength = bytesPerPupHeader AND b.pupType = aData THEN { StatIncr[statProbesReceived]; SendAck[him]; } ELSE StatIncr[statEmptyFunnys]; }; IF him.sendAck AND (him.inputQueue.length = 0 OR ackWantedBefore) THEN SendAck[him]; }; halfOpen => SendRfc[him]; ENDCASE --idle, closed, finishing-- => SendAbort[him]; ack => { IF b.pupLength < bytesPerAck THEN { IF CommFlags.doStats THEN StatIncr[statMouseTrap]; GOTO SkipThisAck; }; IF CommFlags.doStats THEN StatIncr[statAcksReceived]; IF (thisID - him.ackedID) < 0 OR (thisID = him.ackedID AND him.probeCounter = 0) THEN { IF CommFlags.doStats THEN StatIncr[statDuplicateAcks]; GOTO SkipThisAck; }; him.probeCounter _ 0; IF him.aDataOut THEN { myRetrTime: PupPktOps.Pulses _ him.retransmitPulses; responseTime: PupPktOps.Pulses _ ProcessorFace.GetClockPulses[] - him.timer; responseTime _ MIN[responseTime, maxRetransmitPulses]; myRetrTime _ (6*myRetrTime + myRetrTime + 2*responseTime)/8; myRetrTime _ MAX[minRetransmitPulses, MIN[myRetrTime, maxRetransmitPulses]]; him.retransmitPulses _ myRetrTime; him.aDataOut _ FALSE; him.clumpsSinceBump _ him.clumpsSinceBump + 1; IF him.clumpsSinceBump > clumpsBeforeBump THEN ThrottleForward[him]; }; IF him.allocatedPups = 0 THEN BROADCAST him.stateChange; him.hisMaxAllocate _ b.numberOfPupsAhead; IF him.hisMaxAllocate = 0 THEN { him.probeCounter _ 1; IF CommFlags.doStats THEN StatIncr[statEmptyAlloc]; }; him.allocatedPups _ MIN[him.hisMaxAllocate, him.pathMaxAllocate]; IF him.outEnd = 0 THEN BROADCAST him.stateChange; -- in case first time him.outEnd _ MIN[b.maximumBytesPerPup, him.dataBytesPerPup]; IF ~him.sameNet THEN him.outEnd _ MIN[him.outEnd, PupTypes.maxDataBytesPerGatewayPup]; IF (thisID - him.maxOutputID) + b.numberOfBytesAhead > 0 THEN him.maxOutputID _ b.numberOfBytesAhead + thisID; him.ackedID _ thisID; IF him.sentBuffer = NIL THEN him.sentBuffer _ DequeuePup[him.sentQueue]; WHILE him.sentBuffer # NIL AND thisID > Flip[him.sentBuffer.pupID] DO IF (him.unackedPups _ him.unackedPups - 1) = 0 THEN { SELECT him.state FROM -- last packet has been ACKed talking => him.state _ open; finishing => him.state _ end; ENDCASE => SendAbort[him]; BROADCAST him.stateChange; }; ReturnFreePupBuffer[him.sentBuffer]; him.sentBuffer _ DequeuePup[him.sentQueue]; ENDLOOP; UNTIL him.sentBuffer = NIL DO PupRouterSendThis[him.sentBuffer]; IF CommFlags.doStats THEN StatIncr[statDataPacketsRetransmitted]; him.sentBuffer _ DequeuePup[him.sentQueue]; ENDLOOP; EXITS SkipThisAck => NULL; }; ENDCASE => GotOther[him, him.c]; IF him.c # NIL THEN GO TO freeC; EXITS freeC => { ReturnFreePupBuffer[him.c]; him.c _ NIL; }; }; SendAttention: PUBLIC ENTRY PROC [him: Instance] = { ENABLE UNWIND => NULL; WHILE him.outIntPending DO WAIT him.stateChange; ENDLOOP; him.outIntPending _ TRUE; SendInt[him]; }; WaitForAttention: PUBLIC ENTRY PROC [him: Instance] = { ENABLE UNWIND => NULL; WHILE him.seenIntSeq = him.inIntSeq DO WAIT him.waitingForInterrupt; ENDLOOP; him.seenIntSeq _ him.seenIntSeq + 1; }; }. PupPktHot.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. HGM March 14, 1981 11:40 AM Andrew Birrell June 23, 1983 4:31 pm Levin, August 9, 1983 9:44 am Russ Atkinson, February 4, 1985 12:40:12 pm PST Only called by InputPacket Retransmit things which have not been acknowledged in a reasonable time. Such things include RFCs and ENDs as well as data. recycle things that have timed out this packet has been ACKed already last packet has been ACKed couldn't get buffer, use one of ours flush anything left on the him.sentQueue flush anything left on the him.sentQueue If a buffer is on a device output queue, wait until it comes back. We can actually get one packet ahead at this point. This is a desperate attempt to avoid an instability It is/(was?) also a nasty bug under some strange case that Andrew found Beware of rounding down, assume return ack takes as long as a send packet This goes unstable if much of the time is due to somebody else's packets him.retransmitPulses _ ((him.retransmitPulses+old)*old)/(old+1); we don't use mark, only aMark aMark or aData Wait until all our packets have been acked so we don't shoot them down. now wait for allocate not really, but ..... last packet has been ACKed nice - just what we wanted funny length from way back there answer probes immediately Try to avoid the funny stable SLOW case him.retransmitPulses _ 2*Smooth[responseTime] him.retransmitPulses _ 2*((7/8)*(him.retransmitPulses/2)+(1/8)*responseTime) him.retransmitPulses _ (7*him.retransmitPulses+2*responseTime)/8 Κ€˜codešœ™Kšœ Οmœ7™BKšœ™Kšœ%™%K™K™/K™—šΟk ˜ Kšœžœ˜(Kšœžœ˜%Kšœ žœ˜%Kšœ žœ˜#Kšœ žœ!˜1Kšœ žœ˜ K˜ K˜ Kšœžœe˜rKšœ žœ˜$Kšœ žœ)˜7K˜—šœ žœžœžœ˜0KšžœY˜`Kšžœ˜!Kšžœ+˜/K˜Kšœžœžœ˜9K˜Kšœžœžœžœ˜(Kšœžœžœžœ˜+Kšœžœžœžœ˜#K˜Kšœ™š Οnœžœžœžœžœ˜,Kšœ žœ ˜Kšœžœ ˜šžœžœž˜Kšœžœ ˜(Kšœžœ˜*Kšžœžœ˜—Kšœ˜K˜—šŸ œžœžœžœ˜4KšœH™HKšœ2™2šžœž˜K˜7šžœ ž˜šœ ˜ šžœžœ žœ˜3Kšœ'˜'KšœΟc˜,Kšœ˜—šžœ'ž˜,Kšœžœžœ˜@—Kšœ˜—šœ˜šž˜Kšœ"™"Kšžœžœžœ,˜HKšžœžœžœžœ˜"šžœ.žœ˜6Kšœ"™"šžœ-žœ˜5Kšœ™šžœ ž˜Kšœ˜Kšœ˜Kšžœ˜—Kšž œ˜Kšœ˜—Kšœ$˜$Kšœžœ˜Kšœ˜—Kšžœžœ˜ Kšžœ˜—šžœžœžœ(žœ˜IK˜šžœ(žœ˜0Kšœ$™$Kšžœžœ ˜EKšœ+˜+Kšœ"˜"Kšžœžœ(˜AKšœ+˜+Kšœ˜—Kšœ˜—Kšœ˜—Kšœ žœ'žœ˜GKšœžœ'žœ˜Bšœ ˜ šž˜Kšœ(™(Kšžœžœžœ,˜HKšžœžœžœžœ˜"Kšœ&˜&Kšœ$˜$Kšœžœ˜Kšžœ˜—Kšœ˜—Kšžœ˜—šžœžœ,ž˜HK˜ —Kšžœ˜Kšžœ˜—šžœž˜šž˜Kšœ(™(Kšžœžœžœ,˜HKšžœžœžœžœ˜"Kšœ&˜&Kšœ$˜$Kšœžœ˜Kšžœ˜—KšœB™BKšžœžœžœ˜8Kšžœ˜—Kšœ˜K˜—šŸ œžœžœžœ˜.Kšœ'˜'Kšžœžœžœžœ˜K˜ K˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ+˜+Kšœžœ˜Kšœ˜K˜Kšžœžœ˜3šžœGž˜MK˜&—šžœ&ž˜,Kšœžœ.˜H—Kšœ˜K˜—šŸœžœ˜)Kšœžœ˜$Kšœ˜Kšœ3™3Kšžœ,žœžœ˜:Kšœžœ-˜FKšœF˜FKšœ˜K˜—šŸ œžœžœ˜/šžœžœ˜!Kšœ3™3KšœG™GKšœž œ˜K˜CKšžœ˜ Kšœ˜—šžœžœ,žœž˜bKšœžœ˜$Kšœ.˜.KšœI™IKšœH™HKšœ@™@Kšœ ˜ Kšžœ˜—Kšœ'˜'Kšœ˜K˜—šŸœžœžœ˜*Kšœ˜šžœž˜ Kšžœ ž˜Kš žœžœ!žœžœžœ˜8—˜Kšœžœžœ-˜PK˜—Kšœ1˜1K˜Kšœ ˜ K˜Kšœ˜Kšœ˜K˜Kšžœžœ˜1šžœžœžœž˜EKšœ, ˜<—Kšœžœ˜Kšœ˜K˜—š Ÿœžœžœžœžœžœ˜GKšžœžœžœ˜šžœž˜!šžœžœž˜Kšœžœ2˜OKšœžœžœ˜Kšžœžœ˜——Kšžœžœ ˜Ašžœžœžœ˜Kšžœžœžœ2˜RKšžœ˜Kšœ˜—šžœž˜šžœ ž˜šœ˜K˜"K˜AKšœ˜—K˜+Kšžœ˜&——Kšžœžœ žœ˜?Kšœ˜K˜—š Ÿ œžœžœžœžœžœ˜CKšžœžœžœ˜Kšžœ˜#Kšœ˜K˜—šŸœžœžœ"˜2šžœžœ2ž˜NK˜—šžœ ž˜šœ˜šžœžœ˜K˜K˜=Kšœ˜—K˜Kšœ˜—K˜(Kšžœ œ˜9—Kšœ˜K˜—šŸœžœžœ ˜4K˜"K˜K˜$K˜K˜Kšžœžœ˜2Kšœ˜K˜—šŸ œžœžœ"˜8šžœ ž˜šœ˜Kšœ!˜!šžœ ˜"Kšžœ˜šžœ˜Kšœžœ˜.Kšœ 9˜MKšœ˜Kšœ&˜&Kšœ˜——Kšœ˜Kšœ˜KšœH˜HKšœ™Kšžœžœ,žœ%žœ˜ƒšžœžœ˜Kšœ™Kšœ+˜+Kšœžœ˜Kšœ˜—K˜Kšžœžœžœžœ˜:Kšœ˜—K˜(Kšžœ œžœžœ˜J—Kšœ˜K˜—šŸ œžœžœ˜-šžœ ž˜šœ˜KšœG™Gšž˜šžœ ž˜Kšœžœ˜ Kšœ žœ˜ Kšžœžœ˜ —Kšžœ˜—Kšœ™šžœ*žœ%ž˜Yšžœ ž˜Kšœ™Kšœžœ˜&Kšžœžœ˜ —Kšžœ˜—Kšžœžœ˜+Kšœ˜—K˜(Kšžœ œžœ˜;—Kšœ˜K˜—šŸœžœ˜'Kšœžœ˜.Kšœ˜—K˜šŸœžœžœ"˜Bšžœžœž˜šœ ˜ šžœ-žœ˜5Kšœ™šžœ ž˜Kšœ˜Kšœ˜Kšžœ˜—Kšž œ˜Kšœ˜—K˜K˜—Kšœžœ˜+Kšžœ!˜(—Kšœ˜K˜—šŸœžœžœžœ˜&šžœž˜Kšœ ˜ Kšžœžœžœ˜$Kšžœ˜—Kšœ˜K˜—šŸ œžœžœ"˜9Kšžœžœžœ˜Kšœžœ˜Kšœžœ˜$Kšœ ˜ K˜šžœžœžœ%žœ˜YKšžœžœ(˜AKšžœžœ˜ Kšœ˜K˜—šžœ ž˜˜šžœ ž˜šœ˜Kšžœ žœžœžœ˜Bšžœ ˜"šžœ˜Kšœžœ!˜0šžœž˜šœ˜Kšœ™KšœJ˜JKšœ"˜"Kšžœ˜Kšœžœ˜ Kšœ˜—šžœ˜ šžœž˜šžœž˜šžœ˜K˜'—šžœ˜K˜'—Kšžœ.˜5——Kšœ˜Kšœžœ˜ Kšœ˜——Kšœ˜—šžœ˜Kšœ ™ šžœž˜šžœ!žœ˜8šžœ˜Kšœ˜Kšœ ˜ Kšœ˜—Kšžœ˜——Kšœ˜——Kšœ™šžœ žœžœž˜FKšœ ˜ —Kšœ˜—K˜Kšžœ œ˜6K˜——šœ˜šžœžœ˜#Kšžœžœ˜2Kšžœ ˜Kšœ˜—Kšžœžœ˜5Kšœ'™'šžœžœžœžœ˜WKšžœžœ˜6Kšžœ ˜Kšœ˜—Kšœ˜šžœžœ˜Kšœ4˜4KšœL˜LKšœžœ$˜6Kšœ-™-KšœL™LKšœ@™@K˜