From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-0.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37C33C32789 for ; Fri, 2 Nov 2018 17:10:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C9ED62082E for ; Fri, 2 Nov 2018 17:10:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="NnXqRetM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C9ED62082E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ideasonboard.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728075AbeKCCSj (ORCPT ); Fri, 2 Nov 2018 22:18:39 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:48778 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726700AbeKCCSj (ORCPT ); Fri, 2 Nov 2018 22:18:39 -0400 Received: from avalon.localnet (dfj612ybrt5fhg77mgycy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:2e86:4862:ef6a:2804]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5A5A81263; Fri, 2 Nov 2018 18:10:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1541178645; bh=N2Vtu/m22G3w60MPHjNcl8TEMOraOVx3sOXRq4nJZb0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NnXqRetMJ02sTQ1NPbVUmlqksf18I1dWfzjhpbq6deUU7VsoUQ7xo+GKvqe8r0R41 LAS3ZPwaBlj089B/y4ior/KlhiM6AKnj9WJqhguniu2yUQ08fgiNQf4bupjoEip9NO 1J9Cdu+QaCQgY9edP+5vfYOA4IqLr4MKywvE41Gk= From: Laurent Pinchart To: Alan Stern Cc: Felipe Balbi , Paul Elder , Bin Liu , kieran.bingham@ideasonboard.com, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, rogerq@ti.com Subject: Re: [PATCH 4/6] usb: gadget: add functions to signal udc driver to delay status stage Date: Fri, 02 Nov 2018 19:10:53 +0200 Message-ID: <3595344.euAgJ7Kpbg@avalon> Organization: Ideas on Board Oy In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Alan, On Friday, 2 November 2018 18:18:45 EET Alan Stern wrote: > On Fri, 2 Nov 2018, Laurent Pinchart wrote: > > On Friday, 2 November 2018 15:17:20 EET Felipe Balbi wrote: > >> Laurent Pinchart writes: > >>>>>>> +void usb_ep_delay_status(struct usb_ep *ep) > >>>>>>> > >>>>>>> +{ > >>>>>>> + ep->delayed_status = true; > >>>>>>> +} > >>>>>>> +EXPORT_SYMBOL_GPL(usb_ep_delay_status); > >>>>>> > >>>>>> Is usb_ep_set_delay_status() better? I thought it implies > >>>>>> get/return action if a verb is missing in the function name. > >>>>> > >>>>> For what it's worth, I understand the function name as "delay the > >>>>> status stage", with "delay" being a verb. Maybe the short > >>>>> description could be updated accordingly. > >>>>> > >>>>> Is there a reason for adding a new function for this? This is > >>>>> exactly what the USB_GADGET_DELAYED_STATUS return value from the setup > >>>>> callback is meant for (and it is already used by some gadget drivers). > >>>> > >>>> In theory, we might be able to use USB_GADGET_DELAYED_STATUS for > >>>> this. However, there are a few ambiguities that prevent us from doing > >>>> so. > >>>> > >>>> First of all, we want to delay only the status stage for control OUT > >>>> requests; according to composite.h, USB_GADGET_DELAYED_STATUS is for > >>>> delaying the "data/status stages". Does this mean that it delays the > >>>> status stage only or does it delay both stages? If the slash means > >>>> "and", then we cannot use USB_GADGET_DELAYED_STATUS. > > The comment in composite.h is wrong; it should refer only to the status > stage. In fact, it should refer only to the status stage for > control-OUT transfers; there's no reason ever to delay the status stage > of a control-IN transfer (the driver should instead delay the data > stage if it needs to). Agreed. > >>>> Furthermore, we have found that USB_GADGET_DELAYED_STATUS is racey, > >>>> which has already been observed in the UVC gadget driver previously > >>>> [0]. The raceiness stems from the fact that things can happen in > >>>> between returning USB_GADGET_DELAYED_STATUS and the composite layer > >>>> reacting to it - especially if usb_composite_setup_continue is called > >>>> within that window it causes a WARN. In any case, the fact that the > >>>> mechanism itself is racey suggests that it needs improvement, and using > >>>> it wouldn't be a good solution in this case. > > I don't understand this at all. The composite layer reacts to > USB_GADGET_DELAYED_STATUS as soon as it receives the return value. Can > Paul or Laurent give a more explicit example of this race? The composite layer only handles USB_GADGET_DELAYED_STATUS for USB_REQ_SET_CONFIGURATION (in set_config()) and for USB_REQ_SET_INTERFACE (in composite_setup()). It increments cdev->delayed_status immediately. Then, in usb_composite_setup_continue(), if cdev->delayed_status is not zero, it queues a ZLP, and warns otherwise. This mechanism delays the data stage, not the status stage (or, to be precise, it delays the status stage insofar as the status stage comes after the data stage), and only supports control OUT requests with 0 bytes of data (which is the case of both USB_REQ_SET_INTERFACE and USB_REQ_SET_CONFIGURATION). For all other requests, the composite layer passes USB_GADGET_DELAYED_STATUS to the UDC. The three UDCs that implement USB_GADGET_DELAYED_STATUS support set a delayed_status flag in an internal structure. I haven't inspected in details what they do next as I'm not familiar with all of them, but the dwc3 driver just skips the handling of the status phase in dwc3_ep0_xfernotready() and delays it to __dwc3_gadget_ep0_queue(). This only works for 0-length requests, with no data phase. Even when limited to 0-length control OUT requests, this mechanism is racy. The setup handler, when it wants to delay the status phase, will queue asynchronous work that will, when it completes, call usb_composite_setup_continue() to proceed with the status phase. Queuing the work has to be done before the setup handler returns, and the cdev- >delayed_status is only incremented after the setup handler returns, in composite_setup(). There is thus a time window during which the asynchronous work can call usb_composite_setup_continue() before cdev->delayed_status has been incremented. We have managed to hit this in practice, with a surprisingly high rate seeing how small the window is. Now that I've written all this, I realize that cdev->delayed_status is guarded by cdev->lock. I thus wonder whether our analysis was correct, or if we were hitting a different bug :-S Paul, could you test this again ? Please note, however, that the race described here is not related to this patch series, except in how it influences the API design to avoid race conditions. > Assuming you are correct, wouldn't it make sense to fix or eliminate > the race by changing composite.c? I was about to write that we would need to lock access to cdev- >delayed_status, and found out that we already use cdev->lock to do so. More investigations are needed. Please note, however, that USB_GADGET_DELAYED_STATUS is limited to 0-length control OUT requests, so the problem that led to this patch series still exists, even if the race condition I thought was there doesn't exist. > >>>>> Is it a question of when the gadget driver learns that it will need > >>>>> to delay the status stage? If that's the case, > >>>> > >>>> Not really. > >>>> > >>>>> why not always return > >>>>> USB_GADGET_DELAYED_STATUS from the setup callback? Then instead of > >>>> calling usb_ep_delay_status() when a delay is needed, you could > >>>>> queue the status request when a delay isn't needed. > >>>> > >>>> Theoretically this might work, but see the problems mentioned above. > >>>> > >>>>> As a more general solution, Felipe has said that a UDC driver should > >>>>> _never_ carry out the status stage transaction until the gadget > >>>>> driver has told it to do so. Then there would be no need for any sort > >>>>> of delay indicator. > >>>> > >>>> Yeah, but, > >>>> > >>>>> (But implementing this would require significant > >>>>> changes to a bunch of different drivers...) > >>>> > >>>> exactly :/ > >> > >> add a flag to gadget structure. Something like > >> "supports_explicit_status_stage" and add a new return value > >> USB_EXPLICIT_STATUS_STAGE. > >> > >> Then, take uvc for example, implement the new setup: > >> > >> if (supports_explicit_status_stage) > >> > >> return USB_EXPLICIT_STATUS_STAGE; > >> > >> then on dwc3 you would: > >> > >> switch (ret) { > >> case USB_EXPLICIT_STATUS_STAGE: > >> > >> case USB_GADGET_DELAYED_STATUS: > >> wait_for_status_request_queue(); > >> > >> break; > >> > >> default: > >> start_status_stage(); > >> > >> } > >> > >> If this works with dwc3 + uvc, then we have a good recipe on how to > >> implement for the other drivers. > > > > Given that we need to delay the status stage and not the data stage, we > > can't explicitly request the status stage through a usb request queue. > > Why not? The status stage for a control-OUT transfer is simply a > zero-length IN transaction. It's easy to queue a request for such a > transaction. Is the issue that there's no way to specify the direction > of the request (hence no direct way to tell whether a zero-length > request is for the data stage or the status stage)? OK, I suppose we could queue a request for this, in which case we would have to queue two requests for control OUT transfers (one for the data stage and one for the status stage). I'm however not convinced that would be the best API to handle the status stage, as the function driver would need to queue a request and the UDC would then need to check whether that request corresponds to a status stage and process it accordingly. A new operation specific to this would be easier for both the function driver and the UDC in my opinion. There's also the fact that requests can specify a completion handler, but only the data stage request would see its completion handler called (unless we require UDCs to call completion requests at the completion of the status stage, but I'm not sure that all UDCs can report the event to the driver, and that would likely be useless as nobody needs that feature). > Admittedly, it might be nice to provide a library routine in the UDC > core to queue such requests, since it involves a bunch of uninteresting > boilerplate operations. > > > Would a new explicit function call work for you for that purpose ? > > It would be okay, but I question whether one is really needed. I think the API would be cleaner, but it might just be a matter of taste. > >>> Alan, Felipe, how do we move forward with this ? There are several > >>> issues with the existing control request handling mechanism in the USB > >>> gadget stack, and while Paul could work on improving the mechanism, we > >>> need to provide clear guidance regarding the direction we want to > >>> take. > >>> > >>> For reference, the issues I know about for the USB_GADGET_DELAYED_STATUS > >>> mechanism are > >>> > >>> - The mechanism is inherently racy. It relies on signaling the delay > >>> at the very end of the processing in the setup handler, which by > >>> definition occurs after the work to process the control request is > >>> queued (in the generic sense, regardless of whether this involves a > >>> kernel workqueue or passing the work to userspace). There is thus a race > >>> window after queuing the work and before signaling the delay during > >>> which the work handler could signal completion. > > I'm not at all sure what you're talking about here. Do you mean this > code near the end of composite_setup()? > > check_value: > /* respond with data transfer before status phase? */ > if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) { > req->length = value; > req->context = cdev; > req->zero = value < w_length; > value = composite_ep0_queue(cdev, req, GFP_ATOMIC); > > Plainly the code checks for USB_GADGET_DELAYED_STATUS _before_ queuing > req, not after. So where's the race? Please see above. > >> We won't fix this until all functions and UDCs are converted over, but > >> it's doable. > > > > It could be fixed by signaling the delay through an explicit function call > > before queueing the work instead of through a return value though, but I > > agree that long term requesting the status stage explicitly would likely > > be cleaner. > > Yes, I agree that relying on an implicit status stage is not a good > idea for the long term. > > >>> - The mechanism is poorly documented. As Paul mentioned, comments in > >>> the code state that USB_GADGET_DELAYED_STATUS delay the "data/status > >>> stages". This is very unclear, and the only three UDCs that implement > >>> the mechanism seem to do so in different ways: > > We can fix comments and documentation pretty easily. :-) It's harder to fix them if different implementations interpret them in different ways :-) That might not be the case though, as mentioned above I haven't studied the three UDCs that implement this in details, I only had a look at the dwc3. > >>> - The mtu driver states in a comment that it will "handle the delay > >>> STATUS phase till receive ep_queue on ep0". > >>> > >>> - The bdc driver states in a comment that "The ep0 state will remain > >>> WAIT_FOR_DATA_START till we received ep_queue on ep0". > >>> > >>> - The dwc3 driver seems to handle USB_GADGET_DELAYED_STATUS for the > >>> SET_CONFIG request only. > >> > >> that's the only one that has needed it so far. I'm all for making status > >> stage ALWAYS explicit, that will, in the long run, simplify UDC > >> drivers and make the API easier to understand. > >> > >>> - The mechanism relies on queueing a request to the UDC to signal that > >>> it should continue with the status stage. That request can be queued > >>> either by the USB gadget function driver directly, or by the composite > >>> layer in usb_composite_setup_continue() (the latter is restricted to > >>> requests that carry no data as it sets the request length to 0). This is > >>> problematic if we want to delay the status phase after completing the > >>> data phase, in order to validate the setup phase data and the data phase > >>> data (for a control OUT request) together. > >> > >> It shouldn't cause problems, actually. Most of the issues come from the > >> fact that sometimes gadget driver just returns a success and expects UDC > >> to initiate status stage and sometimes gadget driver wants to handle > >> status stage explicitly. > > > > Requesting the status stage explicitly requires an API to do so (quite > > obviously). Your proposal is to use the usb request queue as a signal to > > continue to the next stage. My point is that this can't work for control > > OUT requests, where we may want to delay the status stage after the data > > is received by the UDC, and thus after the request is queued. We need a > > different API for that. > > Why so? Consider the following logic for ep0 in the UDC: > > A SETUP packet is received, for an OUT transfer. > > If setup.wLength > 0 then the next request queued for ep0 is > the data stage, so it is an OUT request. > > Otherwise (i.e., if setup.wLength == 0 or for the second > request queued after the SETUP is received), the next request > is the status stage, so it must be a 0-length IN request. As explained above, yes, I agree that we could use the request queue operation both to queue a request for the data stage, and to request processing the status stage. I still think a separate function would be best to request processing the status stage (at the very least as a helper that would queue the request), but I could be convinced otherwise. > This requires the UDC to specifically keep track of the direction of > the current transfer and whether or not a data-stage transfer has > already been queued. That shouldn't be hard. It's "just" a state machine so it wouldn't be too hard. What we need to agree on is how the state machine operates, and then the API to control it. That's what I tried to describe below in my previous e-mail. > (But it does involve a > race in cases where the host gets tired of waiting and issues another > SETUP packet before the processing of the first transfer is finished.) I wonder how many UDCs handle that race correctly today :-) > The corresponding logic for IN transfers is simpler, since IN transfers > are not allowed to have zero length. The first request following the > SETUP packet is the data stage and the second is the status stage. > > > For control IN, we may want to delay the data stage if we can't respond > > directly, or proceed with the data stage immediately. In both cases this > > can be signaled by a request being queued. There is no need to delay the > > status stage as it's initiated by the host. > > Yes. > > > For control OUT, we may want to delay the data stage if we need to > > validate the setup stage data asynchronously. Proceeding to the data stage > > can be signaled by queueing a request. We may also want to delay the > > status stage if we need to validate the data stage data asynchronously. > > This can't be signaled by queueing a request. > > It can be, if we use the logic outlined above. > > > I wonder if there's really a use case for delaying the data stage of > > control OUT requests, as it seems to me that we can perform the > > asynchronous validation of the setup and data stages together, in which > > case we would always proceed to the data stage, and only potentially > > delay the status stage. However, if we switch to an explicit API where > > the transition from the setup to the data stage is triggered by queueing > > a request, and given that such a transition may need to be delayed for > > the control IN case, delaying the data stage for control OUT would > > essentially come for free. What do you think about this ? Should we allow function drivers to delay the data stage of control OUT requests ? > > In any case we need an API to delay the status stage of a control OUT > > request. There are two options here. We can consider that the status > > stage shouldn't be delayed by default and add a new function to be called > > from the data stage completion handler to request a status stage delay > > (using the return value of the completion handler isn't a good idea as it > > would be racy as explained above). A second function would be needed to > > request the status stage (which, as explained above too, can't be done by > > queueing a request). A second option is to consider that the status stage > > is delayed by default until explcitly required. In both cases the same > > new function is needed to request the status stage. > > > > Note that delaying the data stage and delaying the status stage are two > > different problems, and don't necessarily need to be solved together. > > However, if I understand things correctly, we currently delay the data > > stage of a few control OUT requests (they all have a 0 bytes data stage) > > as a mean to completion of the request. I believe that this use case > > could be implemented by delaying the status stage instead, so the two are > > still related in a way. > > > > If we end up moving to explicit state handling, with the data stage being > > entered by queueing a request, and the status stage being entered by > > calling a new function, control OUT requests with 0 bytes of data that > > can be handled synchronously in the setup handler would require function > > drivers to both queue a zero-length request and call the status function. > > This would make the function code more complex, and I wonder whether a > > shortcut would be a good idea, perhaps in the form of a flag in the > > request that tells the UDC to automatically proceed to the status stage > > immediately after the data stage. Or we could make that behaviour the > > default when the request doesn't have a completion handler (as moving > > explicitly to the status stage should be done at the earliest from the > > data stage completion handler). >From an API point of view, towards function drivers, I really want an explicit function to proceed with the status stage. That could internally queue a ZLP request or call another API, but in any case I don't want the status stage ZLP request to be visible to the function drivers. Do you agree with this ? To simplify function drivers, do you think the above proposal of adding a flag to the (data stage) request to request an automatic transition to the status stage is a good idea ? We could even possibly invert the logic and transition to the status stage when the flag is not set. Essentially this would call the status stage request function right after the data stage request completion handler returns, instead of forcing all function drivers to do so explicitly at the end of the completion handler. > >>> For those reasons I think a new mechanism is needed. It should either > >>> signal the status phase delay through an explicit function call > >>> instead of a return value (to solve the race mentioned above), or by > >>> requiring all requests to be explicitly completed (but that will require > >>> changing all USB function drivers). Furthermore, the mechanism need to > >>> support delaying the status phase after queuing the request for the data > >>> phase, so we need an explicit way to signal that the UDC should proceed > >>> with the status phase, other than queueing the request. > >>> > >>> Thoughts ? Preferences ? > >> > >> how about making status stage always explicit? > > > > If we implement a proof of concept, could you help us converting drivers > > over to the new API ? I'll assume we'll have to address all UDCs first, > > and then the function drivers. > > I'll certainly help for the drivers I'm familiar with. Thank you. -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [4/6] usb: gadget: add functions to signal udc driver to delay status stage From: Laurent Pinchart Message-Id: <3595344.euAgJ7Kpbg@avalon> Date: Fri, 02 Nov 2018 19:10:53 +0200 To: Alan Stern Cc: Felipe Balbi , Paul Elder , Bin Liu , kieran.bingham@ideasonboard.com, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, rogerq@ti.com List-ID: SGkgQWxhbiwKCk9uIEZyaWRheSwgMiBOb3ZlbWJlciAyMDE4IDE4OjE4OjQ1IEVFVCBBbGFuIFN0 ZXJuIHdyb3RlOgo+IE9uIEZyaSwgMiBOb3YgMjAxOCwgTGF1cmVudCBQaW5jaGFydCB3cm90ZToK PiA+IE9uIEZyaWRheSwgMiBOb3ZlbWJlciAyMDE4IDE1OjE3OjIwIEVFVCBGZWxpcGUgQmFsYmkg d3JvdGU6Cj4gPj4gTGF1cmVudCBQaW5jaGFydCB3cml0ZXM6Cj4gPj4+Pj4+PiArdm9pZCB1c2Jf ZXBfZGVsYXlfc3RhdHVzKHN0cnVjdCB1c2JfZXAgKmVwKQo+ID4+Pj4+Pj4gCj4gPj4+Pj4+PiAr ewo+ID4+Pj4+Pj4gKwllcC0+ZGVsYXllZF9zdGF0dXMgPSB0cnVlOwo+ID4+Pj4+Pj4gK30KPiA+ Pj4+Pj4+ICtFWFBPUlRfU1lNQk9MX0dQTCh1c2JfZXBfZGVsYXlfc3RhdHVzKTsKPiA+Pj4+Pj4g Cj4gPj4+Pj4+IElzIHVzYl9lcF9zZXRfZGVsYXlfc3RhdHVzKCkgYmV0dGVyPyBJIHRob3VnaHQg aXQgaW1wbGllcwo+ID4+Pj4+PiBnZXQvcmV0dXJuIGFjdGlvbiBpZiBhIHZlcmIgaXMgbWlzc2lu ZyBpbiB0aGUgZnVuY3Rpb24gbmFtZS4KPiA+Pj4+PiAKPiA+Pj4+PiBGb3Igd2hhdCBpdCdzIHdv cnRoLCBJIHVuZGVyc3RhbmQgdGhlIGZ1bmN0aW9uIG5hbWUgYXMgImRlbGF5IHRoZQo+ID4+Pj4+ IHN0YXR1cyBzdGFnZSIsIHdpdGggImRlbGF5IiBiZWluZyBhIHZlcmIuIE1heWJlIHRoZSBzaG9y dAo+ID4+Pj4+IGRlc2NyaXB0aW9uIGNvdWxkIGJlIHVwZGF0ZWQgYWNjb3JkaW5nbHkuCj4gPj4+ Pj4gCj4gPj4+Pj4gSXMgdGhlcmUgYSByZWFzb24gZm9yIGFkZGluZyBhIG5ldyBmdW5jdGlvbiBm b3IgdGhpcz8gIFRoaXMgaXMKPiA+Pj4+PiBleGFjdGx5IHdoYXQgdGhlIFVTQl9HQURHRVRfREVM QVlFRF9TVEFUVVMgcmV0dXJuIHZhbHVlIGZyb20gdGhlIHNldHVwCj4gPj4+Pj4gY2FsbGJhY2sg aXMgbWVhbnQgZm9yIChhbmQgaXQgaXMgYWxyZWFkeSB1c2VkIGJ5IHNvbWUgZ2FkZ2V0IGRyaXZl cnMpLgo+ID4+Pj4gCj4gPj4+PiBJbiB0aGVvcnksIHdlIG1pZ2h0IGJlIGFibGUgdG8gdXNlIFVT Ql9HQURHRVRfREVMQVlFRF9TVEFUVVMgZm9yCj4gPj4+PiB0aGlzLiBIb3dldmVyLCB0aGVyZSBh cmUgYSBmZXcgYW1iaWd1aXRpZXMgdGhhdCBwcmV2ZW50IHVzIGZyb20gZG9pbmcKPiA+Pj4+IHNv Lgo+ID4+Pj4gCj4gPj4+PiBGaXJzdCBvZiBhbGwsIHdlIHdhbnQgdG8gZGVsYXkgb25seSB0aGUg c3RhdHVzIHN0YWdlIGZvciBjb250cm9sIE9VVAo+ID4+Pj4gcmVxdWVzdHM7IGFjY29yZGluZyB0 byBjb21wb3NpdGUuaCwgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBpcyBmb3IKPiA+Pj4+IGRl bGF5aW5nIHRoZSAiZGF0YS9zdGF0dXMgc3RhZ2VzIi4gRG9lcyB0aGlzIG1lYW4gdGhhdCBpdCBk ZWxheXMgdGhlCj4gPj4+PiBzdGF0dXMgc3RhZ2Ugb25seSBvciBkb2VzIGl0IGRlbGF5IGJvdGgg c3RhZ2VzPyBJZiB0aGUgc2xhc2ggbWVhbnMKPiA+Pj4+ICJhbmQiLCB0aGVuIHdlIGNhbm5vdCB1 c2UgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUy4KPiAKPiBUaGUgY29tbWVudCBpbiBjb21wb3Np dGUuaCBpcyB3cm9uZzsgaXQgc2hvdWxkIHJlZmVyIG9ubHkgdG8gdGhlIHN0YXR1cwo+IHN0YWdl LiAgSW4gZmFjdCwgaXQgc2hvdWxkIHJlZmVyIG9ubHkgdG8gdGhlIHN0YXR1cyBzdGFnZSBmb3IK PiBjb250cm9sLU9VVCB0cmFuc2ZlcnM7IHRoZXJlJ3Mgbm8gcmVhc29uIGV2ZXIgdG8gZGVsYXkg dGhlIHN0YXR1cyBzdGFnZQo+IG9mIGEgY29udHJvbC1JTiB0cmFuc2ZlciAodGhlIGRyaXZlciBz aG91bGQgaW5zdGVhZCBkZWxheSB0aGUgZGF0YQo+IHN0YWdlIGlmIGl0IG5lZWRzIHRvKS4KCkFn cmVlZC4KCj4gPj4+PiBGdXJ0aGVybW9yZSwgd2UgaGF2ZSBmb3VuZCB0aGF0IFVTQl9HQURHRVRf REVMQVlFRF9TVEFUVVMgaXMgcmFjZXksCj4gPj4+PiB3aGljaCBoYXMgYWxyZWFkeSBiZWVuIG9i c2VydmVkIGluIHRoZSBVVkMgZ2FkZ2V0IGRyaXZlciBwcmV2aW91c2x5Cj4gPj4+PiBbMF0uIFRo ZSByYWNlaW5lc3Mgc3RlbXMgZnJvbSB0aGUgZmFjdCB0aGF0IHRoaW5ncyBjYW4gaGFwcGVuIGlu Cj4gPj4+PiBiZXR3ZWVuIHJldHVybmluZyBVU0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIGFuZCB0 aGUgY29tcG9zaXRlIGxheWVyCj4gPj4+PiByZWFjdGluZyB0byBpdCAtIGVzcGVjaWFsbHkgaWYg dXNiX2NvbXBvc2l0ZV9zZXR1cF9jb250aW51ZSBpcyBjYWxsZWQKPiA+Pj4+IHdpdGhpbiB0aGF0 IHdpbmRvdyBpdCBjYXVzZXMgYSBXQVJOLiBJbiBhbnkgY2FzZSwgdGhlIGZhY3QgdGhhdCB0aGUK PiA+Pj4+IG1lY2hhbmlzbSBpdHNlbGYgaXMgcmFjZXkgc3VnZ2VzdHMgdGhhdCBpdCBuZWVkcyBp bXByb3ZlbWVudCwgYW5kIHVzaW5nCj4gPj4+PiBpdCB3b3VsZG4ndCBiZSBhIGdvb2Qgc29sdXRp b24gaW4gdGhpcyBjYXNlLgo+IAo+IEkgZG9uJ3QgdW5kZXJzdGFuZCB0aGlzIGF0IGFsbC4gIFRo ZSBjb21wb3NpdGUgbGF5ZXIgcmVhY3RzIHRvCj4gVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBh cyBzb29uIGFzIGl0IHJlY2VpdmVzIHRoZSByZXR1cm4gdmFsdWUuICBDYW4KPiBQYXVsIG9yIExh dXJlbnQgZ2l2ZSBhIG1vcmUgZXhwbGljaXQgZXhhbXBsZSBvZiB0aGlzIHJhY2U/CgpUaGUgY29t cG9zaXRlIGxheWVyIG9ubHkgaGFuZGxlcyBVU0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIGZvciAK VVNCX1JFUV9TRVRfQ09ORklHVVJBVElPTiAoaW4gc2V0X2NvbmZpZygpKSBhbmQgZm9yIFVTQl9S RVFfU0VUX0lOVEVSRkFDRSAoaW4gCmNvbXBvc2l0ZV9zZXR1cCgpKS4gSXQgaW5jcmVtZW50cyBj ZGV2LT5kZWxheWVkX3N0YXR1cyBpbW1lZGlhdGVseS4gVGhlbiwgaW4gCnVzYl9jb21wb3NpdGVf c2V0dXBfY29udGludWUoKSwgaWYgY2Rldi0+ZGVsYXllZF9zdGF0dXMgaXMgbm90IHplcm8sIGl0 IHF1ZXVlcyAKYSBaTFAsIGFuZCB3YXJucyBvdGhlcndpc2UuCgpUaGlzIG1lY2hhbmlzbSBkZWxh eXMgdGhlIGRhdGEgc3RhZ2UsIG5vdCB0aGUgc3RhdHVzIHN0YWdlIChvciwgdG8gYmUgcHJlY2lz ZSwgCml0IGRlbGF5cyB0aGUgc3RhdHVzIHN0YWdlIGluc29mYXIgYXMgdGhlIHN0YXR1cyBzdGFn ZSBjb21lcyBhZnRlciB0aGUgZGF0YSAKc3RhZ2UpLCBhbmQgb25seSBzdXBwb3J0cyBjb250cm9s IE9VVCByZXF1ZXN0cyB3aXRoIDAgYnl0ZXMgb2YgZGF0YSAod2hpY2ggaXMgCnRoZSBjYXNlIG9m IGJvdGggVVNCX1JFUV9TRVRfSU5URVJGQUNFIGFuZCBVU0JfUkVRX1NFVF9DT05GSUdVUkFUSU9O KS4gRm9yIGFsbCAKb3RoZXIgcmVxdWVzdHMsIHRoZSBjb21wb3NpdGUgbGF5ZXIgcGFzc2VzIFVT Ql9HQURHRVRfREVMQVlFRF9TVEFUVVMgdG8gdGhlIApVREMuCgpUaGUgdGhyZWUgVURDcyB0aGF0 IGltcGxlbWVudCBVU0JfR0FER0VUX0RFTEFZRURfU1RBVFVTIHN1cHBvcnQgc2V0IGEgCmRlbGF5 ZWRfc3RhdHVzIGZsYWcgaW4gYW4gaW50ZXJuYWwgc3RydWN0dXJlLiBJIGhhdmVuJ3QgaW5zcGVj dGVkIGluIGRldGFpbHMgCndoYXQgdGhleSBkbyBuZXh0IGFzIEknbSBub3QgZmFtaWxpYXIgd2l0 aCBhbGwgb2YgdGhlbSwgYnV0IHRoZSBkd2MzIGRyaXZlciAKanVzdCBza2lwcyB0aGUgaGFuZGxp bmcgb2YgdGhlIHN0YXR1cyBwaGFzZSBpbiBkd2MzX2VwMF94ZmVybm90cmVhZHkoKSBhbmQgCmRl bGF5cyBpdCB0byBfX2R3YzNfZ2FkZ2V0X2VwMF9xdWV1ZSgpLiBUaGlzIG9ubHkgd29ya3MgZm9y IDAtbGVuZ3RoIHJlcXVlc3RzLCAKd2l0aCBubyBkYXRhIHBoYXNlLgoKRXZlbiB3aGVuIGxpbWl0 ZWQgdG8gMC1sZW5ndGggY29udHJvbCBPVVQgcmVxdWVzdHMsIHRoaXMgbWVjaGFuaXNtIGlzIHJh Y3kuIApUaGUgc2V0dXAgaGFuZGxlciwgd2hlbiBpdCB3YW50cyB0byBkZWxheSB0aGUgc3RhdHVz IHBoYXNlLCB3aWxsIHF1ZXVlIAphc3luY2hyb25vdXMgd29yayB0aGF0IHdpbGwsIHdoZW4gaXQg Y29tcGxldGVzLCBjYWxsIAp1c2JfY29tcG9zaXRlX3NldHVwX2NvbnRpbnVlKCkgdG8gcHJvY2Vl ZCB3aXRoIHRoZSBzdGF0dXMgcGhhc2UuIFF1ZXVpbmcgdGhlIAp3b3JrIGhhcyB0byBiZSBkb25l IGJlZm9yZSB0aGUgc2V0dXAgaGFuZGxlciByZXR1cm5zLCBhbmQgdGhlIGNkZXYtCj5kZWxheWVk X3N0YXR1cyBpcyBvbmx5IGluY3JlbWVudGVkIGFmdGVyIHRoZSBzZXR1cCBoYW5kbGVyIHJldHVy bnMsIGluIApjb21wb3NpdGVfc2V0dXAoKS4gVGhlcmUgaXMgdGh1cyBhIHRpbWUgd2luZG93IGR1 cmluZyB3aGljaCB0aGUgYXN5bmNocm9ub3VzIAp3b3JrIGNhbiBjYWxsIHVzYl9jb21wb3NpdGVf c2V0dXBfY29udGludWUoKSBiZWZvcmUgY2Rldi0+ZGVsYXllZF9zdGF0dXMgaGFzIApiZWVuIGlu Y3JlbWVudGVkLiBXZSBoYXZlIG1hbmFnZWQgdG8gaGl0IHRoaXMgaW4gcHJhY3RpY2UsIHdpdGgg YSBzdXJwcmlzaW5nbHkgCmhpZ2ggcmF0ZSBzZWVpbmcgaG93IHNtYWxsIHRoZSB3aW5kb3cgaXMu CgpOb3cgdGhhdCBJJ3ZlIHdyaXR0ZW4gYWxsIHRoaXMsIEkgcmVhbGl6ZSB0aGF0IGNkZXYtPmRl bGF5ZWRfc3RhdHVzIGlzIGd1YXJkZWQgCmJ5IGNkZXYtPmxvY2suIEkgdGh1cyB3b25kZXIgd2hl dGhlciBvdXIgYW5hbHlzaXMgd2FzIGNvcnJlY3QsIG9yIGlmIHdlIHdlcmUgCmhpdHRpbmcgYSBk aWZmZXJlbnQgYnVnIDotUyBQYXVsLCBjb3VsZCB5b3UgdGVzdCB0aGlzIGFnYWluID8gUGxlYXNl IG5vdGUsIApob3dldmVyLCB0aGF0IHRoZSByYWNlIGRlc2NyaWJlZCBoZXJlIGlzIG5vdCByZWxh dGVkIHRvIHRoaXMgcGF0Y2ggc2VyaWVzLCAKZXhjZXB0IGluIGhvdyBpdCBpbmZsdWVuY2VzIHRo ZSBBUEkgZGVzaWduIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9ucy4KCj4gQXNzdW1pbmcgeW91IGFy ZSBjb3JyZWN0LCB3b3VsZG4ndCBpdCBtYWtlIHNlbnNlIHRvIGZpeCBvciBlbGltaW5hdGUKPiB0 aGUgcmFjZSBieSBjaGFuZ2luZyBjb21wb3NpdGUuYz8KCkkgd2FzIGFib3V0IHRvIHdyaXRlIHRo YXQgd2Ugd291bGQgbmVlZCB0byBsb2NrIGFjY2VzcyB0byBjZGV2LQo+ZGVsYXllZF9zdGF0dXMs IGFuZCBmb3VuZCBvdXQgdGhhdCB3ZSBhbHJlYWR5IHVzZSBjZGV2LT5sb2NrIHRvIGRvIHNvLiBN b3JlIAppbnZlc3RpZ2F0aW9ucyBhcmUgbmVlZGVkLgoKUGxlYXNlIG5vdGUsIGhvd2V2ZXIsIHRo YXQgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBpcyBsaW1pdGVkIHRvIDAtbGVuZ3RoIApjb250 cm9sIE9VVCByZXF1ZXN0cywgc28gdGhlIHByb2JsZW0gdGhhdCBsZWQgdG8gdGhpcyBwYXRjaCBz ZXJpZXMgc3RpbGwgCmV4aXN0cywgZXZlbiBpZiB0aGUgcmFjZSBjb25kaXRpb24gSSB0aG91Z2h0 IHdhcyB0aGVyZSBkb2Vzbid0IGV4aXN0LgoKPiA+Pj4+PiBJcyBpdCBhIHF1ZXN0aW9uIG9mIHdo ZW4gdGhlIGdhZGdldCBkcml2ZXIgbGVhcm5zIHRoYXQgaXQgd2lsbCBuZWVkCj4gPj4+Pj4gdG8g ZGVsYXkgdGhlIHN0YXR1cyBzdGFnZT8gIElmIHRoYXQncyB0aGUgY2FzZSwKPiA+Pj4+IAo+ID4+ Pj4gTm90IHJlYWxseS4KPiA+Pj4+IAo+ID4+Pj4+IHdoeSBub3QgYWx3YXlzIHJldHVybgo+ID4+ Pj4+IFVTQl9HQURHRVRfREVMQVlFRF9TVEFUVVMgZnJvbSB0aGUgc2V0dXAgY2FsbGJhY2s/ICBU aGVuIGluc3RlYWQgb2YKPiA+Pj4+IGNhbGxpbmcgdXNiX2VwX2RlbGF5X3N0YXR1cygpIHdoZW4g YSBkZWxheSBpcyBuZWVkZWQsIHlvdSBjb3VsZAo+ID4+Pj4+IHF1ZXVlIHRoZSBzdGF0dXMgcmVx dWVzdCB3aGVuIGEgZGVsYXkgaXNuJ3QgbmVlZGVkLgo+ID4+Pj4gCj4gPj4+PiBUaGVvcmV0aWNh bGx5IHRoaXMgbWlnaHQgd29yaywgYnV0IHNlZSB0aGUgcHJvYmxlbXMgbWVudGlvbmVkIGFib3Zl Lgo+ID4+Pj4gCj4gPj4+Pj4gQXMgYSBtb3JlIGdlbmVyYWwgc29sdXRpb24sIEZlbGlwZSBoYXMg c2FpZCB0aGF0IGEgVURDIGRyaXZlciBzaG91bGQKPiA+Pj4+PiBfbmV2ZXJfIGNhcnJ5IG91dCB0 aGUgc3RhdHVzIHN0YWdlIHRyYW5zYWN0aW9uIHVudGlsIHRoZSBnYWRnZXQKPiA+Pj4+PiBkcml2 ZXIgaGFzIHRvbGQgaXQgdG8gZG8gc28uICBUaGVuIHRoZXJlIHdvdWxkIGJlIG5vIG5lZWQgZm9y IGFueSBzb3J0Cj4gPj4+Pj4gb2YgZGVsYXkgaW5kaWNhdG9yLgo+ID4+Pj4gCj4gPj4+PiBZZWFo LCBidXQsCj4gPj4+PiAKPiA+Pj4+PiAoQnV0IGltcGxlbWVudGluZyB0aGlzIHdvdWxkIHJlcXVp cmUgc2lnbmlmaWNhbnQKPiA+Pj4+PiBjaGFuZ2VzIHRvIGEgYnVuY2ggb2YgZGlmZmVyZW50IGRy aXZlcnMuLi4pCj4gPj4+PiAKPiA+Pj4+IGV4YWN0bHkgOi8KPiA+PiAKPiA+PiBhZGQgYSBmbGFn IHRvIGdhZGdldCBzdHJ1Y3R1cmUuIFNvbWV0aGluZyBsaWtlCj4gPj4gInN1cHBvcnRzX2V4cGxp Y2l0X3N0YXR1c19zdGFnZSIgYW5kIGFkZCBhIG5ldyByZXR1cm4gdmFsdWUKPiA+PiBVU0JfRVhQ TElDSVRfU1RBVFVTX1NUQUdFLgo+ID4+IAo+ID4+IFRoZW4sIHRha2UgdXZjIGZvciBleGFtcGxl LCBpbXBsZW1lbnQgdGhlIG5ldyBzZXR1cDoKPiA+PiAKPiA+PiBpZiAoc3VwcG9ydHNfZXhwbGlj aXRfc3RhdHVzX3N0YWdlKQo+ID4+IAo+ID4+IAlyZXR1cm4gVVNCX0VYUExJQ0lUX1NUQVRVU19T VEFHRTsKPiA+PiAKPiA+PiB0aGVuIG9uIGR3YzMgeW91IHdvdWxkOgo+ID4+IAo+ID4+IHN3aXRj aCAocmV0KSB7Cj4gPj4gY2FzZSBVU0JfRVhQTElDSVRfU1RBVFVTX1NUQUdFOgo+ID4+IAo+ID4+ IGNhc2UgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUzoKPiA+PiAJd2FpdF9mb3Jfc3RhdHVzX3Jl cXVlc3RfcXVldWUoKTsKPiA+PiAJCj4gPj4gICAgICAgICBicmVhazsKPiA+PiAKPiA+PiBkZWZh dWx0Ogo+ID4+IAlzdGFydF9zdGF0dXNfc3RhZ2UoKTsKPiA+PiAKPiA+PiB9Cj4gPj4gCj4gPj4g SWYgdGhpcyB3b3JrcyB3aXRoIGR3YzMgKyB1dmMsIHRoZW4gd2UgaGF2ZSBhIGdvb2QgcmVjaXBl IG9uIGhvdyB0bwo+ID4+IGltcGxlbWVudCBmb3IgdGhlIG90aGVyIGRyaXZlcnMuCj4gPiAKPiA+ IEdpdmVuIHRoYXQgd2UgbmVlZCB0byBkZWxheSB0aGUgc3RhdHVzIHN0YWdlIGFuZCBub3QgdGhl IGRhdGEgc3RhZ2UsIHdlCj4gPiBjYW4ndCBleHBsaWNpdGx5IHJlcXVlc3QgdGhlIHN0YXR1cyBz dGFnZSB0aHJvdWdoIGEgdXNiIHJlcXVlc3QgcXVldWUuCj4gCj4gV2h5IG5vdD8gIFRoZSBzdGF0 dXMgc3RhZ2UgZm9yIGEgY29udHJvbC1PVVQgdHJhbnNmZXIgaXMgc2ltcGx5IGEKPiB6ZXJvLWxl bmd0aCBJTiB0cmFuc2FjdGlvbi4gIEl0J3MgZWFzeSB0byBxdWV1ZSBhIHJlcXVlc3QgZm9yIHN1 Y2ggYQo+IHRyYW5zYWN0aW9uLiAgSXMgdGhlIGlzc3VlIHRoYXQgdGhlcmUncyBubyB3YXkgdG8g c3BlY2lmeSB0aGUgZGlyZWN0aW9uCj4gb2YgdGhlIHJlcXVlc3QgKGhlbmNlIG5vIGRpcmVjdCB3 YXkgdG8gdGVsbCB3aGV0aGVyIGEgemVyby1sZW5ndGgKPiByZXF1ZXN0IGlzIGZvciB0aGUgZGF0 YSBzdGFnZSBvciB0aGUgc3RhdHVzIHN0YWdlKT8KCk9LLCBJIHN1cHBvc2Ugd2UgY291bGQgcXVl dWUgYSByZXF1ZXN0IGZvciB0aGlzLCBpbiB3aGljaCBjYXNlIHdlIHdvdWxkIGhhdmUgCnRvIHF1 ZXVlIHR3byByZXF1ZXN0cyBmb3IgY29udHJvbCBPVVQgdHJhbnNmZXJzIChvbmUgZm9yIHRoZSBk YXRhIHN0YWdlIGFuZCAKb25lIGZvciB0aGUgc3RhdHVzIHN0YWdlKS4gSSdtIGhvd2V2ZXIgbm90 IGNvbnZpbmNlZCB0aGF0IHdvdWxkIGJlIHRoZSBiZXN0IApBUEkgdG8gaGFuZGxlIHRoZSBzdGF0 dXMgc3RhZ2UsIGFzIHRoZSBmdW5jdGlvbiBkcml2ZXIgd291bGQgbmVlZCB0byBxdWV1ZSBhIApy ZXF1ZXN0IGFuZCB0aGUgVURDIHdvdWxkIHRoZW4gbmVlZCB0byBjaGVjayB3aGV0aGVyIHRoYXQg cmVxdWVzdCBjb3JyZXNwb25kcyAKdG8gYSBzdGF0dXMgc3RhZ2UgYW5kIHByb2Nlc3MgaXQgYWNj b3JkaW5nbHkuIEEgbmV3IG9wZXJhdGlvbiBzcGVjaWZpYyB0byB0aGlzIAp3b3VsZCBiZSBlYXNp ZXIgZm9yIGJvdGggdGhlIGZ1bmN0aW9uIGRyaXZlciBhbmQgdGhlIFVEQyBpbiBteSBvcGluaW9u LiAKVGhlcmUncyBhbHNvIHRoZSBmYWN0IHRoYXQgcmVxdWVzdHMgY2FuIHNwZWNpZnkgYSBjb21w bGV0aW9uIGhhbmRsZXIsIGJ1dCBvbmx5IAp0aGUgZGF0YSBzdGFnZSByZXF1ZXN0IHdvdWxkIHNl ZSBpdHMgY29tcGxldGlvbiBoYW5kbGVyIGNhbGxlZCAodW5sZXNzIHdlIApyZXF1aXJlIFVEQ3Mg dG8gY2FsbCBjb21wbGV0aW9uIHJlcXVlc3RzIGF0IHRoZSBjb21wbGV0aW9uIG9mIHRoZSBzdGF0 dXMgCnN0YWdlLCBidXQgSSdtIG5vdCBzdXJlIHRoYXQgYWxsIFVEQ3MgY2FuIHJlcG9ydCB0aGUg ZXZlbnQgdG8gdGhlIGRyaXZlciwgYW5kIAp0aGF0IHdvdWxkIGxpa2VseSBiZSB1c2VsZXNzIGFz IG5vYm9keSBuZWVkcyB0aGF0IGZlYXR1cmUpLgoKPiBBZG1pdHRlZGx5LCBpdCBtaWdodCBiZSBu aWNlIHRvIHByb3ZpZGUgYSBsaWJyYXJ5IHJvdXRpbmUgaW4gdGhlIFVEQwo+IGNvcmUgdG8gcXVl dWUgc3VjaCByZXF1ZXN0cywgc2luY2UgaXQgaW52b2x2ZXMgYSBidW5jaCBvZiB1bmludGVyZXN0 aW5nCj4gYm9pbGVycGxhdGUgb3BlcmF0aW9ucy4KPiAKPiA+IFdvdWxkIGEgbmV3IGV4cGxpY2l0 IGZ1bmN0aW9uIGNhbGwgd29yayBmb3IgeW91IGZvciB0aGF0IHB1cnBvc2UgPwo+IAo+IEl0IHdv dWxkIGJlIG9rYXksIGJ1dCBJIHF1ZXN0aW9uIHdoZXRoZXIgb25lIGlzIHJlYWxseSBuZWVkZWQu CgpJIHRoaW5rIHRoZSBBUEkgd291bGQgYmUgY2xlYW5lciwgYnV0IGl0IG1pZ2h0IGp1c3QgYmUg YSBtYXR0ZXIgb2YgdGFzdGUuCgo+ID4+PiBBbGFuLCBGZWxpcGUsIGhvdyBkbyB3ZSBtb3ZlIGZv cndhcmQgd2l0aCB0aGlzID8gVGhlcmUgYXJlIHNldmVyYWwKPiA+Pj4gaXNzdWVzIHdpdGggdGhl IGV4aXN0aW5nIGNvbnRyb2wgcmVxdWVzdCBoYW5kbGluZyBtZWNoYW5pc20gaW4gdGhlIFVTQgo+ ID4+PiBnYWRnZXQgc3RhY2ssIGFuZCB3aGlsZSBQYXVsIGNvdWxkIHdvcmsgb24gaW1wcm92aW5n IHRoZSBtZWNoYW5pc20sIHdlCj4gPj4+IG5lZWQgdG8gcHJvdmlkZSBjbGVhciBndWlkYW5jZSBy ZWdhcmRpbmcgdGhlIGRpcmVjdGlvbiB3ZSB3YW50IHRvCj4gPj4+IHRha2UuCj4gPj4+IAo+ID4+ PiBGb3IgcmVmZXJlbmNlLCB0aGUgaXNzdWVzIEkga25vdyBhYm91dCBmb3IgdGhlIFVTQl9HQURH RVRfREVMQVlFRF9TVEFUVVMKPiA+Pj4gbWVjaGFuaXNtIGFyZQo+ID4+PiAKPiA+Pj4gLSBUaGUg bWVjaGFuaXNtIGlzIGluaGVyZW50bHkgcmFjeS4gSXQgcmVsaWVzIG9uIHNpZ25hbGluZyB0aGUg ZGVsYXkKPiA+Pj4gYXQgdGhlIHZlcnkgZW5kIG9mIHRoZSBwcm9jZXNzaW5nIGluIHRoZSBzZXR1 cCBoYW5kbGVyLCB3aGljaCBieQo+ID4+PiBkZWZpbml0aW9uIG9jY3VycyBhZnRlciB0aGUgd29y ayB0byBwcm9jZXNzIHRoZSBjb250cm9sIHJlcXVlc3QgaXMKPiA+Pj4gcXVldWVkIChpbiB0aGUg Z2VuZXJpYyBzZW5zZSwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHRoaXMgaW52b2x2ZXMgYQo+ID4+ PiBrZXJuZWwgd29ya3F1ZXVlIG9yIHBhc3NpbmcgdGhlIHdvcmsgdG8gdXNlcnNwYWNlKS4gVGhl cmUgaXMgdGh1cyBhIHJhY2UKPiA+Pj4gd2luZG93IGFmdGVyIHF1ZXVpbmcgdGhlIHdvcmsgYW5k IGJlZm9yZSBzaWduYWxpbmcgdGhlIGRlbGF5IGR1cmluZwo+ID4+PiB3aGljaCB0aGUgd29yayBo YW5kbGVyIGNvdWxkIHNpZ25hbCBjb21wbGV0aW9uLgo+IAo+IEknbSBub3QgYXQgYWxsIHN1cmUg d2hhdCB5b3UncmUgdGFsa2luZyBhYm91dCBoZXJlLiAgRG8geW91IG1lYW4gdGhpcwo+IGNvZGUg bmVhciB0aGUgZW5kIG9mIGNvbXBvc2l0ZV9zZXR1cCgpPwo+IAo+IGNoZWNrX3ZhbHVlOgo+IAkv KiByZXNwb25kIHdpdGggZGF0YSB0cmFuc2ZlciBiZWZvcmUgc3RhdHVzIHBoYXNlPyAqLwo+IAlp ZiAodmFsdWUgPj0gMCAmJiB2YWx1ZSAhPSBVU0JfR0FER0VUX0RFTEFZRURfU1RBVFVTKSB7Cj4g CQlyZXEtPmxlbmd0aCA9IHZhbHVlOwo+IAkJcmVxLT5jb250ZXh0ID0gY2RldjsKPiAJCXJlcS0+ emVybyA9IHZhbHVlIDwgd19sZW5ndGg7Cj4gCQl2YWx1ZSA9IGNvbXBvc2l0ZV9lcDBfcXVldWUo Y2RldiwgcmVxLCBHRlBfQVRPTUlDKTsKPiAKPiBQbGFpbmx5IHRoZSBjb2RlIGNoZWNrcyBmb3Ig VVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBfYmVmb3JlXyBxdWV1aW5nCj4gcmVxLCBub3QgYWZ0 ZXIuICBTbyB3aGVyZSdzIHRoZSByYWNlPwoKUGxlYXNlIHNlZSBhYm92ZS4KCj4gPj4gV2Ugd29u J3QgZml4IHRoaXMgdW50aWwgYWxsIGZ1bmN0aW9ucyBhbmQgVURDcyBhcmUgY29udmVydGVkIG92 ZXIsIGJ1dAo+ID4+IGl0J3MgZG9hYmxlLgo+ID4gCj4gPiBJdCBjb3VsZCBiZSBmaXhlZCBieSBz aWduYWxpbmcgdGhlIGRlbGF5IHRocm91Z2ggYW4gZXhwbGljaXQgZnVuY3Rpb24gY2FsbAo+ID4g YmVmb3JlIHF1ZXVlaW5nIHRoZSB3b3JrIGluc3RlYWQgb2YgdGhyb3VnaCBhIHJldHVybiB2YWx1 ZSB0aG91Z2gsIGJ1dCBJCj4gPiBhZ3JlZSB0aGF0IGxvbmcgdGVybSByZXF1ZXN0aW5nIHRoZSBz dGF0dXMgc3RhZ2UgZXhwbGljaXRseSB3b3VsZCBsaWtlbHkKPiA+IGJlIGNsZWFuZXIuCj4gCj4g WWVzLCBJIGFncmVlIHRoYXQgcmVseWluZyBvbiBhbiBpbXBsaWNpdCBzdGF0dXMgc3RhZ2UgaXMg bm90IGEgZ29vZAo+IGlkZWEgZm9yIHRoZSBsb25nIHRlcm0uCj4gCj4gPj4+IC0gVGhlIG1lY2hh bmlzbSBpcyBwb29ybHkgZG9jdW1lbnRlZC4gQXMgUGF1bCBtZW50aW9uZWQsIGNvbW1lbnRzIGlu Cj4gPj4+IHRoZSBjb2RlIHN0YXRlIHRoYXQgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUyBkZWxh eSB0aGUgImRhdGEvc3RhdHVzCj4gPj4+IHN0YWdlcyIuIFRoaXMgaXMgdmVyeSB1bmNsZWFyLCBh bmQgdGhlIG9ubHkgdGhyZWUgVURDcyB0aGF0IGltcGxlbWVudAo+ID4+PiB0aGUgbWVjaGFuaXNt IHNlZW0gdG8gZG8gc28gaW4gZGlmZmVyZW50IHdheXM6Cj4gCj4gV2UgY2FuIGZpeCBjb21tZW50 cyBhbmQgZG9jdW1lbnRhdGlvbiBwcmV0dHkgZWFzaWx5LiAgOi0pCgpJdCdzIGhhcmRlciB0byBm aXggdGhlbSBpZiBkaWZmZXJlbnQgaW1wbGVtZW50YXRpb25zIGludGVycHJldCB0aGVtIGluIApk aWZmZXJlbnQgd2F5cyA6LSkgVGhhdCBtaWdodCBub3QgYmUgdGhlIGNhc2UgdGhvdWdoLCBhcyBt ZW50aW9uZWQgYWJvdmUgSSAKaGF2ZW4ndCBzdHVkaWVkIHRoZSB0aHJlZSBVRENzIHRoYXQgaW1w bGVtZW50IHRoaXMgaW4gZGV0YWlscywgSSBvbmx5IGhhZCBhIApsb29rIGF0IHRoZSBkd2MzLgoK PiA+Pj4gICAtIFRoZSBtdHUgZHJpdmVyIHN0YXRlcyBpbiBhIGNvbW1lbnQgdGhhdCBpdCB3aWxs ICJoYW5kbGUgdGhlIGRlbGF5Cj4gPj4+ICAgU1RBVFVTIHBoYXNlIHRpbGwgcmVjZWl2ZSBlcF9x dWV1ZSBvbiBlcDAiLgo+ID4+PiAgIAo+ID4+PiAgIC0gVGhlIGJkYyBkcml2ZXIgc3RhdGVzIGlu IGEgY29tbWVudCB0aGF0ICJUaGUgZXAwIHN0YXRlIHdpbGwgcmVtYWluCj4gPj4+ICAgV0FJVF9G T1JfREFUQV9TVEFSVCB0aWxsIHdlIHJlY2VpdmVkIGVwX3F1ZXVlIG9uIGVwMCIuCj4gPj4+ICAg Cj4gPj4+ICAgLSBUaGUgZHdjMyBkcml2ZXIgc2VlbXMgdG8gaGFuZGxlIFVTQl9HQURHRVRfREVM QVlFRF9TVEFUVVMgZm9yIHRoZQo+ID4+PiAgIFNFVF9DT05GSUcgcmVxdWVzdCBvbmx5Lgo+ID4+ IAo+ID4+IHRoYXQncyB0aGUgb25seSBvbmUgdGhhdCBoYXMgbmVlZGVkIGl0IHNvIGZhci4gSSdt IGFsbCBmb3IgbWFraW5nIHN0YXR1cwo+ID4+IHN0YWdlIEFMV0FZUyBleHBsaWNpdCwgdGhhdCB3 aWxsLCBpbiB0aGUgbG9uZyBydW4sIHNpbXBsaWZ5IFVEQwo+ID4+IGRyaXZlcnMgYW5kIG1ha2Ug dGhlIEFQSSBlYXNpZXIgdG8gdW5kZXJzdGFuZC4KPiA+PiAKPiA+Pj4gLSBUaGUgbWVjaGFuaXNt IHJlbGllcyBvbiBxdWV1ZWluZyBhIHJlcXVlc3QgdG8gdGhlIFVEQyB0byBzaWduYWwgdGhhdAo+ ID4+PiBpdCBzaG91bGQgY29udGludWUgd2l0aCB0aGUgc3RhdHVzIHN0YWdlLiBUaGF0IHJlcXVl c3QgY2FuIGJlIHF1ZXVlZAo+ID4+PiBlaXRoZXIgYnkgdGhlIFVTQiBnYWRnZXQgZnVuY3Rpb24g ZHJpdmVyIGRpcmVjdGx5LCBvciBieSB0aGUgY29tcG9zaXRlCj4gPj4+IGxheWVyIGluIHVzYl9j b21wb3NpdGVfc2V0dXBfY29udGludWUoKSAodGhlIGxhdHRlciBpcyByZXN0cmljdGVkIHRvCj4g Pj4+IHJlcXVlc3RzIHRoYXQgY2Fycnkgbm8gZGF0YSBhcyBpdCBzZXRzIHRoZSByZXF1ZXN0IGxl bmd0aCB0byAwKS4gVGhpcyBpcwo+ID4+PiBwcm9ibGVtYXRpYyBpZiB3ZSB3YW50IHRvIGRlbGF5 IHRoZSBzdGF0dXMgcGhhc2UgYWZ0ZXIgY29tcGxldGluZyB0aGUKPiA+Pj4gZGF0YSBwaGFzZSwg aW4gb3JkZXIgdG8gdmFsaWRhdGUgdGhlIHNldHVwIHBoYXNlIGRhdGEgYW5kIHRoZSBkYXRhIHBo YXNlCj4gPj4+IGRhdGEgKGZvciBhIGNvbnRyb2wgT1VUIHJlcXVlc3QpIHRvZ2V0aGVyLgo+ID4+ IAo+ID4+IEl0IHNob3VsZG4ndCBjYXVzZSBwcm9ibGVtcywgYWN0dWFsbHkuIE1vc3Qgb2YgdGhl IGlzc3VlcyBjb21lIGZyb20gdGhlCj4gPj4gZmFjdCB0aGF0IHNvbWV0aW1lcyBnYWRnZXQgZHJp dmVyIGp1c3QgcmV0dXJucyBhIHN1Y2Nlc3MgYW5kIGV4cGVjdHMgVURDCj4gPj4gdG8gaW5pdGlh dGUgc3RhdHVzIHN0YWdlIGFuZCBzb21ldGltZXMgZ2FkZ2V0IGRyaXZlciB3YW50cyB0byBoYW5k bGUKPiA+PiBzdGF0dXMgc3RhZ2UgZXhwbGljaXRseS4KPiA+IAo+ID4gUmVxdWVzdGluZyB0aGUg c3RhdHVzIHN0YWdlIGV4cGxpY2l0bHkgcmVxdWlyZXMgYW4gQVBJIHRvIGRvIHNvIChxdWl0ZQo+ ID4gb2J2aW91c2x5KS4gWW91ciBwcm9wb3NhbCBpcyB0byB1c2UgdGhlIHVzYiByZXF1ZXN0IHF1 ZXVlIGFzIGEgc2lnbmFsIHRvCj4gPiBjb250aW51ZSB0byB0aGUgbmV4dCBzdGFnZS4gTXkgcG9p bnQgaXMgdGhhdCB0aGlzIGNhbid0IHdvcmsgZm9yIGNvbnRyb2wKPiA+IE9VVCByZXF1ZXN0cywg d2hlcmUgd2UgbWF5IHdhbnQgdG8gZGVsYXkgdGhlIHN0YXR1cyBzdGFnZSBhZnRlciB0aGUgZGF0 YQo+ID4gaXMgcmVjZWl2ZWQgYnkgdGhlIFVEQywgYW5kIHRodXMgYWZ0ZXIgdGhlIHJlcXVlc3Qg aXMgcXVldWVkLiBXZSBuZWVkIGEKPiA+IGRpZmZlcmVudCBBUEkgZm9yIHRoYXQuCj4gCj4gV2h5 IHNvPyAgQ29uc2lkZXIgdGhlIGZvbGxvd2luZyBsb2dpYyBmb3IgZXAwIGluIHRoZSBVREM6Cj4g Cj4gCUEgU0VUVVAgcGFja2V0IGlzIHJlY2VpdmVkLCBmb3IgYW4gT1VUIHRyYW5zZmVyLgo+IAo+ IAlJZiBzZXR1cC53TGVuZ3RoID4gMCB0aGVuIHRoZSBuZXh0IHJlcXVlc3QgcXVldWVkIGZvciBl cDAgaXMKPiAJdGhlIGRhdGEgc3RhZ2UsIHNvIGl0IGlzIGFuIE9VVCByZXF1ZXN0Lgo+IAo+IAlP dGhlcndpc2UgKGkuZS4sIGlmIHNldHVwLndMZW5ndGggPT0gMCBvciBmb3IgdGhlIHNlY29uZAo+ IAlyZXF1ZXN0IHF1ZXVlZCBhZnRlciB0aGUgU0VUVVAgaXMgcmVjZWl2ZWQpLCB0aGUgbmV4dCBy ZXF1ZXN0Cj4gCWlzIHRoZSBzdGF0dXMgc3RhZ2UsIHNvIGl0IG11c3QgYmUgYSAwLWxlbmd0aCBJ TiByZXF1ZXN0LgoKQXMgZXhwbGFpbmVkIGFib3ZlLCB5ZXMsIEkgYWdyZWUgdGhhdCB3ZSBjb3Vs ZCB1c2UgdGhlIHJlcXVlc3QgcXVldWUgb3BlcmF0aW9uIApib3RoIHRvIHF1ZXVlIGEgcmVxdWVz dCBmb3IgdGhlIGRhdGEgc3RhZ2UsIGFuZCB0byByZXF1ZXN0IHByb2Nlc3NpbmcgdGhlIApzdGF0 dXMgc3RhZ2UuIEkgc3RpbGwgdGhpbmsgYSBzZXBhcmF0ZSBmdW5jdGlvbiB3b3VsZCBiZSBiZXN0 IHRvIHJlcXVlc3QgCnByb2Nlc3NpbmcgdGhlIHN0YXR1cyBzdGFnZSAoYXQgdGhlIHZlcnkgbGVh c3QgYXMgYSBoZWxwZXIgdGhhdCB3b3VsZCBxdWV1ZSAKdGhlIHJlcXVlc3QpLCBidXQgSSBjb3Vs ZCBiZSBjb252aW5jZWQgb3RoZXJ3aXNlLgoKPiBUaGlzIHJlcXVpcmVzIHRoZSBVREMgdG8gc3Bl Y2lmaWNhbGx5IGtlZXAgdHJhY2sgb2YgdGhlIGRpcmVjdGlvbiBvZgo+IHRoZSBjdXJyZW50IHRy YW5zZmVyIGFuZCB3aGV0aGVyIG9yIG5vdCBhIGRhdGEtc3RhZ2UgdHJhbnNmZXIgaGFzCj4gYWxy ZWFkeSBiZWVuIHF1ZXVlZC4gIFRoYXQgc2hvdWxkbid0IGJlIGhhcmQuCgpJdCdzICJqdXN0IiBh IHN0YXRlIG1hY2hpbmUgc28gaXQgd291bGRuJ3QgYmUgdG9vIGhhcmQuIFdoYXQgd2UgbmVlZCB0 byBhZ3JlZSAKb24gaXMgaG93IHRoZSBzdGF0ZSBtYWNoaW5lIG9wZXJhdGVzLCBhbmQgdGhlbiB0 aGUgQVBJIHRvIGNvbnRyb2wgaXQuIFRoYXQncyAKd2hhdCBJIHRyaWVkIHRvIGRlc2NyaWJlIGJl bG93IGluIG15IHByZXZpb3VzIGUtbWFpbC4KCj4gKEJ1dCBpdCBkb2VzIGludm9sdmUgYQo+IHJh Y2UgaW4gY2FzZXMgd2hlcmUgdGhlIGhvc3QgZ2V0cyB0aXJlZCBvZiB3YWl0aW5nIGFuZCBpc3N1 ZXMgYW5vdGhlcgo+IFNFVFVQIHBhY2tldCBiZWZvcmUgdGhlIHByb2Nlc3Npbmcgb2YgdGhlIGZp cnN0IHRyYW5zZmVyIGlzIGZpbmlzaGVkLikKCkkgd29uZGVyIGhvdyBtYW55IFVEQ3MgaGFuZGxl IHRoYXQgcmFjZSBjb3JyZWN0bHkgdG9kYXkgOi0pCgo+IFRoZSBjb3JyZXNwb25kaW5nIGxvZ2lj IGZvciBJTiB0cmFuc2ZlcnMgaXMgc2ltcGxlciwgc2luY2UgSU4gdHJhbnNmZXJzCj4gYXJlIG5v dCBhbGxvd2VkIHRvIGhhdmUgemVybyBsZW5ndGguICBUaGUgZmlyc3QgcmVxdWVzdCBmb2xsb3dp bmcgdGhlCj4gU0VUVVAgcGFja2V0IGlzIHRoZSBkYXRhIHN0YWdlIGFuZCB0aGUgc2Vjb25kIGlz IHRoZSBzdGF0dXMgc3RhZ2UuCj4gCj4gPiBGb3IgY29udHJvbCBJTiwgd2UgbWF5IHdhbnQgdG8g ZGVsYXkgdGhlIGRhdGEgc3RhZ2UgaWYgd2UgY2FuJ3QgcmVzcG9uZAo+ID4gZGlyZWN0bHksIG9y IHByb2NlZWQgd2l0aCB0aGUgZGF0YSBzdGFnZSBpbW1lZGlhdGVseS4gSW4gYm90aCBjYXNlcyB0 aGlzCj4gPiBjYW4gYmUgc2lnbmFsZWQgYnkgYSByZXF1ZXN0IGJlaW5nIHF1ZXVlZC4gVGhlcmUg aXMgbm8gbmVlZCB0byBkZWxheSB0aGUKPiA+IHN0YXR1cyBzdGFnZSBhcyBpdCdzIGluaXRpYXRl ZCBieSB0aGUgaG9zdC4KPiAKPiBZZXMuCj4gCj4gPiBGb3IgY29udHJvbCBPVVQsIHdlIG1heSB3 YW50IHRvIGRlbGF5IHRoZSBkYXRhIHN0YWdlIGlmIHdlIG5lZWQgdG8KPiA+IHZhbGlkYXRlIHRo ZSBzZXR1cCBzdGFnZSBkYXRhIGFzeW5jaHJvbm91c2x5LiBQcm9jZWVkaW5nIHRvIHRoZSBkYXRh IHN0YWdlCj4gPiBjYW4gYmUgc2lnbmFsZWQgYnkgcXVldWVpbmcgYSByZXF1ZXN0LiBXZSBtYXkg YWxzbyB3YW50IHRvIGRlbGF5IHRoZQo+ID4gc3RhdHVzIHN0YWdlIGlmIHdlIG5lZWQgdG8gdmFs aWRhdGUgdGhlIGRhdGEgc3RhZ2UgZGF0YSBhc3luY2hyb25vdXNseS4KPiA+IFRoaXMgY2FuJ3Qg YmUgc2lnbmFsZWQgYnkgcXVldWVpbmcgYSByZXF1ZXN0Lgo+IAo+IEl0IGNhbiBiZSwgaWYgd2Ug dXNlIHRoZSBsb2dpYyBvdXRsaW5lZCBhYm92ZS4KPiAKPiA+IEkgd29uZGVyIGlmIHRoZXJlJ3Mg cmVhbGx5IGEgdXNlIGNhc2UgZm9yIGRlbGF5aW5nIHRoZSBkYXRhIHN0YWdlIG9mCj4gPiBjb250 cm9sIE9VVCByZXF1ZXN0cywgYXMgaXQgc2VlbXMgdG8gbWUgdGhhdCB3ZSBjYW4gcGVyZm9ybSB0 aGUKPiA+IGFzeW5jaHJvbm91cyB2YWxpZGF0aW9uIG9mIHRoZSBzZXR1cCBhbmQgZGF0YSBzdGFn ZXMgdG9nZXRoZXIsIGluIHdoaWNoCj4gPiBjYXNlIHdlIHdvdWxkIGFsd2F5cyBwcm9jZWVkIHRv IHRoZSBkYXRhIHN0YWdlLCBhbmQgb25seSBwb3RlbnRpYWxseQo+ID4gZGVsYXkgdGhlIHN0YXR1 cyBzdGFnZS4gSG93ZXZlciwgaWYgd2Ugc3dpdGNoIHRvIGFuIGV4cGxpY2l0IEFQSSB3aGVyZQo+ ID4gdGhlIHRyYW5zaXRpb24gZnJvbSB0aGUgc2V0dXAgdG8gdGhlIGRhdGEgc3RhZ2UgaXMgdHJp Z2dlcmVkIGJ5IHF1ZXVlaW5nCj4gPiBhIHJlcXVlc3QsIGFuZCBnaXZlbiB0aGF0IHN1Y2ggYSB0 cmFuc2l0aW9uIG1heSBuZWVkIHRvIGJlIGRlbGF5ZWQgZm9yCj4gPiB0aGUgY29udHJvbCBJTiBj YXNlLCBkZWxheWluZyB0aGUgZGF0YSBzdGFnZSBmb3IgY29udHJvbCBPVVQgd291bGQKPiA+IGVz c2VudGlhbGx5IGNvbWUgZm9yIGZyZWUuCgpXaGF0IGRvIHlvdSB0aGluayBhYm91dCB0aGlzID8g U2hvdWxkIHdlIGFsbG93IGZ1bmN0aW9uIGRyaXZlcnMgdG8gZGVsYXkgdGhlIApkYXRhIHN0YWdl IG9mIGNvbnRyb2wgT1VUIHJlcXVlc3RzID8KCj4gPiBJbiBhbnkgY2FzZSB3ZSBuZWVkIGFuIEFQ SSB0byBkZWxheSB0aGUgc3RhdHVzIHN0YWdlIG9mIGEgY29udHJvbCBPVVQKPiA+IHJlcXVlc3Qu IFRoZXJlIGFyZSB0d28gb3B0aW9ucyBoZXJlLiBXZSBjYW4gY29uc2lkZXIgdGhhdCB0aGUgc3Rh dHVzCj4gPiBzdGFnZSBzaG91bGRuJ3QgYmUgZGVsYXllZCBieSBkZWZhdWx0IGFuZCBhZGQgYSBu ZXcgZnVuY3Rpb24gdG8gYmUgY2FsbGVkCj4gPiBmcm9tIHRoZSBkYXRhIHN0YWdlIGNvbXBsZXRp b24gaGFuZGxlciB0byByZXF1ZXN0IGEgc3RhdHVzIHN0YWdlIGRlbGF5Cj4gPiAodXNpbmcgdGhl IHJldHVybiB2YWx1ZSBvZiB0aGUgY29tcGxldGlvbiBoYW5kbGVyIGlzbid0IGEgZ29vZCBpZGVh IGFzIGl0Cj4gPiB3b3VsZCBiZSByYWN5IGFzIGV4cGxhaW5lZCBhYm92ZSkuIEEgc2Vjb25kIGZ1 bmN0aW9uIHdvdWxkIGJlIG5lZWRlZCB0bwo+ID4gcmVxdWVzdCB0aGUgc3RhdHVzIHN0YWdlICh3 aGljaCwgYXMgZXhwbGFpbmVkIGFib3ZlIHRvbywgY2FuJ3QgYmUgZG9uZSBieQo+ID4gcXVldWVp bmcgYSByZXF1ZXN0KS4gQSBzZWNvbmQgb3B0aW9uIGlzIHRvIGNvbnNpZGVyIHRoYXQgdGhlIHN0 YXR1cyBzdGFnZQo+ID4gaXMgZGVsYXllZCBieSBkZWZhdWx0IHVudGlsIGV4cGxjaXRseSByZXF1 aXJlZC4gSW4gYm90aCBjYXNlcyB0aGUgc2FtZQo+ID4gbmV3IGZ1bmN0aW9uIGlzIG5lZWRlZCB0 byByZXF1ZXN0IHRoZSBzdGF0dXMgc3RhZ2UuCj4gPiAKPiA+IE5vdGUgdGhhdCBkZWxheWluZyB0 aGUgZGF0YSBzdGFnZSBhbmQgZGVsYXlpbmcgdGhlIHN0YXR1cyBzdGFnZSBhcmUgdHdvCj4gPiBk aWZmZXJlbnQgcHJvYmxlbXMsIGFuZCBkb24ndCBuZWNlc3NhcmlseSBuZWVkIHRvIGJlIHNvbHZl ZCB0b2dldGhlci4KPiA+IEhvd2V2ZXIsIGlmIEkgdW5kZXJzdGFuZCB0aGluZ3MgY29ycmVjdGx5 LCB3ZSBjdXJyZW50bHkgZGVsYXkgdGhlIGRhdGEKPiA+IHN0YWdlIG9mIGEgZmV3IGNvbnRyb2wg T1VUIHJlcXVlc3RzICh0aGV5IGFsbCBoYXZlIGEgMCBieXRlcyBkYXRhIHN0YWdlKQo+ID4gYXMg YSBtZWFuIHRvIGNvbXBsZXRpb24gb2YgdGhlIHJlcXVlc3QuIEkgYmVsaWV2ZSB0aGF0IHRoaXMg dXNlIGNhc2UKPiA+IGNvdWxkIGJlIGltcGxlbWVudGVkIGJ5IGRlbGF5aW5nIHRoZSBzdGF0dXMg c3RhZ2UgaW5zdGVhZCwgc28gdGhlIHR3byBhcmUKPiA+IHN0aWxsIHJlbGF0ZWQgaW4gYSB3YXku Cj4gPiAKPiA+IElmIHdlIGVuZCB1cCBtb3ZpbmcgdG8gZXhwbGljaXQgc3RhdGUgaGFuZGxpbmcs IHdpdGggdGhlIGRhdGEgc3RhZ2UgYmVpbmcKPiA+IGVudGVyZWQgYnkgcXVldWVpbmcgYSByZXF1 ZXN0LCBhbmQgdGhlIHN0YXR1cyBzdGFnZSBiZWluZyBlbnRlcmVkIGJ5Cj4gPiBjYWxsaW5nIGEg bmV3IGZ1bmN0aW9uLCBjb250cm9sIE9VVCByZXF1ZXN0cyB3aXRoIDAgYnl0ZXMgb2YgZGF0YSB0 aGF0Cj4gPiBjYW4gYmUgaGFuZGxlZCBzeW5jaHJvbm91c2x5IGluIHRoZSBzZXR1cCBoYW5kbGVy IHdvdWxkIHJlcXVpcmUgZnVuY3Rpb24KPiA+IGRyaXZlcnMgdG8gYm90aCBxdWV1ZSBhIHplcm8t bGVuZ3RoIHJlcXVlc3QgYW5kIGNhbGwgdGhlIHN0YXR1cyBmdW5jdGlvbi4KPiA+IFRoaXMgd291 bGQgbWFrZSB0aGUgZnVuY3Rpb24gY29kZSBtb3JlIGNvbXBsZXgsIGFuZCBJIHdvbmRlciB3aGV0 aGVyIGEKPiA+IHNob3J0Y3V0IHdvdWxkIGJlIGEgZ29vZCBpZGVhLCBwZXJoYXBzIGluIHRoZSBm b3JtIG9mIGEgZmxhZyBpbiB0aGUKPiA+IHJlcXVlc3QgdGhhdCB0ZWxscyB0aGUgVURDIHRvIGF1 dG9tYXRpY2FsbHkgcHJvY2VlZCB0byB0aGUgc3RhdHVzIHN0YWdlCj4gPiBpbW1lZGlhdGVseSBh ZnRlciB0aGUgZGF0YSBzdGFnZS4gT3Igd2UgY291bGQgbWFrZSB0aGF0IGJlaGF2aW91ciB0aGUK PiA+IGRlZmF1bHQgd2hlbiB0aGUgcmVxdWVzdCBkb2Vzbid0IGhhdmUgYSBjb21wbGV0aW9uIGhh bmRsZXIgKGFzIG1vdmluZwo+ID4gZXhwbGljaXRseSB0byB0aGUgc3RhdHVzIHN0YWdlIHNob3Vs ZCBiZSBkb25lIGF0IHRoZSBlYXJsaWVzdCBmcm9tIHRoZQo+ID4gZGF0YSBzdGFnZSBjb21wbGV0 aW9uIGhhbmRsZXIpLgoKRnJvbSBhbiBBUEkgcG9pbnQgb2YgdmlldywgdG93YXJkcyBmdW5jdGlv biBkcml2ZXJzLCBJIHJlYWxseSB3YW50IGFuIGV4cGxpY2l0IApmdW5jdGlvbiB0byBwcm9jZWVk IHdpdGggdGhlIHN0YXR1cyBzdGFnZS4gVGhhdCBjb3VsZCBpbnRlcm5hbGx5IHF1ZXVlIGEgWkxQ IApyZXF1ZXN0IG9yIGNhbGwgYW5vdGhlciBBUEksIGJ1dCBpbiBhbnkgY2FzZSBJIGRvbid0IHdh bnQgdGhlIHN0YXR1cyBzdGFnZSBaTFAgCnJlcXVlc3QgdG8gYmUgdmlzaWJsZSB0byB0aGUgZnVu Y3Rpb24gZHJpdmVycy4gRG8geW91IGFncmVlIHdpdGggdGhpcyA/CgpUbyBzaW1wbGlmeSBmdW5j dGlvbiBkcml2ZXJzLCBkbyB5b3UgdGhpbmsgdGhlIGFib3ZlIHByb3Bvc2FsIG9mIGFkZGluZyBh IGZsYWcgCnRvIHRoZSAoZGF0YSBzdGFnZSkgcmVxdWVzdCB0byByZXF1ZXN0IGFuIGF1dG9tYXRp YyB0cmFuc2l0aW9uIHRvIHRoZSBzdGF0dXMgCnN0YWdlIGlzIGEgZ29vZCBpZGVhID8gV2UgY291 bGQgZXZlbiBwb3NzaWJseSBpbnZlcnQgdGhlIGxvZ2ljIGFuZCB0cmFuc2l0aW9uIAp0byB0aGUg c3RhdHVzIHN0YWdlIHdoZW4gdGhlIGZsYWcgaXMgbm90IHNldC4gRXNzZW50aWFsbHkgdGhpcyB3 b3VsZCBjYWxsIHRoZSAKc3RhdHVzIHN0YWdlIHJlcXVlc3QgZnVuY3Rpb24gcmlnaHQgYWZ0ZXIg dGhlIGRhdGEgc3RhZ2UgcmVxdWVzdCBjb21wbGV0aW9uIApoYW5kbGVyIHJldHVybnMsIGluc3Rl YWQgb2YgZm9yY2luZyBhbGwgZnVuY3Rpb24gZHJpdmVycyB0byBkbyBzbyBleHBsaWNpdGx5IAph dCB0aGUgZW5kIG9mIHRoZSBjb21wbGV0aW9uIGhhbmRsZXIuCgo+ID4+PiBGb3IgdGhvc2UgcmVh c29ucyBJIHRoaW5rIGEgbmV3IG1lY2hhbmlzbSBpcyBuZWVkZWQuIEl0IHNob3VsZCBlaXRoZXIK PiA+Pj4gc2lnbmFsIHRoZSBzdGF0dXMgcGhhc2UgZGVsYXkgdGhyb3VnaCBhbiBleHBsaWNpdCBm dW5jdGlvbiBjYWxsCj4gPj4+IGluc3RlYWQgb2YgYSByZXR1cm4gdmFsdWUgKHRvIHNvbHZlIHRo ZSByYWNlIG1lbnRpb25lZCBhYm92ZSksIG9yIGJ5Cj4gPj4+IHJlcXVpcmluZyBhbGwgcmVxdWVz dHMgdG8gYmUgZXhwbGljaXRseSBjb21wbGV0ZWQgKGJ1dCB0aGF0IHdpbGwgcmVxdWlyZQo+ID4+ PiBjaGFuZ2luZyBhbGwgVVNCIGZ1bmN0aW9uIGRyaXZlcnMpLiBGdXJ0aGVybW9yZSwgdGhlIG1l Y2hhbmlzbSBuZWVkIHRvCj4gPj4+IHN1cHBvcnQgZGVsYXlpbmcgdGhlIHN0YXR1cyBwaGFzZSBh ZnRlciBxdWV1aW5nIHRoZSByZXF1ZXN0IGZvciB0aGUgZGF0YQo+ID4+PiBwaGFzZSwgc28gd2Ug bmVlZCBhbiBleHBsaWNpdCB3YXkgdG8gc2lnbmFsIHRoYXQgdGhlIFVEQyBzaG91bGQgcHJvY2Vl ZAo+ID4+PiB3aXRoIHRoZSBzdGF0dXMgcGhhc2UsIG90aGVyIHRoYW4gcXVldWVpbmcgdGhlIHJl cXVlc3QuCj4gPj4+IAo+ID4+PiBUaG91Z2h0cyA/IFByZWZlcmVuY2VzID8KPiA+PiAKPiA+PiBo b3cgYWJvdXQgbWFraW5nIHN0YXR1cyBzdGFnZSBhbHdheXMgZXhwbGljaXQ/Cj4gPiAKPiA+IElm IHdlIGltcGxlbWVudCBhIHByb29mIG9mIGNvbmNlcHQsIGNvdWxkIHlvdSBoZWxwIHVzIGNvbnZl cnRpbmcgZHJpdmVycwo+ID4gb3ZlciB0byB0aGUgbmV3IEFQSSA/IEknbGwgYXNzdW1lIHdlJ2xs IGhhdmUgdG8gYWRkcmVzcyBhbGwgVURDcyBmaXJzdCwKPiA+IGFuZCB0aGVuIHRoZSBmdW5jdGlv biBkcml2ZXJzLgo+IAo+IEknbGwgY2VydGFpbmx5IGhlbHAgZm9yIHRoZSBkcml2ZXJzIEknbSBm YW1pbGlhciB3aXRoLgoKVGhhbmsgeW91Lgo=