norm-1.5.8+dfsg2/0000755000000000000000000000000013325321451010366 5ustar norm-1.5.8+dfsg2/BUILD.TXT0000644000000000000000000000270611572257507011647 0ustar Building NORM ============= NORM can be built using the Waf build tool, included in the distribution. To see a full list of options, run: ./waf -h Configuring ----------- To perform the configure checks, run: ./waf configure Some options for the configure step: --prefix= - Directory to install files to (Default - /usr/local) --debug - Builds a debug build (with debugging symbols), otherwise an optimized library is built. --build-python - Builds the Python extension --build-java - Builds the Java extension You must set the JAVA_HOME environment variable to the location of your JDK directory Building -------- To build the library, simply run: ./waf To build examples along with the library, run: ./waf --targets=ex1,ex2,... Where ex1,ex2 is the name of the example you want to build (see ./waf list). Additionally, you can add the "--targets=*" flag to build all the example programs. Installing ---------- To install, run: ./waf install This will install the compiled library and headers to wherever your prefix was specified. (See configure flags) Uninstalling ------------ Waf tracks the files it installs, so run: ./waf uninstall to remove all files from a previous ./waf install Cleaning -------- ./waf clean will delete all compiled files and configuration settings. ./waf distclean will do the same as clean, and additionally delete the waf cache files. norm-1.5.8+dfsg2/LICENSE.TXT0000644000000000000000000000235512240477051012061 0ustar /********************************************************************* * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution. * * "This product includes software written and developed * by Code 5520 of the Naval Research Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * ********************************************************************/norm-1.5.8+dfsg2/NormSocketBindingNotes.txt0000644000000000000000000002033411660364214015525 0ustar NORM SOCKET BINDING NOTES ========================= NORM supports a number of socket binding options to allow for multiple paradigms of use. The default operation of NORM involves two separate sockets: 1) a "tx_socket" used for sender transmission and reception of unicast feedback, and 2) a "rx_socket" used for reception of packets sent to the "session" address/port By default both sockets are bound to INADDR_ANY with the rx_socket using the "session port" number and the tx_socket using a port freely assigned by the operating system unless the NormSetTxPort() API is invoked. The INADDR_ANY binding allows the sockets to receive packets from any remote address/port thus support NORM's typical multicast operation compatible with both unicast and multicast feedback and even "many-to-one" unicast reception (if unicast feedback is set via NormSetDefaultUnicastNack()). Some optional binding behaviors are invoked depending upon some additional NORM API calls. For example, the "rx_socket" can be optionally bound to the session address. This restricts the rx_socket to receive only packets specifically directed to the configured session address. The session address must be a multicast address or valid local IP address for this to work. And in the latter case, the NormSession MUST be operated only as a NORM receiver (i.e., NormStartSender() will result in transmissions to self only!) The rationale for the separate tx_socket and rx_socket usage was to enable NORM senders to detect when unicast feedback is used so that proper protocol behaviors are invoked (e.g. NORM_CMD(REPAIR_ADV)). Note that the code base _may_ be eventually updated so this is no longer necessary (e.g. through use of the "recvmsg()" system call with proper socket configuration to receive UDP packet destination address header information). It may still be the case that a use case for separate send/recv sockets may persist and the code will continue to support that although it is possible that it may become the optional behavior rather than the default. bind semantics: localAddr / localPort connect semantics: remoteAddr / remotePort +-------------------------------+-------------------------------+---------------------------------------+ | bind() state | connect() state | | +---------------+---------------+---------------+---------------+ Behaviors | | localAddr | localPort | remoteAddr | remotePort | | +---------------+---------------+---------------+---------------+---------------------------------------+ | INADDR_ANY | 0 | NONE | OS-assigned port, sendto() any | +---------------+---------------+---------------+---------------+---------------------------------------+ | INADDR_ANY | | NONE | from any to <*/port>, sendto() any | +---------------+---------------+---------------+---------------+---------------------------------------+ | | | NONE | from any to . sendto() any | +---------------+---------------+---------------+---------------+---------------------------------------+ | INADDR_ANY | | remoteAddr | remotePort | from remote to <*/port> | +---------------+---------------+---------------+---------------+---------------------------------------+ | | | remoteAddr | remotePort | from remote to only | +---------------+---------------+---------------+---------------+---------------------------------------+ The Rules: If you don't bind(), you don't receive anything. If you connect() you can only send to the specified connected addr / port. Cannot connect to multicast addr. Can only bind to multicast or valid local IP addr With port reuse, each multicast socket will get a copy of matching inbound multicast packets. In fact, with an INADDR_ANY bind, the socket will get packets for _any_ group joined if the port number matches. But with an inbound unicast packet, only one socket with closest matching binding will get the packet. This includes the bind() (i.e. local addr/port) _and_ connect() (i.e. remote addr/port) state with regard to the incoming packet where the most specific match is considered the best match. Thus these bind/connect combinations are important in order to achieve some desired set of behaviors. DESIRED BEHAVIORS: 1) NORM sender / receiver operation with feedback to the session port and/or unicast feedback. 2) Binding packet reception for socket(s) to specific address(es) with or without port reuse NormSetTxPort() currently has option to bind the tx_socket to a specific local address (txAddress) NormSetRxPortReuse() currently has option to bind rx_socket to multicast session address. TBD - Need to add "NormSetRxAddress()" to bind rx_socket to non-session local address 3) Connecting socket(s) to remote unicast addr/port so that reused port demuxing works properly (This is probably applicable only to unicast sessions) So, the following conditions should be true to "connect" the socket: 1) Session address is unicast 2) Port reuse is true. XXX - finish these thoughts and revise the implementation!!!!! REQUIREMENTS Enumerate some use cases and the corresponding socket behavior requirements 1) Default: sender/receiver multicast operation w/ mcast and ucast feedback tx_socket : sendto() session addr/port,sender(s) addr/port recvfrom() receiver src addr/port to local ucast addr rx_socket : recvfrom() sender addr/port to session addr/port If rxAddr is unspecified, can also receive to unicast 2) Sender-only one-to-many tx_socket : sendto() session addr/port,sender(s) addr/port recvfrom() receiver src addr/port to local ucast addr rx_socket : recvfrom() sender addr/port to session addr/port (mcast feedback) 3) Receive-only many-to-one unicasts tx_socket : sendto() senders addr/port rx_socket : recvfrom() senders addr/port to session port 4) Bi-directional unicast tx_socket : sendto() session addr/port rx_socket : recvfrom() session addr/* to session port IMPLEMENTATION NOTES: 1) Default binding rx_socket : INADDR_ANY / tx_socket : INADDR_ANY / 0 (any port) Implementation Details: This is the default behavior if none of the additional API calls described below are made. --------------------------------------------------------------------------- 2) The NormSetTxPort(txPort, enableReuse, txAddr) lets this be modified by: a) if (txPort != sessionPort) tx_socket is bound to b) if (txPort == sessionPort) rx_socket is used for transmission, too c) if "enableReuse" is true, PORT/ADDR REUSE is set for tx_socket d) if txAddr is valid, the tx_socket (or (TBD) rx_socket if txPort == sessionPort) is bound to the given which must be a valid IP addr for the host (This means only unicast packets for that address are received on that socket. Thus the binding is _not_ made for the rx_socket case if the session address is a multicast address! Implementation Details: TBD --------------------------------------------------------------------------- 3) The NormSetRxPortReuse(enable, bindToSessionAddr) modifies the default binding as follows: a) If is "true", PORT/ADDR REUSE is set for the rx_socket b) if is "true" _and_ the session address is multicast, the rx_socket binding is / . This enables the same port number to be reused for different multicast session addresses _and_ restricts the rx_socket to receive only packets destined for the sessionAddr. In this case, unicast feedback to the rx_socket (i.e. in the case of above where txPort == sessionPort) will NOT work! TBD - The code resolves this conflict by ... Implementation Details: TBD --------------------------------------------------------------------------- 4) The NormSetTxOnly() causes only the tx_socket to be opened and no rx_socket is opened. In fact, the rx_socket is closed if it is already open (unless txPort == sessionPort ala above) Implementation Details: TBD norm-1.5.8+dfsg2/README-Java.txt0000644000000000000000000000676413270621275012766 0ustar Java JNI bindings for NORM ========================== By: Jason Rush Peter Griffin updates covering waf build system by Duc Nguyen Updated: 2018-03-14 The Java JNI bindings for NORM provide Java bindings for the NORM C API. For documentation about the main NORM API calls, refer to the NORM Developers guide in the regular NORM distribution. The JNI bindings for NORM can be built using two methods. The original method uses Make and an Ant build.xml script in makefiles/java. The newer method uses the waf build system and builds for all platforms with various configurations via configuration switches. ------------ Requirements ------------ Java JNI bindings for NORM requires at least Java 1.5; however, it has also been tested with Java 1.6 and Java 1.8 The NORM library should be built prior to building the Java JNI bindings since they link against it. ### Using Ant and Make ### Apache Ant is required for building the class files and jar file. ### Python waf ### Tested with Python 2 but Python 3 should be ok. ------------ Building ------------ ### Using Ant and Make ### The build files for Java JNI bindings for NORM are located in the makefiles/java directory. To build the NORM jar file, execute Apache Ant in the makefiles/java directory: ant jar This will produce a norm-.jar file in the lib/ directory. To build the accompanying NORM native bindings library, execute make in the makefiles/java directory with the correct make file for your system: make -f Makefile.linux This will produce a libmil_navy_nrl_norm.so file in the lib/ directory. ### Python waf ### Reconfigure waf to use java and choose the target on a windows system: > cd > waf configure --build-java --msvc_target=x64 The msvc_target flag allows you to choose the target Windows architecture. The default is "x86" (i.e. 32bit arch) Build the NORM libraries: > waf build The output will be in the build/ directory. Copy both mil_navy_nrl_norm.* and norm-1.* to the location the JRE libraries. ------------ Installation ------------ The norm-.jar file must be on the classpath. The libmil_navy_nrl_norm.so file must be installed in a location that Java will search at runtime for native libraries. The search path is dependent upon the operating system: Windows: Windows system directories Current working directory PATH environment variable Unix: Current working directory LD_LIBRARY_PATH environment variable You can also specify the directory with the java.library.path Java system property on startup: java -Djava.library.path= ... Finally the native library can also be installed in the JRE's library directory. This allows all programs that use the JRE to access the library: /lib/i386/ If you observe an "java.lang.UnsatisfiedLinkError" exception while running your application, you do not have the libmil_navy_nrl_norm.so installed in the correct location. If you're running on Windows, you also need to have the PATH environment variable set with along with the -Djava.library.path= ------------ Examples ------------ Examples using the Java JNI bindings for NORM are provided in the examples/java directory. Running on Windows (could be put in a .bat script): set PATH=%PATH%; java -Djava.library.path= ... Running on Linux or MacOS: java -Djava.library.path= ... norm-1.5.8+dfsg2/README-PyNorm.txt0000644000000000000000000000576412302432102013310 0ustar PyNORM - Python Wrapper for NORM & Extras ========================================= By: Tom Wambold PyNORM provides a thin wrapper around the NORM C API in the main package. It also provides several additional modules in the extra package to provide higher level usage of NORM. For documentation about the main NORM API calls, refer to the NORM Developers guide in the regular NORM distribution. Also, the files in the examples/python directory have a lot of good info on how to use the library. For simple apps, see the normFileSend and normFileReceive scripts. ------------ Requirements ------------ PyNORM has been tested on Python versions 2.5, 2.6, and 2.7. The code may work on earlier versions, but was not tested. PyNORM requires NORM to be built as a shared library (.so, .dylib, .dll), so that Python's "ctypes" module can load it. Ctypes will look for the library in similar places as your system's compiler. On UNIX systems, this is usually /usr/lib and /usr/local/lib, etc. On Windows, this searches folders in the PATH environment variable. On Windows, PyNORM requires the "PyWin32" module, available at: http://sf.net/projects/pywin32 ------------- Installation ------------- A "setup.py" script is included that installs the 'pynorm' packages. Note, as mentioned above, the NORM shared library must be installed on your system. The 'waf' install script will do this or it can be built with the NORM 'makefiles' and manually emplaced. If you use the 'setup.py' script, you do _not_ need to use the '--build-python' option of the 'waf' configuration script even if you use 'waf' to build the NORM shared library. The 'waf' build tool can also be used to install the 'pynorm' package. For example, to build and install "libnorm.so" and "pynorm" on Linux, use the following steps. cd norm/makefiles make -f Makefile.linux libnorm.so sudo cp libnorm.so /usr/local/lib/ cd ../ sudo python setup.py install On MacOS, the same steps can be used, but using "libnorm.dylib" instead. ----------------------- Examples ----------------------- Some 'pynorm' *.py examples are in the "norm/examples" directory. The 'normMsgr.py' example is functionally equivalent to the 'normMsgr.cpp' example and the 'java/NormMsgr.java' example and illustrates multi-threaded use of the 'pynorm' package for NORM-based data transmission and reception. Note the "NORM_OBJECT_DATA" model is used and may provide out-of-order delivery of the transmitted messages. A similar 'normStreamer.py' example will be provided in the future to illustrate the NORM ordered, message stream delivery mode of operation. ----------------------- "Extra" Package Modules ----------------------- manager.py: This provides a callback-driven event loop for NORM. It operates on a separate thread, calling registered functions in response to NORM events. logparser.py: This provides a function to reads NORM debug "reports" (printed at debug level 3 or higher) from a log file, and parses them into Python objects. norm-1.5.8+dfsg2/README.TXT0000644000000000000000000001046712147212775011745 0ustar NORM SOURCE CODE RELEASE AUTHORIZATION TO USE AND DISTRIBUTE By receiving this distribution, you have agreed to the following terms governing the use and redistribution of the prototype NRL NORM software release written and developed by Brian Adamson and Joe Macker: Redistribution and use in source and binary forms, with or without modification, are permitted provided that: (1) source code distributions retain this paragraph in its entirety, (2) all advertising materials mentioning features or use of this software display the following acknowledgment: "This product includes software written and developed by the Naval Research Laboratory (NRL)." The name of NRL, the name(s) of NRL employee(s), or any entity of the United States Government may not be used to endorse or promote products derived from this software, nor does the inclusion of the NRL written and developed software directly or indirectly suggest NRL or United States Government endorsement of this product. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. --------------------------------------------------------------------- This is a release of the NRL MDP source code. For most purposes, the authors would prefer that the code not be re-distributed so that users will obtain the latest (and most debugged/improved) release from the official NORM web site: SOURCE CODE =========== The following items can be build from this source code release: 1) libnorm.a - static NORM library for Unix platforms, or Norm.lib - static NORM protocol library for Win32 platforms (These libraries can be used by applications using the NORM API. The file "normApi.h" provides function prototypes for NORM API calls and the included "Norm Developer's Guide" provides a reference manual for NORM application development using this API. Additional tutorial material and API usage examples will be provided as additional documentation in the future) 2) norm (or norm.exe (WIN32) - command-line "demo" application built from "common/normApp.cpp" (The included "Norm User's Guide" provides a rough overview of how to use this demo app. This demo application is useful for file transfers (and streaming on Unix)) 3) normTest (or normTest.exe (WIN32)) - very simple test application (The "normTest" application (see "common/normTest.cpp") is really just a simple playground for preliminary testing of the NORM API and does not do anything useful. But it does provide a very simple example of NORM API usage. More sophisticated (and better-documented) examples of NORM API usage will be provided in the future. 4) There is also an "examples" directory in the source code tree that contains some simplified examples of NORM API usage. The example set will be expanded as time progresses. NRL also has started some apps built around NORM including: A) A reliable multicast "chat" application (users can share files and images, too) with a GUI. Like IRC with no server needed. B) An application for reliably "tunneling" real-time UDP packet streams (like RTP video or audio) using NORM's streaming capability. OTHER FILES: ============ NormDeveloperGuide.pdf - PDF version of NORM Developer's Guide (nice for printing) NormDeveloperGuide.html - HTML version of NORM Developer's Guide with Hyperlinked content (nice for browsing) NormUserGuide.pdf - Guide to "norm" demo app usage VERSION.TXT - NORM version history notes README.TXT - this file NOTES: ====== The NORM code depends upon the current "Protolib" release. The NORM source code tarballs contain an appropriate release of "Protolib" as part of the NORM source tree. If the NORM code is checked out from our CVS server, it is necessary to also check out "protolib" separately and provide paths to it for NORM to build. -------- Brian Adamson +1-202-404-1194 Information Technology Division Naval Research Laboratory 4555 Overlook Avenue Washington DC 20375 22 May 2013 norm-1.5.8+dfsg2/TODO.TXT0000644000000000000000000000536111643142152011541 0ustar TODO: 0) Fix implementation of NORM_DATA_FLAG_REPAIR. 2) Add mechanism to allow window-based control of NORM server transmission rate. 7) Build "norm daemon" using API. 10) Release wxNormChat project 11) Test, release "naft" (updated "raft") for reliable UDP streaming. 13) Fix ns-2 issue when Agent/NORM is attached to ns-2 node ZERO and results in a NormNode attempting to be assigned NORM_NODE_NONE as a node id. 14) IMPORTANT: double check ACKing in reponse to watermark polling and relation to cc feedback suppression, etc ... watermark acks should be unicast and not affect cc feedback? 17) Set objectId in TX_FLUSH_COMPLETED and TX_WATERMARK_COMPLETED events. 18) Add APIs for managing remote server state kept at receiver 22) Implement LDPC FEC code within NORM as alternative to Reed Solomon 23) Add ability to control receiver cache on a per-sender basis? (max_pending_range, etc) 26) Add API calls to get error information 27) Add API calls to read logged statistics ========================= COMPLETED: 1) Implement unicast feedback of NACK messages and server re-advertisement for suppressing the unicast feedback. (COMPLETED) 3) Implement TFMCC and/or PGM-CC congestion control mechanisms within NORM. (TFMCC COMPLETED) 4) A single squelch message should be sent per repair cycle? The squelch works to "synchronize" clients to the server repair window. As the code is currently implemented, the server might generate a squelch per NACK. This might be OK since the occurrence of squelch _should_ be rare. The debug statistics should keep a count of squelch events. (COMPLETED) 5) Implement positive acknowledgement mechanism per the NORM spec. (COMPLETED - needs more testing) 6) Implement and document simple API to control and access NORM features. (COMPLETED and enhancement in progress) 8) JAVA API for NRL NORM Protocol library (COMPLETED - Thanks Peter Griffin & Jason Rush) 9) Correct/complete user guide for "norm" demo app (COMPLETED) 12) Can we eliminate rapid clr norm-cc probing when data is not being actively sent? (COMPLETED) 15) Implement TX_OBJECT_SENT event (COMPLETED) 19) Fix "activity_timer" interval setting (COMPLETED) 20) Fix issue related to setting tx cache count_max > 256! Fix NormSession::SetTxCacheBounds() ... tx_table may need to be resized accordingly (COMPLETED, but needs testing). 21) Double-check watermark check code around line 600 of normSession.cpp (COMPLETED - reimplemented, adding tx_repair_pending index to use instead of seeking each time) 24) Look at NormStreamObject::StreamAdvance() for "push-enabled" streams (COMPLETED) 25) Improved, consistent socket binding options norm-1.5.8+dfsg2/VERSION.TXT0000644000000000000000000007750513320271232012126 0ustar NORM Version History Version 1.5.8 ============= - Corrections to eliminate compiler warnings and suport kfreebsd builds (Thanks to Luca Buccassi) Version 1.5.7 ============= - Fixed issue with NormSession::SenderRemoveAckingNode() method where the removed NormAckingNode instance was not being properly deleted. (Thanks to Chad Gioia) - Fixed bug in normPrecoder (npc) when building on 64-bit architectures (Thanks to Leon Meyer) - Fixed bug in JNI NormNode.getAddress() method where an "unsigned short" type was used instead of "UINT16" to receive the port portion of the address. (Thanks to Jame Nguyen) - Reduced warnings, added gnu and other build options to 'waf' wscripts (Thanks to Luca Buccassi) - Greatly improved high speed performance via enhancements to Protolib - Fixed bugs related to coding block id wrapping for very long-lived (or very high speed) NORM sessions. - Added NormSocket API extension in "norm/examples" that provides a sockets-like API and client-server connection-oriented paradigm for using NORM. This currently supports a byte-stream service for both multicast and unicast using NORM_OBJECT_STREAM. This API extension is still work in progress and will be expanded to include message-stream service support as well as NORM's file/data object modes. The "norm/examples/normClient.cpp" (and "normServer.cpp) illustrates use of the the API extension defined in "norm/examples/normSocket.h" - Added "normStreamer" example that provides the same function as the "normMsgr" example except using NORM_OBJECT_STREAM. - The bug fixes and performance enhancements make this a key update. The NORM Developer's Guide is not yet updated to described some of the new API features added. - Added APIs to iterate through sender "Acking Node List" to determine who has and who has not acknowledged a watermark acknowledgement request. - Added NormSetAutoAckingNodes() call with NormTrackingStatus to automate detection of new group members. The Acking Node List iterator function NormGetNextAckingNode() can be used to learn who has joined and the NORM_ACKING_NODE_NEW provides notification to the application of new members. - The 'waf' build scripts assign the current version number to the NORM shared library built for better version control/tracking. Version 1.5r6 ============= - Fixed Protolib ProtoBitmask bug for NDEBUG (release) builds. This is an IMPORTANT fix! (Thanks to Deepak Pengoria and Kirill Kropivyanskiy) - Fix to use of gmtime() call in normApp.cpp for WIN32 builds Version 1.5r5 ============= - Added NORM_REMOTE_SENDER_RESET event to notify app when the sender has been reset due to instance id, etc change - Fixed possibly critical issue in Protolib ProtoDispatcher where threaded dispatcher use (as the NORM API uses) could possibly result in timers not being serviced properly. Most likely the issue could only occur under certain, heavier NORM API usage patterns. Nonetheless, this is an important fix. (Thanks to Michael Savisko of Arris). - Fixed FreeBSD build (Thanks to Hans Duedal) - Changed from 'b' (build) numbering schema to 'r' (release) to reduce confusion with respect to "beta" versus "stable" releases. - Note there are some "in-progress" API extensions in this release that are not yet described in the developer's guide documentation. Version 1.5b4 ============= - Corrected change in behavior of non-blocking version of NormGetNextEvent() call to be consistent with documentation Version 1.5b3 ============= - Added API functions to support integration of NORM into ZeroMQ Version 1.5b2 ============= - Fixed bug with "graceful" stream closure when the sender application did not first flush the stream before calling NormStreamClose() - Added NORM_TX_FLUSH_COMPLETED notification for active stream flushes, including the end of transmission flush when a stream has been gracefully closed. - Added NORM_SYNC_STREAM sync policy that is equivalent to NORM_SYNC_CURRENT but attempts to sync to _start_ of stream (byte offset 0) - Fixed issue with ackowledged, graceful stream closure to allow application to choose to reset watermark before closing stream. The app needs to close streams that remain unacknowledged at closure (i.e. catch TX_WATERMARK_COMPLETED notification check acking status). Acknowledged, graceful shutdown streams, are automatically closed. - Fixed issue with compilation for NormObjectSize constructor, MSB(), and LSB() methods on 32-bit systems. (Thanks to Bill Skiba). Version 1.5b1 ============= - Rolled up all of the features described in Version 1.4b4 below as a new "stable release" even though some minor documentation issues are pending. - Also includes the beginnings of code for "auto population" of the sender acking node list for easier (less precoordination) invocation of ACK-based flow control, etc Version 1.4b4 ============= - Added option to set NORM receiver "rx cache count max", i.e. the maximum number of pending object for which the receiver will keep state (per sender). The "NormSetRxCacheLimit()" API call was added to control this option. - Implemented timer-based flow control so that NORM sender apps will not force purge of old buffered objects (or stream data) for which there is "recent" NACK activity. What is considered "recent" is based upon "flowControlFactor*GRTT_sender*(1 + backoffFactor)". Note that a "flowControlFactor" of 2.0 is default, but can be adjusted. A new API call "NormSetFlowControl()" will be provided for this. Note that if insufficient buffering is allocated, this flow control may limit transmission rate for a given (delay*bandwidth, packetLoss conditions. However, the likely alternative (if flow control is disabled) is that reliability would not be perfectly maintained. Note that enabling the sender "push" option of course overrides the flow control for streams. For file/data objects, the app could choose to explicitly cancel (dequeue) objects or disable the flow control if the app wishes to "push ahead" regardless of impact to reliability. Note that when "pushing", NORM strives to provide whatever reliability is possible given the buffering/delay/bandwidth constraints the app imposes. - Fixed problem with NormServeNode::PassiveRepairCheck() that caused NORM to sometimes falsely acknowledge an object that was not yet received (Thanks to Jeff Bush for finding this one). - Added initial option for Explicit Congestion Notification (ECN) support in "real-world" code. This includes raw packet capture (via ProtoCap) so that ECN header info can be examined and setting ECT-Capable Transport (ECT) bits in IP TOS/Trafffic Class header field. - Fixed bug in NORM API "NormFileGetName()" call that would overrun buffer (Thanks to Adrian Cox) - Fixed bug with NORM probe_timer "lockup" when tx_rate is set to 0.0 (Thanks again to Adrian Cox) - Added experimental receiver "real-time" buffer management option. (not yet in API). Causes receiver to enqueue new data in favor of old, incomplete data when buffer-constrained. _May_ be useful for apps where receipt of "fresh" data is more important than reliability. - Added "requeue" option to "norm" test app to allow multiple retransmissions of a file to be "stitched" together by a NORM receiver. See the NormRequeueObject() API call. Thanks to Keith Hogie/ Ed Criscuolo for suggesting this. - Enhanced NormSetRxPortReuse() behavior when bindSessionToAddr is true such that for unicast sessions a UDP socket "connect()" call is made to effectively "bind" the NormSession rx_socket to the remote unicast addr. This _should_ enable proper demultiplexing of multiple unicast sessions using the same port. (Note that this same technique _may_ be adopted in the future for Source-Specific Multicast (SSM) support as well where a NormSession is associated with a specific remote single sender.) - Added code to NormServerNode::Activate() so that when a previously INACTIVE remote sender becomes active again (reactivated) that the receiver automatically kicks off a new cycle of self-initiated NACKing for any pending objects. Note this code applies when the "reactivation" is due to a non-object message (e.g. NORM_CMD) as reception of an object message (NORM_DATA/ NORM_INFO) will re-awaken NACKing as needed anyway. (Thanks to Jeff Bush for helping determine the utility of this) - The NORM source code tree has been re-organized. - Added Python language binding to NORM API, examples, etc (Thanks to Tom Wambold) - Added WAF build scripts, etc (Thanks again to Tom Wambold) - iPhone Makefile added (Thanks yet again to Tom Wambold) - Bug fix to NORM receiver "rx_object_table" and "rx_pending_mask" interplay in NormSenderNode class. (Thanks to Dave Talmage for stressing NORM enough to find this) - Bug fix with parsing of "limit" command in normApp.cpp (Thanks again to Dave Talmage) - Fixed bug in "NormSessionMgr::NewSession()" where a call was made to NormSession::SetTxPort() that should not have been! - Changed API calls to use "SetTx-XXX" and "SetRx-XXX" more consistently instead of "SetTransmit-XXX", etc. Sorry for a change to a couple of key API calls, but this will be nicer in the long term. - Fixed problems with NormSession::SenderQueueAppCmd() and NormSession::SenderQueueSquelch() where there as two different mis-uses of the NormSession::msg_pool. Thanks to Richard Edell (MITRE) for finding this one. - Fixed problem introduced with new support of multiple "fec_id" types (this version) where receiver processing of NORM_CMD messages with FecPayloadId content (e.g. FLUSH, SQUELCH, etc) _before_ reception of NORM_DATA would result in erroneous messages being generated. Thanks again to Richard Edell (MITRE) for identifying this. - Added optional parameter to NormSetCongestionControl() to allow NORM-CC operation to collect feedback but NOT actually adjust transmission rate. Also added NORM_TX_RATE_CHANGED notification to inform app of when rate change (or suggested change) occurs. - Fixed issue where a small object where INFO was received but no DATA was not causing receiver NACK process to start upon FLUSH receipt as it should. (Thanks to John Unger for finding this!) - Updated JAVA JNI binding code courtesy patches from Kenn Fynn (Dark Corner Software) - Fixed bug where remote sender fec_id value was not cached when only NORM_INFO has been received (thanks to Qingjun Xiao of GSU) - Added NormSetAutoAckingNodes() API call (and underlying code) to allow sender acking node list to be "auto populated" based on hearing any message from a receiver (and/or optionally sender). Also added NormGetNextAckingNode() API call to allow iteration through acking node list to determine status (learn of who is listening, etc). A feature _may_ be added to notify the sender application when new receivers are detected (and added to the list) and maybe even allow per-receiver control of whether an ACK should be solicited or not. I.e., the acking node list would become more of a "tracked" receiver list. - Added enhanced congestion control feature where the receiver always limits the reported rate back to the sender at no more than double the observed receive rate. Adds LIMIT flag to feedback cc flags to facilitate this reporting. This is not part of RFC 5740 but not incompatible with it ... just works a little better. In the future, another way to do this might be to adjust the reported loss value accordingly ... and that would be RFC 5740 compliant although there should be an errata or addendum to the RFC for this. - Added ECN-based congestion control and simple loss-tolerant congestion control options. These will be better documented and perhaps extended in the future. - Added extended precision loss estimate reporting by using "RESERVED" field in CC feedback extension header. Again, non-RFC 5740 but backwards compatible. This helps over large bandwidth-delay links to get to higher data rates. Some more work will be done in this area such as perhaps returning to some form of slow start (exponential increase) behavior after many consecutive RTT with no congestion events. Probably should mirror the return to slow start behavior that occurs when data transmission is idle. This needs to be evaluated as NORM may start being unfairly aggressive in such environments. - This code has the beginnings of an approach to enable automated population of the sender "acking node list" - This code release needs to be more fully documented, but was important to get online since it has _many_ improvements over the prior "stable release" Version 1.4b3 ============= - Fixed many (hopefully all) cases where NORM_DATA message FLAG_REPAIR was not always being set when it should resulting in receivers sometimes "syncing" (or "re-syncing") to sender repair transmissions when they shouldn't ... sometimes resulting in duplicative stream data being delivered to the receiver app. - Fixed case when repair request for old NORM_OBJECT_STREAM segment could lockup advancement of stream when stream "push" is enabled. (Thanks to Greg Lauer, Clifton Lin, BAE Systems CBMANET team) - Added command-line options to "norm" demo app for "txrobustfactor" and "rxrobustfactor" - Added "NormNodeFreeBuffers()" API call and changed NORM behavior to require app to free buffers allocate for remote sender unless indefinite persistence is desired. - Added "rxpersist" command-line option to "norm" demo app to make "norm" demo app receivers keep full state on remote senders' indefinitely. - Fixed issue with NormSession::QueueTxObject() where ASSERT() failure occurred depending upon previous tx object enqueue/dequeue history (Thanks to Jeff Bush for finding this one) - Changed repeated scheduling of receiver remote sender inactivity timer to ensure that busy CPU doesn't result in premature inactivity indication. - Fixed issue with fix for stream lockup problem from below. (this is in version 1.4b3a) Version 1.4b2 ============= - Fixed bug where NormObjectCancel() usage could result in extra "release" of reference to NormObject (Thanks to Alan McKechnie) - Fixed minor issue with "repeatcount" command of "normApp.cpp" where only the abbreviated command "repeat" was accepted. (Thanks to Deric Sullivan) - Added NormSetTxRobustFactor(), NormSetDefaultRxRobustFactor(), and NormNodeSetRobustFactor() API calls - Fixed issue with CC_INACTIVE being prematurely declared and modified NORM RxSocketHandler to read a maximum of 100 consecutive packets from socket at a time (This makes sure that receivers service timeouts, provide feedback more timely, etc) (Thanks to Peter Lu) - Fixed case when repair request for old NORM_OBJECT_STREAM segment could lockup advancement of stream. (Also thanks to Peter Lu) Version 1.4b1 ============= - Fixed condition where receivers kept state for remote senders "stuck" with CC feedback (cc_enable) even if newer NORM_CMD(CC) messages indicate that sender CC operation has been disabled. - Fixed error in NormSession::SetTOS() method that transmogrifried the default TTL value into TOS under certain conditions. (thanks to Ron in 't Velt yet again for finding this and the one above). - Made NormFile read/write more persistent (e.g. when EINT occurs) - Fixed NormObject::PassiveRepairCheck() bug that incorrectly reported no repair needed when in fact, the last segment was missing. - Fixed ProtoSlidingBitmask error that interfered with proper sender stream advancement under severe conditions - NORM still used old "MDP" FEC codecs but now explicitly check for FEC ID == 129 and FEC instance id == 0. Can be built with -DASSUME_MDP_FEC to avoid this check in case of backward compatbility issue. Future NORM release will be using new FEC implementation for Reed-Solomon coding but will continue to support compile-time backwards compatibility option to use old MDP FEC encoder. - Added "lowDelay" and other options to "norm" demo application - Modified "lowDelay" option for silent receiver use to allow control of FEC block delay (how many blocks to wait before passing partially-received coding blocks to application). - Added "Norm Pre-Coder" (NPC) utility to distribution. Version 1.3b9 ============= - Fixed ProtoSocket WINVER stuff and NormApplicationMsg::SetContent() (thanks to Stefan Titze for these) - Fixed issue in NormSession::OnRepairTimeout() where a debug message erroneously dereferenced a NormObject pointer as NormFileObject (led to run-time issue in optimized code build) (thanks to Charlie Davis once again) - Fixed places where NORM_CMD(FLUSH/SQUELCH) messages didn't have FEC source block length properly set (thanks to Ron in 't Velt) - Fixed misuse of "delete" operator where "delete[]" should have been used instead in "normEncoder.cpp" (thanks to Jon of Totient?) - Fixed error in NormQuantizeRate() and NormUnQuantizeRate() functions in "normMessage.h". (Thanks to Julian Onions for getting it right in the Ethereal NORM dissector he created). - Fixed case in NormObject::NextServerMsg() where old recovered block could cause assertion failure (thanks to John Wood for the stress testing) - Fixed "normApi.cpp" code that was resulting in NormServerNode reference counts not being updated properly (thanks to Jon Dyte for this) - Fixed missed initialization of NormServerNode::nominal_packet_count and NormLossEstimator2::init members (Thanks to Jon Dyte again). - Fixed bug where NORM_DATA messages containing FEC parity content had 8 bytes of extraneous content appended in their payload (Thanks to Jon Jannucci for finding this one). - Fixed bug where receiver loss estimate returning to ZERO could result in a floating point exception in NormSession::CalculateRate() (thanks to Ian Downard for finding this one) - Re-ordered NORM_DATA "payload_length" and "payload_msg_start" fields to be consistent with revised NORM spec. - Corrected the detection of "data loss" when application (or API) fails to consume received stream data before it is discarded. - Fixed bug where when small "txbuffersize" was set for sender, but a relatively large FEC block size was kept, the sender app would not be notified by stream "vacancy" - Fixed bug with initialization of grtt_estimate when NormSetTransmitRate() was called _before_ NormStartSender() - Fixed intermediate issue where flush_timer mis-scheduling caused sender to "hang" (Thanks to Scott Bates for quickly noticing this) Version 1.3b8 ============= - Fixed implementation of NormQuantizeGroupSize() in "normMessage.h" (Thanks to David Lucas for finding the bug) - Fixed some issues with NORM/Protolib ns-2 support - Added API NormGetGrtt() and NormNodeGetGrtt() calls to support some application needs. - Modified transmission of FEC parity segments such that their length is only as big as needed to support the maximum sent segment size for the associated block (this allows more latitude for stream apps in setting their sender segment size and flushing). - Added NORM_CC_ACTIVE and NORM_CC_INACTIVE notifications to indicate whether receivers are actively providing congestion control feedback (Thanks to Charlie Davis for the great suggestion) - Fixed some floating-point exceptions that could occur in receiver congestion control tracking under extreme circumstances. This included enhancement of receiver receive rate tracking. (Thanks to Ian Downard for finding these issues) - Changed naming of "SERVER" notifications in API to "SENDER" notifications to be consistent with the rest of API. - Debug statistics now indicate correct nack/suppressed counts for silent receiver operation (i.e. none) - Refined activity timeout of remote sender (still need to give the app more control over resource allocation) Version 1.3b7 ============= - Deprecated NORM stream payload flags in favor of "payload_msg_start" field per revised NORM specification (draft-ietf-rmt-pi-nom-revised-00) This included interpreting NORM_DATA (source segment) messages for NORM_OBJECT_STREAM with "payload_len" field value of ZERO as "stream control" messages where the "payload_msg_start" field serves as the stream control message type indications. The "End-of-Stream" control message consists of "payload_msg_start" = 0 when "payload_len" = 0. No other stream control messages are yet defined. The next revision of the NORM spec will describe this. (Thus for NORM stream purposes, this NORM version is _not_ interoperable with previous versions) - Fixed problem where NormServerNode "retrieval_pool" had allocated segments one byte too small (although this is OBE with the above deprecation of stream flags which is what the byte was used for) - Fixed bug where sender objects were not properly "closed" when the object table was cleaned upon NormStopSender() - Added support to VC++ .Net workspace for building "Norm.dll" (NORM as a dynamic linked library) and similarly added option to build "libnorm.dylib" for MacOS. ("libnorm.so" for other Unix platforms should already work). - Fixed NormSetTOS() call. - Added option to NormSetPortReuse() to maintain INADDR_ANY binding if desired. - Refined management of NORM sender stream buffer so sender wouldn't prematurely discard buffer stream blocks when alot of small segments (smaller than segment_size) were buffered. - Added NormStopInstance() call to provide means for multi-threaded NORM apps to stop the NORM protocol engine and awake any other thread blocked on NormGetNextEvent() to signal shutdown of NormInstance. - Also updated code so ns-2 build works and tested w/ ns-2.29 Version 1.3b6 ============= - Fixed some oversite bugs that crept in with changes in 1.3b5 (Fixed code related to NormNode/NormObject retain and release) - Changed NORM_TX_QUEUE_VACANCY posting behavior to be less chatty. NORM_TX_QUEUE_VACANCY now posted _only_ after a call to NormStreamWrite() fails to fulfill a full write request (i.e. returns less than the "numBytes" requested to be written) This helps prevent build up of these notifications in multi- threaded applications that write to a stream in a different thread than is fetching events via NormGetNextEvent(). - Added NORM_TX_WATERMARK_COMPLETED notification and NormGetAckingStatus() function to provide API support for optional positive acknowledgment (ACK) collection in NORM implementation. Note that use of NormAddAckingNode(session, NORM_NODE_NONE) enables a NACK-based watermark flushing concurrent with ongoing data transmission that can be used as a scalable application-level flow control mechanism. Version 1.3b5 ============= - Changed ProtoSocket::GetInterfaceAddress() and related methods on Win32 to use different system APIs depending on Windows version. - Fixed some details related to compilation with g++ 4.x. - Various issues fixed thanks to input from Timothy Chaplin. - Fixed some issues where attempt to resync rx stream after long outages (at high data rates) called assertion failures (Thanks to Charlie Davis for finding this one) - Fixed problem where, on Win32, the sender GRTT estimate was not being updated (in the downward direction) properly. - Changes to Protolib & Norm to support build of shared libraries (Thanks to Dave Talmage & Timothy Mann) - Added "NormSetRxPortReuse()" API and code support to allow (with care) multiple NORM instances on the same host. - Fixes to NORM congestion control including: 1) measurement of "recv_rate" at low transmission rates fixed (made sure measurement was over sufficient interval at low rates including cc startup) 2) Re-instated code to reduce rate when feedback stopped being received. 3) Changed to time-based aging of feedback to "deactivate" stale congestion control feedback representative state kept by sender. 4) Fixed mis-set of PLR flag as CLR flag and fixed bug in updating CC node list upon CC feedback reception. (Thanks to Praveen Gopala for prompting all of this) - Fixes for Win32 large file support "in normFile.cpp" (Thanks to Titze Stefan for this fix). - Added "NormSetGrttMax()", "NormSetGrttProbingMode()", and "NormSetGrttProbingInterval()" APIs to control NORM GRTT measurement/estimation process. (Thanks to Dave Lucas for prompting me here) - Changed posting of NORM_TX_QUEUE_VACANCY for streams such that new postings of this event are made, _only_ after a successful call to NormStreamWrite() ... This results in reduced posting of unnecessary vacancy events, but now the onus is on the app to pay attention to this event, since another of it's type won't be posted until the app calls NormStreamWrite() with non-zero content length. (Thanks to Charlie Davis for bringing this to my attention) - Made sure messages from self are ignored unless loopback is explicitly enabled (see NormSetLoopback()) even for operating systems whose ProtoSocket::SetLoopback() doesn't work properly. Version 1.3b4 ============= - Added NormSetTxCacheBounds(), see NormDevGuide for details - Fixed issue with NormStreamSeekMsgStart() that crept in somehow (Thanks to Jody Hagins for finding it). - Added code to check that NormFileEnqueue() argument is actually a file and not a directory name (Thanks to Charlie Shyr for finding this) - Fixed NormSession::Open() so that IPv6 works Version 1.3b3 ============= - Added NORM_TX_FLUSH_COMPLETE notification so the sender app can make an educated guess as to when his receivers are all happy. - Added NORM API sample code in "examples" directory. - Added NormObjectGetBytesPending() call for receivers to use to monitor reception progress. Version 1.3b2 ============= - Added "graceful" stream shutdown option to NORM API via the NormStreamClose() call. - Embedded FLAG_STREAM_END flag in "payload_reserved" field of NORM_DATA messages. This is beyond the current RFC 3940 spec for NORM, but probably something to push for addition to the next revision of the spec. - Embedded equivalent FLAG_MSG_START in "payload_reserved" field of NORM_DATA messages. This allows message boundary recovery for streams upon FEC decoding. Again, this is "beyond" the current NORM spec, but probably a good idea (Other stream control functions might use this field as well) - Added Visual Studio .NET project files Version 1.3b1 ============= - Prevented pile-up of TX_QUEUE_VACANCY notifications - Fix/optimization to ProtoDispatcher threaded operation to prevent possible (although minor) race condition during threaded operation. - Added NORM API calls: NormSetTxSocketBuffer(), NormSetRxSocketBuffer(), NormSetUserData(), NormGetUserData(), and implemented overlooked NormGetDescriptor() - Thanks again to Charlie Davis for finding some performance deficiencies. Version 1.2b9 ============= - Fixed bugs with NormServerNode::retrieval_pool mgmnt (Thanks to Charlie Davis for tracking these down!!!) - Changed ProtoDispatcher thread stuff so threads (e.g. the NORM API thread) are only actively signaled and interrupted when absolutely necessary - Added support for NORM_TX_QUEUE_VACANCY notification (for NORM_OBJECT_STREAM only at the moment) Version 1.2b8 ============= - Fixed bug introduced during "alignment" changes in previous release. - Fixed Protolib WIN32 build issue Version 1.2b7 ============= - Changed normMessage.[h|cpp] to fix alignment issues (and other alignment stuff) - Fixed bug in NormCmdCCMsg::Iterator::GetNextNode() (might significantly help CC performance - Fixed NormServerNode::FreeBuffers() bug which could result in seg fault on remote server timeout or at app shutdown - Fixed bug where tx_sequence count was being incremented for all transmitted messages (The "fix" does not yet address separate increment of messages sent to different addresses, etc). The bug impacted congestion control performance when nodes acted as sender _and_ receiver (caused receives to overestimate packet loss) Version 1.2b6 ============= - Added normApi.cpp into libNorm.a (Norm.lib (WIN32)) builds - Fixed Solaris build (new protolib code) - Included very rough user's guide for "norm" demo app Version 1.2b5 ============= - Initial release with theoretically-working API (including "Norm Developer's Guide!") Version 1.2b4 ============= - Finally remembered to update this file! - Added "help" command to "norm" demo app (Thanks Marinho Barcellos!) - New rxbuffer mgmnt scheme to better use limited buffer space. - Removed explicit rate limit on receiver feedback messages - API more complete and established better API naming conventions (documentation soon to follow, I promise!) - There have been some "cc" tweaks and bug fixes. - NORM RFC 3940 was released and this version is in compliance. - Added optional positive acknowledgements for sender-defined "watermarks". - Fixed multicast leave problem when interfaceName was used for join Version 1.1b9 ============= - There have been a number of bug fixes since 1.1b3. This release fixes a bug in NormBlockBuffer::Remove() and NormObjectBuffer::Remove(). (Thanks Thava!) Version 1.1b3 ============= - Started keeping version history. This release includes some bug fixes, smoother congestion control operation, etc over some of the earlier releases. Please address bug reports, suggestions etc to the email list: mailto:norm-dev@pf.itd.nrl.navy.mil norm-1.5.8+dfsg2/doc/0000755000000000000000000000000013320270771011136 5ustar norm-1.5.8+dfsg2/doc/NormDeveloperGuide.html0000644000000000000000000144375712426727351015617 0ustar NORM Developer's Guide (version 1.5b5)

NORM Developer's Guide (version 1.5b5)

Abstract

This document describes an application programming interface (API) for the Nack-Oriented Reliable Multicast (NORM) protocol implementation developed by the Protocol Engineering and Advance Networking (PROTEAN) Research Group of the United States Naval Research Laboratory (NRL). The NORM protocol provides general purpose reliable data transport for applications wishing to use Internet Protocol (IP) Multicast services for group data delivery. NORM can also support unicast (point-to-point) data communication and may be used for such when deemed appropriate. The current NORM protocol specification is given in the Internet Engineering Task Force (IETF) RFC 3940. This document is currently a reference guide to the NORM API of the NRL reference implementation. More tutorial material may be include in a future version of this document or a separate developer's tutorial may be created at a later date.


Table of Contents

1. Background
2. Overview
2.1. API Initialization
2.2. Session Creation and Control
2.3. Data Transport
2.3.1. Data Transmission
2.3.2. Data Reception
2.4. API Event Notification
3. Build Notes
3.1. Unix Platforms
3.2. Win32/WiNCE Platforms
4. API Reference
4.1. API Variable Types and Constants
4.1.1. NormInstanceHandle
4.1.2. NormSessionHandle
4.1.3. NormSessionId
4.1.4. NormNodeHandle
4.1.5. NormNodeId
4.1.6. NormObjectHandle
4.1.7. NormObjectType
4.1.8. NormSize
4.1.9. NormObjectTransportId
4.1.10. NormEventType
4.1.11. NormEvent
4.1.12. NormDescriptor
4.1.13. NormFlushMode
4.1.14. NormProbingMode
4.1.15. NormSyncPolicy
4.1.16. NormNackingMode
4.1.17. NormRepairBoundary
4.1.18. NormAckingStatus
4.2. API Initialization and Operation
4.2.1. NormCreateInstance()
4.2.2. NormDestroyInstance()
4.2.3. NormStopInstance()
4.2.4. NormRestartInstance()
4.2.5. NormSetCacheDirectory()
4.2.6. NormGetNextEvent()
4.2.7. NormGetDescriptor()
4.3. Session Creation and Control Functions
4.3.1. NormCreateSession()
4.3.2. NormDestroySession()
4.3.3. NormSetUserData()
4.3.4. NormGetUserData()
4.3.5. NormGetLocalNodeId()
4.3.6. NormSetTxPort()
4.3.7. NormSetTxOnly()
4.3.8. NormSetRxPortReuse()
4.3.9. NormSetMulticastInterface()
4.3.10. NormSetSSM()
4.3.11. NormSetTTL()
4.3.12. NormSetTOS()
4.3.13. NormSetLoopback()
4.3.14. NormSetFragmentation()
4.4. NORM Sender Functions
4.4.1. NormStartSender()
4.4.2. NormStopSender()
4.4.3. NormSetTxRate()
4.4.4. NormGetTxRate()
4.4.5. NormSetTxSocketBuffer()
4.4.6. NormSetFlowControl()
4.4.7. NormSetCongestionControl()
4.4.8. NormSetTxRateBounds()
4.4.9. NormSetTxCacheBounds()
4.4.10. NormSetAutoParity()
4.4.11. NormGetGrttEstimate()
4.4.12. NormSetGrttEstimate()
4.4.13. NormSetGrttMax()
4.4.14. NormSetGrttProbingMode()
4.4.15. NormSetGrttProbingInterval()
4.4.16. NormSetBackoffFactor()
4.4.17. NormSetGroupSize()
4.4.18. NormSetTxRobustFactor()
4.4.19. NormFileEnqueue()
4.4.20. NormDataEnqueue()
4.4.21. NormRequeueObject()
4.4.22. NormStreamOpen()
4.4.23. NormStreamClose()
4.4.24. NormStreamWrite()
4.4.25. NormStreamFlush()
4.4.26. NormStreamSetAutoFlush()
4.4.27. NormStreamSetPushEnable()
4.4.28. NormStreamHasVacancy()
4.4.29. NormStreamMarkEom()
4.4.30. NormSetWatermark()
4.4.31. NormCancelWatermark()
4.4.32. NormAddAckingNode()
4.4.33. NormRemoveAckingNode()
4.4.34. NormGetNextAckingNode()
4.4.35. NormGetAckingStatus()
4.4.36. NormSendCommand()
4.4.37. NormCancelCommand()
4.5. NORM Receiver Functions
4.5.1. NormStartReceiver()
4.5.2. NormStopReceiver()
4.5.3. NormSetRxCacheLimit()
4.5.4. NormSetRxSocketBuffer()
4.5.5. NormSetSilentReceiver()
4.5.6. NormSetDefaultUnicastNack()
4.5.7. NormNodeSetUnicastNack()
4.5.8. NormSetDefaultSyncPolicy()
4.5.9. NormSetDefaultNackingMode()
4.5.10. NormNodeSetNackingMode()
4.5.11. NormObjectSetNackingMode()
4.5.12. NormSetDefaultRepairBoundary()
4.5.13. NormNodeSetRepairBoundary()
4.5.14. NormSetDefaultRxRobustFactor()
4.5.15. NormNodeSetRxRobustFactor()
4.5.16. NormStreamRead()
4.5.17. NormStreamSeekMsgStart()
4.5.18. NormStreamGetReadOffset()
4.6. NORM Object Functions
4.6.1. NormObjectGetType()
4.6.2. NormObjectHasInfo()
4.6.3. NormObjectGetInfoLength()
4.6.4. NormObjectGetInfo()
4.6.5. NormObjectGetSize()
4.6.6. NormObjectGetBytesPending()
4.6.7. NormObjectCancel()
4.6.8. NormObjectRetain()
4.6.9. NormObjectRelease()
4.6.10. NormFileGetName()
4.6.11. NormFileRename()
4.6.12. NormDataAccessData()
4.6.13. NormDataDetachData()
4.6.14. NormObjectGetSender()
4.7. NORM Node Functions
4.7.1. NormNodeGetId()
4.7.2. NormNodeGetAddress()
4.7.3. NormNodeGetGrtt()
4.7.4. NormNodeGetCommand()
4.7.5. NormNodeFreeBuffers()
4.7.6. NormNodeDelete()
4.7.7. NormNodeRetain()
4.7.8. NormNodeRelease()
4.8. NORM Debugging Functions
4.8.1. NormSetDebugLevel()
4.8.2. NormOpenDebugLog()
4.8.3. NormCloseDebugLog()
4.8.4. NormOpenDebugPipe()
4.8.5. NormCloseDebugPipe()

1. Background

This document describes an application programming interface (API) for the Nack-Oriented Reliable Multicast (NORM) protocol implementation developed by the Protocol Engineering and Advance Networking (PROTEAN) Research Group of the United States Naval Research Laboratory (NRL). The NORM protocol provides general purpose reliable data transport for applications wishing to use Internet Protocol (IP) Multicast services for group data delivery. NORM can also support unicast (point-to-point) data communication and may be used for such when deemed appropriate. The current NORM protocol specification is given in the Internet Engineering Task Force (IETF) RFC 5740.

The NORM protocol is designed to provide end-to-end reliable transport of bulk data objects or streams over generic IP multicast routing and forwarding services. NORM uses a selective, negative acknowledgement (NACK) mechanism for transport reliability and offers additional protocol mechanisms to conduct reliable multicast sessions with limited "a priori" coordination among senders and receivers. A congestion control scheme is specified to allow the NORM protocol to fairly share available network bandwidth with other transport protocols such as Transmission Control Protocol (TCP). It is capable of operating with both reciprocal multicast routing among senders and receivers and with asymmetric connectivity (possibly a unicast return path) from the senders to receivers. The protocol offers a number of features to allow different types of applications or possibly other higher-level transport protocols to utilize its service in different ways. The protocol leverages the use of FEC-based repair and other proven reliable multicast transport techniques in its design.

The NRL NORM library attempts to provide a general useful capability for development of reliable multicast applications for bulk file or other data delivery as well as support of stream-based transport with possible real-time delivery requirements. The API allows access to many NORM protocol parameters and control functions to tailor performance for specific applications. While default parameters, where provided, can be useful to a potential wide range of requirements, the many different possible group communication paradigms dictate different needs for different applications. Even with NORM, the developer should have a thorough understanding of the specific application's group communication needs.

2. Overview

The NORM API has been designed to provide simple, straightforward access to and control of NORM protocol state and functions. Functions are provided to create and initialize instances of the NORM API and associated transport sessions (NormSessions). Subsequently, NORM data transmission (NormSender) operation can be activated and the application can queue various types of data (NormObjects) for reliable transport. Additionally or alternatively, NORM reception (NormReceiver) operation can also be enabled on a per-session basis and the protocol implementation alerts the application of receive events.

By default, the NORM API will create an operating system thread in which the NORM protocol engine runs. This allows user application code and the underlying NORM code to execute somewhat independently of one another. The NORM protocol thread notifies the application of various protocol events through a thread-safe event dispatching mechanism and API calls are provided to allow the application to control NORM operation. (Note: API mechanisms for lower-level, non-threaded control and execution of the NORM protocol engine code may also be provided in the future.)

The NORM API operation can be roughly summarized with the following categories of functions:

  1. API Initialization

  2. Session Creation and Control

  3. Data Transport

  4. API Event Notification

Note the order of these categories roughly reflects the order of function calls required to use NORM in an application. The first step is to create and initialize, as needed, at least one instance of the NORM API. Then one or more NORM transport sessions (where a "session" corresponds to data exchanges on a given multicast group (or unicast address) and host port number) may be created and controlled. Applications may participate as senders and/or receivers within a NORM session. NORM senders transmit data to the session destination address (usually an IP multicast group) while receivers are notified of incoming data. The NORM API provides and event notification scheme to notify the application of significant sender and receiver events. There are also a number support functions provided for the application to control and monitor its participation within a NORM transport session.

2.1. API Initialization

The NORM API requires that an application explicitly create at least one instance of the NORM protocol engine that is subsequently used as a conduit for further NORM API calls. By default, the NORM protocol engine runs in its own operating system thread and interacts with the application in a thread-safe manner through the API calls and event dispatching mechanism.

In general, only a single thread should access the NormGetNextEvent() API call for a given NormInstance. This function serves as the conduit for delivering NORM protocol engine events to the application. A NORM application can be designed to be single-threaded, even with multiple active NormSessions, but also multiple API instances can be created (see NormCreateInstance()) as needed for applications with specific requirements for accessing and controlling participation in multiple NormSessions from separate operating system multiple threads. Or, alternatively, a single NormInstance could be used, with a "master thread" serving as an intermediary between the NormGetNextEvent() function, demultiplexing and dispatching events as appropriate to other "child threads" that are created to handle "per-NormSession" input/output. The advantage of this alternative approach is that the end result would be one NORM protocol engine thread plus one "master thread" plus one "child thread" per NormSession instead of two threads (protocol engine plus application thread) per NormSession if such multi-threaded operation is needed by the application.

2.2. Session Creation and Control

Once an API instance has been successfully created, the application may then create NORM transport session instances as needed. The application can participate in each session as a sender and/or receiver of data. If an application is participating as a sender, it may enqueue data transport objects for transmission. The control of transmission is largely left to the senders and API calls are provided to control transmission rate, FEC parameters, etc. Applications participating as receivers will be notified via the NORM API's event dispatching mechanism of pending and completed reliable reception of data along with other significant events. Additionally, API controls for some optional NORM protocol mechanisms, such as positive acknowledgment collection, are also provided.

Note when multiple senders are involved, receivers allocate system resources (buffer space) for each active sender. With a very large number of concurrently active senders, this may translate to significant memory allocation on receiver nodes. Currently, the API allows the application to control how much buffer space is allocated for each active sender (NOTE: In the future, API functions may be provided limit the number of active senders monitored and/or provide the application with finer control over receive buffer allocation, perhaps on a per sender basis).

2.3. Data Transport

The NORM protocol supports transport of three basic types of data content. These include the types NORM_OBJECT_FILE and NORM_OBJECT_DATA which represent predetermined, fixed-size application data content. The only differentiation with respect to these two types is the implicit "hint" to the receiver to use non-volatile (i.e. file system) storage or memory. This "hint" lets the receiver allocate appropriate storage space with no other information on the incoming data. The NORM implementation reads/writes data for the NORM_OBJECT_FILE type directly from/to file storage, while application memory space is accessed for the NORM_OBJECT_DATA type. The third data content type, NORM_OBJECT_STREAM, represents unbounded, possibly persistent, streams of data content. Using this transport paradigm, traditional, byte-oriented streaming transport service (e.g. similar to that provided by a TCP socket) can be provided. Additionally, NORM has provisions for application-defined message-oriented transport where receivers can recover message boundaries without any "handshake" with the sender. Stream content is buffered by the NORM implementation for transmission/retransmission and as it is received.

2.3.1. Data Transmission

The behavior of data transport operation is largely placed in the control of the NORM sender(s). NORM senders controls their data transmission rate, forward error correction (FEC) encoding settings, and parameters controlling feedback from the receiver group. Multiple senders may operate in a session, each with independent transmission parameters. NORM receivers learn needed parameter values from fields in NORM message headers.

NORM transport "objects" (file, data, or stream) are queued for transmission by NORM senders. NORM senders may also cancel transmission of objects at any time. The NORM sender controls the transmission rate either manually (fixed transmission rate) or automatically when NORM congestion control operation is enabled. The NORM congestion control mechanism is designed to be "friendly" to other data flows on the network, fairly sharing available bandwidth.NormSetAutoParity()) to achieve reliable transfer) receive object transmission before any extensive repair process that may be required to satisfy other receivers with poor network connectivity. The repair boundary can also be set for individual remote senders using the NormNodeSetRepairBoundary() function.NORM_OBJECT_FILE objects. This function must be called before any file objects may be received and thus should be called before any calls to NormStartReceiver() are made. However, note that the cache directory may be changed even during active NORM reception. In this case, the new specified directory path will be used for subsequently-received files. Any files received before a directory path change will remain in the previous cache location. Note that the NormFileRename() function may be used to rename, and thus potentially move, received files after reception has begun.

By default, the NORM sender transmits application-enqueued data content, providing repair transmissions (usually in the form of FEC messages) only when requested by NACKs from the receivers. However, the application may also configure NORM to proactively send some amount of FEC content along with the original data content to create a "robust" transmission that, in some cases, may be reliably received without any NACKing activity. This can allow for some degree of reliable protocol operation even without receiver feedback available. NORM senders may also requeue (within the limits of "transmit cache" settings) objects for repeat transmission, and receivers may combine together multiple transmissions to reliably receive content. Additionally, hybrid proactive/reactive FEC repair operation is possible with the receiver NACK process as a "backup" for when network packet loss exceeds the repair capability of the proactive FEC settings.

The NRL NORM implementation also supports optional collection of positive acknowledgment from a subset of the receiver group at application-determined positions during data transmission. The NORM API allows the application to specify the receiver subset ("acking node list") and set "watermark" points for which positive acknowledgement is collected. This process can provide the application with explicit flow control for an application-determined critical set of receivers in the group.

For a NORM application to perform data transmission, it must first create a session using NormCreateSession() and make a call to NormStartSender() before sending actual user data. The functions NormFileEnqueue(), NormDataEnqueue(), and NormStreamWrite() are available for the application to pass data to the NORM protocol engine for transmission. Note that to use NormStreamWrite(), a "sender stream" must first be created using NormStreamOpen(). In the case of NormFileEnqueue() and NormDataEnqueue(), the NORM protocol engine directly accesses the application file or memory space to refer to the transmitted content and does not make its own copy of this data.

The calls to enqueue transport objects or write to a stream may be called at any time, but the NORM_TX_QUEUE_EMPTY and NORM_TX_QUEUE_VACANCY notification events (see NormGetNextEvent()) provide useful cues for when these functions may be successfully called. Typically, an application might catch both NORM_TX_QUEUE_EMPTY and NORM_TX_QUEUE_VACANCY event types as cues for enqueuing additional transport objects or writing to a stream. However, an application may choose to cue off of NORM_TX_QUEUE_EMPTY only if it wishes to provide the "freshest" data to NORM for transmission. The advantage of additionally using NORM_TX_QUEUE_VACANCY is that if the application uses this cue to fill up NORM transport object or stream buffers, it can keep the NORM stream busy sending data and realize the highest possible transmission rate when attempting very high speed communication (Otherwise, the NORM protocol engine may experience some "dead air time" waiting for the application thread to respond to a NORM_TX_QUEUE_EMPTY event). Note the sender application can control buffer depths as needed with the NormSetTxCacheBounds() and NormStreamOpen() calls. Additionally, it is possible for applications to configure the transmit object "cache" (see NormSetTxCacheBounds()) and use the NormRequeueObject() call (for objects that have not yet received a NORM_TX_OBJECT_PURGED notification) to effect a sort of "data carousel" operation with repeated transmission of the cached objects. The NORM_TX_OBJECT_SENT notification can be used a cue to properly control the "requeue" cycle(s).

The NORM implementation provides a form of timer-based flow control that limits how quickly sender applications may enqueue new objects or stream data for transmission. The NormSetFlowControl() call is provided to control this behavior, including the option to disable it. This timer-based mechanism is a type of "soft" flow control by allowing receivers "sufficient" time to request repair of pending data the sender has enqueued. A more explicit form of flow control using the optional "watermark flushing" mechanism is described below.

Another cue that can be leveraged by the sender application to determine when it is appropriate to enqueue (or write) additional data for transmission is the NORM_TX_WATERMARK_COMPLETED event. This event is posted when the flushing or explicit positive acknowledgment collection process has completed for a "watermark" point in transmission that was set by the sender (see NormSetWatermark() and NormAddAckingNode()). A list of NormNodeId values can be supplied from which explicit acknowledgement is expected and/or the NormNodeId NORM_NODE_NONE can be set (using NormAddAckingNode()) for completion of a NACK-based version of the watermark flushing procedure. This flushing process can be used as a flow control mechanism for NORM applications. Note this is distinct from NORM's congestion control mechanism that, while it provides network-friendly transmission rate control, does guarantee flow control to receiving nodes.NORM_NODE_NONE can be set (using NormAddAckingNode()) for completion of a NACK-based version of the watermark flushing procedure. This flushing process can be used as a flow control mechanism for NORM applications. Note this is distinct from NORM's congestion control mechanism that, while it provides network-friendly transmission rate control, does guarantee flow control to receiving nodes.

2.3.2. Data Reception

NORM receiver applications learn of active senders and their corresponding pending and completed data transfers, etc via the API event dispatching mechanism. By default, NORM receivers use NACK messages to request repair of transmitted content from the originating sender as needed to achieve reliable transfer. Some API functions are available to provide some additional control over the NACKing behavior, such as initially NACKing for NORM_INFO content only or even to the extent of disabling receiver feedback (silent receiver or emission-controlled (EMCON) operation) entirely. Otherwise, the parameters and operation of reliable data transmission are left to sender applications and receivers learn of sender parameters in NORM protocol message headers and are instructed by NORM_CMD messages from the sender(s).

With respect to the NORM API, the receiver application is informed of new senders and receive data objects via the the NORM_REMOTE_SENDER_NEW and NORM_RX_OBJECT_NEW notifications, respectfully. Additionally, object reception progress is indicated with the NORM_RX_OBJECT_UPDATED notification and this also serves as an indicator for the NORM_OBJECT_STREAM type that the receive application should make calls to NormStreamRead() to read newly received stream content. NORM sender status is also conveyed via the NORM_REMOTE_SENDER_ACTIVE and NORM_REMOTE_SENDER_INACTIVE notifications. For example, the receiver application may use the NORM_REMOTE_SENDER_INACTIVE as a cue to make calls to NormNodeFreeBuffers() and/or NormNodeDelete() to free memory resources allocated for buffering received content for the given sender. The amount of memory allocated per sender is set in the NormStartReceiver() call.

2.4. API Event Notification

An asynchronous event dispatching mechanism is provided to notify the application of significant NORM protocol events. The centerpiece of this is the NormGetNextEvent() function that can be used to retrieve the next NORM protocol engine event in the form of a NormEvent structure. This function will typically block until a NormEvent occurs. However, non-blocking operation may be achieved by using the NormGetDescriptor() call to get a NormDescriptor (file descriptor) value (Unix int or Win32 HANDLE) suitable for use in a asynchronous I/O monitoring functions such as the Unix select() or Win32 MsgWaitForMultipleObjects() system calls. The a NormDescriptor will be signaled when a NormEvent is available. For Win32 platforms, dispatching of a user-defined Windows message for NORM event notification is also planned for a future update to the NORM API.

3. Build Notes

To build applications that use the NORM library, a path to the "normApi.h" header file must be provided and the linker step needs to reference the NORM library file ("libnorm.a" for Unix platforms and "Norm.lib" for Win32 platforms). NORM also depends upon the NRL Protean Protocol Prototyping toolkit "Protokit" library (a.k.a "Protolib") (static library files "libProtokit.a" for Unix and "Protokit.lib" for Win32). Shared or dynamically-linked versions of these libraries may also be built from the NORM source code or provided. Depending upon the platform, some additional library dependencies may be required to support the needs of NORM and/or Protokit. These are described below.

The "makefiles" directory contains Unix Makefiles for various platforms the "win32" and "wince" sub-directories there contain Microsoft Visual C++ (VC++) and Embedded VC++ project files for building the NORM implementation. Additionally, a "waf" (Python-based build tool) build option is supported that can be used to build and install the NORM library code on the supported platforms. Finally, Python and Java bindings to the NORM API are included and "src/python" and "src/java" directories contain the code for these and the "makefiles/java" directory contains Makefiles to build the NORM Java JNI bindings. Note the "waf" tool can also be used to build the Java and Python bindings.

3.1. Unix Platforms

NORM has been built and tested on Linux (various architectures), MacOS (BSD), Solaris, and IRIX (SGI) platforms. The code should be readily portable to other Unix platforms.

To support IPv6 operation, the NORM and the Protokit library must be compiled with the "HAVE_IPV6" macro defined. This is default in the NORM and Protokit Makefiles for platforms that support IPv6. It is important that NORM and Protokit be built with this macro defined the same. With NORM, it is recommended that "large file support" options be enabled when possible.

The NORM API uses threading so that the NORM protocol engine may run independent of the application. Thus the "POSIX Threads" library must be included ("-pthread") in the linking step. MacOS/BSD also requires the addition of the "-lresolv" (resolver) library and Solaris requires the dynamic loader, network/socket, and resolver libraries ("-lnsl -lsocket -lresolv") to achieve successful compilation. The Makefiles in the NORM source code distribution are a reference for these requirements. Note that MacOS 9 and earlier are not supported.

Additionally, it is critical that the _FILE_OFFSET_BITS macro be consistently defined for the NORM library build and the application build using the library. The distributed NORM Makefiles have -D_FILE_OFFSET_BITS=64 set in the compilation to enable "large file support". Applications built using NORM should have the same compilation option set to operate correctly (The definition of the NormSize type in "normApi.h" depends upon this compilation flag).

3.2. Win32/WiNCE Platforms

NORM has been built using Microsoft's Visual C++ (6.0 and .NET) and Embedded VC++ 4.2 environments. In addition to proper macro definitions (e.g., HAVE_IPV6, etc) that are included in the respective "Protokit" and "NORM" project files, it is important that common code generation settings be used when building the NORM application. The NORM and Protokit projects are built with the "Multi-threading DLL" library usage set. The NORM API requires multi-threading support. This is a critical setting and numerous compiler and linker errors will result if this is not properly set for your application project.

NORM and Protokit also depend on the Winsock 2.0 ("ws2_32.lib" (or "ws2.lib" (WinCE)) and the IP Helper API ("iphlpapi.lib") libraries and these must be included in the project "Link" attributes.

An additional note is that a bug in VC++ 6.0 and earlier compilers (includes embedded VC++ 4.x compilers) prevent compilation of Protokit-based code with debugging capabilities enabled. However, this has been resolved in VC++ .NET and is hoped to be resolved in the future for the WinCE build tools.

Operation on Windows NT4 (and perhaps other older Windows operating systems) requires that the compile time macro WINVER=0x0400 defined. This is because the version of the IP Helper API library (iphlpapi.lib) used by Protolib (and hence NORM) for this system doesn't support some of the functions defined for this library. This may be related to IPv6 support issues so it may be possible that the Protolib build could be tweaked to provide a single binary executable suitable for IPv4 operation only across a large range of Windows platforms.

4. API Reference

This section provides a reference to the NORM API variable types, constants and functions.

4.1. API Variable Types and Constants

The NORM API defines and enumerates a number of supporting variable types and values which are used in different function calls. The variable types are described here.

4.1.1. NormInstanceHandle

The NormInstanceHandle type is returned when a NORM API instance is created (see NormCreateInstance()). This handle can be subsequently used for API calls which require reference to a specific NORM API instance. By default, each NORM API instance instantiated creates an operating system thread for protocol operation. Note that multiple NORM transport sessions may be created for a single API instance. In general, it is expected that applications will create a single NORM API instance, but some multi-threaded application designs may prefer multiple corresponding NORM API instances. The value NORM_INSTANCE_INVALID corresponds to an invalid API instance.

4.1.2. NormSessionHandle

The NormSessionHandle type is used to reference NORM transport sessions which have been created using the NormCreateSession() API call. Multiple NormSessionHandle values may be associated with a given NormInstanceHandle. The special value NORM_SESSION_INVALID is used to refer to invalid session references.

4.1.3. NormSessionId

The NormSessionId type is used by applications to uniquely identify their instance of participation as a sender within a NormSession. This type is a parameter to the NormStartSender() function. Robust applications can use different NormSessionId values when initiating sender operation so that receivers can discriminate when a sender has terminated and restarted (whether intentional or due to system failure). For example, an application could cache its prior NormSessionId value in non-volatile storage which could then be recovered and incremented (for example) upon system restart to produce a new value. The NormSessionId value is used for the value of the instance_id field in NORM protocol sender messages (see the NORM protocol specification) and receivers use this field to detect sender restart within a NormSession.

4.1.4. NormNodeHandle

The NormNodeHandle type is used to reference state kept by the NORM implementation with respect to other participants within a NormSession. Most typically, the NormNodeHandle is used by receiver applications to dereference information about remote senders of data as needed. The special value NORM_NODE_INVALID corresponds to an invalid reference.

4.1.5. NormNodeId

The NormNodeId type corresponds to a 32-bit numeric value which should uniquely identify a participant (node) in a given NormSession. The NormNodeGetId() function can be used to retrieve this value given a valid NormNodeHandle. The special value NORM_NODE_NONE corresponds to an invalid (or null) node while the value NORM_NODE_ANY serves as a wild card value for some functions.

4.1.6. NormObjectHandle

The NormObjectHandle type is used to reference state kept for data transport objects being actively transmitted or received. The state kept for NORM transport objects is temporary, but the NORM API provides a function to persistently retain state associated with a sender or receiver NormObjectHandle (see NormObjectRetain()) if needed. For sender objects, unless explicitly retained, the NormObjectHandle can be considered valid until the referenced object is explicitly canceled (see NormObjectCancel()) or purged from the sender transmission queue (see the event NORM_TX_OBJECT_PURGED). For receiver objects, these handles should be treated as valid only until a subsequent call to NormGetNextEvent() unless, again, specifically retained. The special value NORM_OBJECT_INVALID corresponds to an invalid transport object reference.

4.1.7. NormObjectType

The NormObjectType type is an enumeration of possible NORM data transport object types. As previously mentioned, valid types include:

  1. NORM_OBJECT_FILE

  2. NORM_OBJECT_DATA, and

  3. NORM_OBJECT_STREAM

Given a NormObjectHandle, the application may determine an object's type using the NormObjectGetType() function call. A special NormObjectType value, NORM_OBJECT_NONE, indicates an invalid object type.

4.1.8. NormSize

The NormSize is the type used for NormObject size information. For example, the NormObjectGetSize() function returns a value of type NormSize. The range of NormSize values depends upon the operating system and NORM library compilation settings. With "large file support" enabled, as is the case with distributed NORM library "Makefiles", the NormSize type is a 64-bit integer. However, some platforms may support only 32-bit object sizes.

4.1.9. NormObjectTransportId

The NormObjectTransportId type is a 16-bit numerical value assigned to NormObjects by senders during active transport. These values are temporarily unique with respect to a given sender within a NormSession and may be "recycled" for use for future transport objects. NORM sender nodes assign these values in a monotonically increasing fashion during the course of a session as part of protocol operation. Typically, the application should not need access to these values, but an API call such as NormObjectGetTransportId() (TBD) may be provided to retrieve these values if needed. (Note this type may be deprecated; i.e., it may not be needed at since the NormRequeueObject() function is implemented using handles only, but _some_ applications requiring persistence even after a system reboot may need the ability to recall previous transport ids?)

4.1.10. NormEventType

The NormEventType is an enumeration of NORM API events. "Events" are used by the NORM API to signal the application of significant NORM protocol operation events (e.g., receipt of a new receive object, etc). A description of possible NormEventType values and their interpretation is given below. The function call NormGetNextEvent() is used to retrieve events from the NORM protocol engine.

4.1.11. NormEvent

The NormEvent type is a structure used to describe significant NORM protocol events. This structure is defined as follows:

typedef struct
{
    NormEventType     type;
    NormSessionHandle session; 
    NormNodeHandle    node;
    NormObjectHandle  object;
} NormEvent;

The type field indicates the NormEventType and determines how the other fields should be interpreted. Note that not all NormEventType fields are relevant to all events. The session, node, and object fields indicate the applicable NormSessionHandle, NormNodeHandle, and NormObjectHandle, respectively, to which the event applies. NORM protocol events are made available to the application via the NormGetNextEvent() function call.

4.1.12. NormDescriptor

The NormDescriptor type can provide a reference to a corresponding file descriptor (Unix int or Win32 HANDLE) for the NormInstance. For a given NormInstanceHandle, the NormGetDescriptor() function can be used to retrieve a NormDescriptor value that may, in turn, used in appropriate system calls (e.g. select() or MsgWaitForMultipleObjects()) to asynchronously monitor the NORM protocol engine for notification events (see NormEvent description).

4.1.13. NormFlushMode

The NormFlushMode type consists of the following enumeration:

enum NormFlushMode
{
    NORM_FLUSH_NONE,
    NORM_FLUSH_PASSIVE,
    NORM_FLUSH_ACTIVE
};

The use and interpretation of these values is given in the descriptions of NormStreamFlush() and NormStreamSetAutoFlush() functions.

4.1.14. NormProbingMode

The NormProbingMode type consists of the following enumeration:

enum NormProbingMode
{
    NORM_PROBE_NONE,
    NORM_PROBE_PASSIVE,
    NORM_PROBE_ACTIVE
};

The use and interpretation of these values is given in the description of NormSetGrttProbingMode() function.

4.1.15. NormSyncPolicy

The NormSyncPolicy type consists of the following enumeration:

enum NormSyncPolicy
{
    NORM_SYNC_CURRENT,
    NORM_SYNC_ALL
};

The use and interpretation of these values is given in the descriptions of the NormSetDefaultSyncPolicy() function.

4.1.16. NormNackingMode

The NormNackingMode type consists of the following enumeration:

enum NormNackingMode
{
    NORM_NACK_NONE,
    NORM_NACK_INFO_ONLY,
    NORM_NACK_NORMAL
};

The use and interpretation of these values is given in the descriptions of the NormSetDefaultNackingMode(), NormNodeSetNackingMode() and NormObjectSetNackingMode() functions.

4.1.17. NormRepairBoundary

The NormRepairBoundary types consists of the following enumeration:

enum NormRepairBoundary
{
    NORM_BOUNDARY_BLOCK,
    NORM_BOUNDARY_OBJECT
};

The interpretation of these values is given in the descriptions of the NormSetDefaultRepairBoundary() and NormNodeSetRepairBoundary() functions.

4.1.18. NormAckingStatus

The NormAckingStatus consist of the following enumeration:

enum NormAckingStatus
{
    NORM_ACK_INVALID, 
    NORM_ACK_FAILURE,
    NORM_ACK_PENDING,
    NORM_ACK_SUCCESS
};

The interpretation of these values is given in the descriptions of the NormGetAckingStatus() function.

4.2. API Initialization and Operation

The first step in using the NORM API is to create an "instance" of the NORM protocol engine. Note that multiple instances may be created by the application if necessary, but generally only a single instance is required since multiple NormSessions may be managed under a single NORM API instance.

4.2.1. NormCreateInstance()

4.2.1.1. Synopsis
#include <normApi.h>

NormInstanceHandle NormCreateInstance(bool priorityBoost = false);
4.2.1.2. Description

This function creates an instance of a NORM protocol engine and is the necessary first step before any other API functions may be used. With the instantiation of the NORM protocol engine, an operating system thread is created for protocol execution. The returned NormInstanceHandle value may be used in subsequent API calls as needed, such NormCreateSession(), etc. The optional priorityBoost parameter, when set to a value of true, specifies that the NORM protocol engine thread be run with higher priority scheduling. On Win32 platforms, this corresponds to THREAD_PRIORITY_TIME_CRITICAL and on Unix systems with the sched_setscheduler() API, an attempt to get the maximum allowed SCHED_FIFO priority is made. The use of this option should be carefully evaluated since, depending upon the application's scheduling priority and NORM API usage, this may have adverse effects instead of a guaranteed performance increase!

4.2.1.3. Return Values

A value of NORM_INSTANCE_INVALID is returned upon failure. The function will only fail if system resources are unavailable to allocate the instance and/or create the corresponding thread.

4.2.2. NormDestroyInstance()

4.2.2.1. Synopsis
#include <normApi.h>

void NormDestroyInstance(NormInstanceHandle instanceHandle);
4.2.2.2. Description

The NormDestroyInstance() function immediately shuts down and destroys the NORM protocol engine instance referred to by the instanceHandle parameter. The application should make no subsequent references to the indicated NormInstanceHandle or any other API handles or objects associated with it. However, the application is still responsible for releasing any object handles it has retained (see NormObjectRetain() and NormObjectRelease()).

4.2.2.3. Return Values

The function has no return value.

4.2.3. NormStopInstance()

4.2.3.1. Synopsis
#include <normApi.h>

void NormStopInstance(NormInstanceHandle instanceHandle);
4.2.3.2. Description

This function immediately stops the NORM protocol engine thread corresponding to the given instanceHandle parameter. It also posts a "dummy" notification event so that if another thread is blocked on a call to NormGetNextEvent(), that thread will be released. Hence, for some multi-threaded uses of the NORM API, this function may be useful as a preliminary step to safely coordinate thread shutdown before a call is made to NormDestroyInstance(). After NormStopInstance() is called and any pending events posted prior to its call have been retrieved, NormGetNextEvent() will return a value of false.

When this function is invoked, state for any NormSessions associated with the given instance is "frozen". The complementary function, NormRestartInstance() can be subsequently used to "unfreeze" and resume NORM protocol operation (a new thread is created and started).

4.2.3.3. Return Values

The function has no return value.

4.2.4. NormRestartInstance()

4.2.4.1. Synopsis
#include <normApi.h>

bool NormRestartInstance(NormInstanceHandle instanceHandle);
4.2.4.2. Description

This function creates and starts an operating system thread to resume NORM protocol engine operation for the given instanceHandle that was previously stopped by a call to NormStopInstance(). It is not expected that this function will be used often, but there may be special application cases where "freezing" and later resuming NORM protocol operation may be useful.

4.2.4.3. Return Values

The function returns true when the NORM protocol engine thread is successfully restarted, and false otherwise.

4.2.5. NormSetCacheDirectory()

4.2.5.1. Synopsis
#include <normApi.h>

bool NormSetCacheDirectory(NormInstanceHandle    instanceHandle,
                           const char*           cachePath);
4.2.5.2. Description

This function sets the directory path used by receivers to cache newly-received NORM_OBJECT_FILE content. The instanceHandle parameter specifies the NORM protocol engine instance (all NormSessions associated with that instanceHandle share the same cache path) and the cachePath is a string specifying a valid (and writable) directory path.

4.2.5.3. Return Values

The function returns true on success and false on failure. The failure conditions are that the indicated directory does not exist or the process does not have permissions to write.

4.2.6. NormGetNextEvent()

4.2.6.1. Synopsis
#include <normApi.h>

bool NormGetNextEvent(NormInstanceHandle instanceHandle,
                      NormEvent*         theEvent);
4.2.6.2. Description

This function retrieves the next available NORM protocol event from the protocol engine. The instanceHandle parameter specifies the applicable NORM protocol engine, and the theEvent parameter must be a valid pointer to a NormEvent structure capable of receiving the NORM event information. For expected reliable protocol operation, the application should make every attempt to retrieve and process NORM notification events in a timely manner.

Note that this is currently the only blocking call in the NORM API. But non-blocking operation may be achieved by using the NormGetDescriptor() function to obtain a descriptor (int for Unix or HANDLE for WIN32) suitable for asynchronous input/output (I/O) notification using such system calls the Unix select() or Win32 WaitForMultipleObjects() calls. The descriptor is signaled when a notification event is pending and a call to NormGetNextEvent() will not block.NormGetNextEvent

4.2.6.3. Return Values

The function returns true when a NormEvent is successfully retrieved, and false otherwise. Note that a return value of false does not indicate an error or signify end of NORM operation.

4.2.6.4. NORM Notification Event Types

The following table enumerates the possible NormEvent values and describes how these notifications should be interpreted as they are retrieved by the application via the NormGetNextEvent() function call.

Sender Notifications:

 

NORM_TX_QUEUE_VACANCY

This event indicates that there is room for additional transmit objects to be enqueued, or, if the handle of NORM_OBJECT_STREAM is given in the corresponding event "object" field, the application may successfully write to the indicated stream object. Note this event is not dispatched until a call to NormFileEnqueue(), NormDataEnqueue(), or NormStreamWrite() fails because of a filled transmit cache or stream buffer.

NORM_TX_QUEUE_EMPTY

This event indicates the NORM protocol engine has no new data pending transmission and the application may enqueue additional objects for transmission. If the handle of a sender NORM_OBJECT_STREAM is given in the corresponding event "object" field, this indicates the stream transmit buffer has been emptied and the sender application may write to the stream (Use of NORM_TX_QUEUE_VACANCY may be preferred for this purpose since it allows the application to keep the NORM protocol engine busier sending data, resulting in higher throughput when attempting very high transfer rates).

NORM_TX_FLUSH_COMPLETED

This event indicates that the flushing process the NORM sender observes when it no longer has data ready for transmission has completed. The completion of the flushing process is a reasonable indicator (with a sufficient NORM "robust factor" value) that the receiver set no longer has any pending repair requests. Note the use of NORM's optional positive acknowledgement feature is more deterministic in this regards, but this notification is useful when there are non-acking (NACK-only) receivers. The default NORM robust factor of 20 (20 flush messages are sent at end-of-transmission) provides a high assurance of reliable transmission, even with packet loss rates of 50%.

NORM_TX_WATERMARK_COMPLETED

This event indicates that the flushing process initiated by a prior application call to NormSetWatermark() has completed The posting of this event indicates the appropriate time for the application to make a call NormGetAckingStatus() to determine the results of the watermark flushing process.

NORM_TX_OBJECT_SENT

This event indicates that the transport object referenced by the event's "object" field has completed at least one pass of total transmission. Note that this does not guarantee that reliable transmission has yet completed; only that the entire object content has been transmitted. Depending upon network behavior, several rounds of NACKing and repair transmissions may be required to complete reliable transfer.

NORM_TX_OBJECT_PURGED

This event indicates that the NORM protocol engine will no longer refer to the transport object identified by the event's "object' field. Typically, this will occur when the application has enqueued more objects than space available within the set sender transmit cache bounds (see NormSetTxCacheBounds()). Posting of this notification means the application is free to free any resources (memory, files, etc) associated with the indicated "object". After this event, the given "object" handle (NormObjectHandle) is no longer valid unless it is specifically retained by the application.NormObjectHandle

NORM_TX_CMD_SENTThis event indicates that an application-defined command previously enqueued with a call to NormSendCommand() has been transmitted, including any repetition.
NORM_TX_RATE_CHANGEDThis event indicates that NORM Congestion Control operation has adjusted the transmission rate. The NormGetTxRate() call may be used to retrieve the new corresponding transmission rate. Note that if NormSetCongestionControl() was called with its adjustRate parameter set to false, then no actual rate change has occurred and the rate value returned by NormGetTxRate() reflects a "suggested" rate and not the actual transmission rate.

NORM_LOCAL_SENDER_CLOSED

This event is posted when the NORM protocol engine completes the "graceful shutdown" of its participation as a sender in the indicated "session" (see NormStopSender()).

NORM_CC_ACTIVE

This event indicates that congestion control feedback from receivers has begun to be received (This also implies that receivers in the group are actually present and can be used as a cue to begin data transmission.). Note that congestion control must be enabled (see NormSetCongestionControl()) for this event to be posted. Congestion control feedback can be assumed to be received until a NORM_CC_INACTIVE event is posted.

NORM_CC_INACTIVE

This event indicates there has been no recent congestion control feedback received from the receiver set and that the local NORM sender has reached its minimum transmit rate. Applications may wish to refrain from new data transmission until a NORM_CC_ACTIVE event is posted. This notification is only posted when congestion control operation is enabled (see NormSetCongestionControl()) and a previous NORM_CC_ACTIVE event has occurred.

Receiver Notifications:

 

NORM_REMOTE_SENDER_NEW

This event is posted when a receiver first receives messages from a specific remote NORM sender. This marks the beginning of the interval during which the application may reference the provided "node" handle (NormNodeHandle).

NORM_REMOTE_SENDER_ACTIVE

This event is posted when a previously inactive (or new) remote sender is detected operating as an active sender within the session.

NORM_REMOTE_SENDER_INACTIVE

This event is posted after a significant period of inactivity (no sender messages received) of a specific NORM sender within the session. The NORM protocol engine frees buffering resources allocated for this sender when it becomes inactive.

NORM_REMOTE_SENDER_PURGED

This event is posted when the NORM protocol engine frees resources for, and thus invalidates the indicated "node" handle.

NORM_RX_OBJECT_NEW

This event is posted when reception of a new transport object begins and marks the beginning of the interval during which the specified "object" (NormObjectHandle) is valid.

NORM_RX_OBJECT_INFO

This notification is posted when the NORM_INFO content for the indicated "object" is received.

NORM_RX_OBJECT_UPDATED

This event indicates that the identified receive "object" has newly received data content.

NORM_RX_OBJECT_COMPLETED

This event is posted when a receive object is completely received, including available NORM_INFO content. Unless the application specifically retains the "object" handle, the indicated NormObjectHandle becomes invalid and must no longer be referenced.

NORM_RX_OBJECT_ABORTED

This notification is posted when a pending receive object's transmission is aborted by the remote sender. Unless the application specifically retains the "object" handle, the indicated NormObjectHandle becomes invalid and must no longer be referenced.

NORM_RX_CMD_NEWThis event indicates that an application-defined command has been received from a remote sender. The NormEvent node element indicates the NormNodeHandle value associated with the given sender. The NormNodeGetCommand() call can be used to retrieve the received command content.

Miscellaneous Notifications:

 

NORM_GRTT_UPDATED

This notification indicates that either the local sender estimate of GRTT has changed, or that a remote sender's estimate of GRTT has changed. The "sender" member of the NormEvent is set to NORM_NODE_INVALID if the local sender's GRTT estimate has changed or to the NormNodeHandle of the remote sender that has updated its estimate of GRTT.

NORM_EVENT_INVALID

This NormEventType indicates an invalid or "null" notification which should be ignored.

4.2.6.5. Return Values

This function generally blocks the thread of application execution until a NormEvent is available and returns true when a NormEvent is available. However, there are some exceptional cases when the function may immediately return even when no event is pending. In these cases, the return value is false indicating the NormEvent should be ignored.

Win32 Note: A future version of this API will provide an option to have a user-defined Window message posted when a NORM API event is pending. (Also some event filtering calls may be provided (e.g. avoid the potentially numerous NORM_RX_OBJECT_UPDATED events if not needed by the application)).

4.2.7. NormGetDescriptor()

4.2.7.1. Synopsis
#include <normApi.h>

NormDescriptor NormGetDescriptor(NormInstanceHandle instance);
4.2.7.2. Description

This function is used to retrieve a NormDescriptor (Unix int file descriptor or Win32 HANDLE) suitable for asynchronous I/O notification to avoid blocking calls to NormGetNextEvent(). A NormDescriptor is available for each protocol engine instance created using NormCreateInstance(). The descriptor returned is suitable for use as an input (or "read") descriptor which is signaled when a NORM protocol event is ready for retrieval via NormGetNextEvent(). Hence, a call to NormGetNextEvent() will not block when the descriptor has been signaled. The Unix select() or Win32 WaitForMultipleObjects() system calls can be used to detect when the NormDescriptor is signaled. Note that for Unix select() call usage, the NORM descriptor should be treated as a "read" descriptor.

4.2.7.3. Return Values

A NormDescriptor value is returned which is valid until a call to NormDestroyInstance() is made. Upon error, a value of NORM_DESCRIPTOR_INVALID is returned.

4.3. Session Creation and Control Functions

Whether participating in a NORM protocol session as a sender, receiver, or both, there are some common API calls used to instantiate a NormSession and set some common session parameters. Functions are provided to control network socket and multicast parameters. Additionally, a "user data" value may be associated with a NormSessionHandle for programming convenience when dealing with multiple sessions.

4.3.1. NormCreateSession()

4.3.1.1. Synopsis
#include <normApi.h
NormSessionHandle NormCreateSession(NormInstanceHandle       instance,
                                    const char*              address,
                                    unsigned short           port,
                                    NormNodeId               localId);
4.3.1.2. Description

This function creates a NORM protocol session (NormSession) using the address (multicast or unicast) and port parameters provided. While session state is allocated and initialized, active session participation does not begin until a call is made to NormStartSender() and/or NormStartReceiver() to join the specified multicast group (if applicable) and start protocol operation. The following parameters are required in this function call:

instance

This must be a valid NormInstanceHandle previously obtained with a call to NormCreateInstance().

address

This points to a string containing an IP address (e.g. dotted decimal IPv4 address (or IPv6 address) or name resolvable to a valid IP address. The specified address (along with the port number) determines the destination of NORM messages sent. For multicast sessions, NORM senders and receivers must use a common multicast address and port number. For unicast sessions, the sender and receiver must use a common port number, but specify the other node's IP address as the session address (Although note that receiver-only unicast nodes who are providing unicast feedback to senders will not generate any messages to the session IP address and the address parameter value is thus inconsequential for this special case).

port

This must be a valid, unused port number corresponding to the desired NORM session address. See the address parameter description for more details.

localId

The localId parameter specifies the NormNodeId that should be used to identify the application's presence in the NormSession. All participant's in a NormSession should use unique localId values. The application may specify a value of NORM_NODE_ANY or NORM_NODE_ANY for the localId parameter. In this case, the NORM implementation will attempt to pick an identifier based on the host computer's "default" IP address (based on the computer's default host name). Note there is a chance that this approach may not provide unique node identifiers in some situations and the NORM protocol does not currently provide a mechanism to detect or resolve NormNodeId collisions. Thus, the application should explicitly specify the localId unless there is a high degree of confidence that the default IP address will provide a unique identifier.

4.3.1.3. Return Values

The returned NormSessionHandle value is valid until a call to NormDestroySession() is made. A value of NORM_SESSION_INVALID is returned upon error.

4.3.2. NormDestroySession()

4.3.2.1. Synopsis
#include <normApi.h>

void NormDestroySession(NormSessionHandle sessionHandle);
4.3.2.2. Description

This function immediately terminates the application's participation in the NormSession identified by the sessionHandle parameter and frees any resources used by that session. An exception to this is that the application is responsible for releasing any explicitly retained NormObjectHandle values (See NormObjectRetain() and NormObjectRelease()).

4.3.2.3. Return Values

This function has no returned values.

4.3.3. NormSetUserData()

4.3.3.1. Synopsis
#include <normApi.h>

void NormSetUserData(NormSessionHandle sessionHandle,
                     const void*       userData);
4.3.3.2. Description

This function allows the application to attach a value to the previously-created NormSession instance specified by the sessionHandle parameter. This value is not used or interpreted by NORM, but is available to the application for use at the programmer's discretion. The set userData value can be later retrieved using the NormGetUserData() function call.

4.3.3.3. Return Values

This function has no returned values.

4.3.4. NormGetUserData()

4.3.4.1. Synopsis
#include <normApi.h>

const void* NormGetUserData(NormSessionHandle sessionHandle);
4.3.4.2. Description

This function retrieves the "user data" value set for the specified sessionHandle with a prior call to NormSetUserData().

4.3.4.3. Return Values

This function returns the user data value set for the specified session. If no user data value has been previously set, a NULL (i.e., (const void*)0) value is returned.

4.3.5. NormGetLocalNodeId()

4.3.5.1. Synopsis
#include <normApi.h>

NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle);
4.3.5.2. Description

This function retrieves the NormNodeId value used for the application's participation in the NormSession identified by the sessionHandle parameter. The value may have been explicitly set during the NormCreateSession() call or may have been automatically derived using the host computer's "default" IP network address.

4.3.5.3. Return Valuess

The returned value indicates the NormNode identifier used by the NORM protocol engine for the local application's participation in the specified NormSession.

4.3.6. NormSetTxPort()

4.3.6.1. Synopsis
#include <normApi.h>

bool NormSetTxPort(NormSessionHandle sessionHandle,
                   unsigned short    txPort,
                   bool              enableReuse = false,
                   const char*       txBindAddress = (const char*)0);
4.3.6.2. Description

This function is used to force NORM to use a specific port number for UDP packets sent for the specified sessionHandle. Additionally, it can optionally enable reuse of the specified port number and/or specify a specific source address binding that is used for packet transmission. By default, NORM uses separate port numbers for packet transmission and session packet reception (the receive port is specified as part of the NormCreateSession() call), allowing the operating system to pick a freely available port for transmission. This call allows the application to pick a specific port number for transmission, and furthermore allows the application to even specify the same port number for transmission as is used for reception. However, the use of separate transmit/receive ports allows NORM to discriminate when unicast feedback is occurring and thus it is not generally recommended that the transmit port be set to the same value as the session receive port.

The enableReuse parameter, when set to true, allows that the specified port may be reused for multiple sessions, but care must be taken when enabling this option. The txBindAddress parameter allows specification of a specific source address binding for packet transmission. The specified address MUST be a valid unicast IP address assigned and configured for the host system. Additionally, the address specified must be compatible with multicast routing and/or the interfaces specified in any calls to NormSetMulticastInterface() for the given session when IP multicast is used.

When the txPort is set equal to the session port number and a txBindAddress is not specified or set equal to the session address, a single socket is used for both transmission and reception. If the same port number is desired for both packet transmission and reception, and a specific source address binding is set, then the enableReuse parameter MUST be (and is automatically) set to true for successful operation. In this case, the receive socket is bound to session address if it is multicast and the transmit socket is bound to the specified txAddress although both are bound to the same port number.

Note this call MUST be made before any calls to NormStartSender() or NormStartReceiver() for the given session to work as described.

4.3.6.3. Return Values

This function returns true upon success and false upon failure. Failure will occur if a txBindAddress is provided that does not correspond to a valid, configured IP address for the local host system.

4.3.7. NormSetTxOnly()

4.3.7.1. Synopsis
#include <normApi.h>

void NormSetTxOnly(NormSessionHandle sessionHandle,
                   bool              txOnly,
                   bool              connectToSessionAddress = false);
4.3.7.2. Description

This function limits the NormSession to perform NORM sender functions only. It also limits the underlying NORM UDP socket usage to open only a single transmit socket (tx_socket) and does not open or bind a receive socket for the given session address or port number. Thus, if this property is set, any NORM receivers MUST enable unicast feedback via a call to the NormSetDefaultUnicastNack() or appropriate NormNodeSetUnicastNack() function in order for their feedback messages (NACKs and ACKs) to be received by this sender. The purpose of this function is to allow NORM sender sessions to be created as separate process from a corresponding NORM receiver session for the same session address and port number. By default (when this call is not made), a NormSession, even when acting as only a sender (see NormStartSender()) opens two separate UDP sockets including a "receive" socket bound to the session port number and a "transmit" socket used for message transmission and reception of unicast feedback messages when receivers are so configured.

The optional connectToSessionAddress parameter, when set to true, causes the underlying NORM code to "connect()" the UDP socket to the session (remote receiver) address and port number. If the corresponding NORM remote receiver instance uses NormSetTxPort() to set its transmit port to the same as the session port number, the result is a unique binding between this "tx only" sender instance and the remote NORM receiver instance. With proper use of NormSetRxPortReuse(), this allows multiple senders to be properly associated (i.e., binded with respect to UDP socket packet demultiplexing) with multiple receivers on a single host (all using the same session port number). Note the NORM receiver MUST also use the NormSetDefaultUnicastNack() call so that its feedback messages are directed to the "tx only" sender address/port. The motivation for this API call is to allow systems have NORM sender and receiver instances in separate processes supporting a set (e.g. a mesh) of unicast connections to other hosts. The only constraint is that the senders uses a "tx port" number that is different from the "rx port" number. This enables firewall configurations that only open a pair of UDP ports and allow for connection among an arbitrary number of hosts. This option is really only relevant for unicast NORM sessions.

4.3.7.3. Return Values

This function has no return values.

4.3.8. NormSetRxPortReuse()

4.3.8.1. Synopsis
#include <normApi.h>

void NormSetRxPortReuse(NormSessionHandle session,
                        bool              enableReuse,
                        const char*       rxBindAddress = (const char*)0,
                        const char*       senderAddress = (const char*)0,
                        UINT16            senderPort = 0);
4.3.8.2. Description

This function allows the user to control the port reuse and binding behavior for the receive socket used for the given NORM sessionHandle. When the enablReuse parameter is set to true, reuse of the NormSession port number by multiple NORM instances or sessions is enabled.

If the optional rxBindAddress is supplied (an IP address or host name in string form), the socket will bind() to the given address when it is opened in a call to NormStartReceiver() or NormStartSender(). The rxBindAddress MUST be the session multicast address (if it is a multicast session) or a valid local unicast address in the case of NORM unicast operation. This binding limits the socket to receive only packets destined for the specified rxBindAddress. This allows multiple NORM sessions to reuse the same port number, but use different multicast addresses (or allow for multiple NORM sessions for multiple local unicast addresses).

The optional senderAddress and senderPort parameters can be used to connect() the underlying NORM receive socket to specific address/port. This limits the socket to receiving only packets from the specified senderAddress/senderPort. This, with receive port reuse enabled, allows for multiple NORM receiver instances to be listening to different NORM senders and have proper UDP socket demultiplexing occur. Note that it is also possible to have single NORM receiver receive transmissions from multiple senders, but in some cases it may be desirable for separate NORM processes or threads to be used to handle reception from separate senders. Thus, this socket binding option is provided.

When this call is not made in any form, the default socket binding to IP address INADDR_ANY (equivalent to when this call is made and rxBindAddress is set to NULL) allows the NormSession receive socket to receive any multicast or unicast transmissions to the session port number provided in the call to NormCreateSession(). This allows a NORM receiver to receive from senders sending to a multicast session address or the receiver's unicast address. As mentioned, enabling port reuse and binding the session destination address allows multiple NORM sessions on the same port number, but participating in different multicast groups.

Note this call MUST be made before any calls to NormStartSender() or NormStartReceiver() for the given sessionHandle to succeed.

This call could also be used in conjunction with NormSetMulticastInterface() so that multiple NormSessions, using the same port and multicast address, could separately cover multiple network interfaces (and some sort of application-layer bridging of reliable multicast could be realized if desired).

4.3.8.3. Return Values

This function has no return values.

4.3.9. NormSetMulticastInterface()

4.3.9.1. Synopsis
#include <normApi.h>

bool NormSetMulticastInterface(NormSessionHandle session,
                               const char*       interfaceName);
4.3.9.2. Description

This function specifies which host network interface is used for IP Multicast transmissions and group membership. This should be called before any call to NormStartSender() or NormStartReceiver() is made so that the IP multicast group is joined on the proper host interface. However, if a call to NormSetMulticastInterface() is made after either of these function calls, the call will not affect the group membership interface, but only dictate that a possibly different network interface is used for transmitted NORM messages. Thus, the code:

NormSetMulticastInterface(session, "interface1");
NormStartReceiver(session, ...);
NormSetMulticastInterface(session, "interface2");

will result in NORM group membership (i.e. multicast reception) being managed on "interface1" while NORM multicast transmissions are made via "interface2".

4.3.9.3. Return Values

A return value of true indicates success while a return value of false indicates that the specified interface was invalid. This function will always return true if made before calls to NormStartSender() or NormStartReceiver(). However, those calls may fail if an invalid interface was specified with the call described here.

4.3.10. NormSetSSM()

4.3.10.1. Synopsis
#include <normApi.h>

bool NormSetSSM(NormSessionHandle session,
                const char*       sourceAddress);
4.3.10.2. Description

This function sets the source address for Source-Specific Multicast (SSM) operation. This should be called before any call to NormStartSender() or NormStartReceiver() is made so that the proper group join is done. The receiver application MUST also use the NormSetDefaultUnicastNack() call so that feedback traffic is directed back to appropriate sender.

4.3.10.3. Return Values

A return value of true indicates success while a return value of false indicates that the specified source address was invalid. Note that if a valid IP address is specified but is improper for SSM (e.g., an IP multicast address) the later calls to NormStartSender() or NormStartReceiver() may fail.

4.3.11. NormSetTTL()

4.3.11.1. Synopsis
#include <normApi.h>

bool NormSetTTL(NormSessionHandle session,
                unsigned char     ttl);
4.3.11.2. Description

This function specifies the time-to-live (ttl) for IP Multicast datagrams generated by NORM for the specified sessionHandle. The IP TTL field limits the number of router "hops" that a generated multicast packet may traverse before being dropped. For example, if TTL is equal to one, the transmissions will be limited to the local area network (LAN) of the host computers network interface. Larger TTL values should be specified to span large networks. Also note that some multicast router configurations use artificial "TTL threshold" values to constrain some multicast traffic to an administrative boundary. In these cases, the NORM TTL setting must also exceed the router "TTL threshold" in order for the NORM traffic to be allowed to exit the administrative area.

4.3.11.3. Return Values

A return value of true indicates success while a return value of false indicates that the specified ttl could not be set. This function will always return true if made before calls to NormStartSender() or NormStartReceiver(). However, those calls may fail if the desired ttl value cannot be set.

4.3.12. NormSetTOS()

4.3.12.1. Synopsis
#include <normApi.h>

bool NormSetTOS(NormSessionHandle       sessionHandle,
                unsigned char           tos);
4.3.12.2. Description

This function specifies the type-of-service (tos) field value used in IP Multicast datagrams generated by NORM for the specified sessionHandle. The IP TOS field value can be used as an indicator that a "flow" of packets may merit special Quality-of-Service (QoS) treatment by network devices. Users should refer to applicable QoS information for their network to determine the expected interpretation and treatment (if any) of packets with explicit TOS marking.

4.3.12.3. Return Values

A return value of true indicates success while a return value of false indicates that the specified tos could not be set. This function will always return true if made before calls to NormStartSender() or NormStartReceiver(). However, those calls may fail if the desired tos value cannot be set.

4.3.13. NormSetLoopback()

4.3.13.1. Synopsis
#include <normApi.h>

void NormSetLoopback(NormSessionHandle sessionHandle,
                     bool              loopbackEnable);
4.3.13.2. Description

This function enables or disables loopback operation for the indicated NORM sessionHandle. If loopbackEnable is set to true, loopback operation is enabled which allows the application to receive its own message traffic. Thus, an application which is both actively receiving and sending may receive its own transmissions. Note it is expected that this option would be principally be used for test purposes and that applications would generally not need to transfer data to themselves. If loopbackEnable is false, the application is prevented from receiving its own NORM message transmissions. By default, loopback operation is disabled when a NormSession is created.

4.3.13.3. Return Values

This function has no return values.

4.3.14. NormSetFragmentation()

4.3.14.1. Synopsis
#include <normApi.h>

bool NormSetFragmentation(NormSessionHandle sessionHandle,
                          bool              fragmentation);
4.3.14.2. Description

This function sets an underlying socket option that enables or disables IP datagram fragmentation by network intermediate systems according to whether the fragmentation parameter is set to a value of true or false, respectively. If set to true to enable fragmentation, the DF (don't fragment) bit of the headers of NORM UDP/IP packets sent will be cleared. Otherwise the DF bit is set and packets will not be fragmented by network devices if they exceed a link Maximum Transmission Unit (MTU) and will instead be dropped. For IP Multicast destinations, some operating systems may always set the DF bit of transmitted packets, regardless of the setting here and the underlying socket option status. Typically, the DF bit is set (i.e., fragmentation disabled) by default on most operating systems.

This call is not currently functional on the Mac OSX system that does not support the needed IP_MTU_DISCOVER or IP_DONTFRAG socket options.

4.3.14.3. Return Values

This function returns true upon success and false upon failure.

4.4. NORM Sender Functions

The functions described in this section apply only to NORM sender operation. Applications may participate strictly as senders or as receivers, or may act as both in the context of a NORM protocol session. The NORM sender is responsible for most parameters pertaining to its transmission of data. This includes transmission rate, data segmentation sizes, FEC coding parameters, stream buffer sizes, etc.

4.4.1. NormStartSender()

4.4.1.1. Synopsis
#include <normApi.h>

bool NormStartSender(NormSessionHandle        sessionHandle,
                     NormSessionId            instanceId,
                     unsigned long            bufferSpace,
                     unsigned short           segmentSize,
                     unsigned char            blockSize,
                     unsigned char            numParity);
4.4.1.2. Description

The application's participation as a sender within a specified NormSession begins when this function is called. This includes protocol activity such as congestion control and/or group round-trip timing (GRTT) feedback collection and application API activity such as posting of sender-related NormEvent notifications. The parameters required for this function call include:

sessionHandle

This must be a valid NormSessionHandle previously obtained with a call to NormCreateSession().

instanceId

Application-defined value used as the instance_id field of NORM sender messages for the application's participation within a session. Receivers can detect when a sender has terminated and restarted if the application uses different instanceId values when initiating sender operation. For example, a robust application could cache previous instanceId values in non-volatile storage and gracefully recover (without confusing receivers) from a total system shutdown and reboot by using a new instanceId value upon restart.

bufferSpace

This specifies the maximum memory space (in bytes) the NORM protocol engine is allowed to use to buffer any sender calculated FEC segments and repair state for the session. The optimum bufferSpace value is function of the network topology bandwidth*delay product and packet loss characteristics. If the bufferSpace limit is too small, the protocol may operate less efficiently as the sender is required to possibly recalculate FEC parity segments and/or provide less efficient repair transmission strategies (resort to explicit repair) when state is dropped due to constrained buffering resources. However, note the protocol will still provide reliable transfer. A large bufferSpace allocation is safer at the expense of possibly committing more memory resources.

segmentSize

This parameter sets the maximum payload size (in bytes) of NORM sender messages (not including any NORM message header fields). A sender's segmentSize value is also used by receivers to limit the payload content of some feedback messages (e.g. NORM_NACK message content, etc.) generated in response to that sender. Note different senders within a NormSession may use different segmentSize values. Generally, the appropriate segment size to use is dependent upon the types of networks forming the multicast topology, but applications may choose different values for other purposes. Note that application designers MUST account for the size of NORM message headers when selecting a segmentSize. For example, the NORM_DATA message header for a NORM_OBJECT_STREAM with full header extensions is 48 bytes in length. In this case, the UDP payload size of these messages generated by NORM would be up to (48 + segmentSize) bytes.

blockSize

This parameter sets the number of source symbol segments (packets) per coding block, for the systematic Reed-Solomon FEC code used in the current NORM implementation. For traditional systematic block code "(n,k)" nomenclature, the blockSize value corresponds to "k". NORM logically segments transport object data content into coding blocks and the blockSize parameter determines the number of source symbol segments (packets) comprising a single coding block where each source symbol segment is up to segmentSize bytes in length.. A given block's parity symbol segments are calculated using the corresponding set of source symbol segments. The maximum blockSize allowed by the 8-bit Reed-Solomon codes in NORM is 255, with the further limitation that (blockSize + numParity) <= 255.

numParity

This parameter sets the maximum number of parity symbol segments (packets) the sender is willing to calculate per FEC coding block. The parity symbol segments for a block are calculated from the corresponding blockSize source symbol segments. In the "(n,k)" nomenclature mention above, the numParity value corresponds to "n - k". A property of the Reed-Solomon FEC codes used in the current NORM implementation is that one parity segment can fill any one erasure (missing segment (packet)) for a coding block. For a given blockSize, the maximum numParity value is (255 - blockSize). However, note that computational complexity increases significantly with increasing numParity values and applications may wish to be conservative with respect to numParity selection, given anticipated network packet loss conditions and group size scalability concerns. Additional FEC code options may be provided for this NORM implementation in the future with different parameters, capabilities, trade-offs, and computational requirements.

These parameters are currently immutable with respect to a sender's participation within a NormSession. Sender operation must be stopped (see NormStopSender()) and restarted with another call to NormStartSender() if these parameters require alteration. The API may be extended in the future to support additional flexibility here, if required. For example, the NORM protocol "intance_id" field may possibly be leveraged to permit a node to establish multiple virtual presences as a sender within a NormSession in the future. This would allow the sender to provide multiple concurrent streams of transport, with possibly different FEC and other parameters if appropriate within the context of a single NormSession. Again, this extended functionality is not yet supported in this implementation.

4.4.1.3. Return Values

A value of true is returned upon success and false upon failure. The reasons failure may occur include limited system resources or that the network sockets required for communication failed to open or properly configure. (TBD - Provide a NormGetError(NormSessionHandle sessionHandle) function to retrieve a more specific error indication for this and other functions.)

4.4.2. NormStopSender()

4.4.2.1. Synopsis
#include <normApi.h>

void NormStopSender(NormSessionHandle sessionHandle,
                    bool              graceful = false);
4.4.2.2. Description

This function terminates the application's participation in a NormSession as a sender. By default, the sender will immediately exit the session identified by the sessionHandle parameter without notifying the receiver set of its intention. However a "graceful shutdown" option, enabled by setting the graceful parameter to true, is provided to terminate sender operation gracefully, notifying the receiver set its pending exit with appropriate protocol messaging. A NormEvent, NORM_LOCAL_SENDER_CLOSED, is dispatched when the graceful shutdown process has completed.

4.4.2.3. Return Values

This function has no return values.

4.4.3. NormSetTxRate()

4.4.3.1. Synopsis
#include <normApi.h>

void NormSetTxRate(NormSessionHandle sessionHandle,
                   double            rate);
4.4.3.2. Description

This function sets the transmission rate (in bits per second (bps)) limit used for NormSender transmissions for the given sessionHandle. For fixed-rate transmission of NORM_OBJECT_FILE or NORM_OBJECT_DATA, this limit determines the data rate at which NORM protocol messages and data content are sent. For NORM_OBJECT_STREAM transmissions, this is the maximum rate allowed for transmission (i.e. if the application writes to the stream at a lower rate, a lower average NORM transmission rate will occur). Note that the application will need to consider the overhead of NORM protocol headers when determining an appropriate transmission rate for its purposes. When NORM congestion control is enabled (see NormSetCongestionControl()), the rate set here will be set, but congestion control operation, if enabled, may quickly readjust the transmission rate.

4.4.3.3. Return Values

This function has no return values.

4.4.4. NormGetTxRate()

4.4.4.1. Synopsis
#include <normApi.h>

double NormGetTxRate(NormSessionHandle sessionHandle);
4.4.4.2. Description

This function retrieves the current sender transmission rate in units of bits per second (bps) for the given sessionHandle. When NORM congestion control is enabled (see NormSetCongestionControl()), this reflects the current rate set (or suggested) by NORM congestion control operation. Otherwise, this returns the rate that was set with the NormSetTxRate() call.

4.4.4.3. Return Values

This function returns the sender transmission rate in units of bits per second (bps).

4.4.5. NormSetTxSocketBuffer()

4.4.5.1. Synopsis
#include <normApi.h>

bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle,
                           unsigned int      bufferSize);
4.4.5.2. Description

This function can be used to set a non-default socket buffer size for the UDP socket used by the specified NORM sessionHandle for data transmission. The bufferSize parameter specifies the desired socket buffer size in bytes. Large transmit socket buffer sizes may be necessary to achieve high transmission rates when NORM, as a user-space process, is unable to precisely time its packet transmissions. Similarly, NORM receivers may need to set large receive socket buffer sizes to achieve successful, sustained high data rate reception (see NormSetRxSocketBuffer()). Typically, it is more important to set the receive socket buffer size (see NormSetRxSocketBuffer()) as this maintains reliability (i.e. by avoiding receive socket buffer overflow) at high data rates while setting a larger transmit socket buffer size allows higher average transmission rates to be achieved.

4.4.5.3. Return Values

This function returns true upon success and false upon failure. Possible failure modes include an invalid sessionHandle parameter, a call to NormStartReceiver() or NormStartSender() has not yet been made for the session, or an invalid bufferSize was given. Note some operating systems may require additional system configuration to use non-standard socket buffer sizes.

4.4.6. NormSetFlowControl()

4.4.6.1. Synopsis
#include <normApi.h>

void NormSetFlowControl(NormSessionHandle sessionHandle,
                        double            flowControlFactor);
4.4.6.2. Description

This function controls a scaling factor that is used for sender timer-based flow control for the the specified NORM sessionHandle. Timer-based flow control works by preventing the NORM sender application from enqueueing new transmit objects or stream data that would purge "old" objects or stream data when there has been recent NACK activity for those old objects or data. If the flowControlFactor is set to ZERO, then the flow control mechanism is effectively disabled. Larger flowControlFactor values enforce more robust flow control by forcing the sender to maintain state longer, but then larger transmit buffer, stream buffer, transmit cache bounds and receive cache limits (see NormStartSender(), NormStreamOpen(), NormSetTxCacheBounds(), and NormSetRxCacheLimit(), respectively) may be needed to maintain throughput in larger <delay*bandwidth, loss> conditions. Effectively, a larger flowControlFactor can favor reliability over throughput when buffer-constrained.

The flowControlFactor is used to compute a delay time for when a sender buffered object (or block of stream data) may be released (i.e. purged) after transmission or applicable NACKs reception. The delay time function is:

flowControlDelay = flowControlFactor * GRTT * (backoffFactor + 1)

where the "GRTT" is the sender's advertised GRTT estimate and the backoffFactor is the sender's configured timer-based feedback scaling factor.

The default value (when this function is not called) of the flowControlFactor is 2.0. Note that a NORM application can also implement more explicit, deterministic flow control through use of the NormSetWatermark() API call, potentially even requiring positive acknowledgement of older data before enqueueing new data. Note that using the NormSetWatermark() API call with a NORM_NODE_NONE member in acking node list to force a "full" watermark flush is somewhat equivalent to timer-based flow control with a flowControlFactor equal to 2.0 * txRobustFactor.

If such explicit flow control is implemented by the application, then a reduced flowControlFactor (or even ZERO) may be used. If "push mode" is enabled for a NORM_OBJECT_STREAM (see NormStreamSetPushEnable()), then flow control has no effect for the stream.

4.4.6.3. Return Values

This function has no return values.

4.4.7. NormSetCongestionControl()

4.4.7.1. Synopsis
#include <normApi.h>

void NormSetCongestionControl(NormSessionHandle sessionHandle,
                              bool              enable,
                              bool              adjustRate = true);
4.4.7.2. Description

This function enables (or disables) the NORM sender congestion control operation for the session designated by the sessionHandle parameter. For best operation, this function should be called before the call to NormStartSender() is made, but congestion control operation can be dynamically enabled/disabled during the course of sender operation. If the value of the enable parameter is true, congestion control operation is enabled while it is disabled for enable equal to false. When congestion control operation is enabled, the NORM sender automatically adjusts its transmission rate based on feedback from receivers. If bounds on transmission rate have been set (see NormSetTxRateBounds()) the rate adjustment will remain within the set bounds. The application will be notified of any changes to the sender transmission rate via a NormEvent of type NORM_TX_RATE_CHANGED.

The rate set by NormSetTxRate() has no effect when congestion control operation is enabled, unless the adjustRate parameter here is set to false. When the adjustRate parameter is set to false, the NORM Congestion Control operates as usual, with feedback collected from the receiver set and the "current limiting receiver" identified, except that no actual adjustment is made to the sender's transmission rate. I.e., the transmission rate that was set by NormSetTxRate() is observed by the sender regardless of the feedback received. The NORM_TX_RATE_CHANGED notification will still occur as if the rate were being adjusted and the value returned by NormGetTxRate() reflects the rate that would have been used had the adjustRate parameter been enabled even though no actual rate change has occurred. The purpose of this variation of NORM Congestion Control operation is to allow applications to get a "suggested" rate from the NORM-CC mechanism. But, it is important to note that this "suggested" rate may or may not be appropriate since the operation of the NORM-CC algorithm is somewhat dependent on the associated NORM sender load on the network. For example, the "suggested" rate may be artificially high if the sender application has not been correspondingly setting the rate and actively transmitting data at that rate. This optional mode of operation is provided for EXPERIMENTAL purposes and is NOT RECOMMENDED for typical use of NORM.

NORM's congestion algorithm provides rate adjustment to fairly compete for available network bandwidth with other TCP, NORM, or similarly governed traffic flows.

(TBD - Describe the NormSetEcnSupport() function as this experimental option matures.)

4.4.7.3. Return Values

This function has no return values.

4.4.8. NormSetTxRateBounds()

4.4.8.1. Synopsis
#include <normApi.h>

bool NormSetTxRateBounds(NormSessionHandle sessionHandle,
                               double            rateMin,
                               double            rateMax);
4.4.8.2. Description

This function sets the range of sender transmission rates within which the NORM congestion control algorithm is allowed to operate for the given sessionHandle. By default, the NORM congestion control algorithm operates with no lower or upper bound on its rate adjustment. This function allows this to be limited where rateMin corresponds to the minimum transmission rate (bps) and rateMax corresponds to the maximum transmission rate. One or both of these parameters may be set to values less than zero to remove one or both bounds. For example, the call "NormSetTxRateBounds(session, -1.0, 64000.0)" will set an upper limit of 64 kbps for the sender transmission rate with no lower bound. These rate bounds apply only when congestion control operation is enabled (see NormSetCongestionControl()). If the current congestion control rate falls outside of the specified bounds, the sender transmission rate will be adjusted to stay within the set bounds.

4.4.8.3. Return Values

This function returns true upon success. If both rateMin and rateMax are greater than or equal to zero, but (rateMax < rateMin), the rate bounds will remain unset or unchanged and the function will return false.

4.4.9. NormSetTxCacheBounds()

4.4.9.1. Synopsis
#include <normApi.h>

void NormSetTxCacheBounds(NormSessionHandle sessionHandle,
                                NormSize          sizeMax,
                                unsigned int      countMin,
                                unsigned int      countMax);
4.4.9.2. Description

This function sets limits that define the number and total size of pending transmit objects a NORM sender will allow to be enqueued by the application. Setting these bounds to large values means the NORM protocol engine will keep history and state for previously transmitted objects for a larger interval of time (depending upon the transmission rate) when the application is actively enqueueing additional objects in response to NORM_TX_QUEUE_EMPTY notifications. This can allow more time for receivers suffering degraded network conditions to make repair requests before the sender "purges" older objects from its "transmit cache" when new objects are enqueued. A NORM_TX_OBJECT_PURGED notification is issued when the enqueuing of a new transmit object causes the NORM transmit cache to overflow, indicating the NORM sender no longer needs to reference the designated old transmit object and the application is free to release related resources as needed.

The sizeMax parameter sets the maximum total size, in bytes, of enqueued objects allowed, providing the constraints of the countMin and countMax parameters are met. The countMin parameter sets the minimum number of objects the application may enqueue, regardless of the objects' sizes and the sizeMax value. For example, the default sizeMax value is 20 Mbyte and the default countMin is 8, thus allowing the application to always have at least 8 pending objects enqueued for transmission if it desires, even if their total size is greater than 20 Mbyte. Similarly, the countMax parameter sets a ceiling on how many objects may be enqueued, regardless of their total sizes with respect to the sizeMax setting. For example, the default countMax value is 256, which means the application is never allowed to have more than 256 objects pending transmission enqueued, even if they are 256 very small objects. Note that countMax must be greater than or equal to countMin and countMin is recommended to be at least two.

Note that in the case of NORM_OBJECT_FILE objects, some operating systems impose limits (e.g. 256) on how many open files a process may have at one time and it may be appropriate to limit the countMax value accordingly. In other cases, a large countMin or countMax may be desired to allow the NORM sender to act as virtual cache of files or other data available for reliable transmission. Future iterations of the NRL NORM implementation may support alternative NORM receiver "group join" policies that would allow the receivers to request transmission of cached content.

The utility of the NormRequeueObject() API call also depends on the parameters set by this function. The NormRequeueObject() call will only succeed when the given objectHandle corresponds to an object maintained in the NORM senders "transmit cache".

4.4.9.3. Return Values

This function has no return value.

4.4.10. NormSetAutoParity()

4.4.10.1. Synopsis
#include <normApi.h>

void NormSetAutoParity(NormSessionHandle sessionHandle,
                       unsigned char     autoParity);
4.4.10.2. Description

This function sets the quantity of proactive "auto parity" NORM_DATA messages sent at the end of each FEC coding block. By default (i.e., autoParity = 0), FEC content is sent only in response to repair requests (NACKs) from receivers. But, by setting a non-zero value for autoParity, the sender can automatically accompany each coding block of transport object source data segments ((NORM_DATA messages) with the set number of FEC segments. The number of source symbol messages (segments) per FEC coding block is determined by the blockSize parameter used when NormStartSender() was called for the given sessionHandle.

The use of proactively-sent "auto parity" may eliminate the need for any receiver NACKing to achieve reliable transfer in networks with low packet loss. However, note that the quantity of "auto parity" set adds overhead to transport object transmission. In networks with a predictable level of packet loss and potentially large round-trip times, the use of "auto parity" may allow lower latency in the reliable delivery process. Also, its use may contribute to a smaller amount of receiver feedback as only receivers with exceptional packet loss may need to NACK for additional repair content.

The value of autoParity set must be less than or equal to the numParity parameter set when NormStartSender() was called for the given sessionHandle.

4.4.10.3. Return Values

This function has no return values.

4.4.11. NormGetGrttEstimate()

4.4.11.1. Synopsis
#include <normApi.h>

double NormGetGrttEstimate(NormSessionHandle sessionHandle);
4.4.11.2. Description

This function returns the sender's current estimate(in seconds) of group round-trip timing (GRTT) for the given NORM session. This function may be useful for applications to leverage for other purposes the assessment of round-trip timing made by the NORM protocol engine. For example, an application may scale its own timeouts based on connectivity delays among participants in a NORM session. Note that the NORM_GRTT_UPDATED event is posted (see NormGetNextEvent()) by the NORM protocol engine to indicate when changes in the local sender or remote senders' GRTT estimate occurs.

4.4.11.3. Return Values

This function returns the current sender group round-trip timing (GRTT) estimate (in units of seconds). A value of -1.0 is returned if an invalid session value is provided.

4.4.12. NormSetGrttEstimate()

4.4.12.1. Synopsis
#include <normApi.h>

void NormSetGrttEstimate(NormSessionHandle sessionHandle,
                         double            grtt);
4.4.12.2. Description

This function sets the sender's estimate of group round-trip time (GRTT) (in units of seconds) for the given NORM sessionHandle. This function is expected to most typically used to initialize the sender's GRTT estimate prior to the call to NormStartSender() when the application has a priori confidence that the default initial GRTT value of 0.5 second is inappropriate. The sender GRTT estimate will be updated during normal sender protocol operation after sender startup or if this call is made while sender operation is active. For experimental purposes (or very special application needs), this API provides a mechanism to control or disable the sender GRTT update process (see NormSetGrttProbingMode()). The grtt value (in seconds) will be limited to the maximum GRTT as set (see NormSetGrttMax()) or the default maximum of 10 seconds.

The sender GRTT is advertised to the receiver group and is used to scale various NORM protocol timers. The default NORM GRTT estimation process dynamically measures round-trip timing to determine an appropriate operating value. An overly-large GRTT estimate can introduce additional latency into the reliability process (resulting in a larger virtual delay*bandwidth product for the protocol and potentially requiring more buffer space to maintain reliability). An overly-small GRTT estimate may introduce the potential for feedback implosion, limiting the scalability of group size.

Also note that the advertised GRTT estimate can also be limited by transmission rate. When the sender transmission rate is low, the GRTT is also governed to a lower bound of the nominal packet transmission interval (i.e., 1/txRate). This maintains the "event driven" nature of the NORM protocol with respect to receiver reception of NORM sender data and commands.

4.4.12.3. Return Values

This function has no return values.

4.4.13. NormSetGrttMax()

4.4.13.1. Synopsis
#include <normApi.h>

void NormSetGrttMax(NormSessionHandle sessionHandle,
                    double            grttMax);
4.4.13.2. Description

This function sets the sender's maximum advertised GRTT value for the given NORM sessionHandle. The grttMax parameter, in units of seconds, limits the GRTT used by the group for scaling protocol timers, regardless of larger measured round trip times. The default maximum for the NRL NORM library is 10 seconds. See the NormSetGrttEstimate() function description for the purpose of the NORM GRTT measurement process.

4.4.13.3. Return Values

This function has no return values.

4.4.14. NormSetGrttProbingMode()

4.4.14.1. Synopsis
#include <normApi.h>

void NormSetGrttProbingMode(NormSessionHandle sessionHandle,
                            NormProbingMode   probingMode);
4.4.14.2. Description

This function sets the sender's mode of probing for round trip timing measurement responses from the receiver set for the given NORM sessionHandle. Possible values for the probingMode parameter include NORM_PROBE_NONE, NORM_PROBE_PASSIVE, and NORM_PROBE_ACTIVE. The default probing mode is NORM_PROBE_ACTIVE. In this mode, the receiver set explicitly acknowledges NORM sender GRTT probes ((NORM_CMD(CC) messages) with NORM_ACK responses that are group-wise suppressed. Note that NORM receivers also will include their response to GRTT probing piggy-backed on any NORM_NACK messages sent in this mode as well to minimize feedback.

Note that the NORM_PROBE_ACTIVE probing mode is required and automatically set when NORM congestion control operation is enabled (see NormSetCongestionControl()). Thus, when congestion control is enabled, the NormSetGrttProbingMode() function has no effect.

If congestion control operation is not enabled, the NORM application may elect to reduce the volume of feedback traffic by setting the probingMode to NORM_PROBE_PASSIVE. Here, the NORM sender still transmits NORM_CMD(CC) probe messages multiplexed with its data transmission, but the receiver set does not explicitly acknowledge these probes. Instead the receiver set is limited to opportunistically piggy-backing responses when NORM_NACK messages are generated. Note that this may, in some cases, introduce some opportunity for bursts of large volume receiver feedback when the sender's estimate of GRTT is incorrect due to the reduced probing feedback. But, in some controlled network environments, this option for passive probing may provide some benefits in reducing protocol overhead.

Finally, the probingMode can be set to NORM_PROBE_NONE to eliminate the overhead (and benefits) of NORM GRTT measurement entirely. In this case, the sender application must explicitly set its estimate of GRTT using the NormSetGrttEstimate() function. See this function for a description of the purpose of the NORM GRTT measurement.

4.4.14.3. Return Values

This function has no return values.

4.4.15. NormSetGrttProbingInterval()

4.4.15.1. Synopsis
#include <normApi.h>

void NormSetGrttProbingInterval(NormSessionHandle sessionHandle,
                                double            intervalMin,
                                double            intervalMax);
4.4.15.2. Description

This function controls the sender GRTT measurement and estimation process for the given NORM sessionHandle. The NORM sender multiplexes periodic transmission of NORM_CMD(CC) messages with its ongoing data transmission or when data transmission is idle. When NORM congestion control operation is enabled, these probes are sent once per RTT of the current limiting receiver (with respect to congestion control rate). In this case the intervalMin and intervalMax parameters (in units of seconds) control the rate at which the sender's estimate of GRTT is updated. At session start, the estimate is updated at intervalMin and the update interval time is doubled until intervalMax is reached. This dynamic allows for a rapid initial estimation of GRTT and a slower, steady-state update of GRTT. When congestion control is disabled and NORM GRTT probing is enabled ((NORM_PROBE_ACTIVE or NORM_PROBE_PASSIVE) the intervalMin and intervalMax values also determine the rate at which NORM_CMD(CC) probes are transmitted by the sender. Thus by setting larger values for intervalMin and intervalMax, the NORM sender application can reduce the overhead of the GRTT measurement process. However, this also reduces the ability of NORM to adapt to changes in GRTT.

The default NORM GRTT intervalMin and intervalMax values, i.e., when this call is not made, are 1.0 second and 30.0 seconds, respectively.

4.4.15.3. Return Values

This function has no return values.

4.4.16. NormSetBackoffFactor()

4.4.16.1. Synopsis
#include <normApi.h>

void NormSetBackoffFactor(NormSessionHandle sessionHandle,
                          double            backoffFactor);
4.4.16.2. Description

This function sets the sender's "backoff factor" for the given sessionHandle. The backoffFactor (in units of seconds) is used to scale various timeouts related to the NACK repair process. The sender advertises its backoffFactor setting to the receiver group in NORM protocol message headers. The default backoffFactor for NORM sessions is 4.0 seconds. The backoffFactor is used to determine the maximum time that receivers may delay NACK transmissions (and other feedback messages) as part of NORM's probabilistic feedback suppression technique. For example, the maximum NACK delay time is backoffFactor*GRTT. Thus a large backoffFactor value introduces latency into the NORM repair process. However, a small backoffFactor value causes feedback suppression to be less effective and increases the risk of feedback implosion for large receiver group sizes.

The default setting of 4.0 provides reasonable feedback suppression for moderate to large group sizes when multicast feedback is possible. The NORM specification recommends a backoffFactor value of 6.0 when unicast feedback is used. However, for demanding applications (with respect to repair latency) when group sizes are modest, a small (even 0.0) backoffFactor value can be specified to reduce the latency of reliable data delivery.

4.4.16.3. Return Values

This function has no return values.

4.4.17. NormSetGroupSize()

4.4.17.1. Synopsis
#include <normApi.h>

void NormSetGroupSize(NormSessionHandle sessionHandle,
                      unsigned int      groupSize);
4.4.17.2. Description

This function sets the sender's estimate of receiver group size for the given sessionHandle. The sender advertises its groupSize setting to the receiver group in NORM protocol message headers that, in turn, use this information to shape the distribution curve of their random timeouts for the timer-based, probabilistic feedback suppression technique used in the NORM protocol. Note that the groupSize estimate does not have to be very accurate and values within an order of magnitude of the actual group size tend to produce acceptable performance.

The default groupSize setting in NORM is 1,000 and thus can work well for a wide range of actual receiver group sizes. The penalty of an overly large estimate is statistically a little more latency in reliable data delivery with respect to the round trip time and some potential for excess feedback. A substantial underestimation of groupSize increases the risk of feedback implosion. Currently, the NORM implementation does not attempt to automatically measure groupSize from receiver feedback. Applications could add their own mechanism for this (perhaps keeping explicit track of group membership), or it is possible that future versions of the NRL NORM implementation may have some provision for automatic groupSize estimation by the sender based on receiver feedback messages.

4.4.17.3. Return Values

This function has no return values.

4.4.18. NormSetTxRobustFactor()

4.4.18.1. Synopsis
#include <normApi.h>

void NormSetTxRobustFactor(NormSessionHandle sessionHandle,
                           int               txRobustFactor);
4.4.18.2. Description

This routine sets the "robustness factor" used for various NORM sender functions. These functions include the number of repetitions of "robustly-transmitted" NORM sender commands such as NORM_CMD(FLUSH) or similar application-defined commands, and the number of attempts that are made to collect positive acknowledgement from receivers. These commands are distinct from the NORM reliable data transmission process, but play a role in overall NORM protocol operation. The default txRobustFactor value is 20. This relatively large value makes the NORM sender end-of-transmission flushing and positive acknowledgement collection functions somewhat immune from packet loss. However, for some applications, the default value may make the NORM protocol more "chatty" than desired (particularly if flushing is invoked often). In other situations where the network connectivity may be intermittent or extremely lossy, it may be useful to actually increase this value. The default value (20) is expected to provide reasonable operation across a wide range of network conditions and application types. Since this value is not communicated among NORM participants as part of the protocol operation, it is important that applications consistently set this value among all applications participating in a NORM session.

Setting txRobustFactor to a value of -1 makes the redundant transmission of these commands continue indefinitely until completion. For example, with positive acknowledgement collection, the request process will continue indefinitely until all recipients requested acknowledge or the request is canceled by the application. Similarly, flushing commands would be transmitted repeatedly until data transmission is resumed. Typically, setting txRobustFactor to -1 is not recommended.

4.4.18.3. Return Values

This function has no return values.

4.4.19. NormFileEnqueue()

4.4.19.1. Synopsis
#include <normApi.h>

NormObjectHandle NormFileEnqueue(NormSessionHandle      sessionHandle,
                                 const char*            filename,
                                 const char*            infoPtr = NULL,
                                 unsigned int           infoLen = 0);
4.4.19.2. Description

This function enqueues a file for transmission within the specified NORM sessionHandle. Note that NormStartSender() must have been previously called before files or any transport objects may be enqueued and transmitted. The fileName parameter specifies the path to the file to be transmitted. The NORM protocol engine read and writes directly from/to file system storage for file transport, potentially providing for a very large virtual "repair window" as needed for some applications. While relative paths with respect to the "current working directory" may be used, it is recommended that full paths be used when possible. The optional infoPtr and infoLen parameters are used to associate NORM_INFO content with the sent transport object. The maximum allowed infoLen corresponds to the segmentSize used in the prior call to NormStartSender(). The use and interpretation of the NORM_INFO content is left to the application's discretion. Example usage of NORM_INFO content for NORM_OBJECT_FILE might include file name, creation date, MIME-type or other information which will enable NORM receivers to properly handle the file when reception is complete.

The application is allowed to enqueue multiple transmit objects within in the "transmit cache" bounds (see NormSetTxCacheBounds()) and enqueued objects are transmitted (and repaired as needed) within the limits determined by automated congestion control (see NormSetCongestionControl()) or fixed rate (see NormSetTxRate()) parameters.

4.4.19.3. Return Values

A NormObjectHandle is returned which the application may use in other NORM API calls as needed. This handle can be considered valid until the application explicitly cancels the object's transmission (see NormObjectCancel()) or a NORM_TX_OBJECT_PURGED event is received for the given object. Note the application may use the NormObjectRetain() method if it wishes to refer to the object after the NORM_TX_OBJECT_PURGED notification. In this case, the application, when finished with the object, must use NormObjectRelease() to free any resources used or else a memory leak condition will result. A value of NORM_OBJECT_INVALID is return upon error. Possible failure conditions include the specified session is not operating as a NormSender, insufficient memory resources were available, or the "transmit cache" limits have been reached and all previously enqueued NORM transmit objects are pending transmission. Also the call will fail if the infoLen parameter exceeds the local NormSender segmentSize limit.

4.4.20. NormDataEnqueue()

4.4.20.1. Synopsis
#include <normApi.h>

NormObjectHandle NormDataEnqueue(NormSessionHandle      sessionHandle,
                                 const char*            dataPtr,
                                 unsigned int           dataLen,
                                 const char*            infoPtr = NULL,
                                 unsigned int           infoLen = 0);
4.4.20.2. Description

This function enqueues a segment of application memory space for transmission within the specified NORM sessionHandle. Note that NormStartSender() MUST have been previously called before files or any transport objects may be enqueued and transmitted. The dataPtr parameter must be a valid pointer to the area of application memory to be transmitted and the dataLen parameter indicates the quantity of data to transmit. The NORM protocol engine read and writes directly from/to application memory space so it is important that the application does not modify (or deallocate) the memory space during the time the NORM protocol engine may access this area. After calling NormDataEnqueue() for a specific application "dataPtr" memory space, the application MUST NOT deallocate (or change the contents of) that memory space until a NORM_TX_OBJECT_PURGED notification is received for the given object or the application itself explicitly cancels the object's transmission (see NormObjectCancel()).

The optional infoPtr and infoLen parameters are used to associate NORM_INFO content with the sent transport object. The maximum allowed infoLen corresponds to the segmentSize used in the prior call to NormStartSender(). The use and interpretation of the NORM_INFO content is left to the application's discretion. Example usage of NORM_INFO content for NORM_OBJECT_DATA might include application-defined data typing or other information which will enable NORM receiver applications to properly interpret the received data when reception is complete. Of course, it is possible that the application may embed such typing information in the object data content itself. This is left to the application's discretion.

The application is allowed to enqueue multiple transmit objects within in the "transmit cache" bounds (see NormSetTxCacheBounds()) and enqueued objects are transmitted (and repaired as needed) within the limits determined by automated congestion control (see NormSetCongestionControl()) or fixed rate (see NormSetTxRate()) parameters.

4.4.20.3. Return Values

A NormObjectHandle is returned which the application may use in other NORM API calls as needed. This handle can be considered valid until the application explicitly cancels the object's transmission (see NormObjectCancel()) or a NORM_TX_OBJECT_PURGED event is received for the given object. Note the application may use the NormObjectRetain() method if it wishes to refer to the object after the NORM_TX_OBJECT_PURGED notification. In this case, the application, when finished with the object, must use NormObjectRelease() to free any resources used or else a memory leak condition will result. A value of NORM_OBJECT_INVALID is return upon error. Possible failure conditions include the specified session is not operating as a NormSender, insufficient memory resources were available, or the "transmit cache" limits have been reached and all previously enqueued NORM transmit objects are pending transmission. Also the call will fail if the infoLen parameter exceeds the local NormSender segmentSize limit.

4.4.21. NormRequeueObject()

4.4.21.1. Synopsis
#include <normApi.h>

boolNormRequeueObject(NormSessionHandle sessionHandle,
                      NormObjectHandle  objectHandle);
4.4.21.2. Description

This function allows the application to resend (or reset transmission of) a NORM_OBJECT_FILE or NORM_OBJECT_DATA transmit object that was previously enqueued for the indicated sessionHandle. This function is useful for applications sending to silent (non-NACKing) receivers as it enables the receivers to take advantage of multiple retransmissions of objects (including any auto-parity set, see NormSetAutoParity()) to more robustly receive content. The objectHandle parameter must be a valid transmit NormObjectHandle that has not yet been "purged" from the sender's transmit queue. Upon success, the specified object will be fully retransmitted using the same NORM object transport identifier as was used on its initial transmission. This call may be made at any time to restart transmission of a previously-enqueued object, but the NORM_TX_OBJECT_SENT or NORM_TX_FLUSH_COMPLETED notifications can serve as good cues for an appropriate time to resend an object. If multiple objects are re-queued, they will be resent in order of their initial enqueueing.

The transmit cache bounds set by NormSetTxCacheBounds() determine the number of previously-sent objects retained in the sender's transmit queue and that are thus eligible to be requeued for retransmission. An object may be requeued via this call multiple times, but each distinct requeue should be done after an indication such as NORM_TX_OBJECT_SENT or NORM_TX_FLUSH_COMPLETED for the given object. Otherwise, the object will simply be reset from its current transmission point to transmit from the beginning (i.e. restart). Note that the object type NORM_OBJECT_STREAM cannot currently be requeued.

(TBD - should a "numRepeats" parameter be added to this function?)

4.4.21.3. Return Values

A value of true is returned upon success and a value of false is returned upon failure. Possible reasons for failure include an invalid objectHandle was provided (i.e. a non-transmit object or transmit object that has been "purged" from the transmit queue (see NORM_TX_OBJECT_PURGED)) or the provided object was of type NORM_OBJECT_STREAM.

4.4.22. NormStreamOpen()

4.4.22.1. Synopsis
#include <normApi.h>

NormObjectHandle NormStreamOpen(NormSessionHandle      sessionHandle,
                                unsigned int           bufferSize,
                                const char*            infoPtr = NULL,
                                unsigned int           infoLen = 0);
4.4.22.2. Description

This function opens a NORM_OBJECT_STREAM sender object and enqueues it for transmission within the indicated sessionHandle. NORM streams provide reliable, in-order delivery of data content written to the stream by the sender application. Note that no data is sent until subsequent calls to NormStreamWrite() are made unless NORM_INFO content is specified for the stream with the infoPtr and infoLen parameters. Example usage of NORM_INFO content for NORM_OBJECT_STREAM might include application-defined data typing or other information which will enable NORM receiver applications to properly interpret the received stream as it is being received. The NORM protocol engine buffers data written to the stream for original transmission and repair transmissions as needed to achieve reliable transfer. The bufferSize parameter controls the size of the stream's "repair window" which limits how far back the sender will "rewind" to satisfy receiver repair requests.

NORM, as a NACK-oriented protocol, currently lacks a mechanism for receivers to explicitly feedback flow control status to the sender unless the sender application specifically leverages NORM's optional positive-acknowledgement (ACK) features. Thus, the bufferSize selection plays an important role in reliable delivery of NORM stream content. Generally, a larger bufferSize value is safer with respect to reliability, but some applications may wish to limit how far the sender rewinds to repair receivers with poor connectivity with respect to the group at large. Such applications may set a smaller bufferSize to avoid the potential for large latency in data delivery (i.e. favor peak delivery latency over full reliability). This may result in breaks in the reliable delivery of stream data to some receivers, but this form of quasi-reliability while limiting latency may be useful for some types of applications (e.g. reliable real-time messaging, video or sensor or media data transport). Note that NORM receivers can quickly, automatically "resync" to the sender after such breaks if the application leverages the application message boundary recovery features of NORM (see NormStreamMarkEom()).

Note that the current implementation of NORM is designed to support only one active stream per session, and that any NORM_OBJECT_DATA or NORM_OBJECT_FILE objects enqueued for transmission will not begin transmission until an active stream is closed. Applications requiring multiple streams or concurrent file/data transfer SHOULD generally instantiate multiple NormSessions as needed.

Note there is no corresponding "open" call for receiver streams. Receiver NORM_OBJECT_STREAMs are automatically opened by the NORM protocol engine and the receiver applications is notified of new streams via the NORM_RX_OBJECT_NEW notification (see NormGetNextEvent()).

4.4.22.3. Return Values

A NormObjectHandle is returned which the application may use in other NORM API calls as needed. This handle can be considered valid until the application explicitly cancels the object's transmission (see NormObjectCancel()) or a NORM_TX_OBJECT_PURGED event is received for the given object. Note the application may use the NormObjectRetain() method if it wishes to refer to the object after the NORM_TX_OBJECT_PURGED notification. In this case, the application, when finished with the object, must use NormObjectRelease() to free any resources used or else a memory leak condition will result. A value of NORM_OBJECT_INVALID is return upon error. Possible failure conditions include the specified session is not operating as a NormSender, insufficient memory resources were available, or the "transmit cache" bounds have been reached and all previously enqueued NORM transmit objects are pending transmission. Also the call will fail if the infoLen parameter exceeds the local NormSender segmentSize limit.

4.4.23. NormStreamClose()

4.4.23.1. Synopsis
#include <normApi.h>

void NormStreamClose(NormObjectHandle streamHandle,
                     bool             graceful = false);
4.4.23.2. Description

This function halts transfer of the stream specified by the streamHandle parameter and releases any resources used unless the associated object has been explicitly retained by a call to NormObjectRetain(). No further calls to NormStreamWrite() will be successful for the given streamHandle. The optional graceful parameter, when set to a value of true, may be used by NORM senders to initiate "graceful" shutdown of a transmit stream. In this case, the sender application will be notified that stream has (most likely) completed reliable transfer via the NORM_TX_OBJECT_PURGED notification upon completion of the graceful shutdown process. When the graceful option is set to true, receivers are notified of the stream end via an "stream end" stream control code in NORM_DATA message and will receive a NORM_RX_OBJECT_COMPLETED notification after all received stream content has been read. Otherwise, the stream is immediately terminated, regardless of receiver state. In this case, this function is equivalent to the NormObjectCancel() routine and may be used for sender or receiver streams. So, it is expected this function (NormStreamClose()) will typically be used for transmit streams by NORM senders.

4.4.23.3. Return Values

This function has no return values.

4.4.24. NormStreamWrite()

4.4.24.1. Synopsis
#include <normApi.h>

unsigned int NormStreamWrite(NormObjectHandle streamHandle 
                             const char*      buffer,
                             unsigned int     numBytes);
4.4.24.2. Description

This function enqueues data for transmission within the NORM stream specified by the streamHandle parameter. The buffer parameter must be a pointer to the data to be enqueued and the numBytes parameter indicates the length of the data content. Note this call does not block and will return immediately. The return value indicates the number of bytes copied from the provided buffer to the internal stream transmission buffers. Calls to this function will be successful unless the stream's transmit buffer space is fully occupied with data pending original or repair transmission if the stream's "push mode" is set to false (default, see NormStreamSetPushEnable() for details). If the stream's "push mode" is set to true, a call to NormStreamWrite() will always result in copying of application data to the stream at the cost of previously enqueued data pending transmission (original or repair) being dropped by the NORM protocol engine. While NORM NACK-based reliability does not provide explicit flow control, there is some degree of implicit flow control in limiting writing new data to the stream against pending repairs. Other flow control strategies are possible using the NormSetWatermark() function.NormSetWatermark() function.

The NormEvent values NORM_TX_QUEUE_EMPTY and NORM_TX_QUEUE_VACANCY are posted with the NormEvent::object field set to a valid sender stream NormObjectHandle to indicate when the stream is ready for writing via this function. Note that the NORM_TX_QUEUE_VACANCY event type is posted only after the stream's transmit buffer has been completely filled. Thus, the application must make a call to NormStreamWrite() that copies less than the requested numBytes value (return value less than numBytes) before additional NORM_TX_QUEUE_VACANCY events are posted for the given streamHandle (i.e., the event type is not re-posted until the application has again filled the available stream transmit buffer space). By cueing off of NORM_TX_QUEUE_EMPTY, the application can write its "freshest" available data to the stream, but by cueing off of NORM_TX_QUEUE_VACANCY, an application can keep the NORM protocol engine busiest, to achieve the maximum possible throughput at high data rates.

4.4.24.3. Return Values

This function returns the number of bytes of data successfully enqueued for NORM stream transmission. If the underlying send stream buffer is full, this function may return zero or a value less than the requested numBytes.

4.4.25. NormStreamFlush()

4.4.25.1. Synopsis
#include <normApi.h>

void NormStreamFlush(NormObjectHandle streamHandle,
                     bool             eom = false,
                     NormFlushMode    flushMode = NORM_FLUSH_PASSIVE);
4.4.25.2. Description

This function causes an immediate "flush" of the transmit stream specified by the streamHandle parameter. Normally, unless NormStreamSetAutoFlush() has been invoked, the NORM protocol engine buffers data written to a stream until it has accumulated a sufficient quantity to generate a NORM_DATA message with a full payload (as designated by the segmentSize parameter of the NormStartSender() call). This results in most efficient operation with respect to protocol overhead. However, for some NORM streams, the application may not wish wait for such accumulation when critical data has been written to a stream. The default stream "flush" operation invoked via NormStreamFlush() for flushMode equal to NORM_FLUSH_PASSIVE causes NORM to immediately transmit all enqueued data for the stream (subject to session transmit rate limits), even if this results in NORM_DATA messages with "small" payloads. If the optional flushMode parameter is set to NORM_FLUSH_ACTIVE, the application can achieve reliable delivery of stream content up to the current write position in an even more proactive fashion. In this case, the sender additionally, actively transmits NORM_CMD(FLUSH) messages after any enqueued stream content has been sent. This immediately prompt receivers for repair requests which reduces latency of reliable delivery, but at a cost of some additional messaging. Note any such "active" flush activity will be terminated upon the next subsequent write to the stream. If flushMode is set to NORM_FLUSH_NONE, this call has no effect other than the optional end-of-message marking described here.

The optional eom parameter, when set to true, allows the sender application to mark an end-of-message indication (see NormStreamMarkEom()) for the stream and initiate flushing in a single function call. The end-of-message indication causes NORM to embed the appropriate message start byte offset in the NORM_DATA message generated following a subsequent write to the stream with the NORM_FLAGS_MSG_START flag. This mechanism provide a means for automatic application message boundary recovery when receivers join or re-sync to a sender mid-stream.

Note that frequent flushing, particularly for NORM_FLUSH_ACTIVE operation, may result in more NORM protocol activity than usual, so care must be taken in application design and deployment when scalability to large group sizes is expected.

4.4.25.3. Return Values

This function has no return values.

4.4.26. NormStreamSetAutoFlush()

4.4.26.1. Synopsis
#include <normApi.h>

void NormStreamSetAutoFlush(NormObjectHandle streamHandle
                            NormFlushMode    flushMode);
4.4.26.2. Description

This function sets "automated flushing" for the NORM transmit stream indicated by the streamHandle parameter. By default, a NORM transmit stream is "flushed" only when explicitly requested by the application (see NormStreamFlush()). However, to simplify programming, the NORM API allows that automated flushing be enabled such that the "flush" operation occurs every time the full requested buffer provided to a NormStreamWrite() call is successfully enqueued. This may be appropriate for messaging applications where the provided buffers corresponds to an application messages requiring immediate, full transmission. This may make the NORM protocol perhaps more "chatty" than its typical "bulk transfer" form of operation, but can provide a useful capability for some applications.

Possible values for the flushMode parameter include NORM_FLUSH_NONE, NORM_FLUSH_PASSIVE, and NORM_FLUSH_ACTIVE. The default setting for a NORM stream is NORM_FLUSH_NONE where no flushing occurs unless explicitly requested via NormStreamFlush(). By setting the automated flushMode to NORM_FLUSH_PASSIVE, the only action taken is to immediately transmit any data that has been written to the stream, even if "runt" NORM_DATA messages (with payloads less than the NormSender segmentSize parameter) are generated as a result. If NORM_FLUSH_ACTIVE is specified, the automated flushing operation is further augmented with the additional transmission of NORM_CMD(FLUSH) messages to proactively excite the receiver group for repair requests.

4.4.26.3. Return Values

This function has no return values.

4.4.27. NormStreamSetPushEnable()

4.4.27.1. Synopsis
#include <normApi.h>

void NormStreamSetPushEnable(NormObjectHandle streamHandle,
                             bool             pushEnable);
4.4.27.2. Description

This function controls how the NORM API behaves when the application attempts to enqueue new stream data for transmission when the associated stream's transmit buffer is fully occupied with data pending original or repair transmission. By default (pushEnable = false), a call to NormStreamWrite() will return a zero value under this condition, indicating it was unable to enqueue the new data. However, if pushEnable is set to true for a given streamHandle, the NORM protocol engine will discard the oldest buffered stream data (even if it is pending repair transmission or has never been transmitted) as needed to enqueue the new data. Thus a call to NormStreamWrite() will never fail to copy data. This behavior may be desirable for applications where it is more important to quickly delivery new data than to reliably deliver older data written to a stream. The default behavior for a newly opened stream corresponds to pushEnable equals false. This limits the rate to which an application can write new data to the stream to the current transmission rate and status of the reliable repair process.

4.4.27.3. Return Values

This function has no return values.

4.4.28. NormStreamHasVacancy()

4.4.28.1. Synopsis
#include <normApi.h>

bool NormStreamHasVacancy(NormObjectHandle streamHandle);
4.4.28.2. Description

This function can be used to query whether the transmit stream, specified by the streamHandle parameter, has buffer space available so that the application may successfully make a call to NormStreamWrite(). Normally, a call to NormStreamWrite() itself can be used to make this determination, but this function can be useful when "push mode" has been enabled (see the description of the NormStreamSetPushEnable() function) and the application wants to avoid overwriting data previously written to the stream that has not yet been transmitted. Note that when "push mode" is enabled, a call to NormStreamWrite() will always succeed, overwriting previously-enqueued data if necessary. Normally, this function will return true after a NORM_TX_QUEUE_VACANCY notification has been received for a given NORM stream object.

4.4.28.3. Return Values

This function returns a value of true when there is transmit buffer space to which the application may write and false otherwise.

4.4.29. NormStreamMarkEom()

4.4.29.1. Synopsis
#include <normApi.h>

void NormStreamMarkEom(NormObjectHandle streamHandle);
4.4.29.2. Description

This function allows the application to indicate to the NORM protocol engine that the last data successfully written to the stream indicated by streamHandle corresponded to the end of an application-defined message boundary. The end-of-message indication given here will cause the NORM protocol engine to embed the appropriate message start byte offset in the NORM_DATA message generated that contains the data for the subsequent application call to NormStreamWrite(). Use of this end-of-message marking enables NORM receivers to automatically re-sync to application-defined message boundaries when joining (or re-joining) a NORM session already in progress.

4.4.29.3. Return Values

This function has no return values.

4.4.30. NormSetWatermark()

4.4.30.1. Synopsis
#include <normApi.h>

bool NormSetWatermark(NormSessionHandle sessionHandle,
                      NormObjectHandle  objectHandle, 
                      bool              overrideFlush = true);
4.4.30.2. Description

This function specifies a "watermark" transmission point at which NORM sender protocol operation should perform a flushing process and/or positive acknowledgment collection for a given sessionHandle. For NORM_OBJECT_FILE and NORM_OBJECT_DATA transmissions, the positive acknowledgement collection will begin when the specified object has been completely transmitted. The objectHandle parameter must be a valid handle to a previously-created sender object (see NormFileEnqueue(), NormDataEnqueue(), or NormStreamOpen()). For NORM_OBJECT_STREAM transmission, the positive acknowledgment collection begins immediately, using the current position (offset of most recent data written) of the sender stream as a reference.

The functions NormAddAckingNode() and NormRemoveAckingNode() are used to manage the list of NormNodeId values corresponding to NORM receivers that are expected to explicitly acknowledge the watermark flushing messages transmitted by the sender. Note that the NormNodeId NORM_NODE_NONE may be included in the list. Inclusion of NORM_NODE_NONE forces the watermark flushing process to proceed through a full NORM_ROBUST_FACTOR number of rounds before completing, prompting any receivers that have not completed reliable reception to the given watermark point to NACK for any repair needs. If NACKs occur, the flushing process is reset and repeated until completing with no NACKs for data through the given watermark transmission point are received. Thus, even without explicit positive acknowledgment, the sender can use this process (by adding NORM_NODE_NONE to the session's list of "acking nodes") for a high level of assurance that the receiver set is "happy" (completed reliable data reception) through the given object (or stream transmission point).

The event NORM_TX_WATERMARK_COMPLETED is posted for the given session when the flushing process or positive acknowledgment collection has completed. The process completes as soon as all listed receivers have responded unless NORM_NODE_NONE is included in the "acking node" list. The sender application may use the function NormGetAckingStatus() to determine the degree of success of the flushing process in general or for individual NormNodeId values.

The flushing is conducted concurrently with ongoing data transmission and does not impede the progress of reliable data transfer. Thus the sender may still enqueue NormObjects for transmission (or write to the existing stream) and the positive acknowledgement collection and flushing procedure will be multiplexed with the ongoing data transmission. However, the sender application may wish to defer from or limit itself in sending more data until a NORM_TX_WATERMARK_COMPLETED event is received for the given session. This provides a form of sender->receiver(s) flow control which does not exist in NORM's default protocol operation. If a subsequent call is made to NormSetWatermark() before the current acknowledgement request has completed, the pending acknowledgment request is canceled and the new one begins.

The optional overrideFlush parameter, when set to true, causes the watermark acknowledgment process that is established with this function call to potentially fully supersede the usual NORM end-of-transmission flushing process that occurs. If overrideFlush is set and the "watermark" transmission point corresponds to the last transmission that will result from data enqueued by the sending application, then the watermark flush completion will terminate the usual flushing process. I.e., if positive acknowledgement of watermark is received from the full "acking node list", then no further flushing is conducted. Thus, the overrideFlush parameter should only be set when the "acking node list" contains a complete list of intended recipients. This is useful for small receiver groups (or unicast operation) to reduce the "chattiness" of NORM's default end-of-transmission flush process. Note that once the watermark flush is completed and further data enqueued and transmitted, the normal default end-of-transmission behavior will be resumed unless another "watermark" is set with overrideFlush enabled. Thus, as long as new watermarks are established by successive use of this API call, this effectively "morphs" NORM into a protocol driven by positive acknowledgement behavior.

4.4.30.3. Return Values

The function returns true upon successful establishment of the watermark point. The function may return false upon failure.

4.4.31. NormCancelWatermark()

4.4.31.1. Synopsis
#include <normApi.h>

bool NormCancelWatermark(NormSessionHandle sessionHandle);
4.4.31.2. Description

This function cancels any "watermark" acknowledgement request that was previously set via the NormSetWatermark() function for the given sessionHandle. The status of any NORM receivers that may have acknowledged prior to cancellation can be queried using the NormGetAckingStatus() function even after NormCancelWatermark() is called. Typically, applications should wait until a event has been posted, but in some special cases it may be useful to terminate the acknowledgement collection process early.

4.4.31.3. Return Values

The function has no return values.

4.4.32. NormAddAckingNode()

4.4.32.1. Synopsis
#include <normApi.h>

bool NormAddAckingNode(NormSessionHandle sessionHandle,
                       NormNodeId        nodeId);
4.4.32.2. Description

When this function is called, the specified nodeId is added to the list of NormNodeId values (i.e., the "acking node" list) used when NORM sender operation performs positive acknowledgement (ACK) collection for the specified sessionHandle. The optional NORM positive acknowledgement collection occurs when a specified transmission point (see NormSetWatermark()) is reached or for specialized protocol actions such as positively-acknowledged application-defined commands.

Additionally the special value of nodeId equal to NORM_NODE_NONE may be set to force the watermark flushing process through a full NORM_ROBUST_FACTOR number of rounds regardless of actual acking nodes. Otherwise the flushing process is terminated when all of the nodes in the acking node list have responded. Setting a "watermark" and forcing a full flush process with the special NORM_NODE_NONE value of nodeId enables the resultant NORM_TX_WATERMARK_COMPLETED notification to be a indicator with high (but not absolute) assurance that the receiver set has completed reliable reception of content up through the "watermark" transmission point. This provides a form of scalable reliable multicast "flow control" for NACK-based operation without requiring explicit positive acknowledgement from all group members. Note that the use of the NORM_NODE_NONE value may be mixed with other nodeId for a mix of positive acknowledgement collection from some nodes and a measure of assurance for the group at large.

4.4.32.3. Return Values

The function returns true upon success and false upon failure. The only failure condition is that insufficient memory resources were available. If a specific nodeId is added more than once, this has no effect.

4.4.33. NormRemoveAckingNode()

4.4.33.1. Synopsis
#include <normApi.h>

void NormRemoveAckingNode(NormSessionHandle sessionHandle,
                          NormNodeId        nodeId);
4.4.33.2. Description

This function deletes the specified nodeId from the list of NormNodeId values used when NORM sender operation performs positive acknowledgement (ACK) collection for the specified sessionHandle. Note that if the special nodeId value "NORM_NODE_NONE" has been added to the list, it too must be explicitly removed to change the watermark flushing behavior if desired.

4.4.33.3. Return Values

The function has no return values.

4.4.34. NormGetNextAckingNode()

4.4.34.1. Synopsis
#include <normApi.h>

NormNodeId NormGetNextAckingNode(NormSessionHandle session, bool reset = false);
4.4.34.2. Description

This function iteratively retrieves the NormNodeId values in the "acking node" list maintained by a NORM sender (see NormAddAckingNode()) for the given sessionHandle. If the optional reset parameter is set to a value of true, the first NormNodeId value in the list is returned and subsequent calls to NormGetNextAckingNode()with the reset parameter set to its default false value will iteratively return the remaining NormNodeId values contained in the list. A value of NORM_NODE_NONE is returned when the end of the list is reached.

The "acking node" list is populated with application calls to NormAddAckingNode() or auto-populated if that optional behavior is set for a NormSession. Note that this API does not enable the programmer to check if the NORM_NODE_NONE value itself is contained in the list. The programmer should keep track of that by other means.

The following code example illustrates how to use this call to iterate through the set of stored NormNodeId values and get the current "acking status" for each:

NormNodeId nextNodeId = NormGetNextAckingNode(session, true);
while(NORM_NODE_NONE != nextNodeId)
{
    NormAckingStatus ackingStatus = NormGetAckingStatus(session, nextNodeId);
    printf("ACKing node id = %lu acking status = %d\n", nextNodeId, (int)ackingStatus);
}

As noted below, a good time to check the acking status of the receiver set is after a NORM_TX_WATERMARK_COMPLETED notification has occurred.

4.4.34.3. Return Values

The function iteratively returns NormNodeId values from the given session's local sender "acking node" list. A value of NORM_NODE_NONE is returned when the end of the list is reached.

4.4.35. NormGetAckingStatus()

4.4.35.1. Synopsis
#include <normApi.h>

NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle,
                                     NormNodeId        nodeId = NORM_NODE_ANY);
4.4.35.2. Description

This function queries the status of the watermark flushing process and/or positive acknowledgment collection initiated by a prior call to NormSetWatermark() for the given sessionHandle. In general, it is expected that applications will invoke this function after the corresponding NORM_TX_WATERMARK_COMPLETED event has been posted. Setting the default parameter value nodeId = NORM_NODE_ANY returns a "status" indication for the overall process. Also, individual nodeId values may be queried using the NormNodeId values of receivers that were included in previous calls to NormAddAckingNode() to populate the sender session's acking node list.

If the flushing/acknowledgment process is being used for application flow control, the sender application may wish to reset the watermark and flushing process (using NormSetWatermark()) if the response indicates that some nodes have failed to respond. However, note that the flushing/acknowledgment process itself does elicit NACKs from receivers as needed and is interrupted and reset by any repair response that occurs. Thus, even by the time the flushing process has completed (and NORM_TX_WATERMARK_COMPLETED is posted) once, this is an indication that the NORM protocol has made a valiant attempt to deliver the content. Resetting the watermark process can increase robustness, but it may be in vain to repeat this process multiple times when likely network connectivity has been lost or expected receivers have failed (dropped out, shut down, etc).

4.4.35.3. Return Values

Possible return values include:

NORM_ACK_INVALID

The given sessionHandle is invalid or the given nodeId is not in the sender's acking list.

NORM_ACK_FAILURE

The positive acknowledgement collection process did not receive acknowledgment from every listed receiver (nodeId = NORM_NODE_ANY) or the identified nodeId did not respond.

NORM_ACK_PENDING

The flushing process at large has not yet completed (nodeId = NORM_NODE_ANY) or the given individual nodeId is still being queried for response.

NORM_ACK_SUCCESS

All receivers (nodeId = NORM_NODE_ANY) responded with positive acknowledgement or the given specific nodeId did acknowledge.

4.4.36. NormSendCommand()

4.4.36.1. Synopsis
#include <normApi.h>

bool NormSendCommand(NormSessionHandle session,
                     const char*       cmdBuffer,
                     unsigned int      cmdLength,
                     bool              robust = false); 
4.4.36.2. Description

This function enqueues a NORM application-defined command for transmission. The cmdBuffer parameter points to a buffer containing the application-defined command content that will be contained in the NORM_CMD(APPLICATION) message payload. The cmdLength indicates the length of this content (in bytes) and MUST be less than or equal to the segmentLength value for the given session (see NormStartSender()). The NORM command transmission will be multiplexed with any NORM data transmission. The command is NOT delivered reliably, but can be optionally transmitted with repetition (once per GRTT) according to the NORM transmit robust factor value (see NormSetTxRobustFactor()) for the given session if the robust parameter is set to true. The command transmission is subject to any congestion control or set rate limits for the NORM session. Once the command has been transmitted (with repetition if robust is set to true), a NORM_TX_CMD_SENT notification is issued. An application can only enqueue a single command at a time (i.e. the NORM_TX_CMD_SENT notification must occur before another command can be sent). The NormCancelCommand() call is available to terminate command transmission if needed. Note that if a rapid succession of commands are sent it is possible that the commands may be delivered to the receivers out-of-order. Also, when repetition is requested (i.e., if robust is set to true) the receiver may receive duplicate copies of the same command. It is up to the application to provide any needed mechanism for detecting and/or filtering duplicate command reception.

The application-defined command feature allows NORM applications to provide some out-of-band (with respect to reliable data delivery) signaling to support session management or other functions. The reception of these "atomic" commands is relatively stateless (as compared to reliable data delivery) and thus it is possible for many senders within a group to send commands without extreme resource burden on receivers (i.e. other participants). Again, this "light-weight" signaling mechanism may be used to provide ancillary communication for the group. In the future, an additional API mechanism will be provided to support application-defined positive acknowledgement requests that could conceivably be used to help guarantee command delivery if desired.

4.4.36.3. Return Values

The function returns true upon success. The function may fail, returning false, if the session is not set for sender operation (see NormStartSender()), the cmdLength exceeds the configured session segmentLength, or a previously-enqueued command has not yet been sent.

4.4.37. NormCancelCommand()

4.4.37.1. Synopsis
#include <normApi.h>

void NormCancelCommand(NormSessionHandle session);
4.4.37.2. Description

This function terminates any pending NORM_CMD(APPLICATION) transmission that was previously initiated with the NormSendCommand() call. Due to the asynchrony of the NORM protocol engine thread and the application, it is possible that the command may have been already sent but the NormCancelCommand() call will ensure a NORM_TX_CMD_SENT notification is not issued for that prior command.

The application-defined command feature allows NORM applications to provide some out-of-band (with respect to reliable data delivery) signaling to support session management or other functions. The reception of these "atomic" commands is relatively stateless (as compared to reliable data delivery) and thus it is possible for many senders within a group to send commands without extreme resource burden on receivers (i.e. other participants). Again, this "light-weight" signaling mechanism may be used to provide ancillary communication for the group. In the future, an additional API mechanism will be provided to support application-defined positive acknowledgement requests that could conceivably be used to help guarantee command delivery if desired.

4.4.37.3. Return Values

The function has not return value.

4.5. NORM Receiver Functions

4.5.1. NormStartReceiver()

4.5.1.1. Synopsis
#include <normApi.h>

bool NormStartReceiver(NormSessionHandle sessionHandle,
                       unsigned long     bufferSpace);
4.5.1.2. Description

This function initiates the application's participation as a receiver within the NormSession identified by the sessionHandle parameter. The NORM protocol engine will begin providing the application with receiver-related NormEvent notifications, and, unless NormSetSilentReceiver(true) is invoked, respond to senders with appropriate protocol messages. The bufferSpace parameter is used to set a limit on the amount of bufferSpace allocated by the receiver per active NormSender within the session. The appropriate bufferSpace to use is a function of expected network delay*bandwidth product and packet loss characteristics. A discussion of trade-offs associated with NORM transmit and receiver buffer space selection is provided later in this document. An insufficient bufferSpace allocation will result in potentially inefficient protocol operation, even though reliable operation may be maintained. In some cases of a large delay*bandwidth product and/or severe packet loss, a small bufferSpace allocation (coupled with the lack of explicit flow control in NORM) may result in the receiver "re-syncing" to the sender, resulting in "outages" in the reliable transmissions from a sender (this is analogous to a TCP connection timeout failure).

4.5.1.3. Return Values

A value of true is returned upon success and false upon failure. The reasons failure may occur include limited system resources or that the network sockets required for session communication failed to open or properly configure.

4.5.2. NormStopReceiver()

4.5.2.1. Synopsis
#include <normApi.h>

void NormStopReceiver(NormSessionHandle sessionHandle,
                      unsigned int      gracePeriod = 0);
4.5.2.2. Description

This function ends the application's participation as a receiver in the NormSession specified by the session parameter. By default, all receiver-related protocol activity is immediately halted and all receiver-related resources are freed (except for those which have been specifically retained (see NormNodeRetain() and NormObjectRetain()). However, and optional gracePeriod parameter is provided to allow the receiver an opportunity to inform the group of its intention. This is applicable when the local receiving NormNode has been designated as an active congestion control representative (i.e. current limiting receiver (CLR) or potential limiting receiver (PLR)). In this case, a non-zero gracePeriod value provides an opportunity for the receiver to respond to the applicable sender(s) so the sender will not expect further congestion control feedback from this receiver. The gracePeriod integer value is used as a multiplier with the largest sender GRTT to determine the actual time period for which the receiver will linger in the group to provide such feedback (i.e. "graceTime" = (gracePeriod * GRTT)). During this time, the receiver will not generate any requests for repair or other protocol actions aside from response to applicable congestion control probes. When the receiver is removed from the current list of receivers in the sender congestion control probe messages (or the gracePeriod expires, whichever comes first), the NORM protocol engine will post a NORM_LOCAL_RECEIVER_CLOSED event for the applicable session, and related resources are then freed.

4.5.2.3. Return Values

This function has no return values.

4.5.3. NormSetRxCacheLimit()

4.5.3.1. Synopsis
#include <normApi.h>

void NormSetRxCacheLimit(NormSessionHandle sessionHandle,
                         unsigned short    countMax);
4.5.3.2. Description

This function sets a limit on the number of outstanding (pending) NormObjects for which a receiver will keep state on a per-sender basis. Note that the value countMax sets a limit on the maximum consecutive range of objects that can be pending. The default value (when this function is not called) of countMax is 256. This should be sufficient for most bulk transfer usage, but if small object sizes (e.g. small NORM_OBJECT_DATA messages) are being transferred, it may be useful to raise this limit in cases of high transmission speeds or large <delay*bandwidth, loss> network conditions. If the receiver cache limit is set too small (i.e. for high speed or large <delay*bandwidth> operation), the receiver may not maintain reliable reception or impact session throughput when flow control is enabled (see NormSetFlowControl()). The maximum allowed value of countMax is 16,384.

If this value is changed after NormStartReceiver() has been called, it will only affect newly-detected remote senders, so this should typically be called before NORM receiver operation is initiated.

4.5.3.3. Return Values

This function has no return value.

4.5.4. NormSetRxSocketBuffer()

4.5.4.1. Synopsis
#include <normApi.h>

bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle,
                           unsigned int      bufferSize);
4.5.4.2. Description

This function allows the application to set an alternative, non-default buffer size for the UDP socket used by the specified NORM sessionHandle for packet reception. This may be necessary for high speed NORM sessions where the UDP receive socket buffer becomes a bottleneck when the NORM protocol engine (which is running as a user-space process) doesn't get to service the receive socket quickly enough resulting in packet loss when the socket buffer overflows. The bufferSize parameter specifies the socket buffer size in bytes. Different operating systems and sometimes system configurations allow different ranges of socket buffer sizes to be set. Note that a call to NormStartReceiver() (or NormStartSender()) must have been previously made for this call to succeed (i.e., the socket must be already open).

4.5.4.3. Return Values

This function returns true upon success and false upon failure. Possible reasons for failure include, 1) the specified session is not valid, 2) that NORM "receiver" (or "sender") operation has not yet been started for the given session, or 3) an invalid bufferSize specification was given.

4.5.5. NormSetSilentReceiver()

4.5.5.1. Synopsis
#include <normApi.h>

void NormSetSilentReceiver(NormSessionHandle sessionHandle,
                           bool              silent,
                           INT32             maxDelay = -1);
4.5.5.2. Description

This function provides the option to configure a NORM receiver application as a "silent receiver". This mode of receiver operation dictates that the host does not generate any protocol messages while operating as a receiver within the specified sessionHandle. Setting the silent parameter to true enables silent receiver operation while setting it to false results in normal protocol operation where feedback is provided as needed for reliability and protocol operation. Silent receivers are dependent upon proactive FEC transmission (see NormSetAutoParity()) or using repair information requested by other non-silent receivers within the group to achieve reliable transfers.

The optional maxDelay parameter is most applicable for reception of the NORM_OBJECT_STREAM type. The default value of maxDelay = -1 corresponds to normal operation where source data segments for incompletely-received FEC coding blocks (or transport objects) are passed to the application only when imposed buffer constraints (either the NORM_OBJECT_STREAM buffer size (see NormStreamOpen()) or the FEC receive buffer limit (see NormStartReceiver()) require. Thus, the default behavior (maxDelay = -1), causes the receiver to buffer received FEC code blocks for as long as possible (within buffer constraints as newer data arrives) before allowing the application to read the data. Hence, the receive latency (delay) can be quite long depending upon buffer size settings, transmission rate, etc. When the maxDelay parameter is set to a non-negative value, the value determines the maximum number of FEC coding blocks (according to a NORM sender's current transmit position) the receiver will cache an incompletely-received FEC block before giving the application the (incomplete) set of received source segments. For example, a value of maxDelay = 0 will provide the receive application with any data from the previous FEC block as soon as a subsequent FEC block is begun reception. However, this provide no protection against the possibility of out-of-order delivery of packets by the network. Therefore, if lower latency operation is desired when using silent receivers, a minimum maxDelay value of 1 is recommended. For NORM_OBJECT_FILE and NORM_OBJECT_DATA, the only impact of a non-negative maxDelay value is that previous transport objects will be immediately aborted when subsequent object begin reception. Thus, it is not usually recommended to apply a non-negative maxDelay value when NORM_OBJECT_STREAM is not being used.

4.5.5.3. Return Values

This function has no return values.

4.5.6. NormSetDefaultUnicastNack()

4.5.6.1. Synopsis
#include <normApi.h>

void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle,
                               bool              enable);
4.5.6.2. Description

This function controls the default behavior determining the destination of receiver feedback messages generated while participating in the session. If the enable parameter is true, "unicast NACKing" is enabled for new remote senders while it is disabled for state equal to false. The NACKing behavior for current remote senders is not affected. When "unicast NACKing" is disabled (default), NACK messages are sent to the session address (usually a multicast address) and port, but when "unicast NACKing" is enabled, receiver feedback messages are sent to the unicast address (and port) based on the source address of sender messages received. For unicast NORM sessions, it is recommended that "unicast NACKing" be enabled. Note that receiver feedback messages subject to potential "unicast NACKing" include NACK-messages as well as some ACK messages such as congestion control feedback. Explicitly solicited ACK messages, such as those used to satisfy sender watermark acknowledgement requests (see NormSetWatermark()) are always unicast to the applicable sender. (TBD - provide API option so that all messages are multicast.) The default session-wide behavior for unicast NACKing can be overridden via the NormNodeSetUnicastNack() function for individual remote senders.

4.5.6.3. Return Values

This function has no return values.

4.5.7. NormNodeSetUnicastNack()

4.5.7.1. Synopsis
#include <normApi.h>

void NormNodeSetUnicastNack(NormNodeHandle senderNode,
                            bool           enable);
4.5.7.2. Description

This function controls the destination address of receiver feedback messages generated in response to a specific remote NORM sender corresponding to the senderNode parameter. If enable is true, "unicast NACKing" is enabled while it is disabled for enable equal to false. See the description of NormSetDefaultUnicastNack() for details on "unicast NACKing" behavior.

4.5.7.3. Return Values

This function has no return values.

4.5.8. NormSetDefaultSyncPolicy()

4.5.8.1. Synopsis
#include <normApi.h>

void NormSetDefaultSyncPolicy(NormSessionHandle sessionHandle,
                              NormSyncPolicy   syncPolicy);
4.5.8.2. Description

This function sets the default "synchronization policy" used when beginning (or restarting) reception of objects from a remote sender (i.e., "syncing" to the sender) for the given sessionHandle. The "synchronization policy" is the behavior observed by the receiver with regards to what objects it attempts to reliably receive (via transmissions of Negative Acknowledgements to the sender(s) or group as needed). There are currently two synchronization policy types defined:

NORM_SYNC_CURRENT

Attempt reception of "current" and new objects only. (default)

NORM_SYNC_ALL

Attempt recovery and reliable reception of all objects held in sender transmit object cache and newer objects.

The behavior of a receiver using the default NORM_SYNC_CURRENT policy is to attempt reliable reception only for the first received "current" and newer (with respect to the ordinal NORM object transport identifiers used by the protocol) objects from a given NORM sender. Additionally, reliable reception is only attempted when receiving a non-repair NORM_DATA message (or optionally a NORM positive acknowledgement request) from the first forward error correction (FEC) encoding block of the given object. This somewhat conservative synchronization behavior helps prevent late-joining (or otherwise "flaky" with respect to group membership) receivers from penalizing other receivers in the group by causing the sender to "rewind" and transmit older object content to satisfy the late joiner instead of moving forward with transmission of new content. For large scale, loosely-organized multicast applications, the NORM_SYNC_CURRENT policy is typically recommended.

The NORM_SYNC_ALL policy allows newly joining receivers much more aggressive behavior as they will immediately NACK for all objects from the "current" object backwards through the entire range of objects set by the NormSetRxCacheLimit() function. This behavior depends upon the sender to issue an appropriate NORM_CMD(SQUELCH) response (if applicable) to align (i.e. "synchronize") the new receiver with its current transmit object cache (similar to a "repair window"). This synchronization behavior may be useful for unicast uses of NORM or other applications where the group membership is more carefully managed and it is important that all content (including older content) is received. Note that the sender transmit cache bounds (see NormSetTxCacheBounds()) and the receiver receive cache limit (see NormSetRxCacheLimit()) settings will limit how far back onto the sender transmission history that transmitted objects can be reliably recovered from the "current" transmission point when the receiver begins reception.

When this function is not invoked, the NORM_SYNC_CURRENT behavior is observed as the default receiver synchronization policy. This call SHOULD be made before NormStartReceiver() is called.

4.5.8.3. Return Values

This function has no return values.

4.5.9. NormSetDefaultNackingMode()

4.5.9.1. Synopsis
#include <normApi.h>

void NormSetDefaultNackingMode(NormSessionHandle sessionHandle,
                               NormNackingMode   nackingMode);
4.5.9.2. Description

This function sets the default "nacking mode" used when receiving objects for the given sessionHandle. This allows the receiver application some control of its degree of participation in the repair process. By limiting receivers to only request repair of objects in which they are really interested in receiving, some overall savings in unnecessary network loading might be realized for some applications and users. Available nacking modes include:

NORM_NACK_NONE

Do not transmit any repair requests for the newly received object.

NORM_NACK_INFO_ONLY

Transmit repair requests for NORM_INFO content only as needed.

NORM_NACK_NORMAL

Transmit repair requests for entire object as needed.

This function specifies the default behavior with respect to any new sender or object. This default behavior may be overridden for specific sender nodes or specific object using NormNodeSetNackingMode() or NormObjectSetNackingMode(), respectively. The receiver application's use of NORM_NACK_NONE essentially disables a guarantee of reliable reception, although the receiver may still take advantage of sender repair transmissions in response to other receivers' requests. When the sender provides, NORM_INFO content for transmitted objects, the NORM_NACK_INFO_ONLY mode may allows the receiver to reliably receive object context information from which it may choose to "upgrade" its nackingMode for the specific object via the NormObjectSetNackingMode() call. Similarly, the receiver may changes its default nackingMode with respect to specific senders via the NormNodeSetNackingMode() call. The default "default nackingMode" when this call is not made is NORM_NACK_NORMAL.

4.5.9.3. Return Values

This function has no return values.

4.5.10. NormNodeSetNackingMode()

4.5.10.1. Synopsis
#include <normApi.h>

void NormNodeSetNackingMode(NormNodeHandle  nodeHandle,
                            NormNackingMode nackingMode);
4.5.10.2. Description

This function sets the default "nacking mode" used for receiving new objects from a specific sender as identified by the nodeHandle parameter. This overrides the default nackingMode set for the receive session. See NormSetDefaultNackingMode() for a description of possible nackingMode parameter values and other related information.

4.5.10.3. Return Values

This function has no return values.

4.5.11. NormObjectSetNackingMode()

4.5.11.1. Synopsis
#include <normApi.h>

void NormObjectSetNackingMode(NormObjectHandle objectHandle,
                              NormNackingMode  nackingMode);
4.5.11.2. Description

This function sets the "nacking mode" used for receiving a specific transport object as identified by the objectHandle parameter. This overrides the default nacking mode set for the applicable sender node. See NormSetDefaultNackingMode() for a description of possible nackingMode parameter values and other related information.

4.5.11.3. Return Values

This function has no return values.

4.5.12. NormSetDefaultRepairBoundary()

4.5.12.1. Synopsis
#include <normApi.h>

void NormSetDefaultRepairBoundary(NormSessionHandle  sessionHandle,
                                  NormRepairBoundary repairBoundary);
4.5.12.2. Description

This function allows the receiver application to customize, for a given sessionHandle, at what points the receiver initiates the NORM NACK repair process during protocol operation. Normally, the NORM receiver initiates NACKing for repairs at the FEC code block and transport object boundaries. For smaller block sizes, the NACK repair process is often/quickly initiated and the repair of an object will occur, as needed, during the transmission of the object. This default operation corresponds to repairBoundary equal to NORM_BOUNDARY_BLOCK. Using this function, the application may alternatively, setting repairBoundary equal to NORM_BOUNDARY_OBJECT, cause the protocol to defer NACK process initiation until the current transport object has been completely transmitted.

4.5.12.3. Return Values

This function has no return values.

4.5.13. NormNodeSetRepairBoundary()

4.5.13.1. Synopsis
#include <normApi.h>

void NormNodeSetRepairBoundary(NormNodeHandle     nodeHandle,
                               NormRepairBoundary repairBoundary);
4.5.13.2. Description

This function allows the receiver application to customize, for the specific remote sender referenced by the nodeHandle parameter, at what points the receiver initiates the NORM NACK repair process during protocol operation. See the description of NormSetDefaultRepairBoundary() for further details on the impact of setting the NORM receiver repair boundary and possible values for the repairBoundary parameter.

4.5.13.3. Return Values

This function has no return values.

4.5.14. NormSetDefaultRxRobustFactor()

4.5.14.1. Synopsis
#include <normApi.h>

void NormSetDefaultRxRobustFactor(NormSessionHandle sessionHandle,
                                  int               rxRobustFactor);
4.5.14.2. Description

This routine controls how persistently NORM receivers will maintain state for sender(s) and continue to request repairs from the sender(s) even when packet reception has ceased. The rxRobustFactor value determines how many times a NORM receiver will self-initiate NACKing (repair requests) upon cessation of packet reception from a sender. The default value is 20. Setting rxRobustFactor to -1 will make the NORM receiver infinitely persistent (i.e., it will continue to NACK indefinitely as long as it is missing data content). It is important to note that the NormSetTxRobustFactor() also affects receiver operation in setting the time interval that is used to gauge that sender packet transmission has ceased (i.e., the sender inactivity timeout). This "timeout" interval is a equal of (2 * GRTT * txRobustFactor). Thus the overall timeout before a NORM receiver quits NACKing is (rxRobustFactor * 2 * GRTT * txRobustFactor).

The NormNodeSetRxRobustFactor() function can be used to control this behavior on a per-sender basis. When a new remote sender is detected, the default rxRobustFactor set here is used. Again, the default value is 20.

4.5.14.3. Return Values

This function has no return values.

4.5.15. NormNodeSetRxRobustFactor()

4.5.15.1. Synopsis
#include <normApi.h>

void NormNodeSetRxRobustFactor(NormNodeHandle nodeHandle,
                               int            rxRobustFactor);
4.5.15.2. Description

This routine sets the rxRobustFactor as described in NormSetDefaultRxRobustFactor() for an individual remote sender identified by the nodeHandle parameter. See the description of NormSetDefaultRxRobustFactor() for details

4.5.15.3. Return Values

This function has no return values.

4.5.16. NormStreamRead()

4.5.16.1. Synopsis
#include <normApi.h>

bool NormStreamRead(NormObjectHandle streamHandle,
                    char*            buffer
                    unsigned int*    numBytes);
4.5.16.2. Description

This function can be used by the receiver application to read any available data from an incoming NORM stream. NORM receiver applications "learn" of available NORM streams via NORM_RX_OBJECT_NEW notification events. The streamHandle parameter here must correspond to a valid NormObjectHandle value provided during such a prior NORM_RX_OBJECT_NEW notification. The buffer parameter must be a pointer to an array where the received data can be stored of a length as referenced by the numBytes pointer. On successful completion, the numBytes storage will be modified to indicate the actual number of bytes copied into the provided buffer. If the numBytes storage is modified to a zero value, this indicates that no stream data was currently available for reading.

Note that NormStreamRead() is never a blocking call and only returns failure (false) when a break in the integrity of the received stream occurs. The NORM_RX_OBJECT_UPDATE provides an indication to when there is stream data available for reading. When such notification occurs, the application should repeatedly read from the stream until the numBytes storage is set to zero, even if a false value is returned. Additional NORM_RX_OBJECT_UPDATE notifications might not be posted until the application has read all available data.

4.5.16.3. Return Values

This function normally returns a value of true. However, if a break in the integrity of the reliable received stream occurs (or the stream has been ended by the sender), a value of false is returned to indicate the break. Unless the stream has been ended (and the receiver application will receive NORM_RX_OBJECT_COMPLETED notification for the stream in that case), the application may continue to read from the stream as the NORM protocol will automatically "resync" to streams, even if network conditions are sufficiently poor that breaks in reliability occur. If such a "break" and "resync" occurs, the application may be able to leverage other NORM API calls such as NormStreamSeekMsgStart() or NormStreamGetReadOffset() if needed to recover its alignment with received stream content. This depends upon the nature of the application and its stream content.

4.5.17. NormStreamSeekMsgStart()

4.5.17.1. Synopsis
#include <normApi.h>

bool NormStreamSeekMsgStart(NormObjectHandle streamHandle);
4.5.17.2. Description

This function advances the read offset of the receive stream referenced by the streamHandle parameter to align with the next available message boundary. Message boundaries are defined by the sender application using the NormStreamMarkEom() call. Note that any received data prior to the next message boundary is discarded by the NORM protocol engine and is not available to the application (i.e., there is currently no "rewind" function for a NORM stream). Also note this call cannot be used to skip messages. Once a valid message boundary is found, the application must read from the stream using NormStreamRead() to further advance the read offset. The current offset (in bytes) for the stream can be retrieved via NormStreamGetReadOffset().

4.5.17.3. Return Values

This function returns a value of true when start-of-message is found. The next call to NormStreamRead() will retrieve data aligned with the message start. If no new message boundary is found in the buffered receive data for the stream, the function returns a value of false. In this case, the application should defer repeating a call to this function until a subsequent NORM_RX_OBJECT_UPDATE notification is posted.

4.5.18. NormStreamGetReadOffset()

4.5.18.1. Synopsis
#include <normApi.h>

unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle);
4.5.18.2. Description

This function retrieves the current read offset value for the receive stream indicated by the streamHandle parameter. Note that for very long-lived streams, this value may wrap. Thus, in general, applications should not be highly dependent upon the stream offset, but this feature may be valuable for certain applications which associate some application context with stream position.

4.5.18.3. Return Values

This function returns the current read offset in bytes. The return value is undefined for sender streams. There is no error result.

4.6. NORM Object Functions

The functions described in this section may be used for sender or receiver purposes to manage transmission and reception of NORM transport objects. In most cases, the receiver will be the typical user of these functions to retrieve additional information on newly-received objects. All of these functions require a valid NormObjectHandle argument which specifies the applicable object. Note that NormObjectHandle values obtained from a NormEvent notification may be considered valid only until a subsequent call to NormGetNextEvent(), unless explicitly retained by the application (see NormObjectRetain()). NormObjectHandle values obtained as a result of NormFileEnqueue(), NormDataEnqueue(), or NormStreamOpen() calls can be considered valid only until a corresponding NORM_TX_OBJECT_PURGED notification is posted or the object is dequeued using NormObjectCancel(), unless, again, otherwise explicitly retained (see NormObjectRetain()).

4.6.1. NormObjectGetType()

4.6.1.1. Synopsis
#include <normApi.h>

NormObjectType NormObjectGetType(NormObjectHandle objectHandle);
4.6.1.2. Description

This function can be used to determine the object type ((NORM_OBJECT_DAT, NORM_OBJECT_FILE, or NORM_OBJECT_STREAM) for the NORM transport object identified by the objectHandle parameter. The objectHandle must refer to a current, valid transport object.

4.6.1.3. Return Values

This function returns the NORM object type. Valid NORM object types include NORM_OBJECT_DATA, NORM_OBJECT_FILE, or NORM_OBJECT_STREAM. A type value of NORM_OBJECT_NONE will be returned for an objectHandle value of NORM_OBJECT_INVALID.

4.6.2. NormObjectHasInfo()

4.6.2.1. Synopsis
#include <normApi.h>

bool NormObjectHasInfo(NormObjectHandle objectHandle);
4.6.2.2. Description

This function can be used to determine if the sender has associated any NORM_INFO content with the transport object specified by the objectHandle parameter. This can even be used before the NORM_INFO content is delivered to the receiver and a NORM_RX_OBJECT_INFO notification is posted.

4.6.2.3. Return Values

A value of true is returned if NORM_INFO is (or will be) available for the specified transport object. A value of false is returned otherwise.

4.6.3. NormObjectGetInfoLength()

4.6.3.1. Synopsis
#include <normApi.h>

unsigned short NormObjectGetInfoLength(NormObjectHandle objectHandle);
4.6.3.2. Description

This function can be used to determine the length of currently available NORM_INFO content (if any) associated with the transport object referenced by the objectHandle parameter.

4.6.3.3. Return Values

The length of the NORM_INFO content, in bytes, of currently available for the specified transport object is returned. A value of 0 is returned if no NORM_INFO content is currently available or associated with the object.

4.6.4. NormObjectGetInfo()

4.6.4.1. Synopsis
#include <normApi.h>

unsigned short NormObjectGetInfo(NormObjectHandle         objectHandle,
                                 char*                    buffer,
                                 unsigned short           bufferLen);
4.6.4.2. Description

This function copies any NORM_INFO content associated (by the sender application) with the transport object specified by objectHandle into the provided memory space referenced by the buffer parameter. The bufferLen parameter indicates the length of the buffer space in bytes. If the provided bufferLen is less than the actual NORM_INFO length, a partial copy will occur. The actual length of NORM_INFO content available for the specified object is returned. However, note that until a NORM_RX_OBJECT_INFO notification is posted to the receive application, no NORM_INFO content is available and a zero result will be returned, even if NORM_INFO content may be subsequently available. The NormObjectHasInfo() call can be used to determine if any NORM_INFO content will ever be available for a specified transport object (i.e., determine if the sender has associated any NORM_INFO with the object in question).

4.6.4.3. Return Values

The actual length of currently available NORM_INFO content for the specified transport object is returned. This function can be used to determine the length of NORM_INFO content for the object even if a NULL buffer value and zero bufferLen is provided. A zero value is returned if NORM_INFO content has not yet been received (or is non-existent) for the specified object.

4.6.5. NormObjectGetSize()

4.6.5.1. Synopsis
#include <normApi.h>

NormSize NormObjectGetSize(NormObjectHandle objectHandle);
4.6.5.2. Description

This function can be used to determine the size (in bytes) of the transport object specified by the objectHandle parameter. NORM can support large object sizes for the NORM_OBJECT_FILE type, so typically the NORM library is built with any necessary, related macros defined such that operating system large file support is enabled (e.g., "#define _FILE_OFFSET_BITS 64" or equivalent). The NormSize type is defined accordingly, so the application should be built with the same large file support configuration.

For objects of type NORM_OBJECT_STREAM, the size returned here corresponds to the stream buffer size set by the sender application when opening the referenced stream object.

4.6.5.3. Return Values

A size of the data content of the specified object, in bytes, is returned. Note that it may be possible that some objects have zero data content, but do have NORM_INFO content available.

4.6.6. NormObjectGetBytesPending()

4.6.6.1. Synopsis
#include <normApi.h>

NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle);
4.6.6.2. Description

This function can be used to determine the progress of reception of the NORM transport object identified by the objectHandle parameter. This function indicates the number of bytes that are pending reception (I.e., when the object is completely received, "bytes pending" will equal ZERO). This function is not necessarily applicable to objects of type NORM_OBJECT_STREAM which do not have a finite size. Note it is possible that this function might also be useful to query the "transmit pending" status of sender objects, but it does not account for pending FEC repair transmissions and thus may not produce useful results for this purpose.

4.6.6.3. Return Values

A number of object source data bytes pending reception (or transmission) is returned.

4.6.7. NormObjectCancel()

4.6.7.1. Synopsis
#include <normApi.h>

void NormObjectCancel(NormObjectHandle objectHandle);
4.6.7.2. Description

This function immediately cancels the transmission of a local sender transport object or the reception of a specified object from a remote sender as specified by the objectHandle parameter. The objectHandle must refer to a currently valid NORM transport object. Any resources used by the transport object in question are immediately freed unless the object has been otherwise retained by the application via the NormObjectRetain() call. Unless the application has retained the object in such fashion, the object in question should be considered invalid and the application must not again reference the objectHandle after this call is made.

If the canceled object is a sender object not completely received by participating receivers, the receivers will be informed of the object's cancellation via the NORM protocol NORM_CMD(SQUELCH) message in response to any NACKs requesting repair or retransmission of the applicable object. In the case of receive objects, the NORM receiver will not make further requests for repair of the indicated object, but furthermore, will acknowledge the object as completed with respect to any associated positive acknowledgement requests (see NormSetWatermark()).

4.6.7.3. Return Values

This function has no return value.

4.6.8. NormObjectRetain()

4.6.8.1. Synopsis
#include <normApi.h>

void NormObjectRetain(NormObjectHandle objectHandle);
4.6.8.2. Description

This function "retains" the objectHandle and any state associated with it for further use by the application even when the NORM protocol engine may no longer require access to the associated transport object. Normally, the application is guaranteed that a given NormObjectHandle is valid only while it is being actively transported by NORM (i.e., for sender objects, from the time an object is created by the application until it is canceled by the application or purged (see the NORM_TX_OBJECT_PURGED notification) by the protocol engine, or, for receiver objects, from the time of the object's NORM_RX_OBJECT_NEW notification until its reception is canceled by the application or a NORM_RX_OBJECT_COMPLETED or NORM_RX_OBJECT_ABORTED notification is posted). Note that an application may refer to a given object after any related notification until the application makes a subsequent call to NormGetNextEvent().

When the application makes a call to NormObjectRetain() for a given objectHandle, the application may use that objectHandle value in any NORM API calls until the application makes a call to NormObjectRelease() for the given object. Note that the application MUST make a corresponding call to NormObjectRelease() for each call it has made to NormObjectRetain() in order to free any system resources (i.e., memory) used by that object. Also note that retaining a receive object also automatically retains any state associated with the NormNodeHandle corresponding to the remote sender of that receive object so that the application may use NORM node API calls for the value returned by NormObjectGetSender() as needed.

4.6.8.3. Return Values

This function has no return value.

4.6.9. NormObjectRelease()

4.6.9.1. Synopsis
#include <normApi.h>

void NormObjectRelease(NormObjectHandle objectHandle);
4.6.9.2. Description

This function complements the NormObjectRetain() call by immediately freeing any resources associated with the given objectHandle, assuming the underlying NORM protocol engine no longer requires access to the corresponding transport object. Note the NORM protocol engine retains/releases state for associated objects for its own needs and thus it is very unsafe for an application to call NormObjectRelease() for an objectHandle for which it has not previously explicitly retained via NormObjectRetain().

4.6.9.3. Return Values

This function has no return value.

4.6.10. NormFileGetName()

4.6.10.1. Synopsis
#include <normApi.h>

bool NormFileGetName(NormObjectHandle objectHandle,
                     char*            nameBuffer,
                     unsigned int     bufferLen);
4.6.10.2. Description

This function copies the name, as a NULL-terminated string, of the file object specified by the objectHandle parameter into the nameBuffer of length bufferLen bytes provided by the application. The objectHandle parameter must refer to a valid NormObjectHandle for an object of type NORM_OBJECT_FILE. If the actual name is longer than the provided bufferLen, a partial copy will occur. Note that the file name consists of the entire path name of the specified file object and the application should give consideration to operating system file path lengths when providing the nameBuffer.

4.6.10.3. Return Values

This function returns true upon success and false upon failure. Possible failure conditions include the objectHandle does not refer to an object of type NORM_OBJECT_FILE.

4.6.11. NormFileRename()

4.6.11.1. Synopsis
#include <normApi.h>

bool NormFileRename(NormObjectHandle objectHandle,
                    const char*      fileName);
4.6.11.2. Description

This function renames the file used to store content for the NORM_OBJECT_FILE transport object specified by the objectHandle parameter. This allows receiver applications to rename (or move) received files as needed. NORM uses temporary file names for received files until the application explicitly renames the file. For example, sender applications may choose to use the NORM_INFO content associated with a file object to provide name and/or typing information to receivers. The fileName parameter must be a NULL-terminated string which should specify the full desired path name to be used. NORM will attempt to create sub-directories as needed to satisfy the request. Note that existing files of the same name may be overwritten.

4.6.11.3. Return Values

This function returns true upon success and false upon failure. Possible failure conditions include the case where the objectHandle does not refer to an object of type NORM_OBJECT_FILE and where NORM was unable to successfully create any needed directories and/or the file itself.

4.6.12. NormDataAccessData()

4.6.12.1. Synopsis
#include <normApi.h>

const char* NormDataAccessData(NormObjectHandle objectHandle);
4.6.12.2. Description

This function allows the application to access the data storage area associated with a transport object of type NORM_OBJECT_DATA. For example, the application may use this function to copy the received data content for its own use. Alternatively, the application may establish "ownership" for the allocated memory space using the NormDataDetachData() function if it is desired to avoid the copy.

If the object specified by the objectHandle parameter has no data content (or is not of type NORM_OBJECT_DATA), a NULL value may be returned. The application MUST NOT attempt to modify the memory space used by NORM_OBJECT_DATA objects during the time an associated objectHandle is valid. The length of data storage area can be determined with a call to NormObjectGetSize() for the same objectHandle value.

4.6.12.3. Return Values

This function returns a pointer to the data storage area for the specified transport object. A NULL value may be returned if the object has no associated data content or is not of type NORM_OBJECT_DATA.

4.6.13. NormDataDetachData()

4.6.13.1. Synopsis
#include <normApi.h>

char* NormDataDetachData(NormObjectHandle objectHandle);
4.6.13.2. Description

This function allows the application to disassociate data storage allocated by the NORM protocol engine for a receive object from the NORM_OBJECT_DATA transport object specified by the objectHandle parameter. It is important that this function is called after the NORM protocol engine has indicated it is finished with the data object (i.e., after a NORM_TX_OBJECT_PURGED, NORM_RX_OBJECT_COMPLETED, or NORM_RX_OBJECT_ABORTED notification event). But the application must call NormDataDetachData() before a call is made to NormObjectCancel() or NormObjectRelease() for the object if it plans to access the data content afterwards. Otherwise, the NORM protocol engine will free the applicable memory space when the associated NORM_OBJECT_DATA transport object is deleted and the application will be unable to access the received data unless it has previously copied the content.

Once the application has used this call to "detach" the data content, it is the application's responsibility to subsequently free the data storage space as needed.

4.6.13.3. Return Values

This function returns a pointer to the data storage area for the specified transport object. A NULL value may be returned if the object has no associated data content or is not of type NORM_OBJECT_DATA.

4.6.14. NormObjectGetSender()

4.6.14.1. Synopsis
#include <normApi.h>

NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle);
4.6.14.2. Description

This function retrieves the NormNodeHandle corresponding to the remote sender of the transport object associated with the given objectHandle parameter. Note that the returned NormNodeHandle value is only valid for the same period that the objectHandle is valid. The returned NormNodeHandle may optionally be retained for further use by the application using the NormNodeRetain() function call. The returned value can be used in the NORM Node Functions described later in this document.

4.6.14.3. Return Values

This function returns the NormNodeHandle corresponding to the remote sender of the transport object associated with the given objectHandle parameter. A value of NORM_NODE_INVALID is returned if the specified objectHandle references a locally originated, sender object.

4.7. NORM Node Functions

The functions described in this section may be used for NORM sender or receiver (most typically receiver) purposes to retrieve additional information about a remote NormNode, given a valid NormNodeHandle. Note that, unless specifically retained (see NormNodeRetain()), a NormNodeHandle provided in a NormEvent notification should be considered valid only until a subsequent call to NormGetNextEvent() is made. NormNodeHandle values retrieved using NormObjectGetSender() can be considered valid for the same period of time as the corresponding NormObjectHandle is valid.

4.7.1. NormNodeGetId()

4.7.1.1. Synopsis
#include <normApi.h>

NormNodeId NormNodeGetId(NormNodeHandle nodeHandle);
4.7.1.2. Description

This function retrieves the NormNodeId identifier for the remote participant referenced by the given nodeHandle value. The NormNodeId is a 32-bit value used within the NORM protocol to uniquely identify participants within a NORM session. The participants identifiers are assigned by the application or derived (by the NORM API code) from the host computers default IP address.

4.7.1.3. Return Values

This function returns the NormNodeId value associated with the specified nodeHandle. In the case nodeHandle is equal to NORM_NODE_INVALID, the return value will be NORM_NODE_NONE.

4.7.2. NormNodeGetAddress()

4.7.2.1. Synopsis
#include <normApi.h>

bool NormNodeGetAddress(NormNodeHandle          nodeHandle,
                        char*                   addrBuffer,
                        unsigned int*           bufferLen,
                        unsigned short*         port = NULL);
4.7.2.2. Description

This function retrieves the current network source address detected for packets received from remote NORM sender referenced by the nodeHandle parameter. The addrBuffer must be a pointer to storage of bufferLen bytes in length in which the referenced sender node's address will be returned. Optionally, the remote sender source port number (see NormSetTxPort()) is also returned if the optional port pointer to storage parameter is provided in the call. Note that in the case of Network Address Translation (NAT) or other firewall activities, the source address detected by the NORM receiver may not be the original address of the original NORM sender.

4.7.2.3. Return Values

A value of true is returned upon success and false upon failure. An invalid nodeHandle parameter value would lead to such failure.

4.7.3. NormNodeGetGrtt()

4.7.3.1. Synopsis
#include <normApi.h>

double NormNodeGetId(NormNodeHandle nodeHandle);
4.7.3.2. Description

This function retrieves the advertised estimate of group round-trip timing (GRTT) for the remote sender referenced by the given nodeHandle value. Newly-starting senders that have been participating as a receiver within a group may wish to use this function to provide a more accurate startup estimate of GRTT (see NormSetGrttEstimate()) prior to a call to NormStartSender(). Applications may use this information for other purpose as well. Note that the NORM_GRTT_UPDATED event is posted (see NormGetNextEvent()) by the NORM protocol engine to indicate when changes in the local sender or remote senders' GRTT estimate occurs.

4.7.3.3. Return Values

This function returns the remote sender's advertised GRTT estimate in units of seconds. A value of -1.0 is returned upon failure. An invalid nodeHandle parameter value will lead to such failure.

4.7.4. NormNodeGetCommand()

4.7.4.1. Synopsis
#include <normApi.h>

bool NormNodeGetCommand(NormNodeHandle nodeHandle,
                        char*          buffer,
                        unsigned int*  buflen);
4.7.4.2. Description

This function retrieves the content of an application-defined command that was received from a remote sender associated with the given nodeHandle. This call should be made in response to the NORM_RX_CMD_NEW notification. This notification is issued for each command received. However the application may use this call to poll for received commands if desired. Additionally, the received command length can be "queried" by setting the value referenced by the buflen parameter to ZERO. Upon return, this value referenced by the buflen parameter is adjusted to reflect the command length. Then a subsequent call to NormNodeGetCommand() can be made with an appropriately-sized buffer to retrieve the received command content. The command size will be less than or equal to the NORM segment size configured for the given remote sender.

Note that if a rapid succession of commands are sent it is possible that the commands may be delivered to the receivers out-of-order. Also, when repetition is requested (i.e., if robust is set to true) the receiver may receive duplicate copies of the same command. It is up to the application to provide any needed mechanism for detecting and/or filtering duplicate command reception.

4.7.4.3. Return Values

This function returns true upon successful retrieval of command content. A return value of false indicates that either no command was available or the provided buffer size (buflen parameter) was inadequate. The value referenced by the buflen parameter is adjusted to indicate the actual command length (in bytes) upon return.

4.7.5. NormNodeFreeBuffers()

4.7.5.1. Synopsis
#include <normApi.h>

void NormNodeFreeBuffers(NormNodeHandle nodeHandle);
4.7.5.2. Description

This function releases memory resources that were allocated for a remote sender. For example, the receiver application may wish to free memory resources when receiving a NORM_REMOTE_SENDER_INACTIVE notification for a given remote sender when multiple senders may be providing content. The NORM protocol engine allocates memory for reliable transport buffering on a per sender basis according to the limit set in the NormStartReceiver() call. These buffering resources comprise the majority of the state allocated for a given remote sender. For NORM applications with possibly multiple senders active at different times, this function can be used to manage to amount of memory allocated for reliable reception. If a sender becomes "active" again after a call to NormNodeFreeBuffers(), new memory resources will be allocated. Note that state for any pending (uncompleted) objects will be dropped when this function is called and the receiver may request retransmission and repair of content if the sender once again becomes "active". The application SHOULD call NormObjectCancel() for any pending objects before calling NormNodeFreeBuffers() if it wishes to never receive those pending objects. Alternatively, a call to NormNodeDelete() will completely eliminate all state for a given remote sender and, if that sender becomes "active" again, it will be treated as a completely new sender.

4.7.5.3. Return Values

This function has no return value.

4.7.6. NormNodeDelete()

4.7.6.1. Synopsis
#include <normApi.h>

void NormNodeDelete(NormNodeHandle nodeHandle);
4.7.6.2. Description

This function can be used by a NORM receiver application to completely remove the state associated with a remote sender for the given nodeHandle. For example, when a NORM_REMOTE_SENDER_INACTIVE notification occurs for a given sender, the application may wish to completely free all associated resources. Note this is distinct from the NormNodeFreeBuffers() call where only the buffering resources are freed and other state pertaining to the sender is kept. If the deleted sender again becomes "active", it will be treated as a brand new sender. Unless explicitly retained with a call to NormNodeRetain(), the nodeHandle should be considered invalid after this call is made. Additionally, any NormObjectHandle values for pending objects from this sender are also invalidated (unless otherwise retained), although NORM_RX_OBJECT_ABORTED notifications may be issued for those pending objects.

4.7.6.3. Return Values

This function has no return value.

4.7.7. NormNodeRetain()

4.7.7.1. Synopsis
#include <normApi.h>

void NormNodeRetain(NormNodeHandle nodeHandle);
4.7.7.2. Description

In the same manner as the NormObjectRetain() function, this function allows the application to retain state associated with a given nodeHandle value even when the underlying NORM protocol engine might normally free the associated state and thus invalidate the NormNodeHandle. If the application uses this function, it must make a corresponding call to NormNodeRelease() when finished with the node information to avoid a memory leak condition. NormNodeHandle values (unless retained) are valid from the time of a NORM_REMOTE_SENDER_NEW notification until a complimentary NORM_REMOTE_SENDER_PURGED notification. During that interval, the application will receive NORM_REMOTE_SENDER_ACTIVE and NORM_REMOTE_SENDER_INACTIVE notifications according to the sender's message transmission activity within the session.

It is important to note that, if the NORM protocol engine posts a NORM_REMOTE_SENDER_PURGED notification for a given NormNodeHandle, the NORM protocol engine could possibly, subsequently establish a new, different NormNodeHandle value for the same remote sender (i.e., one of equivalent NormNodeId) if it again becomes active in the session. A new NormNodeHandle may likely be established even if the application has retained the previous NormNodeHandle value. Therefore, to the application, it might appear that two different senders with the same NormNodeId are participating if these notifications are not carefully monitored. This behavior is contingent upon how the application has configured the NORM protocol engine to manage resources when there is potential for a large number of remote senders within a session (related APIs are TBD). For example, the application may wish to control which specific remote senders for which it keeps state (or limit the memory resources used for remote sender state, etc) and the NORM API may be extended in the future to control this behavior.

4.7.7.3. Return Values

This function has no return value.

4.7.8. NormNodeRelease()

4.7.8.1. Synopsis
#include <normApi.h>

void NormNodeRelease(NormNodeHandle nodeHandle);
4.7.8.2. Description

In complement to the NormNodeRetain() function, this API call releases the specified nodeHandle so that the NORM protocol engine may free associated resources as needed. Once this call is made, the application should no longer reference the specified NormNodeHandle, unless it is still valid.

4.7.8.3. Return Values

This function has no return value.

4.8. NORM Debugging Functions

This section describes some additional function calls that are available to set debugging output options and control other aspects of the NORM implementation.

4.8.1. NormSetDebugLevel()

4.8.1.1. Synopsis
#include <normApi.h>

void NormSetDebugLevel(unsigned int level);
4.8.1.2. Description

This function controls the verbosity of NORM debugging output. Higher values of level result in more detailed output. The highest level of debugging is 12. The debug output consists of text written to STDOUT by default but may be directed to a log file using the NormOpenDebugLog() function.

4.8.1.3. Return Values

This function has no return value.

4.8.2. NormOpenDebugLog()

4.8.2.1. Synopsis
#include <normApi.h>

bool NormOpenDebugLog(NormInstanceHandle instance, const char* fileName);
4.8.2.2. Description

This function allows NORM debug output to be directed to a file instead of the default STDERR.

4.8.2.3. Return Values

The function returns true on success. If the specified file cannot be opened a value of false is returned.

4.8.3. NormCloseDebugLog()

4.8.3.1. Synopsis
#include <normApi.h>

bool NormCloseDebugLog(NormInstanceHandle instance);
4.8.3.2. Description

TBD

4.8.3.3. Return Values

TBD

4.8.4. NormOpenDebugPipe()

4.8.4.1. Synopsis
#include <normApi.h>

bool NormOpenDebugPipe(NormInstanceHandle instance, const char* pipeName);
4.8.4.2. Description

TBD

4.8.4.3. Return Values

TBD

4.8.5. NormCloseDebugPipe()

4.8.5.1. Synopsis
#include <normApi.h>

bool NormCloseDebugPipe(NormInstanceHandle instance);
4.8.5.2. Description

TBD

4.8.5.3. Return Values

TBD

norm-1.5.8+dfsg2/doc/NormDeveloperGuide.pdf0000644000000000000000000160424012426727351015406 0ustar %PDF-1.4 %âãÏÓ 6 0 obj <> stream xÚÝKw#ו¦áyþ ÌZb߇²-¹µVYRÉY]M˜LHb™I¦I¦Üò¯ï8ÁK"r¿½¼lSÚHàŒ'"ðÏ7ûÍnþÏ~³ßù6*7^¶ÝymÎ?¼Ùmm>þÿü¯þùf·yû¯ùë·çoöZ[½¿µNÛ\¾™?~»ÛüåúÍÎÿá7Kx·ùëüß_Þüéí›?~³ÛLºÍ”ÍÛŸ?ÿüÜoõèç¿ýðæ‹Íwßÿø·Í_xû?O9ÙMÛˆuî·ÃåõÇÃÍÿºÝüõÓÅûU|Úï¶»ý´q·í´_Ò?Íù›UÆæYèqæöâúj³ßÚ;ûé#:îó~w|§ˆ­Ø|?$·»ñPæ[}õîöîæìüîþûg·ˆù^ì}+»\Âo½¸Ý¼¿>ÿôápu·y¸=¿¹xw¸Ýœ]mÎ>~¼¼8?»wâãÍõ/7g>\\ý²¹¸º;Üü¼ÒØï·²_}ß³óÃæ§/¾úáÛŸþ°ùùúfs÷ëa³ºÉ =åê&ßÿãËïo.æ;rx¿ùñpyqöîò°ùÛ§Ë»ùnÜ.çËÝüƒr<ŸÇg§Oßä§/ƳuÏõùE•[÷Ul< »ëóëËÍŇ—‡ñàïè³çmš_u»õM[lö_–—ÁûͻߗýÃãúúê—‹«Ãáfž]½¦!ÛÊ\}›¯Þ¯~’îvÛ²uäìjVþîp÷¯UPe»[£\ßücüÔŸ¾XåB·®ëà?®é[}æûý*P²jxûõWßgl_óý~ö$-OÏîÙÓh5=%~<ÜÎnÎÝüõæúÓÇÍõÏ‹å]]Œ—Æßççj~‰>¢ÒWß⻳U@æÉúg¬ŸH‰í.Vó³ËÍÓÝø³w×7gw×7¿¯ž6™_ŽëÍÈßýø?ýa»~~}~ð¶ ¾ϲayz%Î_¬p}~Mì×÷xÞ¬Ün~9\nÎ.³C/wO¹Ÿn>^ß67¿CïÏîÎ6óFáêöãõÍÝò yôÛ}»ù×Åí¯ãrw½ù4ßîÛñ~u¸ûüâýé‹o˜“Ÿ~7·‡›ß.Îç{3¾×/ãIz~<ŸîÏòãßÏwfý[iËã;Ê­ž‘ý¼Í _Íkþý4oðs•ØÞ›žÍ×åíõæöÓÇ庺¿Û?}ññzÞ~}ywýåòÅü˜–;w~ýáÃ’Y6ã×óÃÙï›w‡Áñ~yŒ·ŸÎ}þíóÆë_¿ÆÆcÞ’¼´7×o.æWéúe°ŸŸ£ýúvãepþéæfl}×/‡Û‡ó‹ûmøô° ÿâ§Ýn·Þ¬ñp—ç­ø/ë—Üý úèg­x%öÛZß—ù\\l©uÞzŽ_­£àÓëãx›ö|ÃàëÛ¼]Ïs[ë;wvûç¼úy‹ñÍj[ݯÆ×7ç«ívÍ›¶õ7¯à¯ß~3?ßëWÐüç³VÁ¿ùóFJw«Øü ‹uìÙóã]ߥõÖùë‡gùò÷ÍÙü‹ùóaþ‡yëýËØU¿wwÛƒ•Óü‡uýs翨[Ãy;óù=üqÔÕù‹Æ²wtÄ)Ÿ7$ë?zÛÍß®oæ;ñiÞ¾]Ì[½ó ÷á‹åwàâêüòÓûñÿó]ÿùÓݧ9¼~-Éì½Û¯~ÄáfÙ{Yîë±ÄØôÌ[góæôðìÏ­fn÷±þ>ë?‚󯰿}¤ÕzØëzú“²{þÀ§Ï[ƣǸ<´ó›ÃÙø“rv7ß«Ëñ¸Çöà°}ÚÛŠ±—²Þ}Ò˜7\óÖüäU=ïÒìç-ÖñüìÝz“7«À¼qž‰þ|=ÿF]ÝÝ?†­ºÇñâ¾›š,{’ã¶ûíæOó>ÓØú^½?ù‹ºŸŸ”y§ìøÛÕ™ÿâµsÝÁ\`î0¯~nÌ æÙÏ}sðsð ð ð ð ðKðKðKð+ð+ð«ÞoÚí`.0w˜÷~Ó~‚¹Á¼÷›¦=Ìæà'à'à'à'à§à§à§àgàgàgàçàçàçàçàààà—à—à—àWàWàWàW½ßx‹¦ŸÌ{¿‡7=š¹Â¼÷“is¹Ãüüüüüüü ü ü ü üüüüüüüüüüü ü üª÷ÓÝæ óÞO÷;˜ Ì潟NÌ æà'àýC¡(ô…þ¡Ð?ú‡BÿPè ýC¡(ô…þ¡Ð?ú‡BÿPè ýC¡(ô…þ¡Ð?ú‡Aÿ0èýàØ+ýãéýÏÁÜÎ;ƒ«¤Ü'CŸ¯•èüW÷14m7ßÿöìm³Üç*3Þæ=¬ß–Õ­Ù:ô¯Ó7æËnòUjÝþæ­K˜7/P æ- „N‚À¼•II:I:I:IIIII&I&I&IIIHŽw= p €äxçFo~@@)@’B’B’B’B’J’J’J’F’F’F’N’N’N’N’A’A’A’I’I’I’E’E’E’’ã}@r¼5¥HŽwG p ¤¤¤¤’¤’¤’¤‘¤‘¤‘¤‘¤“¤“¤“dddd’d’d’d’d‘d‘däxãJï@@(àÉñþ Œ$IG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇ1ê8FǨãu{­ãœ¼irÿöŠ®’zŸÜÛþ8Yó·û Oo¯ìŸ%4o´ö»ý*4ŽçùöêâîâìòâßËÑ8§ï¥ÌÏ©O²ºÙIoíós ¥@ôÑ[! p æçF½J’’’’’T’T’T’4’4’4’t’t’t’t’ ’ ’ ’L’L’L’,’,’,’,½F½J½B§I I I I*I*I*IIIII:I:I:IIII&I&I&I&IIIHŽÞ ¥HŽÞ ¡€S$Go…€Q€$…$…$…$•$•$•$•$$$$$$$ƒ$ƒ$ƒ$ƒ$“$©ã(u¥Ž£Ôq”:ŽQÇ1ê8FǨãØkç¤>õÖ£¤Ý'wêÏ{ëx¿ý©·NÛÍß·Ëù'H<ž5NS¸¹¾P¶›?}º¸|?ÚÚáöÅçûßää#9úÀ¼s¡€S  0ï@À(˜w @’N’A’A’A’A’I’I’I’E’E’’ã|Kœ 9Ö¬!`ɱf ¥I I I I I*I*I*IIII:I:I:I:IIII&I&I&IIIIHŽ5k@r¬YC@)’cÍB§I I I I*I*I*IIIII:I:I:IIII&I&I&I&IIIHŽ5k(@r¬YC@(àɱf £I IRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥ŽcÔqŒ:ŽQÇ1ê8öZÇ9yWâéâ£äãûõüÒ¦¢vôþÅ~»ù¯«‹ÿ»ùáòìîçë›/¼‰1\Ýî¤ÕBÀ(÷¥@ôÑj! p €ähµ0 €ähµP ¤¤¤¤¤’¤’¤’¤‘¤‘¤‘¤“¤“¤“¤“dddd’d’d’d‘d‘d‘därbl0 €ärblP €ärbl 8HRHRHRHRIRIRIÒHÒHÒHÒHÒIÒIÒI2H2H2H2I2I2I2I²H²H²@r91¶(@r91¶œ ¹œÛŒ$)$)$)$©$©$©$©$i$i$i$é$é$é$$$$IG©ã(u¥Ž£Ôq”:ŽRÇ1ê8FǨãu{­ãœtÕ§#±’ùp̶Ÿ´Z‘£V;½p$¶¯Cÿ½ ̛٭W2ýqš÷øëyê»?Ý”çÑÇb—«›œô1(sƒ€PÀ)PŸXÒŒ$i$i$i$é$é$é$é$$$$™$™$™$Y$Y$Y$Y ¹|ŠI0 €äòA&}@)’Ëg™ô¡€S€$…$…$…$•$•$•$$$$$$$$ƒ$ƒ$ƒ$“$“$“$“$‹$‹$ $—9éJ\>餜 ¹|ÚI0 ¤¤¤¤’¤’¤’¤’¤‘¤‘¤‘¤“¤“¤“ddddd’d’d’d‘d‘däò9(}@(àÉå³P^ œ´¬§>v”|ècûØ??Jzú|úì³ób—çÞ¯ã´Ø?nWç‡ÓÈqÎúNV·89ÆqÎz0 $Æ9ë}@)ç¬÷’ ’ ’L’L’L’,’,’,«Á 8@r¹.W0 €är]®>  I!I!I!I!I%I%I%I#I#I#I'I'I'I'É É É É$É$É$É"É"É"ÉÉåº\}À(’Ëu¹ú€R$—ërõ¡€S€$…$…$…$•$•$•$$$$$$$$ƒ$ƒ$ƒ$“$“$“$“$‹$‹$ $—ërõ¥H.×åêB§H.×åêF’’’’T’¤Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽQÇ1ê8FǨãØkçä=…§wŽ’«Á»“Õà]½û°¾ p Æjg0 $’$“$“$‹$‹$‹$ $—ÕÎ>`Éeµ³(@rYíìB§I I I I*I*I*IIIII:I:I:IIII&I&I&I&IIIH.«}@)’Ëjg 8@rYíìF’’’’T’T’T’T’4’4’4’t’t’t’ ’ ’ ’ ’L’L’L’,’,’,\V;û€PÀ)’ËjçK“qß7Ö;ø}cÒ|þ±,SŪpÌ•ã»ë›ß.»ïç‡ÿ=ïÌ_ž.lŽ¥›|uë“¥t¢€Q !0W(sI:I:IIII&I&I&IIIIHŽ*£HŽ*¥HŽ*¡€S€$…$…$…$•$•$•$$$$$$$$ƒ$ƒ$ƒ$“$“$“$“$‹$‹$ $G€R$G€PÀ)’£Š@À(@’B’B’B’J’J’J’J’F’F’F’N’N’N’A’A’A’A’I’I’I’E’E’’£Š@@(àÉQE^ œŒÇ¥ãd=,’øiI[U‘龊üýp{{q}õjkA¾ºñ Giµ§@A`9J« ËQZm@)p’t’t’t’ ’ ’ ’L’L’L’,’,’,’,¼?J« @òþ(­6 Éû£´Ú€PÀ)@’B’B’B’J’J’J’F’F’F’F’N’N’N’A’A’A’I’I’I’I’E’E’’÷Giµ¥HÞ¥Õ„N¼?J« HRHRHRHRIRIRIRIÒHÒHÒHÒIÒIÒI2H2H2H2H2I2I2I²H²H²@òþ(­6 p €äýQZ/N ÈSU9J>T•Ýþ´ª„¬ªŠ¬ªÊ·ï_ü,û0_ÝðäœãŠ}@)WìèB§I*I*I*IIII:I:I:I:IIII&I&I&IIIIH.ǰõ£H.ǰõ¥H.ǰõ¡€S€$…$…$…$•$•$•$$$$$$$$ƒ$ƒ$ƒ$“$“$“$“$‹$‹$ $—cØú€R$—cØú€PÀ)’Ë1l}À(@’B’B’B’J’J’J’J’F’F’F’N’N’N’A’A’A’A’I’I’I’E’E’’Ë1l}@(àI{­ãœt¬§6v”|\8;ic¾_µ1½ocß]¿õøµqù]Ýðôêí<úùX•jçs‡yõó±"ÕÎ æÙÏ ü ü üüüüüüüüüüü ü ü üª÷[VŸÚ¹Á¼÷[–žÚ¹Â¼÷[ÖÚ¹ÀÜa~~~~ ~ ~ ~~~~~~~~~~~ ~ ~ ~ ~~~Õû-‹Kí\aÞû-+Kí\`î0ïý–U¥vn0?????????????¿¿¿¿¿¿¿¿¿¿êý–µ£v.0w˜÷~輄 ó“úq_Tl•|(*•§EE×g÷Ûç¢òâšÑ\—ju£g×a3˜g?ï·s…yôóñvq;˜;Ì«Ÿ ø ø ø)ø)ø)øøøøø9ø9ø9øøøø%ø%ø%ø%øøøUï'»=Ì潟ìw0˜;Ì{?™&˜ÌÁOÀOÀOÀOÁOÁOÁOÁÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/À/Á/Á/Á¯À¯À¯z?Ýí`.0w˜÷~ºŸ`n0ïýtÚÃ\a~~~~~ ~ ~ ~~~~~~~~~~~ ~ ~ ~~~~ÕûôƒþaÐ?ì•þqRžJÖQò¡dé §ÉúŠ~_²¾÷?‡ó»W׃bù­ãÛž,è@@(à(èD£@B`Þ$@@)@’N’N’N’N’A’A’A’I’I’I’E’E’E’’c¡Fk=P €äXî€PÀ)@’B’B’B’J’J’J’F’F’F’F’N’N’N’A’A’A’I’I’I’I’E’E’’c%J‹A 8@R§‰F’’’’T’T’T’T’4’4’4’t’t’t’ ’ ’ ’ ’L’L’L’,’,’,KE 8@r,½8)(O¶ÉÉlüã³*3­¯ˆÇUæíóýÉ9y|‹ß?^üXßi¬lMöúIBP æ.¡€S  0w)HÒHÒHÒHÒIÒIÒIÒI2H2H2H2I2I2I²H²H²H²@rt)@rt)(@rt)œ$)$)$)$©$©$©$i$i$i$i$é$é$é$$$$™$™$™$™$Y$Y$Y 9º” 9º„N] F’’’’T’T’T’T’4’4’4’t’t’t’ ’ ’ ’ ’L’L’L’,’,’,] B§HŽ.õbà¤!Ýw)_%»Tœ{·__²!.Ùpñï>·wlÌW·xö!¬S?¶~œÝxñn¬ý8ÚñØ|wcéÇÞ[µišú±õã^Mz5éÕ¤WÓ^M{5íÕ´W³^Íz5ëÕ¼Wó^Í{µèÕ¢W‹^-zµìÕ²WË^­zµêÕªU“Ý®K?ö~ܪÉ~êÇÖ[µññgíXûq¯&½šôjÒ«I¯¦½šöjÚ«Y¯f½šõjÞ«y¯æ½š÷jÑ«E¯½ZöjÙ«e¯V½ZõjÕ«U«¦»©[?nÕt¿ïÇÚ[5výXú±÷ã^Mz5éÕ¤WÓ^M{5íÕ¬W³^Íz5ëÕ¼Wó^Í{µèÕ¢W‹^-{µìÕ²Wë»öÝ@ûn }7°¾Xß ìånpÒ–l´€q¸ÝQr¿»æîôx»Ýúê Õ,Rí·f¹ºÅÍÙÕíÇë›»—Κÿr–û*~²Ó濞P æ¿¡ 8 óßRdd’d’d’d‘d‘d‘däX‚€Q$Ç ” 9–` p ¤¤¤¤’¤’¤’¤‘¤‘¤‘¤‘¤“¤“¤“dddd’d’d’d’d‘d‘däX‚€R$Ç „NK00 ¤¤¤¤’¤’¤’¤’¤‘¤‘¤‘¤“¤“¤“ddddd’d’d’d‘d‘däX‚€PàÉ“½÷û}]%wô翾ÏwôǪÈê£Bw÷{ú_ÿ¶ZÞ—®šr•>\=/ÓvoëÌËG«ÕVÅW¹“5óvJ€À¼‚€PÀ)@’F’F’F’N’N’N’A’A’A’A’I’I’I’E’E’’cB§HŽõ@r¬J@@)@’B’B’B’B’J’J’J’F’F’F’N’N’N’N’A’A’A’I’I’I’E’E’E’’c-F+P €äX×€€PÀ)@’B’B’B’J’J’J’F’F’F’F’N’N’N’A’A’A’I’I’I’I’E’E’’c5JW$OúÏcU:N>V¥šNNÜÙÇúóvèŪdÛiN§çªôÂ…àæêfºÊ=;êK(à(Ìûb0 $æ}1(B’B’B’B’J’J’J’F’F’F’N’N’N’N’A’A’A’I’I’I’E’E’E’’cÝ Fë^P €äX÷‚€PÀ)@’B’B’B’J’J’J’F’F’F’F’N’N’N’A’A’A’I’I’I’I’E’E’’cÝ Jë^ 8@r¬{AÀ(@’B’B’B’J’J’J’J’F’F’F’N’N’N’A’A’A’A’I’I’I’E’E’’FǨãØk礡ݗ9_%ËœÅ麗¯¯Â07¡¥Ìýåp{~sññîúæÅ…«}ùê¦' W0 $æ ”yC¡€S€$$$$$$$ƒ$ƒ$ƒ$ƒ$“$“$“$‹$‹$ $Ç„N W0 €äX¸‚€R€$…$…$…$…$•$•$•$$$$$$$$ƒ$ƒ$ƒ$“$“$“$‹$‹$‹$ $ÇÂŒ 9®  ɱp¡€S€$…$…$…$•$•$•$$$$$$$$ƒ$ƒ$ƒ$“$“$“$“$‹$‹$ $Ç”¯Hž˜§…«£äc×™_4']ÇÖWI˜o½to.?Ýþú·ë÷/]:{ÚÊ^W·í\`î0¯~>Nòiçóìç~~~~~~~ ~ ~ ~~~Õû-'õ´s¹Ã¼÷[NèiçóÞo9›§+ÌÁOÀOÀOÀOÀOÁOÁOÁÏÀÏÀÏÀÏÁÏÁÏÁÏÁ/À/À/À/Á/Á/Á¯À¯À¯À¯z¿å”vn0ïý–óuڹ¼÷[NÖiçs‡9ø ø ø ø)ø)ø)øøøøø9ø9ø9øøøø%ø%ø%ø%øøøUï·œ‘ÓÎæ/ûìà?^¢ì8¹ß¿ú9:ûéÙ• ìáâÏ¿_ÿp}yq¾>OE·óŽòêF¿¿¸ì1.S}œ:½žqH<\„¾ (¡oB§@AÀHÒHÒHÒIÒIÒI2H2H2H2H2I2I2I²H²H²@Rv; œ )û‰F”iO¥I I I I I*I*I*IIII:I:I:I:IIII&I&I&IIIIHên¢€Q$u¿§€R$uÚQ@(à I!I!I!I%I%I%I#I#I#I#I'I'I'É É É É$É$É$É$É"É"ÉIÛí) xEò…O¹yXö8J>UNVÙ?»ò€ßWïÎÎÿñú²ÇÃáfû€A^ <žòz@(à(<žòzÀ(x<äõI:IIIII&I&I&IIIH>òz@(àɧA^@òéD×J’’’’’T’T’T’4’4’4’t’t’t’t’ ’ ’ ’L’L’L’,’,’,’,|:äõ€Q$ŸNy= ɧA^œ$)$)$)$©$©$©$i$i$i$i$é$é$é$$$$™$™$™$™$Y$Y$Y ùt"Èë¥À+’¯Ÿr”|ìþÂáS»g'½Ç}øñðñìâæOן®ÞŸÝ¼°,2öó}uëÓÝüv^ý|ìä·sƒyöó±‡ßÎæÑÏÇî};¿¿¿¿¿¿¿¿êý–úv.0w˜÷~Ë};7˜÷~ËÞ|;W˜ƒŸ€Ÿ€Ÿ€Ÿ€Ÿ‚Ÿ‚Ÿ‚ŸŸŸŸƒŸƒŸƒŸƒ_€_€_€_‚_‚_‚____õ~Ë.{;7˜÷~Ëþz;W˜÷~ËÎz;˜;ÌÁOÀOÀOÀOÁOÁOÁÏÀÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/Á/Á/Á/Á¯À¯À¯z¿e¼+Ì_ö;ÙÇ~:‚é(ù´;ž'»ãõì´ì‡O¯ÿjySÿïwgwŸn_<›aWÇ7=9z¨G;Ö]?–~ìý¸Úñ\Ú±õãlÇÞ«y¯æ½ZôjÑ«E¯½ZöjÙ«e¯V½ZõjÕªþv,ýØûq«6vøÛ±õãVmìí·cíǽšôjÒ«I¯&½šöjÚ«i¯f½šõjÖ«y¯æ½š÷jÞ«E¯½ZôjÙ«e¯–½ZõjÕ«U¯V­ÚØ¥oÇÖ[µ±?ߎµ·jcg¾K?ö~Ü«I¯&½šôjÚ«i¯¦½šõjÖ«Y¯f½š÷jÞ«y¯½ZôjÑ«e¯–½ZöjÙ«U¯V½Zµjc½k?~Qídüqwý(¸ŸNMXŸ¦\¾Éã3§ífõ™ûqÞ÷tœùê‡o7ß^]Ü]œ]^üûìîâújsvõ~óýÇÃÍòO/¼Éî[݋ӳ€›ñ8 ¸[?Îv<ÎîÆÚ£Ó»±ôã^-zµìÕ²WË^­zµêÕªU[NúíÆÒ½·jË ¿ÝØúq«¶œíÛµ÷jÒ«I¯&½šôjÚ«i¯¦½šõjÖ«Y¯æ½š÷jÞ«y¯½ZôjÑ«e¯–½ZöjÕ«U¯V½ZµjË)½ÝØúq«¶œÏÛµ·jËɼÝXú±÷ã^Mz5éÕ¤WÓ^M{5íÕ¬W³^Íz5ëÕ¼Wó^Í{µèÕ¢W‹^-{µìÕ²WË^­zµêÕªU[ÎØíÆÚ_T;Ù'¾ß{^íôÞï=ýö)³Û|9oÌ6çÞÌQ_¾~ü27—olº?þôçàêŸeþÇûÛ¯~}óóýîóŸÞí2Ùv/±'†=ÜŸ“»s|ob|Fm¾ž¶{=ú‰/ü‹%½þ®÷÷êéëq¿þóÍ?ߌŸ÷aþßÔÇ[óæ[ü‹Ýr«ûüñ¿;¹ÁÑ7ûõÍo®æŸóÿWïY¤endstream endobj 7 0 obj 10242 endobj 85 0 obj <> stream xÚÝO—Çu`ñ=?vc/ÓU/Þ{KëïøKòˆœñÆlI´I@4mi>ýTfu7ªYÕ÷úøØ‡äÍjÐ? â˨̈»·Ç9ß|óŸ_ݽùæýWw_þì×§ÿýÓW?ûæ«ÿñ«Ã›Ã©þñ«Ã›»Óÿœþìx÷¦ëð6ëÍ7?|õwãíñíáí›ß~üôÃÏ?Ý¿{¸ÿÇŸÞ}xÿ¯÷¯ÿ÷ßüÛö£ÿóùÃÇè·cÖåx»]ôÜÇô^Ò÷¹Ÿø¸éÍý4¯s¿¿¿)~Sü¦ø-ñ[â·Øo›×¹‡ô’Î~Û¼Î=¥³ß6¯sÒÅ/Ä/Ä/Ä/Äoˆß¿!~)~)~)~%~%~%~%~-~-~-~Sü¦øMñ[â·Äo‰ßb¿m^çžÒÙo›×¹éì·ÍëÜCzI¿¿¿¿!~Cü†ø¥ø¥ø¥ø¥ø•ø•ø•øµøµøµøMñ›â7ÅoŠß¿%~‹ý¶yû~Ûïj ž×¿\ø4¯ÏΫy=úr^ó¼þõÃÇ¿ÈêûÝÛuùá—³ÖéßõT ë¢zú·<ÕÄ:©žþýNu`mª…V…V…V…VVVV­&ZM´ZhµÐj¡Õ"«¸;bM¬d‡Ö•¬âx‡5°V´ ´ ´ ´h5Ðj U¢U¢U¢U¢U¡U¡U¡U£U£U£ÕD«‰V­&Z-´ZhµÈjܰ¬d5wXka%«q.Uß?üüÝû?ßÿâ»O÷ï>~úÛíÁú4½Þqù3®ÆWì§ù•ûÞÜO#,÷^Ò÷ÓË]ü¦ø-ñ[â·Øof¹‡ô’Î~Û@Ë=¥³ß6ÓrÒÅ/Ä/Ä/Ä/Äoˆß¿!~)~)~)~%~%~%~%~-~-~-~Sü¦øMñ[â·Äo‰ßb¿mÜåžÒÙo›x¹éì· ½ÜCzI¿¿¿¿!~Cü†ø¥ø¥ø¥ø¥ø•ø•ø•øµøµøµøMñ›â7ÅoŠß¿%~‹ý¶y˜û~ÛïjÐ=ÄuyáÓH|8^¯4ß½x{²Î#ñ¯ï~{ÿòaëñöôß`——ÿõá—ÿñbÀ:ýz‡ñâ’û¯<û1ÞÖ‹+òGcwœƒsq^˜óÈ99O̧[̬V¬Ö¬Ö¬Ö¬Ö¬6Ym²ÚdµÅj‹Õªmw˜ƒsqFµíŽsrFµívóàÌjÁjÁjÁjÁjƒÕ« VKVKVKV+V+V+V+VkVkVkV›¬6Ym²ÚbµÅj‹Õªm3?æäŒjÛÀypFµmÚÇœ‹3«««« V¬6X-Y-Y-Y-Y­X­X­X­Y­Y­Ym²ÚdµÉj“Õ«-V[¨¶ô˜ç›jWSúó÷— ãñ=ËÃÕwÍoOöó<ÿ‹ûÏï?}÷—‡Ÿ^ɳÆåç¯frì§¡œ{H/é‹ûi0çžÒ'÷ýÝUêâWâ×â×â×â×â7ÅoŠß¿%~Küûmƒ:÷^ÒÙoÖ¹§töÛæuîCºø…ø…ø…ø…ø ñâ7Ä/Å/Å/ůįįįįůůÅoŠß¿)~Kü–ø-ñ[ì·òÜS:ûmÓ<÷!ý¶ž{H/éââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦øMñ[â·Äo±_Þ¤é·ý®†ø§åû‹ õxc0×å•ëtQ_¼{oß|}ÿùów?¼Ùw?Üþà݇oßüü㇇O¿ó«?¼ßþâçëáç¸üq×Ã#õmxÄžÒ'÷mxÄ>¤7ö}xÄÒK:ûíÃ#ö”Î~ûðˆ}H¿¿¿¿¿!~Cü†ø¥ø¥ø¥ø•ø•ø•ø•øµøµøµøMñ›â7Åo‰ß¿%~‹ýöá{Jg¿}xÄ>¤³ß>¤‹_ˆ_ˆ_ˆ_ˆß¿!~CüRüRüRüJüJüJüJüZüZüZü¦øMñ›â·Äo‰ß¿Å~çµbê)ýÎkÅÔ‡tö;¯Sé%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-ö;¯SÒoû] ñOõ]\ø4îǼ÷3.Ç}ÜXûØóòú¿áíÀØ~¹º¼þjœç^Ò÷mßmì)}rßöÝÆ>¤7÷¿¿¿¿)~Sü¦ø-ñ[â·Øoßw{H/éì·ï»=¥³ß¾ï6ö!]üBüBüBüBü†ø ñâ—â—â—âWâWâWâWâ×â×â×â7ÅoŠß¿%~Kü–ø-öÛ÷ÝÆžÒÙoßwûÎ~û¾ÛØCzI¿¿¿¿!~Cü†ø¥ø¥ø¥ø¥ø•ø•ø•øµøµøµøMñ›â7ÅoŠß¿%~‹ýö}·±é·ý®†ôçqþË…‡ù8øëq~.ÇùxÞÌä¾ÿô‹wïnëÇӽ˱.?ý“µûƒô!½¹okÿØCzI_Ü·µì)]üJüJüJüZüZüZüZü¦øMñ›â·Äo‰ßb¿}í{H/éì·¯ýcOéì·¯ýcÒÅ/Ä/Ä/Ä/Äoˆß¿!~)~)~)~%~%~%~%~-~-~-~Sü¦øMñ[â·Äo‰ßb¿}í{Jg¿}íûÎ~ûÚ?ö^ÒÅ/Ä/Ä/Äoˆß¿!~)~)~)~)~%~%~%~-~-~-~Sü¦øMñ›â·Äo‰ßb¿}íû~ÛïêàùfáË…O7 µ®¶y©ãº¼Yϯ…òÍÂéfàn^~øê^sc>Ý `ÎÅya>Ý`NÎs±Z±Z±Z³Z³Z³Z³ÚdµÉj“Õ«-V[¨¶oîH98gTÛ7v¤œœQmßÕ‘òàÌjÁjÁjÁjÁjƒÕ« VKVKVKV+V+V+V+VkVkVkV›¬6Ym²ÚbµÅj‹Õªí[7RNΨ¶ïÛHypFµ}ÓFÊÁ¹8³Z°Z°Z°Ú`µÁjƒÕ’Õ’Õ’Õ’ÕŠÕŠÕŠÕšÕšÕšÕ&«MV›¬6Ym±Úbµ…jûÎŒ”ç›jWSøÓ6.žçõcúáÅûœù<¦ÿÓÇ÷ï¾ÿíÇoïÿñÛWžÁ9óÇá×òã8üjNÎóã8üjœóã8üjά֬6Ym²ÚdµÅj‹Õª=ÇÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ãð¡q>4ŽÃ‡ÆqøÐ8ÇáCã8|h‡ý_‡¿\xXGü\Ÿ1_w/ÞT­çg]¾ùë?üôÊ&ã‡õöxùÉ—Òñˆ5±NªqÀ:°6ÕílO¨µ°¢U¢U¢U¢U¡U¡U¡U£U£U£U£ÕD«‰V­Z-´ZdµŸã 5°V²ÚÏð„šXÉj?ÀêÀŠVVVVV­Z ´J´J´J´*´*´*´*´j´j´j´šh5Ñj¢ÕB«…V ­Yí§tBM¬dµÑ u`%«ý|N¨µ°¢U U U Õ@«V­­­­­ ­ ­ ­­­­&ZM´šh5Ñj¡ÕB«EVû!œPÖ[VWãùó ÿå§AþôOù§ƒ|®ï öÅ ÿ»ß¿ròæiTÃåG¯fuÌóiZÇ<87æíÍXÊÁ¹8/ÌÉjÉjÉjÅjÅjÅjÍjÍjÍjÍj“Õ&«MV[¬¶Xm¡Úþ,åà\œQm–rrFµýõWʃ3««««« V¬6X-Y-Y-Y­X­X­X­X­Y­Y­Ym²ÚdµÉj‹Õ«-V[¨¶¿ãJ99£Úþ‚+åÁÕö·[)çâÌjÁjÁjÁjƒÕ« VKVKVKVKV+V+V+VkVkVkV›¬6Ym²ÚdµÅj‹Õªí¯°Rœoª] øO·ïž^¿:©(ç‹÷Wçó­Àï÷5ýßßÿøùþ•g]N?>Æå¸~Eûâ¾½"Š=¥OîÛ+¢Ø‡ôæ¾½"Š]üZüZü¦øMñ›â·Äo‰ßb¿ýQì!½¤³ßþŠ(ö”Î~û+¢Ø‡tñ ñ ñ ñ ñâ7Äoˆ_Š_Š_Š_‰_‰_‰_‰_‹_‹_‹ß¿)~Sü–ø-ñ[â·ØoE{Jg¿ýQìC:ûí¯ˆbé%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-öÛ_Å>¤ßö»š²ŸŽº¸ði?ý»šÇëÅ+¢ëyÿÍß?|÷þÝç‡üðpÿé/GéÃþ£.>ûîý+Sû¶&<Æå¥×‹ÂÔ·Uaì!½¤/îÛÊ0ö”>¹o‹ÃØÅo±ß¾>Œ=¤—töÛ׈±§töÛ—‰±éâââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦ø-ñ[â·Äo±ß¾‚Œ=¥³ß¾ˆŒ}Hg¿}{H/éââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦øMñ[â·Äo±ß¾ÄŒ}H¿íw5«>Oµ_.<¯\W»$f¾x£òp÷<Ö~ýõo^yn¼Î??_y·n{®œúöd9ö”>¹oÏ—cÒ›ûö”9ö.~CüRüRüRüJüJüJüZüZüZüZü¦øMñ›â·Äo‰ßb¿ýitì!½¤³ßþT:ö”Î~û³é؇tñ ñ ñ ñ ñâ7Äoˆ_Š_Š_Š_‰_‰_‰_‰_‹_‹_‹ß¿)~Sü–ø-ñ[â·Øo¢{Jg¿ý¹vìC:ûíO·cé%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-öÛŸ‰Ç>¤ßö»ºýxÚ¡ñâ§•»¼¾Q/c=|y4þ›zåF%Þö¡.?ù“•’¾¸Ÿnd¸§ôÉýt#Ã}Hoî§îâ7Äoˆ_Š_Š_Š_‰_‰_‰_‹_‹_‹_‹ß¿)~Sü–ø-ñ[ì·ÝÈpé%ý¶î)ý¶îCºø…ø…ø…ø…ø ñâ7Ä/Å/Å/ůįįįįůůÅoŠß¿)~Kü–ø-ñ[ì·ÝÈpOéì·ÝÈpÒÙo»‘áÒKºø…ø…ø…ø ñâ7Ä/Å/Å/Å/ůįįįůůÅoŠß¿)~Sü–ø-ñ[ì·ÝÈpÒoû]Ýž<ßÈ|¹ðéFfÝxŽ(^¼â{8~¹‘yyÊìñíêãåå¿ûú•ûœ|;·o†â•#Os öÓœÂ}Hoî§9…{H/é‹ûiNá.~CüRüRüRüJüJüJüJüZüZüZü¦øMñ›â·Äo‰ß¿Å~qw”žÒÙ/éC:ûÅñNzH/éââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦øMñ[â·Äo±ß¸;HÒÙoô’Î~ãx”žÒÅ/Ä/Ä/Äoˆß¿!~CüRüRüRüJüJüJüZüZüZüZü¦øMñ›â·Äo‰ßb¿¼»“Òoû]ÝM¯q8\^¹jŸ¹Ÿ‡×mrýÝïóæëûßÞzó«?¼ß&×Ï7À:Ý ]~úêù~î)}r?ÝérÒ›û¸“ÒKºø¥ø¥ø¥ø•ø•ø•øµøµøµøµøMñ›â7Åo‰ß¿Å~Û]÷^ÒÙo»“àžÒÙo»™à>¤‹_ˆ_ˆ_ˆ_ˆß¿!~CüRüRüRüJüJüJüJüZüZüZü¦øMñ›â·Äo‰ß¿Å~Û}÷”Î~Û­÷!ý¶» î!½¤‹_ˆ_ˆ_ˆß¿!~CüRüRüRüRüJüJüJüZüZüZü¦øMñ›â7Åo‰ß¿Å~Û÷!ý¶ßÕÆÓ½ÈÅ…ÇñxØ×õ¾ýÛ7#Oï)?¼ûôp¾%yå¯|{ø/?}½ëõm×#ìCzsßv=ÂÒKúâ¾íz„]üRüJüJüJüZüZüZüZü¦øMñ›â·Äo‰ßb¿}×#ì!½¤³ß¾ëö”Î~û®G؇tñ ñ ñ ñ ñâ7Äoˆ_Š_Š_Š_‰_‰_‰_‰_‹_‹_‹ß¿)~Sü–ø-ñ[â·Øoßõ{Jg¿}×#ìC:ûí»aé%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-öÛw=Â>¤ßö»ºExzÈþâ§›‰ålOS]ÜL<½+üðñ/r/q——Ÿ½º• ΃scwœƒsq^˜óșՒՊՊՊ՚՚՚՚Õ&«MV›¬¶Xm±ÚBµÇ§˜^ÏÁ¹8£ÚãSL¯çäŒjO1½žgV V V V V¬6Xm°Z²Z²Z²Z±Z±Z±Z±Z³Z³Z³ÚdµÉj“Õ«-V[¬¶Píñ)¦×srFµÇ§˜^σ3ª=>ÅôzÎřՂՂՂÕ« V¬–¬–¬–¬–¬V¬V¬V¬Ö¬Ö¬Ö¬6Ym²ÚdµÉj‹Õ«-T{|Šéõ<8ßT{õ)¦‹ ù¸‡Ðñú›ƒ:\û_^¨ý毿÷ðʱaÛ&¥9.?{½I)ö”>¹o›”bÒ›û¶I)ö^ÒÅ/Å/Å/ůįįįůůůÅoŠß¿)~Kü–ø-öÛ7)ÅÒK:ûí›”bOéì·oRŠ}H¿¿¿¿¿!~Cü†ø¥ø¥ø¥ø•ø•ø•ø•øµøµøµøMñ›â7Åo‰ß¿%~‹ýöMJ±§töÛ7)Å>¤³ß¾I)ö^ÒÅ/Ä/Ä/Äoˆß¿!~)~)~)~)~%~%~%~-~-~-~Sü¦øMñ›â·Äo‰ßb¿}“RìCúm¿«Œçï¾\x¬ÇsêjsŸí-ö‹[‘Ç·Í·"§[Ó¸sùÙ«[ î“ûéVƒûÞÜO·ÜCzI_ÜSüRüRüJüJüJüZüZüZüZü¦øMñ›â·Äo‰ßb¿ýjì!½¤³ß~5ö”Î~û ÔØ‡tñ ñ ñ ñ ñâ7Äoˆ_Š_Š_Š_‰_‰_‰_‰_‹_‹_‹ß¿)~Sü–ø-ñ[â·Øo?{Jg¿ýjìC:ûí'Pcé%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-öÛO Æ>¤ßö»ºxÚyèâÂç[¾~Ä)^¼¼ßz|ýñý¿¿<Éàø6W^~äþág?þñ§wY/®ùãkÏImõå…×ãôëu¦¡¬Mu£¡Öº¨nã3T´šhµÐj¡Õ"«}d†X +Yí£2ÔÄJVû u`E«@«@«@«@«V­Z%Z%Z%ZZZZZ5Z5Z5ZM´šh5Ñj¡ÕB«…V‹¬öqjb%«}Ð…:°’Õ>âB ¬…­­­­Z ´h•h•h•h•hUhUhUhÕhÕhÕh5Ñj¢ÕD«‰V ­Z-²Ú‡U¨ë-««áóùáœ/>©³¯WÄ/^ë­/ûc~ÿñå¹]ùöîôñ‹ëÿóç?<|úøýí!t;jÛÃ蘯ŸN…}rßN§Â>¤7÷ít*ì!½¤/î-~-~-~Sü¦øMñ[â·Äo‰ßb¿ýt*ì)ýöÓ©°éì·ŸN…=¤—tñ ñ ñ ñâ7Äoˆ_Š_Š_Š_Š_‰_‰_‰_‹_‹_‹ß¿)~Sü¦ø-ñ[â·Øo? ûÎ~ûéTØCzIg¿ýt*ì)]üBüBüBü†ø ñâ7Ä/Å/Å/ůįįįůůůÅoŠß¿)~Kü–ø-öÛO§ÂÒoû] áÏ«Ê_.<öÓúóõ³ô‡/Îöó¸~šÅÿtÿyÛ§òm‰ö0.Ìõ"-ö^Ò÷m±{JŸÜ·%[ìC:ûí ·ØCzIg¿}{Jg¿}û.~!~!~!~!~Cü†ø ñKñKñKñ+ñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~Küûí‹¿ØS:ûíKÀ؇töÛ‚±‡ô’.~!~!~!~Cü†ø ñKñKñKñKñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~KüûíËÇØ‡ôÛ~W³æócÕ_.|šJg\?ëp÷â Ïù“7<öñÇß~~åY…ÃÛ5.Àõ©¤”óv&)åà\œæíâË…Çy¾²W£íö_‡£íºmþîýŸy¶ouù®µÅ<87æÓ1çâ¼0Ÿþˆ99³ÚbµÅj Õ¶å[ÌÁ¹8£Ú¶t‹99£Ú¶n‹ypfµ`µ`µ`µ`µÁjƒÕ«%«%«%«««««5«5«5«MV›¬6Ym±ÚbµÅj Õ¶ÅYÌÉÕ¶•Ỹ3ªm˲˜ƒsqfµ`µ`µ`µÁjƒÕ«%«%«%«%««««5«5«5«MV›¬6Ym²ÚbµÅj Õ¶µW̃óMµ«™ói:½¸ð¸wÜžWOïn —‡òÜ=§ÿðãÃÇþéKf‡»yù‘wŸ¾{øÛ+Oïžþ!κ¼øjÏî%}q?ÝùqOé“û6{cÒ›{‹_‹_‹_‹ß¿)~Sü–ø-ñ[ì·âØCzIg¿}ÇžÒÙoŸÇ±éâââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦ø-ñ[â·Äo±ß>ªcOéì·OëØ‡töÛvì!½¤‹_ˆ_ˆ_ˆß¿!~CüRüRüRüRüJüJüJüZüZüZü¦øMñ›â7Åo‰ß¿Å~û,}H¿íw5¤?=Ý{qáó8ý2Þöãå8xÞŸîן~ùùá»^Ý¥n›¨W]þˆë‰{JŸÜ·‰ûÞÜ·‰{H/éâ7ÅoŠß¿%~Küûí5ö^ÒÙoŸ¨±§töÛ'jìCºø…ø…ø…ø…ø ñâ7Ä/Å/Å/ůįįįįůůÅoŠß¿)~Kü–ø-ñ[ì·OÔØS:ûí5ö!ýö‰{H/éââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦øMñ[â·Äo±ß>QcÒoû]ÍÉÏõ— ãî|å!®Þ—Ûž ¼œ¨Ï äÿ…‰ºÞÖ—?âj ûiâæžÒ'÷ÓÄÍ}Ho›{H¿¿)~Sü¦ø-ñ[â·Øo›¸¹‡ô’Î~ÛÄÍ=¥³ß6qsÒÅ/Ä/Ä/Ä/Äoˆß¿!~)~)~)~%~%~%~%~-~-~-~Sü¦øMñ[â·Äo‰ßb¿mâæžÒÙo›¸¹éì·MÜÜCzI¿¿¿¿!~Cü†ø¥ø¥ø¥ø¥ø•ø•ø•øµøµøµøMñ›â7ÅoŠß¿%~‹ý¶‰›û~ÛïjŽ~zð⧉»n<’2^¼ xˆ÷oÞýõö°½Î¾-¨×Ï[äÞÜ·Ú±‡ô’¾¸o‡´cOé“{‰_‰_‰_‹_‹_‹_‹ß¿)~Sü–ø-ñ[ì·ÚŽ=¤—töÛnÇžÒÙo?»û.~!~!~!~!~Cü†ø ñKñKñKñ+ñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~KüûíǺcOéì·ŸìŽ}Hg¿ýpwì!½¤‹_ˆ_ˆ_ˆß¿!~CüRüRüRüRüJüJüJüZüZüZü¦øMñ›â7Åo‰ß¿Å~û¹ï؇ôÛ~W#þóòû— ãð´…ÈõÛ“ÇoOÆ‹›þôñß}øÓo>~{»Õ]þ›ÕAÎÅyaÞ7ªƒœœ'æ}—:ȃ3ª·¨ƒœ‹3ª·§ƒœœQí¼7äÁ™Õ‚Õ‚Õ‚Õ‚Õ« V¬–¬–¬–¬V¬V¬V¬V¬Ö¬Ö¬Ö¬6Ym²ÚdµÅj‹Õ«-T;o@99£Úy÷9ȃ3ª·žƒœ‹3«««« V¬6X-Y-Y-Y-Y­X­X­X­Y­Y­Ym²ÚdµÉj“Õ«-V[¨vÞ_òà|Síj2|~ÇñË…O3äÊëåÃËwóÖ ùî?ýÇOWLGÏË¿{eSäí(íÝÌC¿~”õí( ìCzsߎÒÀÒKú¾¥=¥³ß~”ö!ýö£4°‡ô’.~!~!~!~Cü†ø ñKñKñKñKñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~KüûíGi`ÒÙo?J{H/éì·¥=¥‹_ˆ_ˆ_ˆß¿!~Cü†ø¥ø¥ø¥ø•ø•ø•øµøµøµøµøMñ›â7Åo‰ß¿Å~ûQØCúm¿«iñymòË…q<_y7¯ ¾{ù²Ý—£ï~öî'ç3ïOb/?ññåá̧ ¥/.øã¯^\p1¶–/.x÷þáãkç7ßÖ—_?8Œ}r߯>¤7÷íÁaì!½¤/îSü¦øMñ[â·Äo±ßþà0ö^ÒÙop{Jg¿ýÁaìCºø…ø…ø…ø…ø ñâ7Ä/Å/Å/ůįįįįůůÅoŠß¿)~Kü–ø-ñ[ì·?8Œ=¥³ßþà0ö!ýö‡±‡ô’.~!~!~!~Cü†ø ñKñKñKñKñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~KüûícÒoû]MÙϹði_‡«y|[ƼœÇûb÷ãùú»ÿ÷ÊS§Ï—ŸÿÉ£¹Gé)}rßN¢Æ>¤7÷í$jì!½¤‹_‹_‹_‹ß¿)~Sü–ø-ñ[â·Øo_>ÇžÒÙo_>Ç>¤³ß¾|Ž=¤—tñ ñ ñ ñâ7Äoˆ_Š_Š_Š_Š_‰_‰_‰_‹_‹_‹ß¿)~Sü¦ø-ñ[â·Øo_>Ç>¤³ß¾|Ž=¤—töۗϱ§tñ ñ ñ ñâ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦ø-ñ[â·Øo_>ÇÒoû] áOãúÅ…O›T_=–±m—ãú‹Cÿ>þá§Ëã§)æò#?~~x¹@~úMóÅ%°@¾í5wºêââë½æ°7÷m¯9ì!½¤/îÛ^sØSúä¾Äo‰ßb¿}¯9ì!½¤³ß¾×ö”Î~û^s؇tñ ñ ñ ñ ñâ7Äoˆ_Š_Š_Š_‰_‰_‰_‰_‹_‹_‹ß¿)~Sü–ø-ñ[â·Øoßk{Jg¿}¯9ìC:ûí{Íaé%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-öÛ÷šÃ>¤ßö»šsŸ(¹¸ði"¾±{ó¶z9?žø«ï¾¿ÿå‡ÿûãý¯­_ŸwÆ»øøÕÖØÇô^Ò÷Ç¥_ï)}rÜYúõ.~%~-~-~-~-~Sü¦øMñ[â·Äo±ßÓÎÒ¯÷^ÒÙïigé×{Jg¿§¥_ïCºø…ø…ø…ø…ø ñâ7Ä/Å/Å/ůįįįįůůÅoŠß¿)~Kü–ø-ñ[ì÷´³ôë=¥³ßÓÎÒ¯÷!ýžv–~½‡ô’.~!~!~!~Cü†ø ñKñKñKñKñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~Küû=í,ýzÒoû½º³ôÅ…1_`ìëÇUòÅk‰ÇÇ£ñîáOûý6îÆåǯ¦yî!½¤/î§iž{JŸÜOÓ<÷!]üZüZüZüZü¦øMñ›â·Äo‰ßb¿}{ì!½¤³ß¾Eö”Î~û.!؇tñ ñ ñ ñ ñâ7Äoˆ_Š_Š_Š_‰_‰_‰_‰_‹_‹_‹ß¿)~Sü–ø-ñ[â·Øoß@{Jg¿}ìC:ûíÛˆ`é%]üBüBüBü†ø ñâ—â—â—â—âWâWâWâ×â×â×â7ÅoŠß¿)~Kü–ø-öÛwÁ>¤ßö»šÑŸŸfùraäùÊycí~¼xôøxòâïï÷Iþwø·û÷¯œ“oçvw1òõ§Ç©oOcÒ›ûöô8ö^Ò÷íéqìâ×â7ÅoŠß¿%~Kü–ø-öÛŸÇžÒÙozûÎ~ûÓãØCzI¿¿¿¿!~Cü†ø¥ø¥ø¥ø¥ø•ø•ø•øµøµøµøMñ›â7ÅoŠß¿%~‹ýö§Ç±éì·?=Ž=¤—töÛŸÇžÒÅ/Ä/Ä/Äoˆß¿!~CüRüRüRüJüJüJüZüZüZüZü¦øMñ›â·Äo‰ßb¿ýéqì!ý¶ßÕý¼zþå§y»¯7†>Æ‹—=Oç2>|º÷ÃïþrÿáÕGeî—¾>òv åà\œæíüÊÉybÞ¡ÌjÅjÍjÍjÍjÍj“Õ&«MV[¬¶Xm¡Ú~Þ åà\œQm?ë…rrFµý ʃ3««««« V¬6X-Y-Y-Y­X­X­X­X­Y­Y­Ym²ÚdµÉj‹Õ«-V[¨¶ŸæB99£Ú~” åÁÕös\(çâÌjÁjÁjÁjƒÕ« VKVKVKVKV+V+V+VkVkVkV›¬6Ym²ÚdµÅj‹Õªí‡µPœoª]ÙO»l_\u¾2Öõã,ǯsãr ÿù÷?¿þðú鿇/?~5’cßwÁÒKúâ¾=î‚=¥OîÛã.ØÅ¯Ä¯Å¯Å¯Å¯ÅoŠß¿)~Kü–ø-öÛwÁÒK:ûí»`Oéì·?î‚}H¿¿¿¿¿!~Cü†ø¥ø¥ø¥ø•ø•ø•ø•øµøµøµøMñ›â7Åo‰ß¿%~‹ýöÇ]°§töÛwÁ>¤³ßþ¸ ö^ÒÅ/Ä/Ä/Äoˆß¿!~)~)~)~)~%~%~%~-~-~-~Sü¦øMñ›â·Äo‰ßb¿ýqìCúm¿«þùq—/F?]y½ü~÷âUÕ㸜öÿåÓw4í_~úưÿzÞg}ÈÁ¹8/Ìûœ99OÌû™ÕŠÕšÕšÕšÕšÕ&«MV›¬¶Xm±ÚBµó\98gT;Ïô“3ªzȃ3««««« V¬6X-Y-Y-Y­X­X­X­X­Y­Y­Ym²ÚdµÉj‹Õ«-V[¨vžÚ!'gT;ìgT;Ïëƒsqfµ`µ`µ`µÁjƒÕ«%«%«%«%««««5«5«5«MV›¬6Ym²ÚbµÅj ÕÎC9äÁù¦ÚÕœý¼þþ姉<ûj"?¬—¯“æåDþ«ïüüçW'òã凯r¨§yœj`-¬‹êi§šX'ÕÓ N­ ­­­­­&ZM´šhµÐj¡Õ"«mö¦X +Yms7ÕÄJVÛÐMu`E«@«@«@«@«V­Z%Z%Z%ZZZZZ5Z5Z5ZM´šh5Ñj¡ÕB«…V‹¬¶Éšjb%«m¬¦:°’Õ6SS ¬…­­­­Z ´h•h•h•h•hUhUhUhÕhÕhÕh5Ñj¢ÕD«‰V ­Z-²Úgªë-««Yøij¾¸0æãæŒãêµÍÃ|ùÚf]NÍ_ß?üÃaxÞv<ÖåO¹Þ{H/é‹û¶3 ö”>¹o;bÒÙoß{H/éì·ï ˆ=¥³ß¾3 ö!]üBüBüBüBü†ø ñâ—â—â—âWâWâWâWâ×â×â×â7ÅoŠß¿%~Kü–ø-öÛwÄžÒÙoßûÎ~û΀ØCzI¿¿¿¿!~Cü†ø¥ø¥ø¥ø¥ø•ø•ø•øµøµøµøMñ›â7ÅoŠß¿%~‹ýö±é·ý®Fͧw/.Œõx†Î¼^Êí—ï6öO†Ò>Í£¿üðîß¿òÅéß½.ÊÕ†˜'æÓ¿20Îùôï ÌÁ¹8/ÊÛ>˜“3ªm›d`œQmÛ!sp.ά¬¬¬6Xm°Ú`µdµdµdµdµbµbµbµfµfµfµÉj“Õ&«MV[¬¶Xm¡Ú¶ æÁÕ¶=00çâŒjÛþ˜“3«««« V¬6Xm°Z²Z²Z²Z±Z±Z±Z³Z³Z³Z³ÚdµÉj“Õ«-V[¨¶ír98ßT»îž×&¿\ø4f]½Qw¨—oÔÍË1ð¾ûü^L7Û6Xóxù¡wïß}xÿÓïÜO#õå5{õ|Äãa\^xýE8öæ¾}Ž=¤—ôÅ}ûR{JŸÜ—ø-ñ[ì·AŽ=¤—töÛ¿(ÇžÒÙoÿºû.~!~!~!~!~Cü†ø ñKñKñKñ+ñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~Küûí_²cOéì·ÕŽ}Hg¿ý wì!½¤‹_ˆ_ˆ_ˆß¿!~CüRüRüRüRüJüJüJüZüZüZü¦øMñ›â7Åo‰ß¿Å~û×ô؇ôÛ~WcîÓKg—£îÝãnÌuýeýxùÒÙºˆóîÓ¿ÿòã·çÙýL’ºü7Î$¡>¹ïg’PÒ›û~& õ^Ò÷)~Sü¦ø-ñ[â·Øï|& õ^ÒÙï|& õ”Î~ç3I¨éâââââ7Äoˆß¿¿¿¿¿¿¿¿¿¿¿)~Sü¦ø-ñ[â·Äo±ßùLê)ýÎg’PÒÙï|& õ^ÒÅ/Ä/Ä/Äoˆß¿!~)~)~)~)~%~%~%~-~-~-~Sü¦øMñ›â·Äo‰ßb¿ó™$Ô‡ôÛ~WSðós“ðÓ¼<®ãÅ+añxÂà×÷ÿrù«öó——¿{¸ÿôÃi ~åÄ’Ó?Í—×_ïÀ½¤/îÛ4=¥OîÛ4}Hoî-~-~-~-~Sü¦øMñ[â·Äo±ß>Ícé%ýöi{Jg¿}šÇ>¤‹_ˆ_ˆ_ˆ_ˆß¿!~CüRüRüRüJüJüJüJüZüZüZü¦øMñ›â·Äo‰ß¿Å~û4=¥³ß>ÍcÒÙoŸæ±‡ô’.~!~!~!~Cü†ø ñKñKñKñKñ+ñ+ñ+ñkñkñkñ›â7ÅoŠß¿%~KüûíÓ<ö!ý¶ßÕŒþ¼ú}1§?Oó×O_¼ª' þü݇÷÷ß¿臻·‡™—Ÿà~˜//¿1/¿ž÷qòàܘ÷Yrp.Î ó>'CfµÉj‹Õ«-T;OȃsqFµót 99£Úy4†<8³Z°Z°Z°Z°Ú`µÁjƒÕ’Õ’Õ’ÕŠÕŠÕŠÕŠÕšÕšÕšÕ&«MV›¬¶Xm±Úbµ…jçùrrFµóð ypFµóä 98gV V V V¬6Xm°Z²Z²Z²Z²Z±Z±Z±Z³Z³Z³ÚdµÉj“Õ&«-V[¬¶Pí<ÞBœoª]M¬Ï:_L­ÇÇwãòz¶=¼xã-Oóû‡o¿ý‡÷ÿþ݇?ýöã·÷¯>Ùq8^~þj)óÄ\΃scÞ÷†€œ‹óÂ> stream xÚÝMsו§ñ½>vc/Uçåž³ôKKÓ¶ä¡Ô1o`²D¡M‚ìϧŸÌd1 ÿÇ1Ñ’Ÿ,ü‰/çfÝ›5]×8^ýôßßLW?½þfzþ·ïæÿ{ûÍïúæ_¿=\æúó7‡«iþó¿§«‘‡ëÈ«ŸÞó¿ökËë«ï?||ÿãéîÍ>¼s÷毿ùëoûÓ._ø¿Ÿ^zô¸îÉ·/¿^.zî¥{ ;ô¡{NÐ zBoÝÇ:ø ð+ð+ð+ðkðkðkðkígÓz@×~v8@wèÚÏŽtƒžÐÁÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/À/Á/Á/Áo€ß¿~~~~~ ~ ~­ý|:@wèÚÏtƒžÐµŸÐ:øøøø9ø9ø9ø9øøøø%ø%ø%ø ðà7Ào€____ƒ_ƒ_k¿˜&èý²ßÓ`ýtáüÁqäÙíWëìÊuÚžÙn§íñ0mÿáæîõ霷ç_ϳÉö |5ôÒ}þöuwèC÷ù׳î=¡·î~~~ ~ ~­ýlš ô„®ýìp„еŸÐ:øøøøø9ø9ø9øøøø%ø%ø%ø%ø ðà7À¯À¯À¯À¯Á¯Á¯Á¯µŸOGè]ûùáÝ¡k??NÐ zB??????¿¿¿¿¿¿¿¿~üøøøøø5ø5øµö‹éÝ¡_öÛMÁOóòfއ+'Û+{¾hŸÆå˜gå^ýùêÕéõévûcæ_±üØÏWÿ×Y_fK?ë§Wß~¾{}ûáîÓ~Öž×ÖÃj{ýù¬6¯­eŸ×Öº;ô¡û¼¶ÖÝ 'ôÖ}^‹è~~ ~ ~ ~üø ðàWàWàWà×à×à×ÚoY‹ènкö[Ö"ºtí·¬Etwèàgàgàgàgàçàçàçàààà—à—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~ËZD÷€®ý–µˆî]û-kÝ zB??????¿¿¿¿¿¿¿¿~üøøøøø5ø5øµö[Ö"º;ôË~»ÆÃZ$Ζk‘ŠÝ½ûyY°YŒ¾l”¹¿ùx¿[’禎±}ÍÙ’ä8ÿ”㬟>^¾ñ?/&²·îÖ2™ç•„̦sêÜ2Ï«™Cç’9µZjµÔjC« ­6´ÚÐj¥ÕJ«•Vk­ÖZ­¥Ú²jÙtN¥Ú²b9t–jËrAf×Y«™V3­fZÍ´šk5×j®ÕB«…V ­–Z-µZjµÔjC« ­6´ZiµÒj¥ÕZ«µVk­ÖRmYÈ:KµeA ³ë,ՖՀ̦sê¬ÕL«™V3­æZ͵škµÐj¡ÕB«…VK­–Z-µÚÐjC« ­VZ­´ZiµÒj­ÕZ«µT[F~™]ç‹j»)þiÞßLò_æýcÖnÞŸ¯ÞÌûÇÇyÿïÇ}Ú¾d7îÛtÖŸSn¯ÜÍûºÝç‰_wƒžÐ[÷yê×= —î ~ ~ ~üø ðàWàWàWà×à×à×ÚoYènкö[Vºtí·,twèàgàgàgàgàçàçàçàààà—à—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~Ë:A÷€®ý–¥‚î]û-«Ý zB??????¿¿¿¿¿¿¿¿~üøøøøø5ø5øµö[º;ôË~»ÂÃZÂÏV ùåÊiÿÞÁtØ®%ìñíý«ÿû‡›×¿œþtûþöþ…ƒ¶3èØ~ý<­rè\2/ôʮóy™¤U6Sg­VZ­´ZiµÖj­ÕZª­ó³Ê¦sê,ÕÖÙYåÐYª­ƒ³Ê®³V3­fZÍ´ši5×j®Õ\«…V ­Z-µZjµÔj©Õ†VZmhµÒj¥ÕJ«µVk­ÖZ­¥Ú:«:Kµu4VÙu–jë\¬²éœ:k5Ój¦ÕL«¹Vs­æZ-´ZhµÐj¡ÕR«¥VK­6´ÚÐjC«•V+­VZ­´ZkµÖj-ÕÖáWe×ù¢Únž}º‹¾™i'ßÚÝEÏêíäë›É÷ǯÿ~~—üxÝó”½yÉéþ÷ŸþúþwÛÙ5?¿t+}9[¹½t$VõåH¬ì}辉•Ý 'ôÖ}9+;øø5ø5øµö[ÄÊnкö[ÄÊеßz$Vv‡~~~~~~~~~~~ ~ ~ ~ ~üø ð+ð+ð+ðkðkðkðkí·‰•= k¿õH¬ì]û­Gbe7è ü ü ü üüüüüüüüüüüø ðàWàWàWàWà×à×à×Úo=+»C¿ì·“o%oGåñpåüwän ggbãi þñöÝéîÂVôy ˜G•íëÎ÷¦Ì¿yÖ_¨}þb¾½rw/Z÷€^º/¹ì}è¾ ä²ô„~~~~ ~ ~­ýÖ\vƒžÐµß:Ëеß:ËîÐÁÏÀÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/Á/Á/Á/Áo€ß¿~~~~ ~ ~ ~­ýÖ\ö€®ýÖ\v‡®ýÖ\vƒžÐÁÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/À/Á/Á/Áo€ß¿~~~~~ ~ ~­ýÖ\v‡~Ùo7f?>£f;jÈ3v{;2ÏÎ…>=@ýþ§³[ׇå€ÌüòÍõ7ŸßÝÿÇÝíë›O÷ßß¼þûå©{ž:—ñ=_>N(sË<œ2‡Î%óÏ™ºôÒ}5u¿Ö~Ë´©»AOèÚo™8uèÚo:uwèàgàgàgàgàçàçàçàààà—à—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~Ë<ª{@×~ËHª»C×~ËTª»AOèàgàgàgàçàçàçààààà—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~ËÀª»C¿ì·›DŸöl¦Ñ/3ë°ý­M?;¶VêÖæòòÍõË­Íÿq÷ú/Þݾþz—ÀÁÏ®ýÇ 3︞|{Ýn¤•ÙtN[æyœ•9t.™çYVf×Yª-ƒ¬Ì¦sê,Õ–!VæÐYª-¬Ì®³V3­fZÍ´ši5×j®Õ\«…V ­Z-µZjµÔj©Õ†VZmhµÒj¥ÕJ«µVk­ÖZ­¥Ú2¦Ê:KµeF•Ùu–jË€*³éœ:k5Ój¦ÕL«¹Vs­æZ-´ZhµÐj¡ÕR«¥VK­6´ÚÐjC«•V+­VZ­´ZkµÖj-Õ–)Tf×ù¢Ún°|ºmº.ûËg+Nûí®Ç³óc­FÐåå›ë—t¹£z{÷öÏÞœ^xw½®{™‡ýòçlËîЇîËçlËnÐz˾~ζì]û­Ÿ³-»C×~ëçlËnÐ:øøøø9ø9ø9øøøøø%ø%ø%ø ðà7À¯À¯À¯À¯À¯Á¯Á¯µßú9Û²;tí·~ζì=¡k¿õs¶eèàgàgàgàçàçàçàçàààà—à—à—à7Ào€ß¿~~~~ ~ ~­ýÖÏÙ–Ý _öÛÍ‚O{27óàãÔ8öo¶ÎIÍÈlßmç¡0®«sûU¾º;XºÏC£î}è>ºô„Þ²/C£î]û-C£î]û-C£î=¡ƒŸŸŸŸƒŸƒŸƒ_€_€_€_€_‚_‚_‚ß¿~ü ü ü ü üüüZû-C£î]û-C£î=¡k¿ehÔ= ƒŸŸŸŸƒŸƒŸƒŸƒ_€_€_€_‚_‚_‚ß¿~üøøøø5ø5øµö[†FÝ úe¿Ý(øôn÷ó…1}9ƒØßjœÎ?àíË'¼ýð·ÿ<½¾ÿ§ÆÆe4õí×Ù?uTö€^º/•Ý¡Ù×gÊnкö[Ÿ?*{@×~ë#Hewèàgàgàgàgàçàçàçàààà—à—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~ëÓIeèÚo}@©ì]û­Ï(•Ý 'tð3ð3ð3ðsðsðsð ð ð ð ðKðKðKðà7Ào€_____ƒ_ƒ_k¿õñ¥²;ôË~»aïé^âó…cáaìÆÂ賃;‡ãKoA—SGóë7/XÞ‚~uúõæöãï?|¾{sóñ…­ŽË¯N¾}åþ“We²¯Ÿ½*»AOè­ûòù«²ôÒýx€îÐÁÏÀÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/Á/Á/Á/Áo€ß¿~~~~ ~ ~ ~­ýÖOg•= k¿õZewèÚoýŒVÙ zB??????¿¿¿¿¿¿¿¿~üøøøøø5ø5øµö[?¾Uv‡~Ùo7=Nn› ãðpevÇW¢Îޝìì]àf.[Þ¨Íí×Ù¿O+òò6­Ê¦sêÜ*¯oѪ:—ÌËû³*»ÎRm}sVeÓ9uÖj¦ÕL«™Vs­æZ͵ZhµÐj¡ÕB«¥VK­–Zmhµ¡Õ†V+­VZ­´ZiµÖj­ÕZª­ïÀªì:KµõíW•MçÔYª­o½ª:k5Ój¦ÕL«¹Vs­æZ͵ZhµÐj¡ÕR«¥VK­6´ÚÐjC« ­VZ­´ZiµÖj­ÕZª­o°ªl:_TÛX96>cž»-y‘g9®n£-¯ß¼`½ö_}øÛùGÍ/CåÙuŸ?ÝûõóοÔëû_¼ gSn/Þ?CFö!ûú Ù zBoÝ—gÈÈÐK÷ãºC???????¿¿¿¿¿¿¿¿~üøøøø5ø5ø5øµö[Ÿ!#{@×~ë3ddwèÚo}†Œì=¡ƒŸŸŸŸƒŸƒŸƒ_€_€_€_€_‚_‚_‚ß¿~ü ü ü ü üüüZû­Ï‘Ý¡_öÛMs»ê6>Î}vÕEœňó›p»©n}Æðqû²ÝT7ÿB?Ng—ˆ©î˦»ÍÅ7ݽÜK÷/›î^î}Èþ¸éîånÐzë~8BèÚïqÓÝËÝ¡ƒŸŸŸŸŸƒŸƒŸƒ_€_€_€_‚_‚_‚_‚ß¿~ü ü ü üüüüZû=nº{¹tí÷¸éîåîеß㦻—»AOèàgàgàgàçàçàçààààà—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~›î^îý²ß‹›î6ÆñË›¼û'†ŸŸÅxüT•û§›÷¯N7o.{v¸^¾ဃ¹ÎCfŸt6Sç–9Ž:‡Î%sjµÔj©Õ†VZmhµ¡ÕJ«•V+­ÖZ­µZKµuæʦsê,ÕÖÍš*‡ÎRmÝ©©²ë¬ÕL«™V3­fZ͵šk5×j¡ÕB«…VK­–Z-µZjµ¡Õ†VZ­´ZiµÒj­ÕZ«µVk©¶nÇT9t–jë^L•]g©¶nÄTÙtNµši5Ój¦Õ\«¹Vs­Z-´ZhµÐj©ÕR«¥VZmhµ¡ÕJ«•V+­VZ­µZkµ–jënK•]ç‹j»)üéÝýç çõy®ÚÍëv~HflçõO§¿ÿùÓÛïo>Þ¿ø¨ooß~•ý'sËnÐzë¾|2·ì½t_>™[v‡®ýÖOæ–Ý 'tí·~2·ì]û­ŸÌ-»C???????¿¿¿¿¿¿¿¿~üøøøø5ø5ø5øµö[?™[ö€®ýÖOæ–Ý¡k¿õ“¹e7è ü ü ü üüüüüüüüüüüø ðàWàWàWàWà×à×à×ÚoýdnÙúe¿Ý¨ùtùù°‡+§±¿‰|ŸnŽGè½t·t‡>t÷ ºAOèàààà—à—à—à7Ào€ß¿~~~~ ~ ~­ý–ù_wƒžÐµß²Ð= k¿e5 »C???????¿¿¿¿¿¿¿¿~üøøøø5ø5ø5øµö[Öºtí·¬$twèÚoYOènÐ:øøøø9ø9ø9øøøøø%ø%ø%ø ðà7À¯À¯À¯À¯À¯Á¯Á¯µß² ÑÝ¡_öÛ­0žÖ"Ï>®EjöÍ{l#g”ÿîtÿÓÙµ¤Šãö5ÿøõ…ÍÏ[wúöÒ¯¦ñ#ô€^ºÏ[ëîЇîóßÖºô„~üø ð+ð+ð+ðkðkðkðkí·~¨¨ì]û­**»C×~뇊ÊnÐ:øøøø9ø9ø9øøøøø%ø%ø%ø ðà7À¯À¯À¯À¯À¯Á¯Á¯µßú¡¢²;tí·~¨¨ì=¡k¿õCEeèàgàgàgàçàçàçàçàààà—à—à—à7Ào€ß¿~~~~ ~ ~­ýÖ•Ý _öÛÍèÛI6†yæÅþƒ¼b;Í·Óüÿ¼ùôïw?xa\_¬áÛ×ïnÎënÐzëGè½tÏt‡~üø ðàWàWàWà×à×à×ÚïáÁtªô„®ýL§z@×~¦SÝ¡ƒŸŸŸŸŸƒŸƒŸƒ_€_€_€_‚_‚_‚_‚ß¿~ü ü ü üüüüZû=<˜Nõ€®ýL§ºC×~¦SÝ 'tð3ð3ð3ðsðsðsð ð ð ð ðKðKðKðà7Ào€_____ƒ_ƒ_k¿‡Ó©îÐ/ûí†ô§qþùÂÇqÞz÷@âe¶çí«›óË8ÿ§ÓÝÛû_^8²8ÓË5ìå¡Uõeh•Ý 'ôÖ}Zeè¥û2´Ê~­ýÖ¡UvƒžÐµß:´Êеß:´ÊîÐÁÏÀÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/Á/Á/Á/Áo€ß¿~~~~ ~ ~ ~­ýÖ¡Uö€®ýÖ¡Uv‡®ýÖ¡UvƒžÐÁÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/À/Á/Á/Áo€ß¿~~~~~ ~ ~­ýÖ¡Uv‡~Ùo7Š>>MysáãÐZ¾¿‡íÐê†ÖîAçu›o_ÿÕòÖ}ÙR"{@/Ý—-%²;ô¡û²¥Dvƒ~ ~üø ð+ð+ð+ðkðkðkðkí·n)‘= k¿uK‰ì]û­[Jd7è ü ü ü üüüüüüüüüüüø ðàWàWàWàWà×à×à×ÚoÝR"»C×~ë–Ù zB×~ë–Ù:øøøø9ø9ø9ø9øøøø%ø%ø%ø ðà7Ào€____ƒ_ƒ_k¿uK‰ìý²ßnHºý|aÄÕ»'”,¿l7ã||5ÎÿxûÿN/n)9·/ßí(‘ÙtN[æùwšÌ¡sÉ<«Êì:kµ¡Õ†VZmhµÒj¥ÕJ«µVk­ÖRm¹/³éœ:Kµå&¼Ì¡³T[îÀËì:k5Ój¦ÕL«™Vs­æZ͵ZhµÐj¡ÕR«¥VK­–Zmhµ¡Õ†V+­VZ­´ZkµÖj­ÕZª-·Ùe¥Úr]f×Yª-7Øe6Sg­fZÍ´ši5×j®Õ\«…V ­Z-´ZjµÔj©Õ†VZmhµÒj¥ÕJ«•Vk­ÖZ­¥Úr]f×ù¢Ún’~<”¹¹ðqæ®ýS—¥êfæÎ¯fîßÿãþôé/§»7·wo_xîß¼ÔÙ~•ýÚ—ër›VT—u¨ºÜ ÕdMY[ÔõƬ¨!«²ZoÉŠê²*«õf¬¨&kÊ*­LZ™´2iåÒÊ¥•K«V!­BZ…´Ji•Ò*¥ÕVCZ iUÒª¤UI«’V-­ZZµ²Zo«Šê²*«õ†ª¨&kʪ¬Ö©¢†¬Òʤ•I+“V.­\Z¹´riÒ*¤UH«”V)­RZ i5¤ÕVCZ•´*iUÒª¥UK«VVëMQQMÖKV»ëi4{¾ðq4ëØïn8ž°ÛÑì7w¯Oï^¸j×uôí˯¿þLiÝ[w?Bè¥{ ;ô¡{NÐÁ/Á/Áo€ß¿~~~~ ~ ~ ~­ý–[÷€®ý–I[w‡®ý–y[wƒžÐÁÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/À/Á/Á/Áo€ß¿~~~~~ ~ ~­ý–)]w‡®ý–Y]wƒžÐµß2³ëÐÁÏÀÏÀÏÀÏÁÏÁÏÁÏÁ/À/À/À/Á/Á/Áo€ß¿~ü ü ü üüüZû-s¾îý²ßn†Úüð|aä—çèMû±‡³xµö_îonï^üïãØ¾zÿ¨l•‡Ì˃²U6Sç–yyH¶Ê¡sÉœZ-µZjµ¡Õ†VZmhµÒj¥ÕJ«µVk­ÖRm}(¶Ê¦sê,ÕÖb«:KµõiØ*»ÎZÍ´ši5Ój¦Õ\«¹Vs­Z-´ZhµÔj©ÕR«¥VZmhµ¡ÕJ«•V+­ÖZ­µZkµ–jë#¯U¥Úú¼k•]g©¶>ìZeÓ9uÖj¦ÕL«™Vs­æZ͵ZhµÐj¡ÕB«¥VK­–Zmhµ¡Õ†V+­VZ­´ZiµÖj­ÕZª­O´VÙu¾¨¶ßnÏ?_ø8°_:|8>ìóýÝéæÓI>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðá‡'8|8Ááà Npøp‚Ç>œàðᇧöðáó…1¾<*/wÀ[þØÜ~:Íô0Ï{ûîôÝéþû›÷'ñ8ëܾüÂã¬U7è ½u_g­z@/Ý×ÇY«îÐÁo€ß¿~ü ü ü üüüZû=<ÎZuƒžÐµßÃã¬UèÚïáqÖª;tð3ð3ð3ð3ðsðsðsð ð ð ðKðKðKðKðà7Ào€____ƒ_ƒ_ƒ_k¿‡ÇY«еßÃã¬UwèÚïáqÖªô„~~~~~~~~~~~ ~ ~ ~üø ð+ð+ð+ð+ðkðkðkí÷ð8kÕúe¿ÝŒþødÀÍ…Óü<#ì¦ùqþY“‡çiþÕéîåaþp=ÿ‚ݾz·›F÷¡û¼ÐÝ 'ôÖ}^ èÐK÷¿¿¿~üø ð+ð+ð+ðkðkðkí·,t7è ]û-‹Ýºö[º;tð3ð3ð3ð3ðsðsðsð ð ð ðKðKðKðKðà7Ào€____ƒ_ƒ_ƒ_k¿e1 {@×~Ëb@w‡®ý–Å€î=¡ƒŸŸŸŸƒŸƒŸƒ_€_€_€_€_‚_‚_‚ß¿~ü ü ü ü üüüZû-‹Ýúe¿Ýˆÿ´x¾ðéÖþ´Û©³¼#¼] |ù¬Ê?ÞÜßüîõëÓ§OË?]^,w×—'ŇEÊÐK÷åîºì}è¾~îŽê=¡ƒ____ƒ_ƒ_k¿‡ÏÝQÝ 'tí÷ð¹;ªtí÷ð¹;ª;tð3ð3ð3ð3ðsðsðsð ð ð ðKðKðKðKðà7Ào€____ƒ_ƒ_ƒ_k¿‡ÏÝQ= k¿‡ÏÝQÝ¡k¿‡ÏÝQÝ 'tð3ð3ð3ðsðsðsð ð ð ð ðKðKðKðà7Ào€_____ƒ_ƒ_k¿‡ÏÝQÝ¡_öÛÉ{e6Fm¿Ò:GÇÙÕƒ=ÏÑ<Ýß¼þ…çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£Ãô¦çè0=G‡é9:LÏÑazŽÓst˜ž£ÃþÉ9úù‡9z÷ñìë@ígGH_€å§»7§—'êxø˜úÍ—¸°¯[õÒ=ÐúÐ}Ý×­ºAOè­{___ƒ_ƒ_k¿‡}ݪô„®ýöu«еßþnÕ:øøøøø9ø9ø9øøøø%ø%ø%ø%ø ðà7À¯À¯À¯À¯Á¯Á¯Á¯µßþnÕºö{Ø×­ºC×~ûºU7è ü ü ü üüüüüüüüüüüø ðàWàWàWàWà×à×à×Úïa_·êý²ßn~š˜Ÿ/Œþ²éÃl{eçúl…§yy ú¯þ<ÌoNWß~¾{}ûáîÓ~Rž÷ãöµç“Ö!¡·îÇ#ô€^º/›ÒewèC÷eSºìàçàçàààà—à—à—à7Ào€ß¿~~~~ ~ ~­ýÖMé²ô„®ýÖMé²tí·nJ—Ý¡ƒŸŸŸŸŸƒŸƒŸƒ_€_€_€_‚_‚_‚_‚ß¿~ü ü ü üüüüZû­›ÒeèÚoÝ”.»C×~ë¦tÙ zB??????¿¿¿¿¿¿¿¿~üøøøøø5ø5øµö[7¥ËîÐ/ûíÖ'Ü\ø¸’™g°Ý½ÿÃØ.e¾P]Ö2ßîÿýÍå›þËR£·/ݯ4T.™—u†Ê®óyYd¨l:§Î-shµÐj¡ÕR«¥VK­6´ÚÐjC« ­VZ­´ZiµÖj­ÕZª­ •MçÔYª­‹ •Cg©¶®$Tvµši5Ój¦ÕL«¹Vs­æZ-´ZhµÐj©ÕR«¥VK­6´ÚÐjC«•V+­VZ­µZkµÖj-ÕÖå‚Ê¡³T[× *»ÎRm](¨l:§ÎZÍ´ši5Ój®Õ\«¹V ­Z-´ZhµÔj©ÕR« ­6´ÚÐj¥ÕJ«•V+­ÖZ­µZKµu5 ²ë|Qm7à?-ž/|\ lÿ°š)¶KãÙRàwoÞ|<}úô¶ú¼NËíØ Æ²Ï“±î½tŸ‡cÝúÐ}žu7èà7À¯À¯À¯À¯Á¯Á¯µß2)ënкö[¦eݺö[fÝ:øøøøø9ø9ø9øøøø%ø%ø%ø%ø ðà7À¯À¯À¯À¯Á¯Á¯Á¯µß2Këеß2Nëîеß2QënÐ:øøøø9ø9ø9øøøøø%ø%ø%ø ðà7À¯À¯À¯À¯À¯Á¯Á¯µß2lëîÐ/ûí¦è§çÁ<_˜ÓÕٻm÷Ë'älæm;›·¿ûxÿâÃ!§òí«w7ÈuºûÝ 'ôÖ}^ èÐK÷¿¿¿~üø ð+ð+ð+ðkðkðkí·,t7è ]û-‹Ýºö[º;tð3ð3ð3ð3ðsðsðsð ð ð ðKðKðKðKðà7Ào€____ƒ_ƒ_ƒ_k¿e1 {@×~Ëb@w‡®ý–Å€î=¡ƒŸŸŸŸƒŸƒŸƒ_€_€_€_€_‚_‚_‚ß¿~ü ü ü ü üüüZû-‹Ýúe¿Ýˆÿx¢`sáãbà°?ƒ»|\çf1àg‹?|xÿþæî…Í8ËÍñÉ·_`s\õ忏ì}è¾Ü—Ý 'ôÖ}¹9.;øø5ø5øµö[oŽËnкö[oŽËеßzs\v‡~~~~~~~~~~~ ~ ~ ~ ~üø ð+ð+ð+ðkðkðkðkí·Þ—= k¿õæ¸ì]û­7Çe7è ü ü ü üüüüüüüüüüüø ðàWàWàWàWà×à×à×Úo½9.»C¿ì·›rŸæáç çái¿å˜gGlãyþöãéôûÏ?}ö5¼¶/úùôñåÍ*Ãr{íîþ´ìq„ÐK÷y×Ý¡Ýçy\wƒ~ü ü ü üüüZû-ó¸î=¡k¿e×= k¿e×Ý¡ƒŸŸŸŸŸƒŸƒŸƒ_€_€_€_‚_‚_‚_‚ß¿~ü ü ü üüüüZû-ó¸î]û-ó¸î]û-ó¸î=¡ƒŸŸŸŸƒŸƒŸƒ_€_€_€_€_‚_‚_‚ß¿~ü ü ü ü üüüZû-ó¸îý²ßnÊ~ܬ²¹0“ûîœè1ÎΉæó<þÇÓ»Óý dzœ×&ۗjY]Ö¡ªO²š¬)k«ºlsUZ…´Ji•Ò*¥ÕVCZ i5¤UI«’V%­ZZµ´jeµÞ©ÕdMY•Õz‡^ÔUY­÷æEuY¥•I+“V&­LZ¹´riåÒ*¤UH«V)­RZ¥´Ji5¤ÕVCZ•´*iUÒª¥UK«–V­¬Ö»ì¢†¬Êj½¿.ªËª¬Ö;뢚¬)«´2ieÒʤ•K+—V.­BZ…´ iÒ*¥UJ«”VCZ i5¤UI«’V%­JZµ´jiÕÊj½G.ªËzÉj7c?ÕÜ\ø<ïw‹øÙQÍñ<¿:ÝßÜÞ½t÷ ºAOè­{¡ƒ_€_‚_‚_‚ß¿~üøøøø5ø5øµö{Úiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxè6z§‡Þiã¡wÚxü“;mž/ÌãÕ1íwÚØÙ1ÔÚ®%Þn>^<†zÌܾz·Ð}è>/t7è ½uŸºôÒ=Á/Á/Áo€ß¿~ü ü ü üüüZû-‹Ý zB×~Ëb@÷€®ý–Å€îü ü ü ü üüüüüüüüüüüø ðàWàWàWà×à×à×à×ÚoY èе߲ÐÝ¡k¿e1 »AOèàgàgàgàçàçàçààààà—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~Ëb@w‡~Ùo7â?móy¾ðq10ÆWluMÔ·×~~ûööî­úð«y50¢¶¯Ù­dŸWºô„Þº/›þeè¥û²é_vðKðà7Ào€ß¿¿¿¿¿¿Ö~ë¦Ù zB×~ë¦Ùºö[7ýËîÐÁÏÀÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/Á/Á/Á/Áo€ß¿~~~~ ~ ~ ~­ýÖMÿ²tí·nú—Ý¡k¿uÓ¿ì=¡ƒŸŸŸŸƒŸƒŸƒ_€_€_€_€_‚_‚_‚ß¿~ü ü ü ü üüüZû­›þewè—ýv3þÓ6£ç Ó¾¬bÿÖÀÔÛåÀ—‡úñtÿõ’`þé޵½þóÛ?Î?¾¶®ýü’ÿ:ß|´|cgýôî…¼óÊðÛ+÷ï ÈžÐ[÷åÙzé¾¼3 »Cºðà7Ào€____ƒ_ƒ_k¿õÙ zB×~ë;²tí·¾3 »C???????¿¿¿¿¿¿¿¿~üøøøø5ø5ø5øµö[ß= k¿õÙºö[ßÝ 'tð3ð3ð3ðsðsðsð ð ð ð ðKðKðKðà7Ào€_____ƒ_ƒ_k¿õÙúe¿Ý„ÿôÎÀó…kÜPì¡Çv-ðåÓ¡~øõt÷Õbà8ÿø‹í æÅÀ‡·/ óv=õöÚýÃäUn™—GÉ«:—ÌËsäUv‡ÌËCäUÖjC« ­VZ­´ZiµÖj­ÕZª­ŽWÙtN¥ÚúØx•Cg©¶>3^e×Y«™V3­fZÍ´šk5×j®ÕB«…V ­–Z-µZjµÔjC« ­6´ZiµÒj¥ÕZ«µVk­ÖRm}0¼Ê¡³T[Ÿ ¯²ë,ÕÖG«l:§ÎZÍ´ši5Ój®Õ\«¹V ­Z-´ZhµÔj©ÕR« ­6´ÚÐj¥ÕJ«•V+­ÖZ­µZKµõ¹ï*»ÎÕv“òãýõÍ…3õÖº;ô¡û<]ë~üøøøø5ø5øµö[ælÝ zB×~ˬ­{@×~˸­»C???????¿¿¿¿¿¿¿¿~üøøøø5ø5ø5øµö[&qݺö[†qݺö[æqÝ zB??????¿¿¿¿¿¿¿¿~üøøøøø5ø5øµö[FuÝúe¿Ý þxPvsáã´¾lgùzZ¶Ö]ÜÏëµ}Áç·¹ýõôâ´žžÛ«÷µ‘½u_k#{@/Ý—ÇÚÈîЇîËcmd¿~ü ü ü üüüZû­µ‘Ý 'tí·>ÖFö€®ýÖÇÚÈîÐÁÏÀÏÀÏÀÏÀÏÁÏÁÏÁ/À/À/À/Á/Á/Á/Áo€ß¿~~~~ ~ ~ ~­ýÖÇÚÈеßúXÙºö[k#»AOèàgàgàgàçàçàçààààà—à—à—à7Ào€ß¿¿¿¿¿¿¿Ö~ëcmdwè—ýv3øã~•Í…Óúˆý~•<;ÊêÞz]Û1¶¯ãz^OÇíÅû-)"/[RTKæeKŠÊ®óyÙ’¢²é¬Õ†V+­VZ­´ZkµÖj-ÕÖ-)*›Î©³T[·¤¨:KµuKŠÊ®³V3­fZÍ´ši5×j®Õ\«…V ­Z-µZjµÔj©Õ†VZmhµÒj¥ÕJ«µVk­ÖZ­¥Úº%EåÐYª­[RTv¥Úº%EeÓ9uÖj¦ÕL«™Vs­æZ͵ZhµÐj¡ÕB«¥VK­–Zmhµ¡Õ†V+­VZ­´ZiµÖj­ÕZª­[RTv/ªí†á§-)Ϧ?µÿúírcûz™´~zɘ¿ìüwìaë凳wyTÇñpvÁÕïo^Ÿ‡ƒç×üýídzK–÷~vɇÏwo¾ìTø¨ªýv¾púú;›ÿØ«£¯¯øé—ÛOWo>¼þüþtwõæôéõÇÛ¿>]ÝÜ]Ýüúë»Û×7Ëóh®~ýøáíÇ›÷ï—‡ÔÜÞÝŸ>þ|>éøún¿ðÍëÓÕ_ó»¿üû_{õó‡W÷¿œ®ÎÿR™eyö’ïo^ÿý_~øx;'§7W¯NïnoþöîtõçÏïîçïãÓýòòYÞ‚8[ÔÌ?¡ù¯Ç¯ñ×ß,OÜyXuÿÒ¾«§^¾¯í·´¼•îcîOû¿> stream xÚ•ZK“Û6¾Ï¯@å§j†!ð•›ãØ[®Ý$^gªrñ…CaFŒ)R!©Q&¿~¿_hPr¼å²- Я@È0÷ç›PÜ—7áúí_øûtóãýÍ÷ï¤}¼‘"Ä)ÒH¤‰ âDÜn^OݱíèL]µ»b(ÄÐMl»A<¶(ŽÇº*‹¡j›^œ«~_5ObhÅ óÞ7ƒé3ˆ];´e[‹O¯ÞøôøùT˜Ô¢7ÝsUšÞòzêÚÓñ»û?°Ù\¥´Yw_:Ÿ÷e·±Ã¦ˆv&‘ad:uéžÙ¸”A’³qÓ½0ŠH™døå×?‹²hDQ÷­èOG{òS3nÿÓ«c[5ÃÝÐÞÙ8›Ý\Ù–†ä"Šf'Å‹x0$–=k*÷ãQS­ý£ªtÞÀyoÕ0 ¢îÚcWƒ Ûx*fóî÷F”§®3Í0á8« ?šÒ îûwѤýWŸÂ0š âÕ´õªOLÌ*UAš$îZÏ|< ÉÆq‚ªväj™i–¹„‹½¼mžªÆ˜Žlɇ:SÆüžçÊØxѶböEÅ3Å;—CšZº£mW— ×A¦“M¿½Ís[J•»tß½qªCF•dAʨ‚ÉüóÈßp¨\ÝrBK;ÓWO ¬¾‡ßÝU"¡d,ž«¦Ù‘áâ¿ÕÃWçnÅSlÿÉ—Sýy4÷öáS½ »:Sð‘éE†A¢ùøx蜛ŽîB|OnË)p”¸SŸ P(…ƒP`FÅ’×uf8u8Ãý±k6™Ï ÃÜSGÉx u“ñ{ªØøÆgµ†ó 'rh(Ø/Á/&”Ï™0'É…°}?Nä‚…hN‡˜+Tþh œÕô—œZf*ˆ²Øz»ŠÃ/r21öØEáå¶X‚Õ@öEà£Ïì«§ýî×Ü0 ÂLº<ïjÃ¥”—Spi#ÿŠ7õEïÚQ`aû (ƒ±×Õß@I$9S¦@9­' ™–•;o’Ä™b³Ž]²âÅ3„Hê cœ˜pYDiLY¤CÌ‘.£äˆ?‘Â÷¶! ½{ûæî¡ Ú¤3G`êf­v¼d’€I««‹éLäë¡›ýÏñõR"ç À­è²êi@Ànª?OØ.äMâÝ`‡0Ë}†)O”?þgŒ*uõМ|Ìá8ôeLD8,l¢\›g!®ÇS="æ˜P¦²óÒ;*#ÙFž7é_ÂÆMÝmÒU\HFŠãÝh£Rù‡uŠõÕÅhO,w—*BQæRSêþÏ¡ž‚B7ÙÁÅ¢.æ1榧`,‰;lH½8›º¦ÿçzç ‡É W°Ð>u"Šún¨fR¿ ýÚ9vÚÞf³$Hc—€í•ÊwvÚ™?OUgóaÏA­«çl¹{¯À•p…`î¼þð~ƒ±äêJk—ìŒHZ¢±6z(îÍ*[øÅK›ŽEW ÎyNôOM9Ú¸HvÚ¹ÄR(X<)®42Øvȳ‹¯ì0Ô÷Ð-¨¡œU~ßWÔ_2<´@ÈHéÐp 瀷â Û4¾#+ÔÕqÌŽA޼»µœ± C~L!Æ5@¿¼Ùœ™z2ñÆÓ"7{2£«®æqkáÔS–DÑd÷±N~ÙÄOIp»4SÔX¬ÞöżžÉ`W=¡ÙUåP Æç«ãU¿ºÀ·1fgAâ"Ë•<†Y¥¹ã;®ç·¼é–FAžº“¬K“ÉŽ2ãèIɶt'p@bó˜ñ«)gEÐžêØ³@¡2Ìâ«Ì”ʾ7Xðo!í§=RAJõxå¹Ð¶M¿ÞøïX[ ‚ ·PýmQ·VAÁȳSЍ¼I«;d˜ZnQÀ´„\ ’Œ@üúÌÓ+©8ÓŒ=WL 2†‹*Nr}CÅ6ä^lkM…«æm*Þ‹‚TfŒPq`ð`l¯ózK£P@îáεñ¹¯ÇÚÜR)K~ÓGi,ª$›Xt;d]œ„ªžNˆà§Ó±mfÖ[´ý¦dñnÁÛb‹P¼2É‹P¶-(7±«šŠÉ¦ž c9fÔÃ%Ùj#à0ž6à€OÑ÷mIãÝ\“Ëh*eè74t¤k ž;"(˜FËTžú%–Qà¸ÓAäøÍi¥l& C[‡»³¨4ýíôÐ^0õ GÔ½QÎèoGY¬·S™|u«ÒP^Ø*9ýåjàtäÍAm8UÌÔPCKáÕqˆJEglÞ³ß9ËsÅMéT/šJ}M¡NZ¦@ÍdÛ-A†'#8*çd¨øô®jOýZ³Ya^“_X5g@òûuì_ ÂùPû°IT\#§Ø¶Ÿ½ºXJˆ(cS_/í=*$Q±ÔtyPøÂ×AŠàN|öo âˆs6Üâ∼?e$·‹¥sFi_9°ìE8dŸÔ28_²Kr¡<ñ¦B®©Ùð|Í2#êKÍfm,Ó^_=PÓŸ⮡ԇÇ#]3Æènò{ļÊÁ-E-ôRt·d~³† žÕ°m ´6ÝÐoÌÕ¦T^[%’ˆ8Šñðúxq€xâŽãjˆç PÃÈ„s |Rqä·T²âë/~Κ#óÌ ¥¬·—["Ù‰%£&Ä>W¨Ž–(à4åú—Å+xaŒ‚²ßªÜ‹mçÔØ 4ÑüÔ;ÒlÁû}57ÛBí×*v0É+\ÆrÊ¥@݂ĺãÔîÌb56§ª_è(ã½* "âñúYÑåcü§k 6nÊDÕ·¯GÕ«r¾Å}1@p;s$¨§àbÛž íÑÖ¹ÏÏøƒåF`e)}ƒ×Ñ6 Z»Ú£ö°Ü×4Û/z‰×߉!˜­:¡ùj<Ê­Cè+˜HÇ¥{—€<‚vnSãb:Ã]_^zâçé1Þ¨ØÛýAiä?£P¨Zû×îu&±:ö[­•ôîmø÷¶¸noâ­G««{uO¦è!šKÀ‡b%JØ0­HQ\g´¹I­Áümº»$ÃÔ.i§‹ícwô8d~§2JÒ?õ'[eÃ%ßÏ¢¿TrÅ OøÙö÷7ÕDîšHÅ&?û·öH•-,÷+3hz/§,Û…A:µ¯aäqHwÝ%.Æjû´‘¬Yòxí§+".Ê%úm²CÙ^LqáÚñ!æ@+N`[øÿLpž`ùm$®3=‚]Ð/—ÊêÐ~ÕòÍ0™Ý•gNT»Sˆ ¯U"2G±À7f›r1õ˜(º J9“Í…žŠ3 ŲîG€¤¿”5.¯&æ[Ë%KºÚúÈW\ó¬$³m‹Ü¯3ì÷ë%„}IÜ"Œ.ÃWä!BîþÌ·ÙÈÛûe ¡¸ƒYű(7öÅ}ž?f¢¾‰}Qš\ø Bö]áë8>íoéyù’²ç8+*z”•p ›mvân$Íe€ºjú¨%ÖÅ.ü`©ù‰7´|ö·„*CÓcñ|¹ ´2û‰×"@Y3*^y£ ŠB6>^G}Û‹¦ËDó¿7ÞÐŒþÍô¼]H…¶»ù!´ÛéÝß6fû›ßEƒuþŒ‰Y¥endstream endobj 316 0 obj 3875 endobj 323 0 obj <> stream xÚ•ZßoÜ6~÷_Aø¥)°V$‘úuoiš9\›^»‡¾8È»\[W­´•´vÜ¿þ¾!EФv¯9MsH‡3ß|3T̶/71ÛîðÇøÿñæ»íÍÛ1KD$Øöp“°ÿ%¬HY‘QV$l{¼y“FIôíö?v¸Ê"!¸'ÂÞýü‰}êš©©ÛæÏzjúŽfÄQ ÚõíÇ„%q¸QZªùÛ'É~úüËÌÝ'IÓ(KW޶äçf#›žê‰Õ«O§¶Ù©M™tH³<*o/$ÚLí+Û ²ž$í¬Ç‰õdM7Nu·“¬?`õY¥ÓÐOý®o™ì›Nês¥¹:—{ÒVo¢kF6žF(+;Úï<Ê=«GV³]ßíÏÍÄýÀç ëÃó8ªÌ]•ξ«ÛvŒØw¯l/žx‘FYêiQŸÛisõl8w#­p‡Ã”Ix˜$6Ë4k¦‘õž”‘ ».R/ëOrÀ%tl|'yÄÖ01ÎÜíaØ ƒ;¬óÒLOJ)÷Ö°G=‹ßõA²cÝu° ~ÕŸµ¼»¿(ó(çÜUÀZGÝOpœ «@ÏI*%Ü•xöF‹¨*ÝQ\&Û7㩞vOtÖ£Ü=Õ]3#í1¶ 6/r3ùSÇ%V·øœ¢f#i¥±ÕøÔŸ[˜l·“ãhýö£`eÄÝðI‹8ªxé.þS?ÓOòËôájÞ¿¹ÿVÏcçi”»Sñ”KÖì±ñŒQœ{[y&<‰ªÄ—ݬ7vn@íPëOsØ]Ö6‹ã(«Ü9‘ç Y <*=;oŸãÛ÷Ÿb˜ ØçÞLnqápîvÊG9<û Ä#N†^d=µ¾7’÷²õÌ–&y™æ-›"NEâ© ò§‹±ê9,"ŠÅõ¥¹(£2ó5îySÆoGÁác…·î;­Ž3E;92™\âÚ3³à³.?Hel;6Ç?µ³ßig—ûMלG¥»ˆo1¨—gî0¼L¡É@לDï 8Œ—ÙÕ%yšÃý59䯈>vܰÏBÀäTxògd vì<ù.¸âh&É“}svÔÉjÏîߌò*&$¦‘c,Óé0ïÕ\c×Q!UTúÓï¿%Oï¤ÄeilXSÄ€~ é¨"Às~Ôœe¾L´ÝF™ˆã ’Eö¹Ùë¬iÎâ„YܰÞ“á룣ÌÓ.0 R Þî¿Üoåy˜¹êc{©®tånIÉÁg ;Ñ/yù<^É@/MÛR‚éúé+Ø>ÎÿÜÔKïÉ'0àQvmö›1 @y []Öçp™x¼ÚŽ!:ávçúá_¡ÕDáTG7¢;êøúl‡ŒvRQ2¨A-=Õ슊ۯ)~@1‚3f°a5ð˜Áü‹vDï|ßàE…|¸Ì~·ß7¤'üóÕÇ”2ªòEn”û<ÊÀ—ì*äâÚcuÜŽýQ^ÊX‚kêOzÓ€pØ€[«lÿ;õcãª76k=‡™éÞŒQ]ÿ{çE¸k”$V⥕ûG*,q€¶•3'§HUµy®·r¶¦p r†Í;‘ð™Ø_(ÝØºÎbÇ@ï£GN+™¹þávËXßm!•™¥¼·ŠÝ4+pýWVG‘R-ÓI»¶íw”•沄²?”íîßxÍ Nõá²ìÙo/WBÁѬ[,:únO ¿2]F­ß³f‰¬½ ù ]Yº˜Mà'ˆ8áfô9¸8°2>‚˜ýé³OMEǹÜ~øû¤ú ìpžÎƒô1?áUiÅÉÞ¦‰¡=ïaÅnxRRZ-»i›c£+Ú%$VñÏ‹Ìîâñ„@l•«óA‡¾k¦~ûK™Éß$l"Ñ¢I¢'Fˆ]¹ŠÊÝKôöd™¨g@*z—-ü!r™“H>³¨¸<›'q”9³/¥W½ÊŽØÌ)ºí ùèÿ*zŸê÷À@ª€gWz¨Çf¼ÿö–œWº;­ K~©°tEØ÷D’|¥YxR[߉g{ãs áÄPŒÐ›»Xy\^-D9¼^ãÜ÷eKSÆó‰*•Ñ-ZªU •ivlz=!KîGî„ ˜XI ¾<Øi$>°kϳÿéu®ôì)I‚§¹+žÿþü-[Whs#ú÷ï·ÿþøé®´,“ðåN°…Î¥çž;8³"j“ïßmß]iÓAó¬ô6yyj€³ƒÆ¢†Í…7N ¿žºìÈÛÝ/Mo•§Hž{ÿ¦‰dô·Ö𿻀æþ•i^­ž¢x™7ÐŒrâ«ì0ŸEQ†*Æ™´gèىƠ÷_c>Tuãe¦E&–¹D¯¢’®{_°UzývsM”t¦ßtàGÛ¹Ê/v1Ò¼°¦×)(Ò©ªÕ­ïÐT wŽ…8òõ̦RµIß¾ ÍSQ¢š2×?-ààæEˆ³¶‹×áFP$÷&*ÏFÛO&Þâ<,ÄÓÌ‚=ª½…~·«opÚ ;¨‰ðBÖTKqæjÿëðƒ$-\•¾…H¢2ö&ªÃX”£2,WŠî Äث˙!) ;<©°è5ƒœZ}sÌS/Ð6gž{Ž_·¿|x÷ã5@×­Hgêf󑻇þÜ©ç{Ôõcó€ ¼l‚ÔBÑ?ÁåŽ2ç¿FÛŒÉV…6½öÌ»©2hIËÔ'Û7Ç ýÎt:6ìáu’wýÐ`i\«Þ”bÅmÏÍŽLFê¨cƒOãi=­Ú%ÔJ…«ˆæº¨§tàYj,˜óþg6ö»ß}JªëGLN¼ùU?$° XWZ7'‚Ö$JƒÂºÖÿI³˜>^r$7!¨Ó²|0Ì"+ý½Õƒxøî·—_C ÷ÁqDtÚ;Zö¦ÓØÇr‹/ÀÐ à ¶£Ž´3Ç/ð3jyãT_å±–OêAËSrø+K¥‰.ê¼¥Ìñ˜ †gÔDôôEHçCîNErŸêßýŒNŸÖøÝ._Ì­{$"£Ûò±_U(˜°³uT˜n’ÊBÂÍ+7JÁÂð °ñ8s‡‰ÙG«K9(|x;H¯)N¬>Ù¨¯&×o#\D¹»_ð8REÂSgnç©¢& j‚¤ ² lIãÙš ¶2D +u¹ª‰ý¥ü¢ñÊÞ2èÉôjá’ˆŠ:À&;<ȧÚײDaí‰=7½}r+óòÈÖO#”‚*³Šz9µH™ôŦùÂ;ǘËÕ~xÿ†ªG÷7£ÿí…{ ^˜=l‹Ë5ƒ£°ÿ@ h³êN: ÕȘrzªÔ‡A7}õ?¼ÀJ0§½úGNô2n”-O.î'D¦ÐJÜ”¤™Ùí åþ¡Þý®¿ú¹H'ävú°È™å#}²™x】ǡ?Ÿ"öcØU¦fŒ¾>©?_7ºÙª@¡(½q(6zXx–„›]+Ì×·> }Mœ¹sžCJ.ÜQR¸•õЙl»…ßu¥o4wbÝž›Ê¦_ñªÔîG²…ÒÙÀï½±ã$æ…P„) _·ó#å-¼ækèæF9놪Í6èë8¤&õº_aá¡ëPA%P…T¸°ÁH ž/vô8¼""Íkæ›4§àÊY ÀÜåús™ªàŽÔÖoæFê:D™l¨º¡%?líª1»K¹Îîx£>d¤ŸÍ%ko²”G)}dºú'½süSÏ£ŸžnÚ¥¿Û:GÈ"Hõ²•:®6\¡¬Øü3> stream xÚ•[[“Û6²~Ÿ_ÁÒËqªÆ\oÎdœ““];kOöRåª%A#®%Q!)ËÚ_ºìEy\)§f‚¾0 3‘Oç»(xZÝEão?ÿ统îþò6bÝÜÅAÿÅA&‚,Ãfîï^íËéÜí.Á§W?<ý¦ 7ýÕ§(ŠìŸú^}Åßû}b‘†qžÒÍô:èšòÐî«¶­êCДþôCP7Ayêê}ÙU+ó¬óV‚wï?ü-XÕ‡gÝv8~ìšzÔG ëð/UèC¹ÜéuÐ''QÆiNŸü´Õfœ(F ЗUE?kî‘{½Ú–‡ªÝã#׺­žø*u°ÔÁbÓTú°Þ]ø‡ºÛê&X—]LÅ{âªé¡Uœ……bÇ9·v º;³Éy¦IB'×Íçû`ÃÅ BY¤tRY5» Îy…I$QðS”*T*™õKÚmÙT‡ç dw‹Žb:ï ã0Ë3:^V;¼ª`YÖçjÝmC+ 䡤úç*Œbv†wu³ÿ¨»7 $¿ÁiºË§WŸ~àÂìW‹, UœÒÕ ap3åj[izF‹0“³¯ á>¾‘½«Ì[5ÞèönôJWìr¢"”b~g+^Áw®—ÿÑ«Ž›ÇRoêÆœ9 e®;¦%’AÀúPQÐáKÀÞ¾¡‚k'¾vúÐVüñ–Ù$~Ë"‹„£ˆŽ eÁ±©WºmA{Ë.Ø—4•Fÿyªk9-˜p»¹8ƒ™ÈP&ðh5ÿh ¦]üÑMœ«nk”‰Å€°3˜I€Å …@îüþò,d¿€ÆqàtƲ˜ÎáO¦ ÙþIJŸåd·¬O‡uÙ\‚UyÊ]kp¦Õ]êT‡5;­Â(ÙæKµÌ¡îëÖ(›S‹fŒh2cx2UaR°ÐðÞÕk Æ÷ÁœíGw´yTEF Û%Øœ«×öý“<ñß?PAw Ä):Áú÷?þßãÃÓoùëãõãÄifŠ®s¦Öò;QŠȼ§-€=žÜ¸‚ý©íðÐA[Ó ¸ÍÉTêÑ=.Á·æ®7þv´Q2p\÷ãÎQ²4Œ"6g …ë>µïEšz’OóbDùú´[ëã,1FD^Ì‚Mzæâ„Q„œ.2xÞ• (¼é€ÑYu’Q>›­J8ؾ\ë0øßÚ—?à.™z戟©0ŒsLÉŠPtX7lÖ§™/ûl:Ћgºæðš„X6™êÁo’mZŸ¬»ö@-Γ0òùÍÀ¾Ò„kKÁPÆ2ƒ_€U¬ÊVß;bÂQ; ã,£›œƒö¨WÕ·ÍÞ~ܱ?W»jä©…1ÐFç @Òt€Ùö´lÁÉèC·»¼ž˜Q¬Rôød>AÖ“ÓaxîKì׃µbyí¨éÐá—¡D;Å¡€I¨Ù*'é½Poؾ´­ Z¡ƒç(+à×–|ÍÁF…9;ÿ—ª>µVùíÅ…ôï(¼Á®^•VÞ1㙣ƒà•â„í€ðñ¶ÚéÀþ÷úT2Ì%[JÝb­Q.¯Æìu?€&°àC]eâ‘=gꀂ@é¶s@ÊÆaãÉå%€lE–Ìn“næ‚뵑/ÊvÔ*e5àÿŒ •›ÎÑ-cÒÁ¶lA ãåØVÏ'ë”MÌ÷1œŒSÑ4pñÇ DI,)ÅÙœò´ë,†”±,¥ç¿à ËãqWYMy­`Ó'D ¬0*ƒ«¹GŽÉñ½ÈéC€ !:^EÉu í©5¡­ÕÙèò‚F”9sóÙõ&xûøaÛ–-b{èW¤¹@¢­]‚wÌ Å’îù†½@”Ÿ¦Ã¿iê½yð”$à ÇIFp‡D6ŠØ8Aßkª8 Sàdw›JÀ6Y:û%‹‹”?†O( aìÍ“;&¾Rù 9)Æ Ù0(À·óùÔ8ÕëMñ¢ˆd(UN7çà‰Ä£`ãnõ4hë=~\¸ë5Á)%ÐõÎÄ!ø†uS=W ãTsáDöUE6yÕ|0öU£ËzÑÔKî÷¥ ÙÉ\ § ;"¬Þ#‚›³¢ÃnïG~i¢ØËJ£0‹Ø1¼° „‘°qPs|ÛúÔydQ ŒZS:×3%à€Á’Ì`P®ØøÃ¯×ÈBËæMC6dt†²áìÅÿ;Ø“yîßS6À£ Òv5Ï)6íl¢7sk¸ x<àdîs£5*ÖnýíêK~iX2Éöà÷Ah—³qªþÞ®¨AÄAÌo— ¸6ؽÑz½,WŸyªH‹^æöRÈbc6îRE!õ ­µ˜,ñ‰t’c®òbÃeƒÀ' ¯èp{W¿b]ô^Ær–ÆÖè•qŠáeÛÐ%ÏÉX‚pÅ—³„Æóåq˜Fl|x%™N”Keô•Võ~Y€)ÕÏÚdKöà:«cŸ…ša1³–-À– €&{ó+)ð6®{¼â¦ç …`§|³^W¨”½7] `¨dSïƒ-¿ýüÕBUµ«ÜƒÅØë7XÔžŽÇºAà9Z«Úí´ Bàà  ?³„ø¢ ÏðH¢ ްú|ð8]¢;'wzýŒG³|² L¨ŒôÅ¡Ð„Š¨1ÏqUmcÀ<ÁçMj±`ã ¶ÏM}:€ª”߯5D%û ‹*Vg.‘aˆ:ŠÔ yÊSSp.‘…iÁNóæ·_&Ž +J(:íÜ:®úºg‘ïƒÔ˜ï -&¹1õ±¹\7û8·Ñ©šËÈäy˜æläç®íÓ«\:ÊçP¯Ñ·ï…Î ‡Ìp%æ="Iw*Qàeóy¯Îß·Õj{E!q] ñÞÜI8…³“Nu21õ–œÎ:»¤pœù95fPqQ!œ:Ûñ+~@0žºÌ¤o{„CŽæE‹Ba*é õ$,1°í%¹@ïsºð+N6ñ?Y(à“ÎCÉï‰%³’×× TùÁŠVMej©5ñëÊW(ºv¢{YA‡±‚àˆ”1á># ür*Fƒ½OdˆŽu9:Š/hí”ʃ5ݘ{bùÏt6ÿíð¯YCÁ Šl d&Ñ„T$fçÇ<ÓƒÙã£Ý O5 eä«ÕsE’`ûò³_:(‰q³è7’èq‚1_BW Iô† ßHƒaéK°µ}¹µ ¨°btj]ñÚÃXtH9;2blŸJkg%*Ó0Ž¥hLÝ=ÚŒÎü¡„‹­½ï“P"ë“PÒ$¡®<¯!bõãŸàµ¾ùÔlÛˆ™f*ðç®xJ†—ÉŸõ±­ÙÿŒðVvbmdäd­©l”œØE&S3¹CüÀ‘ñ¾ÐŽâ£ZW xhM«Óo}€iµ[$âZ.L’TÈáCó æ›IN·F}š­ ) Èž/–œ„1OØÚ{d°.‡Øš=߃X‚1†¾¶ájµ²°F~M½d.§Ô‡[ÚQ`NWº’ŠMÐ PÏÖÐÀA/½‡¾È’dïMÖÞRi ¥’þ£^d>*Â:$[{?Õ±À*ËöM‚*9&l‰ÂÙr…n\·…~YyBf½ÇJG ÑŠ¶ò³ÍÖút^ÿÇ ­kxâ¡î|ÇdQœ“œTƒkºàÈ1⯽ø =c»Ñ‘{Š$Ìc:ÇE:•5àÞ«Bõx¨ü¤¼{Lž¶z¬ÕºŒº}uŒO†Äò@4?Ó3ãl©OºÚpé§ú0$¢„> Ho…õ”%ïŒ7*Ø©N7‹?˜Jò‚.0eÿ§ýñ÷ßüãño¿=ýÛÉ›ÍzÔºê˜%m–™5¤>.ãdþȼyxóîáß3&^ÈPJ¶5èõÏÕµ´žÂFvpŽþ‰ ëɸF2ÿéU«ç‘Bþz`Þ?ëîþÚ=~õ7 $+@ÇèZˆ9ü* ÄÿyÊ&b ¾`s‚à÷¤Û1ÅWߺÆ<5iÌ“cÉH5œ&¶'ƒ°ãîâÔÒëçà]1ÇMžøxjÂ2~9ÚöC?÷’)6íÞãåÁ¾zÞb*±ƒàiYC¸0§Ì1ÐeÓ½f”ù аèÊÖ"D9 •7Ü”×0óB5xJrºØkMÀØ•O#ׄ›¢Çå¨M®iP B† ÄyD2ÝK#&õè—úy 1†î¼Ð…!OF‡y™ ÈD§b.›áåÑa^ãBZŸÒᩚ`*w[×­V‚˽ŒÆ‡9;ßæ#Åýb]2½s1]j‹—Õã«sÕnuëŠf ¼“ ÃT@}À¼Ø4Wu W×Jüx^ŒAÏ= '˜H^ƒS&­NV£+×Á96©·œ´8äŠnÇ E)ÛFO&`€±ÖÇnkœÞÔÆµï˜9Oºñ˜íëDsbG#Q9c¿=þéë–3M‹n{#ï§ÿlƒ[ñ ¥,Ê'Ï{A¼+áIX:§O2ˆ—^‚»ŠÂ\AQp’M5`D m&s:^j;t[¤Êg˜³ Uü÷”Ј±‡×…+$ß&Þ*1}4ä©ßwspía*Ù.牖[aTŒY3ÿÁl•ü½y…™8X…ê2.6—èJcÖŽЀzx=3ÞpË?#øFF’®ñ:2Ñ'³qmò‹¾Òµ€;øÅÆÜn؈,S6ŽÁ¬Z2U|‚O£Ó{ür]ç¿ýþáçÇŸfî ̦ÈÙêï íG+¼‰=l!bºçµ(±qõp¦Í¨ljЈcc±òë—q>fá‡bµÛòà§åê«FÉ××ûçñk𥕳ÒèŒl¥´“ÌödûññÝÓ × ¤ÀÖ~_ˆ(ï:?¯elð‹Þ[öä <5È CMç ëum&‹`Å]“Â&?²ÍeµÓ€ à}ú vÓÓñScA·Ã‰0-ÝééÆg5¦ŽNv¨ÿvWŸ¬¤n¤Tãp„®¶¥"[Üäíàâ26ÕÀ4w!T^ø*?6@˜c©=œÆ^ȸ ó¾Tuã7%æ‚MÁöÃÕî´î?;² xœuÕšE嵉4 óˆÇ”q'ê‹_…`ˆLtêË>Õ,MÒÁc[oºÅw“‰ßÝí#•{yéiÅDœñÈ·½þ‚ܤ}É„³íOö˳@#£¬ ¹c”0cvÑZVú „øÛEA¨6nÚ•‡î¥Mp¤Á¡ÊØ,Þ·bó‹S Ö‹Szž7Á+ŒÚï ŠñÈ4W;¿ÄÅH¥Œ}çõÅ1~@Cö/oünhËá=X¢öí/8Á©ÝÂÖ‹É7ë¦ZšÏ/¼†`yJÏèwN+IFy|&DÁëXa‡Ójg>ÀŸûó`w‡½M›·'¿ÂDö»„_í:üi{·ÁÏÃÇ2 2 €SÇ“¤““Ѓd@ÔfÜÏ äø°+0³ùRe4üìI©P© ÆYÆ&ø‰Š9vײYœ—‡gÿ?mðó©²­ºðš¿ûóWìáÿ¹ê RÁãNþ™ãÚùôo“d³íÝ?ƒ<çÿLXcendstream endobj 332 0 obj 4916 endobj 355 0 obj <> stream xÚ­[[WÜ8~çWèð²ä,x,[¾=’@f³3@–°Ã>pNŽéàM·Ýc»!üûýJ¾´JÝîÝ=s&4¨¤’JU_]Tí{Qˆ›—_ÜÌüÍo¿âÿǃ÷7¿|”Bbôá@ ÿI‘"‰%HÅÍòàè´¬Ú']‹ÙZ‹ö)oÅ,/Ž ýîæßã™d^ÙóžÙpªŒÊ¶/uÑê»w"ŸÏ b“/Äÿ~~s~Ö-âJ9LS/Ø‚‰4Ì"/Q©MÀdª|\gÆÆuÙz‚ÑÈÔóã̦¹yÂÙ#¥/K¦ù¨ÄK‡ hU5-î.ÇÐ{¾¹¢“aÒFœA/‰£;ß—\8Gëæ©(®ƒ«Wæid¯÷t:]à*qæ{qhÓr]„\I¬›a-òÙ·²²‰‚ ñüˆ1|Yèùã’Î>« =3j eœé¦Oyƒ?/W M"!uÊÅá‹+Æ„-˜“zçõ·Cœ¡ ‘1žàV¥1R|’aHvkK4ˆF‰Ú kL“1”*ödÙ3°ÉF·ŽÕÝ5zZÓÃÔS[䲪—_t{;lÿîèîÝ„ŠcR°&‹¼œOñ U^±Ëët>?}ƒV\Vs=ÍL…˜¥ØNïÞ9ÖE‡EØ$§bQ4­¨¦6¥å¥aànŠöòi>Ü̸»/?0÷µSe¸S“ØK6Ãùb­›g›5¡")U]-alÅì‰ÛF€‰˜l/0ØÆ¶ZÇÊ‹ÆÌ¨µ^ö6Í(z¼ì•¡øØ ®ñÂÌiŒT~à…Œ—Û®)Q襛B¨zyuvŽ.Ï;€O¢ÑŸí–³?z™A„Ðù;@ !Ëk©<‡=÷'T/:‘šo&ÃÅôˆ@ö ËÅ%“n¨¼Œ±o |¦>ašy©²étÝôéz8EXÔ¦ŒøÍÐÜÝA˜ÒÇéè &Î×µæÖ'eâÉ”Q_ôf§0`m«k-à ÜŒdqjoäWU¶uµK={ÊË¢Yš $ý³Ã’Æ—E´ñ¢é„E©+Œdù9à¥(gmg¾´Þ_ÈS”º1z±Í—ü˜ }¡)æÁ©ÙuG™—pÏÅpQê–_µzAjÓUõ·“‡ºê/^y´SC ¶±LŽï‰ãûm‹yÞë˵ZÿìUÈ$2”µòæ*ÞÕz¦™oáÐv‹þ™T£„}6Þ”KÜ·´'mãÊï!€ZÓÄÛE‘¿ÈÏ·J$38*&ðŽ”B‚ý웉FÈü!îHœ+³g0Ø‘ð|ÁݰH ¡Út{`'H¤½²ˆwĪP){éÿTº`6”‰kÕJZÔOÃŽ„CL¤²—ù/aG¼Tz¬Ýs#î½u$LëX3wƒN"ô–6Ý~Ðÿ'Aˆê¥6[ENŒ(\9È”IˆJ{| d@8qG”…H蔡Gèã¿}ܺRŒJœQîy Œ[ѵ w²3¶‰`HraÛø(ƒÐ“ŠòäyM–±qžx7HìóºÃÏ«,*š\š¢ -Üg ú !S]ëfU•sc|ºûIã›ìÉdäFU0ùxÀ=»¿—>°jgâ¹ÈÇxts(/NR›ôôó'7·„nB,.2¸œÀgã,ÃWy;3 2š‘'Þ¿Š¹~à᲎€í!_/`l»o0¤ 8žÜM¥@¶°å—HrÀÉè”GA§'›ñ¿áM“D:£ùYH‹Ÿ«¼èk+2p11BVÛÏ'àï컥[$û#9ˆ¢{©êâ±(¡dØPð!ÑsPƒaYòôkg‰Í‘D@u kXc³‹"¿„ êÃÎà"2eÏðÄ—jÉUFaYE*³¡"•yX—³Î>òzŒ•ütˆ•Ü4= £ñ²d/ö(;RêSF`Ï-Ýqª-Dqð&öR€dÑÐy¬òÖƒ<ŽÓY0¹ ŠLÂ×]²wÉ5;Æb›Œ)Y^æ³ñ¿Ñõßë§œ§B™—©”¦ªùmG-’cäÆH†¡DE‰ãæ x¶?RF>½?Æ^*wì|ðd= õRvG&–ütùñª×ŠP¦ûÔˆ0zF“‘T%ö¾]ôJÁÇ6½Lø{ÈÆµ)œÒEñ•ŒCcœ¿w|Ç btêí`;Q`Nn €,²”CM`Ñ÷ùì–M”íŒK­%jrá «@9 “|úàá¤Wë ãîèüâÃÕå ™‹QrtIÕJׯÍ!AÇÎ àÅ+idìs3ÃWTþ~)}l»Bˆ²¤ÊtçÖÆI–#ül\Øí5àYZºVî>Ù&™ƒ&*Û¸Ž„ÀzÛùÒĦ~v]œJ{œN1úû~[Ö‹²sRÀž¶š™0Õ8ñ¤óѱÓÉŠ²i뵩 Ý¿Nš´0I#›¿±gcx6m5*ñxtS£oé¶…»{çu®*ðݰWÅ£ÉÞ2ЕHuíÑ¢}¤èY;X“‘·(ˆšÎ²™/ÑiȶÁC_ÚÄÜŽÈ#6PØ_•–0nªä~2βÅöôzmmH©ÔCn9¹!*ÄE’÷:]Ýÿbi(ØêC‚Ì­Ñd¹©ùoJ„ÑVÑ 1q 3·f…¸>¿¸º9ÿúåüòìüúëåùíDÙ V¦lºU^޶KÙHBad[ÜþõõêýßÏ?ÜLs ßK›Šl ‹Žy–â;YJT õ°^pÄÌy‰bRsŠÖHjœSžŽîÝY‹á2FzÜߨ˜y>¥4üÂÔˆv}&BÿXSZloNjH/=d{î3\gpXÖ‚Ž„ÿùùìtúE,„Ö)6ý§¤Ü§ôH¸heë-¥3¶< „2ùr8ãø†¸-£`ĬV÷Þ©ÔIÆf!ôørs}~z±[2“ž ÙTѾ®úw×ÝÐ#„Ib{ʳ[y1ذ× Yš§j½˜‹eþÍuÐA¬ø´ôͤSø.ø~rz+jk/¯á1ö<Þ R cç䔃äË/Ýg]%G‡Àñ€.3{øÁÕ¶³Äx1:'S¼Ägã0ÆfHn¼Î1ô޳ióvmLÆè߬Ëè7ãˆr’_Hð$Ù8GyzßòÙø+嬬w‡6††A®Í¬{úáæÓeÐÈǾù dhDŒëŽÝÒ·ò£-F<‰„Ùd›m|âÙ§6á©ûê3væ ?ËžøÈD,éu)¶ucrz£2ŽEò=§ÂÅ„ë§<;`ÛtÞðÏOìaÇñ/óW“ÜcñÁü¬+mÝ5¤fû<é§Ë}MòúZKt¯+¦ñ£r"H“!,ò#Dè#®GÂ`o³üXký~ý@Ÿ=0K÷ã”ï±{‰œÂ$„Vñ.~gšŠM+„ßJNVÝȈ†ˆ¦BЩ5áeUª4Õºž‘Y,ªÎK’¸çá_ËŽíeÖ¼BDYGÆ ‡Ý)\D˜%6)Çû,öÅÆíZLïº 7ÛJ|9¹fˆ¸=ŠØ8òÌôx¤"½(eârC™i~hÜ`7ù²Zw¹h'Õ]µZŠq‡ h”twç¡ëEaű=aEØ<îv‡ÛE`£²f†ÓOQîíòCzá¶æuî.¯[ªéÏ”‘L¾gTˆeLÉz6åeå)W )MHd_`V¬¼L=-$Y‹DPÙêü™îý øÐCÊn¦{ô]fHnúî/€Àk9{ª«²Z;ýRA±ÃÔ¦ç.4 sÉÜÊNµï)Ç….©eÐQT f’ÚôÏn«T°qÓÓ™?åÝÝ;ê¤ü1=bÛ!ùÁOX?ÂrŸ@t”íNê†a[3œã½‹e ÅÌ@ïŽßð´XLo˜Š˜S&i%“ð@vÙϪf³u µþ¯MKDpBá‹v_¡Òˆ<»…¬ÄgãÜÕHuHÁ10¡<1Ç7„c]ŽB¨{½ãyú'ùq¸ÛCP¦6Þ•·ºwÿ=ö& Ù“=±7Ç3ÝÌêb…>Û;u¶²·<ˆQ¦Ph%òâ¿^žý~þͺhM• a©9wTŸ~¹ê® ¢Ñ,«²À‰LÉ|ßè‚Í &­ž”Ø^®ÑÔºÇçljgöŒmÉøô¦eQpÁP¯Wl¹L©¡¤òœM}Ñ<ÞæEû±ª/Ö‹¶@ÚrÕÕóö¨£R^ÌN)š×¦ÕË.ØçXÁ¤’Ð&6ñ]w™[S TòvÝÐvˆG]8ðôù¢ï@ÞƒÎ*0›âÜös –cI9½‹ |,’g7‘”Œeÿç&œ*¥èÏ¢sôº½b¶•[^ùMBm†>¬yKN«9f±–qa°&_j5ʘ|wöJáè)æúÇ€QöÑù&ÔA¦ìUn¹Ã Ê‘=\”sç¹Ó§‡‹â¥_#Æ–ÞJ2~kŠÓ®y™=Jÿ§ÊC¡â.˱ëûaM>\¬Wóþ+ ;ß×:çA´¾ þjÝs¼.¢" òˆ6d±?¡)­eˆ÷ëb17MC}“"šSž¥êzRnXˆ›x¡dÃOmGô¢dSƬ¡Ä‘}£“Ä¢¸¯óú•2#]–:†8¡½OƒKj¡[ÞÓaÿ%Þä»–ë¦%Àpò e¬‡³ìŒ¾_exÐõÝ"—¤&—~Æ¢(Yaà¡bFaJƒzeZúÖ ¤÷ºœmKämç¹;:ÜÓê˜"Ðå¼'¹yùTÕ¶—ñ)‡F—ó±ÄeŠ/½¤Š/B(ëù„_AúD¹á6[n&0RÉ~Ë=Žò²ˆvQR»>GR¿KO7¾'еܑ9Ï5µ%5°àª‹ÿ/¯Ÿ‘^häAŸ‡4Ã| °›BÁªZ|+ZqhþˆO‡ã}ÞåÞ·Nôì‹>õ ³7^J¦GA˜…°Æ!‚»#*,³ŸÒ‘fòªdFÕÆ ;ŸÒ’ ‚O c¾Ë–ìÓP¦ÓØ3Gn“êüä”Ûüx—SÜݾEuËë«ÐŸ/CêA7þå)¯é9µó×2_vùÓð/ÓhWŸ-U¯`ø…Û3+¡¬>Ü9£1]³Mß6 ìn¹À Râb4ÐÅ Š‘ùF–½ P×jµê^%LeR̪9õ^mŸŒÌ¯½ˆ?Oœé¡/o0þI=rCé®Û[ÓñV Ò ·a÷†ÃÝkÓeVÔ]a¾éRÕm_ ¬„P:»ìj¼£ÚìŠP¤Ü À‘$5&tiË=%nzá´žûäzíiüëSÐ@ä(ö¸7t˜Än!"ÍlÞâÐ)–SI2K¥M¦ßdŇàjèTk¦"n^@UŒÅ]8åøA.îç§9›zÞʾÂÄ^ úH9ÕÆoüB–tØÙ>>Ïô!®ðþdØqÑ…W¼õ‰dcŽÔ]£‡Ã‰‹bVWMõÐòðÁAŠüÁšö¿«ÊÌÆ‹f Õûð׿?ÿÀúÒ'6z¾„.Ìè” NÒçËÓL˜Œy;» ï·¾ ‰õ¬e)8ŠF³ z;¢/_à9¿'ûâD*êÙòÀôžÓçác*Ô$ñŽ_AÈ~ñk7>=> stream xÚZÛrÛ8}÷W ô2I­Íx{˜‡LâÌx*q¼‰7ÙW¥h ¶8¡H IÙñ~ýžx iÖ³5—’ŒÐhtŸ>ÝÐYÈ$b×'!»^žœY_Å÷'¿\Ÿ¼z±Ãw' ñOÄRÎÒ$ â„]oN^}ÙÔ{yýÇ$ÇAžå¶ÐëÕª$¹¢ªžlÉHÆA–;¢§¬`‹GG(É‚(JMïìæÅÕS¿nê³Û¢S+vkOá2 ’(¶§ìÊjÅú¦©n^z²YäRìÉ6[Ò˜•ëvÛmÓöؤ_=[5»UlG»ö»˜LdÆro±¢^±²îz€Äà ‚ mÛTæã”~­ØåÇOXUÞ¶EûÄ–ÍJ1(C³6ÛªèïšvÓì]¹g[EAJ{ÝSfL¦Õù½p¤SˆHØÒîx„‰3^°Û²^•õ}Gf˜tvÌ‘fÎìY¯¯.XÑ*XãÌX"N#ß"¥—Õn¥Œù]»|µu½‡IâÈëã-fù?œCò()í Î!9‘;ãÅ‚­ÊV-û¦-U‡‹¨û¢4¡/ö§/Ò{ÒŸ›â»c‘"ö¢ŠÆ_½ãC`½¸ ÃÐüiŒµ•ê<åe<G•—i„BQþip»dÏíx<Û®cÜD< 8¶èóN°Q\äöJ&.Gçq¢”ÌwïKŠ Ëœñ‚ý~y19fÀ.›^™kq0EÄ<ΑSt|U×rÄ ÏäÁS¸ˆ#Äü¨þq”u¯EŒÁD’ûÃísTÆåºq–Bç,±'é8.›êËaÏ4½á%ÅF¹w x ûÙ»|uÆEÈÔ§ýIýSVê³#y5›ªW#ùZ V,ÎÁK­5î{Žý!mœOà1ÜÄbà„VLÕĈ5€kÛt]‰¯Áƒaè_Iœ:ذǎ"(;rÄŽsÈ4vÔ÷¬kÌÉ'gÜÒ­.‘¨T}_Ö WõÄÚ˜*¬´%SÁSš;-_l·U¹<@ÑãP`ËÔUq7"z˜úá'Sàj\¸úø8é&KÉk}†n±4e=𺛋³­9êx;„\UÖßõÉ{µ Z¿V›¤Üª?wà49ßj ‘)ß3¾œD×£Mg¦7Õ•æ“säÅ)Èš¯Zè6žâjÈ®.«§ºØ”KV5ÅJ¹>FA?·–i‡Í \‚l.ÿ£û‰ˆ*¬,yÖ?m‰±­…DŒìÛSjlñz[ë#{PÔÑiÁ sëØn«»|„°®YuŽ™ b7ž2 ¬yV*îo^þU‡@rÜi>v¸Û! !éˆ|-kÁ_}-/ßœï÷ 8ü(q—ÛÔWËÌ4dÿïÎ@¤¡œD-ÇþP")tÍ]ÿSçÆr|(²iÊ8“x,»²Ù›üˆi:©—ç× 1ôñ|s«VÄX¸ˆ|g¾Ðt\ÀÁï dzÔCÙ6õÌ/ÌÝjJ↌ȅÉ+Cj¦hñG¼üÒ¬4(qóB÷Á)ûíµc‚˜Éi«¡€?eª_{£Ìn:µ[o‹`-3"Êǵ\üˆ“ ÍçAª†ÊT·j‡>p胰Ȍ-È/tü?°ï³à´‰Š[¸'¢w\`ìÞ3÷nMªÞmTKݾ¡‰Õê¿R%é\"8e”$Ó¢SmÛ´Ý!/¤ ØÇ²ªÈéuSèΠ3þ%šm"i‹òÑË'TîmhðEaêoÂÅ‘ž®vM^Ÿ~\t6ƾúè–%ó`YSõÆWTÑË•¹„‚bšôØñoÈü•á‘ò•r–<ÕÓ0ÁÑ<™€ˆÔ^þøÚ22¬µ¿ºœ'ªÎ'|s~ór@k²ÕÅûMUÛ¡Þõ­E“W7ò_8Ë–Ûuµ-Ö*Å›lš°˜ºTIz¡žÛë‚ ¸:âÛâ=¼ÀØû^F9BpZô}lç‰_Ý¡z2'De9Uw䳊|×`»—as‹¦™»{RÌ}>OäÉ$¡óݘ,Ç tŒ?Ê:à ;¦¦OSué¬&ƒó 7/ÇÊ‹ûÍ žšÞ¶Nw!“ôÜ2:I(£W¸iˆzd6£‹oxOÖ)BÃèJyxK”\NKíîï „–Ŷ¸-+XšÎk…û­qA) ñhšú¨ÜëÍ@I¢ÃêK.!çA¯Ã$zÒyôÔ ÔD¥µ†¶AV‡â„'ñX9¶ŒÈÏÇA}qÄ•Ì+7¶(šW3u`g. ë8{öÿ»½ÐLUºÛIŽ1ÏñºÈÔ·T5uË¢Õüø½00[{BEÈø¸.—kÝ´Ð ToUÞB¤,œ¦jÏí'g·®ÀÖ\‹ÄpL{εŸ¿£ñnKx'h©ÍÜ-Qc)Ê_­yÈ?¿žÙœiq¹9¡XèÏãÇŒU'189O“_!è|øjæÑ§õÉý²Ö&mŒM}\®5Íö4±IÉér6|æIk³ÐÒîiš>û*ID-  %øøË3í“oÝ·Ü L&v¤\ðXS&²ÆUEùà§Žýº+ûâ˜ÿ<ùó„flðÿLŽêÂ*¤îÞB­®‘·ÿ¶7ÁZl}ò•ÕØç¿‰Kendstream endobj 377 0 obj 3750 endobj 381 0 obj <> stream xÚ•ZYoÜF~ׯàÛڀİ/ûæøZ-9kk/À€AÍ´$fgH…äXÖ¿OUóªj’3³0âÈbUwu_UwÜ>_DÁíþúÿ=\ü|{ñÓ‡(2¸½¿ADÈ 1YKÜî/^éPÀŸ×·¿"¡ÑšQ7U½¿.›6/7öoy¹ÝYd¹ŠB•iÜ÷§ÈèPÄnÛG ÇOt†Š¦°‰)ñòfó-D’…2c¬Aûòdƒ¢ jÛêÒnƒçG[ypóéó¯=¦Šâ0ÉRÊüæ·ë è÷Å56µÍ[Xâë«Æ®Š¯E¦:õåëx‡S|}õõõò °kÎþõuØ+W¤1*—ªTšI¥ â£SO°ÉËàÎÍá®±lÙî^‚C¢ßW5;µ„mb‘ÒuðÔ›|·k@UÅæ4÷Ç¡¨-üÿÞÖUÑV ÀæÉnŠî ²?ë¯Qñc½ÚÌ5­ #£ý=M‡ÁÏ/ýyµÊüó 5ðlí=]5ÕaœÐïùa×^6‡#ÌD&…T”œÛýÐÎÜÙ›tZ=Ù:o‹ò!h^šÖîƒö>vj}ª«¶ÚT»¨*C“Ôõ˜·ƒ•òÑÕK°‹'°ž·­ó²yªê6hlÓÀjM°Ï_Ъƒâ¦`fg¹+K*A—æú½.ƒ[‚»Ë hѳ-³FU2Ñ~€±qK¦%[™ÛGƾÌr ”È!Ë0\!ð-™¤ÓÒìô¨&‘Ò“w5¯?ÿzÉq¦2¡ÜC ƒ_‡¤¸æñ ʶ·õJWˆaœ<ö”DJ€±7æá¼iªMW"ž‹ö2ÛCÁt›ˆBŠòsÝ' {Á¾ƒÞ×`Eš†“?çuy5Æ5‚™Žê ؤž§èõ4}Çpõ?ßq• Þ(éÑl ?”Ú%«/ï¿|¹þts"WE¨Ê; ü'+…Ê´Ã žA&\zHV}€MØ„L éȤ|yJGj1Q*šŽ®·]iÐÊZ*21€ìsR‘@ˆgÛ,83™0.ž†î^h1uáP0^[€™Åý ¦Š¢ž Tu<åu[lЧ®ç b[nm= ¢Èxþk ªô`hˆØ;™•/³ƒí”tí˜YYŒ°xþCÍM %pØzPEŽÊ÷¶í\¬]·‚L¡¤é™p-èã‹SÀzRT ±;´~êÇBŸÊö ð¾¦Ÿ8¡Ý™Cºà ]Êñ²¡Æì³x85>•}ÇlJ‰Š†ôgrWäöL+‡_ÜB-ݴé'=Qù¥+(ºÁÉÊ/‰i°¬#9m$Ôˆ ÉéE$G©’»©¶–v•i²å 1C¯? å2)(ñ|Ÿ¥¦* cÍØŽ´” p(gÿã¬ʧtûÔ"ݰÀ ƒI«« ® ÂaÚ–¯°š¹%žxÁ"’aÕ–msÊæ"†µå>msÈʱ ,ÐTV@ö˜/ìÔ€ RJ|y ß)(š3iNYÓVÄ4@ñõ<:µÁn„{–È;DÒû”eÐÇŸ]òÊÞ P{Dfà‡ý¢(!Kî{Ü~WKíq¦Ù…jƒyq›·9‚úÒڭ݆Þ$ì…N4-¿Ú;*Î}¢=ÖÇüš’¸T1×–€&X¤)[¬×–w÷4h §£v¿Êk§ÑeÈ*Þ®m É„„9¶|vC³ÇÃ;"h„ýËHa˜’`x«CÃPÑ"í[@×ÝOm‹¦íÞM@QËtzšßù SÇ£)0šá+óÄFÓ’}·«s2% Þt$ÄçD\(Æxâ 4Ö)Ô”Å>;m{¿…O2fHÏÝL;•™Öåx}?4lr‰°Ia~šè0÷õJïÜïà€ŸhJ±J`WTL6µÛÝöTLÄ35޹T3Æ)m U[7öûîßj ¹‰ÅÕ¸àÙÝpûêF÷³Ä!Ækó1n{ÍÌžv ˆ2M™&¥lphµ;õ¾IDJ—˜´òÖ-qäVCÅn¨@˜Á;ðñÌ¡f‘ù#”Ð=àÈ®®öÎb½ýû¼Ú]ÏA p°ãtÎ×R4&äi–ÆUeÎ]¢åÌ.àKúõØ%^ÈhJìÄí¾}úùïïßÞ~ûퟟ?¾_éN¥R¡æûÓ|g‚”’,e™ ¡V$S7;ôD$ @=í_“5CŸþÛö¯r£Ç b,²šsߪćgèÃó„6&Ùôv‹<]s°Â¯iÛà bBÙÑ!¡«¹±?Ú÷ßa‰#ÍJÃL1æ>™\ùW'øhJY”—ç`w$ïxSh%RÄXñZA\ŒchVc‹(˜rÐ{G¼¾¹ZwˆtÌàG†)Y ý!= öñ‘fÊV÷nú4^Î’ÏΑ|ÈqÎàD˜„= J/¥"À÷Ö»~iRF ð³«i‘^7$ +=ëÝP”e”˜ÈÑï³| Æ6]Q—uó”nt‡wðdÉ»áÙÝ"èuÜÞ5| htB7yƒzüîày"cJô½¨ 8üÞ.?PØ7¢„X‰gã²ÄP²Î PB¼,Û¶ö¯ìþKºYLO,µÇÅš’ÑPøpýËJK‹O!ÇG7òÈÊ]øÝ›Û7kó‚WMlxÙê:„÷·#Q\Aé1&Øì/ðeûyø1 vU‰ïwfÿBöoÿìøð§Ç‹{|>MÚŒ›OdPšl& $ÉÜX¿ÿYâ;‡i³…_8jþ‹Xw?û"óip¾$Kh+¼ã8¯¥ £òFˆØ“±ïv‡þÒÆúcþãâ äØÃß©ÄÍŒwö‹È‰ÛÑÓßÍÈbÿJØçOz!¸tendstream endobj 382 0 obj 3483 endobj 410 0 obj <> stream xÚZmoÜÆþ®_±Ð—Ø€Ìr¹Ë·úCaײ“¢–ÛD…¿0¨»•Äô޼<+jÑÿÞg–¤n†GJBÄ‘µ3»Ãy}fvCuyªËþø„ÿnOÞ_žüé£V¿¼9Ñ*Ä¿Z¥‘JĉºÜž¼2ÁëË_AeUN–YNvñåçÏß¾¼ÿÛù_/¿ýrùóù»ÏÄylèÔùSL>²*‰üqk¤1_þ.V“ á‹®R…ZR‡i`2A~Q7Û/׿ºU÷cQ­7®çœŠ§³4Áx¦º;§ŠÝnS®Š®¬+µ-ÔÚu®Ù–V*Uû}hU÷°sjß–Õ­gZÎFYØé>¹î»\½ºzíU¹¬Æ(¹oöÕÊK¶*6›@q­é( $ñ;Õîܪ,6‹ÊKÀ¢9ËA:m^s‘Ik8—括 ’Œ¯›½;["JâÀX!sµ‹/çób¡øÞ3UVk2kÉVeÅ¥²ä(9'B[ÚJ¡Ëõ`ooí!L@Míâƒ#ë¹l ƒ,v CÖ *Ezþ¥ü ‹±>ÙÍ[àMÄQJÞŸÂ(¦øžõ“a¥{á/—}2ËN<³(QŽ@ ªl½×AàÖê¦n†óÌÔ[BxK¬§çõN¶à`qŒ¨,ª…|°(ÎÙúÐ ÔG®´Û"S¬e¿[`P—`n‹8·Ü”×MÑ<¨U½Ý•›¾D´®£ÝÚI2Îà C¨2æ¯r=²D¬—Ý:ÝP/êG*¨nGÓFƒ†^]…a(•öjãT»ßíê¦;U®*®7n}¦Šv ÛUÑ:uOç­Ë¶kÊk‘­Â\œ¹ï\¯"5(`ÈJ&ª )yà9ý\ü›o‹82š¸—|F{údtj“6ã»>“ÊRl Ä샥¤ðJì›ë²CŽéDÞˆâ$ 8;ðÜ:i£$ ¢„êÇZPdÆæ÷òˆ©)åë×FöRK bÐæ|ýLµõÖ©\”fëqÌમ6ÊDþc‡òFɵ ™)rI¤ƒˆ¹|¶Èq*ÅÀ„ Mó 2A‹„ÑB:éûÐÚdËî§õà{ ]ÂKqNIéu0K,'fòò çÍxüÙZÁÍ\I'^»Õ~ëà‘Í4UÅA”eœ×§î¢mËÛ ¡ÖÕ µÔ¤ð=/r»P‚"TÈy _@Nt ²ã¾¡LX "q cm‚ f\ßåzdF¬»¾ž2”È 1Ðü@ÓZäJ@¯$·œfCŠ’ÏÂë쌪ÏðE â¶Ø·hJ¸ö¾*Ûù­q„€;Òh¡nK‰rà¾4Ž Åi®Ôæ·.=‰9R9º"D"ãõiÉÁ¾}ÝŸ1S З _˜(p¯Gˆ @ (%`ˆS;ò6n%º©%$á+„SÙÞüÿoö@Ðãh¡!3 ªù¼?|xU¯IáÞO)/Om„F¬©ÃY½¼¶¶uUwuE3•Õªq5Pã×¥Ùøy€‹“Ï^6¼á¦HyiΗ‹öŽªòàØ¾ÚÕû¦õ`¤ÀwxP-Üô•7j×@¨U½AKé'ú³üŒË©…Úðõ‡]ÿ‚,EÎB)gdÇíf{Wï7k¨¹Ã!«bœÌ!Å8ëž³‰Ö88„Þ&gêZ†ºŒ<ãdûŽº(Aá y÷Ÿ|+Šê²º#µ.>4ú+Æ*áCÂ]†Ó&FÈæbuõj!U¢«ÔBÔË÷¶EySNzõz<òŽŒ òPlû½\÷)@½)E]·ÅƲåÌã@ZÐõáU¤§¹ÔÌçã4!”ÈV‡¨»ñnäÖÔtQw´}9Œ.†ïˆõž_„ª•{vÖ!…$ÿì÷®·ôã¬#Hu¾\¿£Ç$ø8ï€Ü%uk[Wí'/w~¾ÓzH#'y]³&î%¡ïÌÜýÁ¦o<$[˜õ·}é“ òC ¼ìHÒÎ_Li(š¯%–:ûH¬ÓHë¦CJ-†6ä|q=èÇ4Ú¸ëº,C™ÁgŽërSv½ïù „-ÅG¢)¦ÚØæ{Yï[–åËuû—1Úf0Ÿw`†ùJ$èòE¡ãdô‡•$æË"¤?¹ã0`¢Ô¶è àÚ< 尩椇X:&tÉ™Ÿõm˜pbqÄŒ×4Þ‘à`M{Û5û•ï‚F#õ! ôÇSžÌFh—ãL|žÌ3¡ ` ¾ÞWA„°Il…ŽðñKšz>/måÖs Ã¤fÜpþ¦ÞÈx¤AÂQÝ·î-š¥(¨ŸÆnOÎ/O°_3Å©ÚÒϨ 8hsG&ˆŽ~1PoNîNnä%æ‘ùi?JÔ,R÷C®ÝÍ ŽAhA˜÷„ÿ®Òz¿¦ðHŸô ï#oÅ0SSe6Ù¦zÚà.¯vôc'úVÍì«Mëþèºg6Mt€V›“¬Ô¢ÏÉ ×Šc½x?z» j5Tº·µE9h•þOM.wóD¬‹¸÷•™ {;÷ž@„QCJ9ä†xf¸—Û˜wËÅ0ìgñŒø3v‡FýpÝøÔíež‹í_P¡©…IŠjïãmt«îê£ršsúûþ¾4/ûžv@\»Cu§îqè‹î7Ú8¦ñ¾Pg5@=äåÙŒá%ÈnŸ#C0®—~çÆIÚ‰Ý$ô$ C~tX§OãÄÍ$¹G"hô–·" ÂÖ“;ÝDÚr¢'œÜô¹˜·OÍ Ê_Š9[ÜÚâÃ-­¹vËs™4ÓrcrÖ¥Í3ÐeBUõ×Á–®ö´ù#&”OÚ®7cû“„‡Ë×ù¡³g¾y”áçúÊ$@/ÃÏ–ïb5ZßlzˆL÷sÏ/ M3yÄAÛÇ£·X£BØé1Ï¿¡;u[yÐ0Q—H?Ik…¶$ÒGQ‰r±î&ÓQôiYÉ£e÷wåêÎÏMï(ãÌ.h-½P눵ÞÜ0ÓžÃ>ô²e ŸGptU ºÉ¬Õ7þlÙƒlJ<Ûb ”¥h0_Þ+3ô,†-农Wõs^18þ^O¾bHÈ2¾×R3}¨Ïâ“eó´Ü$DP– Y“Í6 œÌƒ¯C§Ü_Ê×/Ö,¾~Ñt¡g_pëGˆ‘9Õhd’œ³õ ÿtFLO")8-͈Ña4îÆ5~|èï£VuCÑT#GU·/»Õ_?Ê©®^ý«*§:­†·7‡ùOHo<Øù_årNùzY¡ëøñÝŇ¿Ÿ÷n@J×£Ò©‰—5^§éÈJ—GÏ›Násº±œž´ýSÕvÔ°<™³èÒÓä±Ä¦œ¢nŽ.øè_ŒÚͨd€å@J¹æë®ZL¢Ôš…ÑÒ—<™¯ÀµöéG!ÝK„`=8éSÑÚv7Wš¯<1ƒ I±N5F×¾y(Ö‡ .]gÏŒ²t„‹8ÓÜÃ"Fú¢€DfÏ­`› °P‡m–è’P,Ñ% }}b´ô”PÑë³^]t¹C ïš’àÄðtˆòß8‡\~A†0C±Í[€ÐÕS)×ähí‹z|_w<¥Š©YãÄŸÛÛ¯EÙ}¬›ÏûÍ›¹BGÓ ¸+w›áv¦]I[?³f|W¯}kªÕ]SWõ¾Ý<ÐoÙ an¢äïšÑ¼h˜r<)¶„`s.Ťì‡ô-sâÖ-ßZÁ—Ñœ1žg†H¤(c fSÝ«×Ë¥¦´9/…f¶r2_ ?nöíÝçEàó˜®xžŸ”÷H_°5eá4gíËÞÂøÌžüvB[ü™ÙQ\XŠÄ=úEèÅíéùïŽØfw'_U…sþíQœ*endstream endobj 411 0 obj 3605 endobj 444 0 obj <> stream xÚ˜moÛ6ÇßûSðÝZ eùü°½²S§ëšÚ™ílP p¥qëØ©-¯(†}÷%;>R’£¤ E÷¿;Š<ýx£Î:EÞuXyñ¥c±œQ.É]qm_-Éê†ä·ØþÁÙ÷”[…BLÛlCæòe µ§2ÊÇ1 †ˆÍÙFR’ël3[ÏïÃ(6aÁ¯¦¥‘Ô+"”Ú8_gÓ²à>½øô²ôMç@)G îŠ4$RÆQåkó¼.&;L4ž^ëwÂq–w·ùê‘ÑpÅiäFn¶ËYñø´ô•H×Pkê êƒ^QN¹¢QÑ0G7‘Œ„qŸ¯#˜e"[}ž/¿ì_ÖúúÊVõÓ0kžQ¦‘´LþHpea±ÉÞgdS1ßä›]Q’›Õb±ŠË žC"¿†8e뢜-ߊ”™ýI@¥†Zõ¶Ä¦·Q²rc§ÞcóX.¨õÇ`‰5“„c1A¬Á%T¦‡Çð`Þ§ÊùhØë7Ћëh‰í)½´l§ô*“5ÒûÔÑÛ+ùìa;Iò5Ð{¤´Ôæ°é”´¬-r­Šyz&%-,ÑHI[LÎA˜PRPÅ©¥ä1HB®p„^Yþnç¨ÒްÖÏáOÍtÒ0–!:éZ:aYA§ñÏåì<^NO™s‘rµ˜Ï"÷04i~6®«òšŠ–ôBڇхì Ñ9ÁZìÕ_ŒÊ(Ý“ø¥$y ~©ð:Y„«êRÝ’_Ê*jä1~aEu–p(€»±øRØÏ¾Æ—ƒ“«“‹Ñ¨?˜ÔëSb(ö‘„Q n¨‹uEºîÙYJª<—¸àT@ÝÔ\)hÆÔs¹!4°PáMà0@e‹#­ŠìÍ VÞüH/áé Ž³ÈÛìfº]ä‡ÕÞ#„5O ãû #DZ@#Fˆ©E–Lc8„¢Óq¸o58Ú!Ö’H»Kÿ­M‹ƒÜžÖã Ç'AB /!!æ3¡rc§n ïˆ: ¬¨™&K€²™])1èž|¨ô8ºØ³°¶_Óa{JÉÀ–¤Èõ~p:¼Îjšìtùª:xáÁ}ì¦Øî@Õý™Îêæ3€Óxî¡NØ~ŽÑˆ eeK8*™Èþ<ì8C%38NŒT?Í­‹0g&Šò ª®’…æ8áâCÒVÙ8¬±Ž";T Î(p5É7üü5›åm3JÅOqÆ'G!,• ÕÖ‚Ë °Ž²ûé|Ý[m—×Óu\>йȡ¹ýðŠ8×­H[@S ý¢ñس ë¦^á… }ð|^Ã!^íð*ApDÓêRݯ†&ì1¼bEýTápаI^ÿÕ-ìN2Å^ox1xÛ]^õΆ'5ØÃNRrhÓ¤G«ƒGŠ(ݰ÷Gÿd’ÆS‡dß18 7‘Ô³CÁµ"w(òm"4ÓB9¬Œ( e>²?ˆáM˜êCœˆñŠa"ƒ3F(`ê,rÎqÚÛæÌÀ®€ƒ$œ‚Wh¯eäuØ•5™•ŸcŠëý¥Ãße*‚0ú;|´)ýö¹{‡< Ø_-œk©Ř8¯ ĆÏ~÷mœáT>¥Woðäc»/ZŽÅ>TqŽ)”¶²`·áµÚw ämƒ ÖGGª¸ä e,²g‹Õ}¶þeCÞmçeÃùgç{'xÜÁ¯Sûá†#( ·rƒÃ-õø^Å»íüM–çsV´Nendstream endobj 445 0 obj 1542 endobj 467 0 obj <> stream xÚ•Yks·ýÎ_¦*Ï(ÈØgÓvF‘e›SÇN%&™ÎhF³"!qr—Ù‡eµÓÿÞs±/`¹Tœx⡉{/€û8÷\Ðc«§…ÇVküõÿ?.¾[-¾yã1!Ùêa!˜‡?‚E’EAÂCé³Õ~qæsÁEÌ_­~$„s)BGŒ}(ÊýÅÚ "žÄŽÔ¯YþxS§uS‘à7oÈÖtoqØ&éÕV³VÎg1W¶`âq/°eÛíϾ)[­‹¼Êªš¬Æ~ÅnWØ·~È#[ã {07{]¦uVä%iÇQì“[Û‹«Õ· Å£ˆíés$÷¶[ø £ðø‹Nz·Ø.Ü 9€ì‰0‡¢ó0ûØIÈGbÎA¶1¢I+ú_Çà î{¡ê,}¼þþîâòŸwË?]¼_¾vb :Òç“ÂkQ»Æðß`íÍÅòý׎±¢®ÆÕÌfÖòÑf‚'f6ûáêÃë凹Í,·ç3Ž€XLqóãååÕÍœ5Kúfz¶kÇÿ÷íÉzUÀ}¨‡,¯uy(umr¯ËÚJ³OÎîqÀ½ÐVMw®XV±ÇÌInéóXØ‚ŸÜe”®cGç8)”®Öev ST}ñœ(VåKË %ã[]Ûùx{vûjÞ ¾ñÀ9{hò5íÌ[ HùÜŸ:ÎK¸ßùÞçÒA°„L)G„]ü°dË<«³t—ý§õnšoØÇCWç¤ÿµ„£³± ŠGØ%;¹³[ÏóÜž•žªÖrjS°)¯œb–%¥²íÓiκ`ëR§µÆYÙWY^Õi¾Ö_õ1–eQëbÐzÌrÍÕ¯·iÍöÍ®Î;ÝAÙ~r.ùý†½íŠíÓgv¯»}7ìþÙl•»lÝú-{`¹†h•–Ïö=”'xäŶÙsvïHÉš…%ÑÔìQçÂn÷ÌŠ¥Œ\µ£bhÏDž(õoMVâzPÜÕöŸ‘»f£ÙßrꂇŒoÿ1Ac¸Ÿ¨±Uö~y hëcíS×Nõèeè(ÜžÝ(ÈÖáÁôô’ÊÜweV”Yýü]QTõ)˜ àÞØQcgé®Ò·¯¾=\?¸ ìàʹàÚbìõþ,zRž„E_)Ä,¢T{ôî ¤"ìJÈ•Îâ–Ac‚<€Í€.cïõCQ’ûvä-tiûŒ@ìQ:µxtç*(ÎîîJŠ ÔøRôbýeÜl*½áÌͨ€ ÊQëg—ç:ëY½5Žh݆že±Yï““‹¶—¡ÍTÏpÉÒˆ€ñj‡æ}“ äôFh•ýŠÒ²îT<¡J…?;ë *u½nL#Ÿ8)§|[Žú)XOSæ@Ò 1§¶Ò|!ç¨Â@#œí\>¥lRŶ*;¢ÔÁ«æ¾BÒyíÜÆý }çÖìk44¤~…dÖ½9oRÆÇ«$굪f½=9)Öj ˜Ôõ­ÓKÄME–ò9ÓõšO8HB³‰%D!) ¤§¡,TÄ -­$; ‡ŒÁæ,vHËt¯Á|¨DB÷ØO[0ÔJ×DŒR7ˆ¾¢‘È’6!¤’)”GuÐëì÷ÑDW]‰ =Q¤úBECµ3ðïnC³Ne_È¡²ÉÙUõ6{$ðéÝĪõVošŠ–³¹Kâå&ìíÜ »&~l¯g¹’ì°Kkñ¾:Ǩö‹²ÔÕ¡È7ÕPÿÉðX`ß+Ðþ=‘‰1Zˆ¶ìêÝõÕÅë»®—¯—«ß­–ß_Ý]âãòòâý| H‰qÔw¬üÈý˜gŸ;üªZ—½8z$ÜCåZvŒCï#guùÂè–êËÄVGé,Mkà@‰ÖùÌŸ’gpý¨Û$اŸ³=&õtòÈ@O%qdk<†9–8Â7—ï®^ß½Y¾ùxÚ›ÊÑó+£Æ´Ñ“bÇ€$b[Š8×¶贅ϪmÑìL¯ÓR?4ÄÑ–à-mKnQ† W±–Q•f¬04þ¼ó-Ñ¿‰sýL7ú ó uµ9<FþRY%4^›’é˜+aˆŒeœº©Àß»Z!ÈߦΤäC¥ä^´Þ œupãÊø1÷„³±.ámýàrJÚRz]W†G憥¼3Ìê±”æ5Z h¨œ@¥ÿt’&Rti¢š£‰¶»6 Ûmí¾&9b?¹ëä gݼ]´ÝQ¨Ó,S&cºÈODž#ÐCÿ© ¡q´¥aÞz–nV.¯ì—¯¹jÍÆÖnÔŽ½˜,}8.7ß9a¶kÊIU*dZâ9†©,:ý”íví„ì¦ hQ|d†ôŽü‹¦¤Ñ5<—D2ʳÉÓ‰k1SZëŽã'‰½Š}Ó{̾ÔëÔPÃ<= Kiè³°œ…m)3 cž©Ë£!o"é"6j1¢ [Ï_4LK…B± IÎÓ¶Ø ÓáUª¦%Ìš¾è¤¿p˜–(}ñ0-0{«nöþTd›ã—i[b@ñ<7>‹AsmÞž¹è‡GOðÝxm+ ØJ¿4.Ó0EvøfÇe[lf\…: d"P¿÷óGœa¢Arƃ/°ýÄÂŽÊ#~dû½Þ`”Ô@jÛ ±lŠ£1È ͧö…tcvvÑÕ“(Ÿ«Ó8³BN,*I:Z-ÐS]ú‰ÞaÌhè’žú#Ýëã‰ñC(tÊdÔ̾`”ôø7hÌ]Jbš°§Iöѯ®&Ï£iÚ§¿:N  ™£MÍòÂ)Í­µyŽ[ÔÜÉvjÇÒ’$CÚçËX€Êþ‘¹X€–…þ Æ€Ìîë š÷ÅhxîéD b€£bT[³iE‹û_ ‡I«ªXg†úRŸÕœ½s³ ‰K¯½¡'—hz€(5®ºüJ€ØÅã¢Mj~0®ž?hƒDÖÔ]KýuŸ¨*™tI¢2Æ~R¤6G/%¥ÞXQ Ä ôZÏ'ßdôÑІ4#Úp{VéÓsœŽÆ(À¹k£þ„¸’Ñ h úÄDtc%g7¡;¾€9ˆàáQõö•ÁL4®^Âc_SžlmXh>÷cû7Ò£BÐù7uµVoìoˆÔw+‹oIx+bî.Í„<:}œ=(NºŸq¡ŒöaýŒ{ü…‘v¿ýöXÃg:˜}&¥äGX7¿võœ½Ãí]JàH¹¿Ø¡­Àìu½£g?ŒAo›l£»kþkñÛ‚4öø;öûゆÒq¾ðÌq[yû»#ËØvñ3˱Ïÿ,VòÓendstream endobj 468 0 obj 2664 endobj 484 0 obj <> stream xÚYkoã6ýî_A¤6³H8¢H½°‹f:f±v§ÁöK€B‘éX[YR%9©ûë÷P‹W–wg0Ǽ—¼¼sïavÿ²rØ}‚Ÿñïiõþ~õö“þܬsðW°Àe/¸”»ß­®wñWò7÷ÿ=ŠGñÈ'bì«nöUΈ˜Oš´ÈÙ6®Y^°ª3ᙜz\*[ÓÁ»# àN÷]u¼úôâ‚{J)ö¥¨v?5Ey—×Mœ'úáúáÍqÿéüÈå‘åZÉÅœkm1öÓ!/Ê:mýâð0•‰_÷áiõñ~eöõàDÁvíçPp±lå¹’»?óE'­¶« ÍÅB.§6°Ô­1ߤy’íךý=ǵߕ)ßþö¿5E!žøs‘®IND>ˆÄÔ{ÄϽˆ?\Óè Öé~Ã^ßÅù:#;ºàÔB–á‡7[ŽtyàÙ±sgcg‰±ºNª´4iÚ…Ï CS‡³ùí ‡GaŸßi=&xºÛéu7:;°ΪYƒüÿòÃ×ïYYM‘ÓùSšk,T:^³¤¨*]—E¾Nó'Ö­ÂSj›«¤Ï}ß·O%¥£P¾ž ëº+𷟼iš(O¶•a §'Q¸u¸tÅâõ½(t˸ŠwºÑñ¯\I[Œ³»†ÅY]°²¨›šÅìj½ßíW€ƒ&íLuûƒ®Ç¡ÐrÄ­{iŠø ¥EŽy¦ë\²®ó†ÕÆÅqÃÒ ‹qøVWC(ÈǬH~%¾5n‚ïíMÖ ¦Ä,‰³Ì¬3õ¤•@SØš&å?ëæ‹þý¶÷²ë)ãeÛ·¡?ˆ7ŸaðˆRÓH7Y,›îjý}^Rø¨·™Žk½æì;0ß°MQÁ ;Ívû¬Io;q\k_ëš›1gié9îÝwæD»vñ¡+?t§7:õŠ0 gmö‹M.”°0Ý¥y\™ªÑ¥ñjoL%EQ¡2PQíêí¾Y¶eR†Ü#û¿ä¸7n©‡0ÁÄ®x.\}]X»˜pšª8ÜåCÄ|öô^¾;hLûÊRÄF N±iW@$KàÝŵd´ÀÍ}bÁr›Úâº!w}[×xÉx ™$À?RM‘cËX©;ÈÒ4ä‚Ït9âQd/#ÁëphY¥HL„(m:C0/ DˆoqsåÁdo$€ÓF•+=íjqA’dY¯oÚ¤îq®ózžsZä¯Ö/æ)_Ùº]ÉöãQL$×\¶´L¹.$‡ IàQaÖ Ù pD˜SL0Íw÷h?oá_ øœæt6@'¡­ö<º^ü: #*€€( ((›$ª píÈ?ô.’ÓK{(7åÛ¢mýèºÆUÆ[)0P¢«‹Ä´}ºÍv®‡cäPû%/('âÒ!ëpíЙW¯6Uñ‡Î¯(bxNÀA‚‚‰» tOB'ŽØ»2Ó;$¨AÝ!|7‹HƒüðÁ¬Œ«¾㪹mB“½D%n`šÕûÇZÿ¶‡%À{´…µ€«}¾©´þC_µX„i¿ëšÒ±í{9GÐ>ŽYE©«njx¸ŽYNçUôfŒ£–Ú‹5$øÐô Ø^O¯ÞðÅiS…Óis–„ÙbgH˜-6GÂìõó$LùÖú§H˜¥yž„)pG$LÍ’0[ŠYCAÐnœd‰6ñ4%@,ï«yžf‹]ÄÓd?ËŽ§)Çå¾°hÙɽô….”Ã}Ÿ(š¨£I63\Öõ©ÛÇQª“7WoÈø^㢭ˆj±ã;v׈_‘Ögžö´Ì3Ë$¸–k‚3ZñúãƒyêQšy|ˆ›InÏù,Œþ—J¬FÉêÖ5<×çiÙ–lÛÛÌÊ”j(CàÙ»ë}áÍE¢ÑãSóp\7U;«›mæãäÑÌïÓµî¯ùïÕo+£±ÃÏP æ‚ksO¾pZs;yû»k³íêg–ãœÿEªãendstream endobj 485 0 obj 2384 endobj 502 0 obj <> stream xÚksܶñ»~ÆýP»#ÁÄ‹¶ÓÇ–·±ÄrÜÎhÆÃ»£t¬yä…äYÖ¿ï.ø8,HžäæáˆÝÅ.°o »º; ØÕþøþ½=ûáêìùë€ øxs&X I…‚+eØÕîì©æ’®ø³«ÿŽ "Ð< û-kuɘ<Ñìw:ó@ù´8d Â\<0Èðó×b†A•pZŒ«mÆnåºÍ«’Õ–‰Ærñüµf1W.¦µ­Yé/!"ò êÍa½Îš†¥åfi©.Œ‹x“ÍÂ*24(¤·Ê»E2V\Ä.Hš‡:ãd£•øÌ®ga¦„غ*79nÈÃv›¶ðGÆrø¼NÛlÃ6y­Ûª¾Gzž‰{2nª¬aeÕ²Œ²\»`ßò¦eUmÙוÝÑu›é•äAþJ§á{âNŬÞåMcåi+vWçmÆ»íéëQ x(õ¨è¡§æ‚­ {WÕ»³ö2öè}k/¿fe{ýôúÙ¸¾¯ÇaðÄ1´‹9CsÁ؇û²Ú7¹µ’€ÇQ¬Ñš»·g—WgHW&àwöw˜p‘°âÌHÅeÎ|è ‹³íÙ õ ý¶ô$—FXfþ”—ëâ°ÉØßKØ–ûœoÿáòàZ‚uw૪*ˆâ&!Oĸ»ýîÑM¹‰ øõS TŸÞ›²iÓrýv[c“pl”CP{ø|Ž<(¥ŠŽä'|Jr¸¿°á/ÐúN-žýmY+МW+ä¬V8`ìUÖ¬ë|†Ü)†“E÷iℲwyCügSÍÖ —Iì¢Fsðãî<˜2ÚvIéÀ¼’¡ ÷­eÔÚA¬œçÒR2ˆy’yðaéªÈØ»÷¿½EgÒVkаÌ÷‰‘‹T•0<È<»©«Ýà¢zªåm^zŽW+*¢šõÁÁøÆ£âÆ=È'ºp¥—.ŠÌ}Z§»¬ÍjÖì³uÞ-){”§×AР3KºßàØgvÍÊwn£[»,„Òškãr2¨ô|S1¨pâ³#ë»Ä‚0ÅÈ™h´t²FZ䶯ò°†ô@K/Œ§=OÐ\ˆÑ°ûB….41ã™l@)P!‚ÁHÖ­  éÞîfuæ³Îr¡BËØÅüš—·víîSUW ‘ÃSUðך̣ªæå ðŸ¢söš Ć›€,—¬©ƒœ*‘íèÆý:+r+Ù¨"Õ¾ÛýÙˆ“ ÷¢Sá0Œü³ÝÎ9=w•Ñúžf[Š Û¥_¨ÑG<„ ÈÁϨ˜Ðè6ŽÔmHPÀÌgõ=KÛ6Ûí[L¦^Oh¸HJ BÊÎÐØÃ…„ævÙ‹OO¼ª†Ø±´¾6èMɯ¢tUÓÂIU B®‚} Р­ÕªMí9oFbì Ä,øõ±Ì¿avýÓ‹w¯~¾´Ÿ¨â€C"´?½y§äõ3(nò­½Ï TÓ=ÐÉhäH4mîËõ¶®Êê€j·?´Ï«C ÿ^Þ<¿Kû»=…kËšû,ÓjJ±¬H [îK!:Ü5Yþkyµ-Ñ ›ì’âR8䙇XGd>/•\d2–°éšKóöuU_ô*'¢Äßîx´ì·‡¢Í÷Eö~õ_¬Y– ¤Ïë¢v»HsLc1!rÀ0gq´ l¸ÉoË´€ p·ÍP×þW¦ Ú€„Ç]ŽºÒ\"ó6¨5PÊA Z~5í<¨ÿ©=Nˆð½Í]ÌyBp®#X6©Ô& =÷‰ÝåÀV¬Ö)ñ%OG˜Î¹«Í8³E€Ö±WÌö`\°=l®ãÎ=0-µ\Dh¹úóøL¡5rÑOõa(&ÀƒFÒn ]°.¥#@Úð$!@~áfb.°¶Ðµ}nD²™\A+È'…‹E\GŠÈ|¶9?ÕDRPîhGŒ]$Š@¡Y~³¾Ë(WŽñ9ífÖÄ|Ê ‰xdÜYTLu—N7±cã œàv‡¸kuÐjâÝ@ÎÈ…ó[ FÛc; öeu ^þA/—ßÜCé³A™lB2æ|Ñ4!G÷LSÏ™¦ Öц³Èo†|ך?Uc8Á˜â]ÑjBq(6Ýùûý`ª:Z6Uuô?ÖT«¢¨(Éí8pw6DZéVv¸'}¹¯š&ÇïK-P8§IEÞ‰úJ&1ÈM0h=¨@«L¢\뤬uk£-J%×1‘ ùo²ï fÍP—¬²9»QÆ)å¡6݃‰AÔLíVQ?k[´ü½í·Ît\ ‚A°q iÃ%Žy¨ÜiXou?)§¾æé©UŽŠÈ%ãG¦åp¨Hž…‹{ôþ¦­1tHaäЈäÒØaÈŠ3'.‚ˆŒ•‰p `|D}ŸÒCÙÙ¡C»›¤±î»ã.€è× 5qAZüAÅ.‡ä2$=å°Þ‘ÀØl¥8GF¢äJ!=)¥»s¡»l/†’1RäP2…F.Ý1rÔƒ»±]p@ïF®ã  ÍGwŒ2ŒkâqëBgÍAˆà%èÝq¤ÜŸý@dÔº[¯—a!ú5&D‘Gƒ<º¬ý*£ÙQ w¼$0îAt#_æSôâzí§¹`gžÊÚhQ¾Áeô}° Au‡1qÈ'=ô0v•ßCÚÍ“5’ºÌ“.Ôî2ÃÑÌ5Òói'Üĵ»ËŒG3K÷ûüï~q{»ú™"¤`Jó(²1ýdÅYmsÖ. ˆ¦ÉRè%KíÛ¿*žÏE%¶kPD B/ hCW®Cãy×¾Øó!ó]¼Ëð›ñÒ+ ]WÕÎöÁÒMwѬ­Ó²Ùå-«ºž 6V˜éöýkÆn¢7²yh·â‡ì€e\UÓSr §âž³üÆ&b[{Ås¢vRBò !ÈX5|~ÿÃ?/_^}þpõÛå‹·K5 xEº.Š~K.#´¶©ìѦ2Þ[J2•v߬]Wu5ûʶdÆLxî†X»c¸ú÷ç_?^~¼üüû‹—/Þ½üOßôÒ±­X°Á¬ðUʲºÈDù7†FyïÆ0±×s.>hÊ“îÔŸ°G\š›éM6ISÀ¾2@¢'š¶ÎÒeˆ=¾¾™HË»Ž±±hŸXF%MB0¨¼ð]i2ß÷Ò°SµÉ›}Ú®·ÀÙ¡lóâM5ð6zéa•ð:/²ËÒZÀr‘`ÞÖÜsr94W:;îz¯Ò6}p=C±/îùÐ×­ ¤ÄÂ_êƒ=²Oxž'êŸ8ä±&¸Þc($ø@ Í‹\Ì:=4Ö¤P¾°ƒ«šTŸãf™ÑÚÖéo\ê^óØŠ*˜\@àô­QƒM€zE$ñâZÞ;LÍòþPF'ü|váyw O2ïûùù;lpµ¨ñÞ Tf)]jwlš5ö™íN_ wðzV==rÿÊh¼.÷DÖ)¬u†`ƒÁ¨?VKƒ³77¸T‡kêR/ßþr58Ô Ö§Ã®›ì©Ðˆ”²¦‹öK=$k!šT”ðXÔihRØ2‰ DCS xù…Ðļk@8s¡éA¨(ÝÎÔì÷9€è؃~Á R¢¾½¡ŽùÈÊï`a*å,I-V†G‚€ÅZõ_e°AxÁc;ªÓQz¿iãn8„Ëž\¯¾r“€×Ëpýôcs2½ÁÒ‡úbv0NÀ_K‘¸ØÈIwTÆ,W†³Â— lP [bmÏc¨÷0Þäå‚wËR¯9ªÂkA(Ý5“‡½øâßÐ!Áʲýè²&)½pa?Žïä¨s±ùOàMŽƒz熞îœàe"ŒÁv¶ù-äÈÀR]n·xuÛ]­t#Ü4o~gͼMIPJy|o«uzŽ*jÛÉ×Ïúè¡B3gjœ^pªJ‰t&U>ræç«„ëžõš-îÙð¸cŒ;½uT«&«©¿Š±“O$€q{‡ƒ—³ñE Ó};ß<°¢*o{‹¶± ,ms? v~]íövŸý'jøx‰¾²NÓB#ru38‡È‘d°Ú×?üðÓç—ïßþòóåÕå«Á»Ñè]t—ÖË…p$Àëö4Þt8+~¡oúƒ´îòv‹1¬óŽ´õsT{|OêjEŸáãháò…ïÓ¨ËMÀÕBœu`R|ý¤ÏmƒxÙ`ÀKÏ¿k4]'è8·×ÏŽ*:}XUÅ2MȆÈÌ[gà+UZÒ»x0Ù`ÝéQíÓ,7ƒ¼¦i›±HŠL’9•=îe6ܲý¹aվϊÀûæ-Í P•Àü•ÞA*¤;€¾”Ôk›Ð¾¥;ÝA6}›íìãÎ,µO÷@§vUoZ|6^æM›¯‡d _Oʼnåñ¾§ 5uK Sî–6[ã§ÓzÓœûÎ píú×Ußõ àaË¡Bíüz×Á;'|K•v/©®Ÿ¾óµ;$ì½ é’‚zÛ~ù¯‹þ²g€ ؅Б×Ýësû{ø»¯Î'CcèXuàþW÷8Žä‡+'/•!EÌØÔzÂËN”1·ÿ % v–œù`¡é‡Pwl¿û~Úñˆ5×P„GÉø¿%XoóŠêIÜ÷¬“…ÿ·KÈ€ÌgÞMƒéüxÈ7Y/æ¯gœ!Æþ„š´g71–ÝɇÀ²ÛÁ»ß&±íÙ'VÂ:ÿ|c–endstream endobj 503 0 obj 3864 endobj 522 0 obj <> stream xÚ[msÜ6’þ®_ÁrÕUœ*›K_î>)²6»·±œ“g7÷ÁU.z†’˜Ì’#­þýuƒØ œñUªlt£~yºÁ ¼Ÿ¯ïñ*¼4óEîàO?’8Jboæ™) ™ŽÔlâ{3[ž®¬5NG ?ˆ6ŽÒÄH ïÃxF"ʀ凡š¯×Ã,' °8œÀ)”ĉƒR%Œ­…a«—É F¥0{—PÁZ•8AF•84W ¥Ôª† ”"djã©¢¥˜eh¶f¡ôREË™(’i*X«’)F ¶Pú@­*³•ÍF™šÃ8dªh)fš­Y(} TÉle3²‡ <ª‚:™ù°¸ªq§ Nb†T#E/Ã°Õ eP#‡R„ôT˜$T%Í©¯à™{ V5LàÄWÌ©¢¥˜eh¶f¡ôREË¡ÌW˜$PEHI}EÈ„›{€«'P I}Å ©*FŠ^†a«Ê *FÎD!¹¯0I¨JžP_Á!3ö@­*·•Í%õ3dªh)fš­Y(} TÉmesÉ}…IUbXñ2óapUãNA|Å ©*FŠ^†a«Ê *F¥`¾Â$*2¨¯à™{€«'p â+fHU1Rô2 [½PöU1r(ó& TIZ•$¹ù°¸ªÄV6Ñ25‡Àõ#E/Ã°Õ eP•ÄV6¡{˜PÁZ•”å2óaÔªR+¯$)Ë+fÈTI­¼bØš…¦V^1r& +¯0Iˆ»¢œ¯È µì>QΕÅ|é!C_ZŠ_‘jÙÀ´JÁ|…IBUWB?•jÈ\cöW6ayÅ ™* É+Œ-.TâB+¯9F•ÄÊ+LÒ€†‰}Í£[š÷Za{Ä6g_[Xs²š‹5L-¨¸€z-Ü7JÃÖj)g ¨Â&„gYØû´Ñ·4#khÄœg<™°ák µ˜3HÉ ÑŒ¬¡s¶X‰{B†¯5”<ñ.a+‹N)Z3²†FÌ™„n¥´)_jFÖЈ9“]­ü2%/ÍÈJ;?,¤:+ØO™Äðµ†ZÌ™¼cEÞ)¬¿åC#æL°Âàc÷vŒµÄ\Ry;õçùÒØn\V;ÕáùÂÕ)Û/+]âí|]éTÕ—U–Nmu¾ìsŠÞË ?§ô9_•95éeu™S™œ/šœ’ñ²²É)Î×4NEwYUãàúó%‡Sp]Vt8°û|EàÔC—Õ*>Ørå2Èî€ÖóxÚ©&.CÔ¦<w°àu ßy4ê`q”D•J%ƒ>³©ǬDXjlÚcK†RfާŒ¬&ãz×Ñî·R1&„Ïò•‘Õ\ï :Q&I‡ðYÆ2²:të-;§aÉ$é>ËXFVm½£æô©$ÂgËÈêo­7¼œv“¤Cø,cYí§õ~”Ó£’LŸe,#«;´Þ.ršeL’᳌ed5oÖ»9N/‹J2!|–±Œ¬ÞÊz³Åi5QI&„Ï2–‘ÕúXï…8 *É„ðYÆ2²:ë­ §QÃ$¥–?1>2²ë§Â‚ž᳌¿³ÐwÚ()ðÓXx›—«ÀÛl§ÑO›«¿ü5ôBx Å à¿1²„Ž¡·9\½mêýë—½¶Ü–Õ›ß'ÒXà²å3$úºl;ßc$‰ôóDPšÍSéíÊF•§~Œ:MTÅiß{wŸî?zmóÒŠ$òƒ8¢´§®÷?‘~˜IÆoÛ7­×<€úÞ—·ðÒÿå¯Ñ¸9o¿A8<ÒûlŸ¼CÙuÅcÙyE[âëÀ—2Á­uvBö(ª+ëÞ+z¯¬w÷}[Ôݡ꺪©a“mÃ–Š¦ %ÿ\íP ÷T=>yE×€Á¶Äµ·å¾*¾íKò|§Ö5»&!ÍÁ°íb_Æì=?×mϯ½—ªòŽÅö~¾CÚ{û¦ë¼¶èA Xµ þÃö.Hæ÷.ÌáÕhUçñÅF1Ø  D|±°hîä=îU節ZAÿgуÑ]tâUýˆG´…sU_÷íÎãØV`BÅñ¸GΰóÞ¶ØïÍ’,Õ,Hõ¢úf\@ì€a†¾ˆbJ|×´‡ÏeÿoEûÇ—·_~äk5ö’ò„MöžŠÎÛ6‡ã¾Äµsçc’R£;›®GÅá°zçb 'óÌßÇ~°÷ö”ÆDÁR Q3Û€‘d:Ctý¯›ÿýúÛõæöþãõý?¾Þ|úø~ä³e“&¹¿þr»¹ý0œˆHr¸ÿÈæã<8Ó¶ã…åz}u(½8h4zØp€‡‚¿Hc? CÊ ¦(«X:ë8Hü@dt žõÏe½ýŽàs_ô§nù¸e¶²ù°°ÅdB“íJ´¥ª.•bmÙA€í†/½¦âܘMÖvøÝ>4:~’Ï:~’@¢_Bn”ˆ;¾&){¿àø*Z›¶÷šo¿—Û´(Û‚ªòl$á)& ÓEÉq’ú2I-É?tÞ›ÿ$~@",0Z²@ðœq>ld`md¹ßYž êìË’]§x„Ì Ž¯é‹=K¾w× !êöîغé™Ì{QG{ß§ŸþûöfóõóíÝF딇gÜ*Ž4—ÇSËêËq-³ÙK©ø 9èù_‘éô`k«¶nÌ#é¼9EŒ¢· Èk@îßJÈ^£ÌøÞ‡òÉÍôt„%ÔeÏ  rÍå×€í+Ÿ Fš,£dÏ!xlÌü8e$.[ú „dÊ…¿Oü8cïËN¼mNõ®CÊHyéÌv Ëðî¸o@ É5Ÿø¹`ïoþûUÔ;8ÇcQµì;¯°AðîϜ֣¥>QsðËa*0–§¸‚w:ž3²1®ÈpŽÌáM²V„`DNXª˜¾_+ Bœë›m³3}ÄàúRAð¯€@õcÙ‘7C'A_rvÍi¦Å9á ð ø€zˆ1΄@ÖÁ4€òã½gáìïÑûþ1Z×kÃßKâ(}ÿz¬0u¾r‚ä.Ù»!¨©n¶ÛS{&¬‘ƒ´ÂÚ¯ÿ¼ÿYÃ…PÊõ¸&!:Žl^ž0 Xð#MYÿy*Op ‡ÆD,e0µ×r† <~$~ŠwGg X…Ùû¢Ú«ŠX¼ªµQAq›Í;$˜qf! “]iBn±%¾©@EQW–K°E$Šˆ„áQ7ÿ¾A.?)&˸%N”N|ùÑ÷~5ÀsL/ `£9E ÔjïÀÇdv?Œ's(A_ç¼€ËC‹©©þ_ÔlïÃX™üŠ ©9µk`³%œ17Õû…9òîÏÙ—ÝPÁù9Ôsº‹)õ[¨ !ñ7Û¡.Q5j¦ÃÓÎ`îŽü' BÊìú¡Gcpñ>\)Tý„”›%6{áâZÆcÅS(Å5°R›ô³€kX3Ïç÷$4áœkñåíRu%„/26M÷“ò75y¡² þ²‰°ùÊøttça4E¼Êè‹}µóNõ^“=ÎíŽåö"Ë…8öÖSv‹yS&2ŒŸX¸¿´!PµÈMžÛÜú3T ‘U¬ÁwMʉÈɳQÄÞÏäYˆœD¥÷»òüÞÁ†!ô8 T9¶Ü´ãÜÏÙŠªæÔÁNëÀ=F!™æsÛãmÅ0Q9ÞXê­Tö2ìÒ‰Cجw7à W {ÝH6w;ƒ-ÛîO»q÷Ò]aÃmêXö•±•¼I¶IçÍ›L-¨¶Õº}$ÑZ_GBJ‰(‘c`ïgìCa°ôÆNEuø³o5GÉ&/»ßOGƒÂ°¾;aìu¦‹ìeYMð¢< éŒÍÓbþŒrÈ5£ÔcÙ¿ù÷=ð^1ƒ¢ Ÿ9XݸOݶ!V´UiIB'òà›…ŸÉë¡3P3&ò`1˜½œ³›éÀ´ÝÜ_on¿Þüíún„[èbBvø+ˆÇŽÐ¢~n›’0ÔlÊÜgŽhª|«‡E0£ÒNHùŽ`f2¤ÑŽV1nLN™ð.ŠÄô!™”¢ÓÊ›V½£+^ZW8eâ+€‘Ã:¤cR¤ÉÌÁÜÑ®–z†©ñ)ÞJõ¶ˆžêÚD³P@-!ÍuŽjw97¦Ñà ¥ueŠ¡—½Kû2ì/ÄÑÆ«À*½=ŸG.r¼íKμí´a?¶Íéˆ÷˜cØ ð/+Ï$t²AÊ nn¾^ßlþþ¯[ÍòøŒE¡©ˆ VmÔkä¢p{Re8?Êa'§É/¼]ѼÛ}„)í»¥; á|è rÍþ€÷Èß°áŒ=–ݺ×G™3”tþ÷ƒˆ0B,(1‡Ë'÷òŠ)í³Ý)“{þ6Øé‰}ÝÃbn+ð~œy³â–ãñáÅôaÀžsŽG‘Ÿ€ÂÔê"lÉØûkå¾ÚƒE,…Zì„1¤-òïwË7ÊŒO†;c®±#·BžHó3˹C•yÈ{– õþǹ4Ø7žCQ’¯Öˆ,2Jd]ˆg~nKÞ;÷±m9Õ’u£N¯^ÆÎK¼vÍ’ÅeÈÒU±e ?ʳEŒpv$Wñ¸¬´£¬„¸Žó-€T™Äìýl¬86ð÷ `알7¥-±¡¹SháPÕÕát8 ‰Š“9N–†×çÙz„Œbóù„éÎÎÔœJfT{¢¾žš#ÃÌKÕ= õàC[@¼T›X—vk>‹BÊæÅ«ƒ/Ž+òY4®zkã÷5‹Òlp•кYdfg°zØ4Ë ²œQRnY ÎÈÞsgäýQp]Y”zóÝf WW—÷>õ~hÓ§a4»âôéS盚.ÉJˆC]„ãÿ#+åjð&ØuÏ)–Cl`\Àê¹EaáˆQ¨®Û¢½ˆTµý%ö"ÀÌÒ„M³nÁT®åë°¿z{¯/u¥9‚îÄ ¼R—d÷v°‚\†E(˜Øй½†0tg¬.u­.áV×ý§†aAxiG%LW¿»ˆU^"Dn~‰“™z¯˜Á®òóE¶ëæ@0¶í÷'m7 “3?YØ-¶DuÓ§~*d·êAú¡Z-ˆ­Â|1·…IL+³1éð_d”Òþž2R—3„@ ~œ3TЊÆx–D”Ptm>öÂz·/ÛgûîKD!s MîN-Îzyª¶Oäªau…Ò|2Þïӗ7Š…ý-dˆ}6¿…„J¼nvåïÜUÀÏHS6£ßL^»èÁÏyœM[-°‰Ù¨ÈtûñÓæVWØw·¿i˜—åæ­8¤HÖ*mpH”+æï‰•Cfôõ¬?Zqëª8Ï×ñ6¤ª¡B¬ì/ÝD¸¼‘æ*Š‘%À1Ac! ÌHÉ^ÔgÇè?ž}õÇlqºKÓyø%Û¶'×bóΙ›æ1âI§n”,í¢K'6åÙ†±`ïK§›xoli” Ê_úÒ‘(6cC;Ær (+dëWqQ–P"÷“ÁÞs *ÔU1„Äê±¾ÁlØóªÙ©¶›cN1~ç‰&KTõ¯`2PŒŒ«ÃñظÌg«wl½ óÝdHAIžm§Âkáéu¹[„å~G䧥Ì!p“p`Ò“ÀÝ5qC踑Ζ‡Y<“ê¡â PÍñLƒ8IhOv" SÊ 3ºÈô‘C±Ç Ïßt$´®Q*l–l8§™–€¢*ýÙ¾UÂïý‰"ÓmäY×™ŒfÆuTá5ûð´ñ£oÝnÌëÀ{K’ÒÛÔ¯£ÕßúÏŒþÖÄ!‹ñçØÃ_øãŒù_aäØÁ/[âªBé,Š®)ÍCýKpø;â?™yZ?(ÉCótó÷¸º©Ç‚¿ àíïƒUx¿2\èìà]g°÷åCð÷ó©®ðAÍÿ¹úó gàß,ÖËÍ¥Z®ó PËèé3gaötõ›WƒœÿvJótendstream endobj 523 0 obj 4961 endobj 540 0 obj <> stream xÚ½\mÜ6’þ>¿Bð}X°‘¢Þö8öÄñ!žÉy;É}ÀÐtÓ3Úí–z[j;þ÷WE‰R)µÆ{À!HÐ"‹U,ÖÛS”&Qðî* ®2ÄYÆEp€ß¡LÌcª‚ý•(òPDˆ“Ì.à)2fÉôøxõÙ]t0)e›È8ŒdÊd–Nrp („šŒ’@eT|dª°d0,à½*#O•QŠUedkUa¨Ê(‡RŒª¤T°UÎXŒªÀcÎ6JÌ®úœÂÈœ8˜G¦Š•2nò7JŒ*V¥Ï0¥‚­*y†,FUò|RÝl”˜]õ (Åpž–ÃðÈT±RÆmX¶ãFé€QÅÊ™(ˆ¤Tð J¢"daUÁGæ>lw5, qÑË8ØGªÊ(Åncdk7ÊP•QÎHa<¨$T¥4Vð‘¹0»êp +ã#SÅJ·aÙŽ¥F+‡R°Xa’@•T)+øÈ܇ ஆœ‚ÄÊøHU¥ØmŒlíFÙª2Ê¡,V˜$T6@b%Íbî>lÀìª_@)$•ñ‘©b¥ŒÛ°lÇÒ£Š•3QH+L¨’E‚Æ >2÷a¸«a¥ˆh¬ŒT•QŠÝÆÈÖn”  *£œ‰"â±Â$¡*JÐXÁGæ>lÀìJ¹Ê*Ace|dªX)ã6”“jÙ€QE¹Ê*Ác…IBUÒbˆS«ñ‘…ÆìW6-h¬ŒL+Åckk90ª¤ªPI€‹Sº'\`ŠóøTáÔÑ©H|G+f¥¤;Emª˜##çÑŠY©¯N…™Ê—eä<ŽbVŠ“î§Z2òu­˜•ÊãäÞ)±[FÎã(f¥ 8‰pʲ#_çÑŠYÉÉNVšRžeä<ŽbV¤“"¦ü3òu#'IJ•¯S2Ø»ÉÀó4ï!ÙuíµOƒÙÐ\ÇÀ^ð4ìáÀuˆêô§T¦­#H?? Cz(jàyðöiÏ9ëøËCŸOC`Y‡G8|@ò Â:zñ°ÛÓð‹WÁ×Á…­ž/¼»^û=䃒œÆýà7îv€õ×dïz€JsÄ,ãD:íêåþÕëÞ™$›#f'Òé&/·—^sÍ$Ù1Ë8‘N³w¹ûóz_*i̳Œéôb—›3¯5e’lŽ˜eœH§UºÜ;y#•4æˆYƉt:™Ë­×Ø1I6GÌ2N¤Óh\î<¼¾‹JsÄ,ãD:}ÀåÆÀk‹˜$›#f'n÷º”úŠ"Ø|½Š‚ÍvzúqsõÃO"0 +ˆàH8“†à(‚Íáêùæ±jýbó÷‰H&À=¥D_Ø|…ª`óºî`slÚNººGÜÜ~üOM×l›} ë‡ªÖÁç“ÖmpÒms>má×çæD¹'pŠQĸ¿ Êz‡4*æé¢2KØ=žÛ ª¹2iXDŒÊQŽ’s)÷Õ®ì`g¨BUïªm‰Z=«›~<Â^ö:D¯¢0*<õ~R$xzÔ™¢*àI|úxýávsýéo×7o¯?~úõ·ï®ßµB™§£/X ö '³l5!bJÄ•EX¤l~Æj'½ÕÇ®jê ù”AÍDÄYJP˜°øt§²nÍ© šû¿ëmܳ5*…˜0±à-Z48”§´H ™+Žgm+ » q¯]Ó2`\Wõn½7]§Oì b‘„1ÄYSîƒÝù„«¾>VÛG³°=êm…ë~øI¦x~EQ?d­ó}¢×ùYp÷¼ŸôÜ@åI˜sMnšÓáöþÕ²CCµH‘ùÏÆá¸ìqI‚§Ë–ܽ@›rÓCþ010Q¡‡ [FϬÕ{îÿ|ºýñ¿®ßl>Ý\ÿ1¸¾w¿ì®iÉhr׺éžpªlè~3Ùda»±Â"!¨8³ç÷7?ÝΟZ å?lE°mÀ[  ¹q?ØxÑ^i–[6Uk"¨ânš‡YÄÈœ u€³Ñ—lãê9ÙÆjŒ¶Q+¶Ie˜\J%R J䀨`ó&• G†‰³ìúSÜÁÄÓBÉ;·8KÃT,ï"ÎE¨R¾‹) ËÖÉ^Ja ÐÝóåª<5»$W¢·'‘»  b”Ëa:~vɾ_Ǿ¿ýúöõ¦/ÂÍeÇêROCç”È+‹2gó3Õ¢œ±D£ñ"ãXA=ÎØ¼¶•¸o›Ãq¯;=k<˜<[d­Ò tbóz÷Ür»?ï ÃÛ¼•›R¿­pRŽP€I¤ÀáçgAŠ‡È¤ë«}y¿_L]2/Ç•Ô%sØ£`{´©+ ~«÷ºíaKy<î«!•>±œm˽9õ®ÄúŒL¼Ì-crèŽ×¾¹ýðë/׃߾B¬³â·"²œz¬õÒIÈK‡ •6âëûJ»VDãT…YÌÒOÔ.˜„’&ŠQr)$6…¶;綃ì›úAŸ(3›-¼+èWŸôg}Òõv(è½8÷FRÍyo’Kÿ/U· ŽºÆÐ™‰sÌ’¹¢âxœc–tÚ†ù_Ú3ª¶d–÷€õnHlJŒ¾æ)—E–Ýý7ã'}h:€l°OÍúÈ^a,éŠÿ‡™ rNl¼þñöãÓ##IrËç_Š ²þû"ƒ,\‰ B9dþ_‰ (Ãj?25ÛB$Ð÷äËePÁ©+Jä5M"fó3H§¬©;½Úéu_ªÁZpŽÔ¡Ê½š/Š€á–w§rss@7·ƒöº9ô 0.æDd–¼¼>i =CL©ÃÀm*„H)Á[~p¬kž ¤sUPBðÔÙ?Ëœ± MR6Æ÷M'18£ã&ˆ1˜8ÁæBŸxZp±ö ßéîMïŒwÐ?ÎçÍÆ—˜á?õ¥˜UEléÏ-Z×` =U<i` !æÆH2³w2¯‡ôïv[P<£h™SIƒî)§)9:O#oSYfÁù‡ªÝêý¾¬usnÁgm™Íü°Oy™mÿ:TºxÂC{à ü÷Õrž¤48«î{Û}†.ÐmW€ oMÞ}tt/º‹ f«>°D"fí­ÆK¯-T©„ধÆDÉó eéqQ„išP~½ô``ËcA¥Ð=C¬Sr¬Ð½¤µ MT4IäÝÇÓn©¨X±U<^ ôáNv¸†Z*ÊiL]×çNð¿…j y ]à©ÕÕRÔ'°wɤ ‚7·o¯¡Íøýõ/ïß.Ä;ô&xžTØgÏ}þÒÕ‚wÎdbWsëJÐc`Ýш™ó4/€lê/¿‚Ì((á8#¶ÌšŒy©qÝåôŠŒÝJœ;Sªî¢oC÷&[¼Ù0‚83ÉÂá¦8Iç¶CýKN'ñíHLÉG§Û|;.Ý2 Ic¶Šd—²v° ¶ø2”œ§`pÉH²yƒÁÐÏêó~ÿìûò\oÛ>6çýîR!ŠLõ⪇º9]¼d£„ñrýûõ͆LäV x`hž˜e,Ã4LBª¹ˆTX¤Œ,ø¨»ó©f¹L(Š‘ýÎç¡Æ 6ÐĆ¢Œ“ùT…;Œs††?Ÿë­9Å]ë“ipî!¾ÿѱîñ¤Ëy@Ú%íÖÛœñý“—[ˆóŒNëíÙp9×]µ‡Š°Ô)(GV®¤G|É à„®0½%«x…b4QË,L 6o¯pœŒ­£+eã”.îNg=€ñ¾;™7ŠLí‚¡í^ @@–§tÁÊ¡ «¤[ኀJ$#¶/|¾‹„͇?7nV/ðÃA¢w³ÇÉ¢(¼Y9›wÚ(GIÂL|Á¿-´¦Ü?c¼”ƒLJü9¼â*»¶ÁÆ7 c4ÊoAu8èýý·!õ*šVÐnBYž½gpÑ¡¦ TüXñ£ˆ”Nëºß ôœ ¨¯‹ŒR¨Ô’3ê¯jûË›0xoÔku¯ïˡƙóÌ‹œr2-Ïr=‰¡KL ºàs¹o—nòhc?hñ&vXö=쀥³UKlô_y’‡PH%| þ6aDÐf”F_x@ˆ,väµÃÛÛÎâ€)ø &ñ×÷ÐÄBwtzÿ*&%äQž üì‘L©v˜ ƒ¦u pí±ü#t|¼¥Í!•0…ÆÛ’ܯô1½-áiZáç”K&P± “˜Û`×| ºmy9È¡J”ðÁ½_?þþztH©›dš;™Ü|Á 1–$ŒÍÀÛ]z„æ ižuäŠR‡ÁÝó×û¶™Iˆ2ƒ >ïu+ì;m^”c×ßš ñÂ='. f"Ƽáóÿù<úζ«Ý:ŒH4â–C̸Âå—0$f‘cƒ=|…`f.ÞAÛUõùÀýPŸ ØÙ÷§xµj*(ñòÛ:?Hü’'¡«Ý‹É"D“Nóh¤[0ÇA­5žÚpNÀÙÝ‹»áˆO¥›³ 0r@·Ÿf:Å;\ŨÌ]Ü;ݽÕíöT»æ4ÝÍ`)úú= s˜’ûV7Ƕnò Ô~g<\]oð³j–†x8˜ß€8ýÌ詇ϣ†¿Ë4ßCùPùÚQÈÿÖ¿,ÔÁ@8¼>Váã²ääýR†¦“á¿MqiÙAº¯[9Rúþ‹ú¦0VÃ÷uÛ•õ–ô¹S‹™„EÎ@µí©ï^üû¢4ÓQD-(ç,HÉ«øß`ÄT-‚]!sèPf:ø½|A( ¢ƒIÉbÐÖË(Z,ˆDN©}CÎuÁPic¶ ÒÖouõ'~i¬÷«ÐDìFØíòÌ@]°ãá5 ÑbÂæ °øùõÍÛ_®ï^í¹êL£2|OaLðÌ'ð%L¿¶l¿ÕÛÇSSc†{ÿÃí÷µÜ`¢Ò}ó P–ðç¨^à‹s:©Úô™S=¹p… ¼tùK7úÏΠÀå[k€ÈZç ½0ß²’ù׋(^X[4G€¢0…LìPã7fM<öä§» y-rßY@E‹Ø&ñž–FߘàZËœ³Ã¨sæè\Èɳû©ã¹ƒðÄ;%¼ÃxBdôwF(ð~¹ŸÞw;_¬rì ‰-/ˆ(çs¤ÒŠÿfðÓš‚Ö¿´Zà©Ü†žõKµ˜Ù~9e„-Öi&Â=´<²dO &¼—bË ÿÇW°/áàÌ« å69êÅ´ö;bï]Û7-„L™xbâñ­ª5±)c',Û(x%ŠÛCÿ·nøÛþÌÙwóî#²çØþqùÕ£ŽþìéšL†)¾ª¯—F‘zû¡ÛÉ aÿD~Kç«wÀù à€ýÛ¼ñ7nŒîIAZ†7+2úÁ”sï;Š„Qñ䕯ÑɼÞ7GóvçݹêÛ;Pó¿¯þy…+ðß\ÙíB?€Ûõ"³ÝžžŽy ³Ç«?‚äü/‹ÈTÉendstream endobj 541 0 obj 4293 endobj 566 0 obj <> stream xÚ•koä¶ñûþ âú!w…͈"õjûÅÍÝ¥_zv0È+Ú«D+m$­÷×w†zq(im_ÃJšrÞò<.ãˆÝ¸ä„–§À" ûªÛc]RÃU‚'Š€ýL¿ÇÜä{ZuÓé[ÀnÕEŸ 9pqA–ŒAͰ¿£}\–ˆ¾Ì @ xDWÃý¡éÔ†[PËÓ.ßîð ÁôC+QÌmuN  ¦…Òz¤Ÿc®bû³³H€ÓÑ5 „ÝUíηZ³þoª½fÛj¿¯h”¼2 aÿâÇK„8÷xàI”üò0l‰¼Àd{„.ë é&7Òæ7A*%H7!D‚ /²‰ ‹õº^39ð Ú8ÆÝöÒ=¤¾ºá“Y€þl(Hx*6áÇ<ë˜Ù¢¡UE/?S)xñ€Sêö‰³‰mˆªþvºýD9_  øA¾öXlÓ¦%œ£— z(£,Ü‹,Ë‘QÐÈ3õp-ºÌhç(­fYÚ¦ïh8‘ j tÅ Þ”}úŒi1m€ÜdƧ¼Ýzž¡ä‰Øt,EŸ1Îsä@™ÔÃÿ „Q蕃ŒÛЦ„?€Èöè¶ÛΞFŒÊBŸ&bRdÖe®!ÜwåS¦!‘QÃô¾/Ø‹k¦°ç;Á%ˆ|.! AO8 ¢(|µ¡ŠÉÄ<Ý kJ8 5CÕ Ä>k±T3Ø`ìú¹¬MÞÇÆ8ŠÖâ݇ͧ› ÐUW…`{ü@ñ »Øà‰>d«Ù‹ºØì6÷´²Ÿ†¡çñ¤ÕÉËmqÌ4ûG |_r¾³·ÐPCzB¸&4YÇT° %½ OdI\L]ðÛ÷ä{ Ð\zC0߀TÀÝ0ëþä=Ι˛Ѐ€žü6 aa»Kë¿Òi–ÕÀáŒ>˜—¼žþ±Ä✠ẵ>àñlA8 ‚©{á\U™¾ÌˆPp ÐY´¨ \f·þ¾jå*ç%Vî/Y¹ Ɔê³×ú9Æøõ*@AUÅ}» Í}Ÿ8ØÖ˜O³Zt63Ït>´ÂmÂ/f:)Á¹ýù#ÏÔÀ³ºª ¥·…•%’ˆƒ,pà`Ê8C¥ù c2ZY èm2h!]@  _3d®aLnn^P’x‘²M^¦IP lÛP¿ìò)*3p¹Öt ÁÄL7å%$JˆæÿÓdBP2-ª þC­a/M¾GèPä»¶ ¡l„§¬«)«Ò&©»ô(”ÂC^v’ÃDMë~¶‡"MLßVœhf$`³Ó‰‚±¿6ym*Ö­3ª5 ¸(ºoû ÉR%¦èYZí+¾§Ö“‘ä±"ØÈÙoUÞ .šƒÞæªß£¾¿õèXádâ#]çqXæ‡pLb²·óè»*]±NG?“ò WùÎ2¯‹z3¿9$Íòë‚ÒÌ-_޳xùº˜1óš—zÎ^çÒ3£~ÙßfÑWrRÍ~žj†$‚Ÿ鳄f¯4êi‘pà;ötÄå²Ò §EÂïÄ¿Óq–ì•F=-~c¼šEk\ çe±iþycMýÃNçqÄ9õYûcÓšÁ’3ÉÇz êI ÜLò×ÊO4 E¨/·êK=WÌqða¡BíGûz e©oC<æÕ±)žYuצy9 Ã^8`PAh&™Î6» Å¥5›I- „—!DrO¾²ˆp=Ì(ºVÄSþr7n Ú/ßj˜P¬· 2ŸB]÷8þLKvùã0¥€ŽSóR‹MYÅý>-àQY ÐlÀ›Þ¹`ßå/Êš•~#ªx@-¡¼†²º©ŠGwrJq°ðïvM¡¡Q¨*  pâ‚¶87U¾oÃß¼©s™O‹j˜4bó36Ö>µ8éÂjþ=._P!c˜a÷wС}0gÆõlº1‹gºió²kh«ûn²úé4ºl9ûLFêžÏƒ„eL]Ù01=3¤zSCÀ½bô‰û£^ìWÓÍŽQ|¡xÙàN$IŒóNŸ‘’ ;ÇãNz0íqЮ†Âgp›×ª® BÂÁ4WAœ÷)!Ä"çBŒœwÂ2M°Š c ž© ‚ãµõY× "XaV&xí€lëŒÝQ­ãy„´!Žmgû÷Ïfó•9W+«LÓ€!²Ïe.±ï'®5ã9['‚þØmô•‹¢ÝULJZú«ós6ˆq™E—ÎtÁ“„|wm[çU áP)òÕ°§]…Íü0lô¢Eæâ1>¸S/pbˆÇ<Ãà9,s¯uv—nÇp5¸ÄS§LºÄ9¨³¤«'QlS}ž<Ùr‚Ûj&ò£Ñ±Ñ{ÐÆ8Óp"i)&¦˜ýq~»;6,/qª­ÿ8j<;,Ì9Ž™ûÀ»¾ýÀ{¹ªE—ñAxÞkÊ àpŒêg bsŠiy8E lªÒè —èÙÌiL tÌ‘¯ ’B¿ÜµÖ+B˦yµ‘Á¾ªq=È Es"ƒ[¬ ™¥”ÄÃnâÛzð¥gO°V¾8N”ØÙMÐýÜ~¥ IÌ… ÜbõµY±9umÉžÐýÓˆ…ZOvçòö®L̘îýŒ‡Ùšc½ú!ªæ›>µÝY9¾%jJÊÞÇucNsû Öì¬Í#Ô„øò©8(Ä÷ Ž3  chŠcàbÅ8¤.ÛošînÃò¦d ¸¾mSÊ yLd‹™¸ùš‰)¨\€l™Ø‰ògÙ&!%âtäÃv—¦üÒ©it§ï憔saØP7ÔXÌ©ùP„¹2Ü%N\Ü‘ØF£Â' ssçêËÇO¿^\ýwM#‰¹æaa±õ1¾òsòòÆ5ÀcA°ú(Þ7Â:EÌÃJ¯ <~UX‰¡ üWˆõCí%DbrvÙO×1£Xóý¡Ð{ð÷Ni&¥¦Ðšì-†‚C)˜.$¼"lÕC  –’ˆýaGw)F›ª » v«ýᬀk¾Ëô½Û‘Ȉà§P³¾£!iQsˆ)HÊ¡7#Öm{§>ኵUDVÔ5¥^8ÂÃ6<žÆˆg«7xD]¥Ûq¬UœÊÇLBÏû†pÕÕ„o‚Þ êµ ýÅBLc”iòö˜ö·„úš†žõŽGyÛ#Ôe ¥ŸËÞàðb›ªa!…Z å‘7{ëF.øÆ¼5 ÄNÚ$ÂP®D¿‘¾6 âEd¢€¡EÞ]eq¹@~2¶ao f;s³âäéØl,†xn!ÿ‰9ÊÏnÖòÄSÈÈÆ?è L¨@¿0Ö¹Zž 9ÆcÀ»ŠŒÞ-Ið¾}¨µ ×Û!ž2ËL[.¡]o”‚•$Ô7Zžm‚’{ Ú®( h½Ñõžó¶ˆ5݇زëw–”.Ò³of,ÞY¶ÁNÜY¶Á–î,ÛßÇ;˰d´~g9ާy£ž.¯šû1صxåh¡8+µÎoÂ'Òú>4A³f)‚šÂ{Ëfè3"góýõåÙe²ùíeü 6ãÝeb„6#”WW9œV÷'«8üã®±ä¸þt}}ùåêômd¼NZ˜äŽøqñƵ¹#Y8¼?]> stream xÚ¥XmoÛ6þî_At– Ç7‰6 hÑ­еXën_üE‘™F…,{’œ4ÿ~GI¶ïôâXƒ ùy¼;>÷H‚-Ÿ‚-3øõþ^¼Z.~üM0©Øò~!™€ɬb6Jx¬ [nW†k®øõòË …ä‘1ÅÞm«Ík_7AÆ1È-XÍ­Ž àù£¯ë|[®®V×Ûz(†ê˜':Bʆ'1±ÏåvWçuÀ î¬3! ÝÃçůˬ'×’m³U— +‘‚ l<èÑÅâaqOƒj˜ãzè³t\E²u滼̊ýÚ³ŸKÜË]Î~Áþ·®Àºƒ?nó5Ãó œ‹ ŽñßâGÂábH1X]@9U£û¥~OËuá1NÏ¥#xVcðêú§ÙäÅ`l#œ<5•< cp¶¬ÊwM°[ÁM’„‚†'<È`/9±Wk¹våC^³û}™…EX¾Ùøuž6¾xf¯6y Ï5kqGY¾öe“wxÕã¯VBºÄ•_³»gäO4¬:ã ºÂáÅû,Ýv·@éäÈ 8jFð§Ü}LàF‡h¥e`Çî+1Mi-Â¥IÂå9Y=³Ê×Û}•x_N•6‡’â¤öµJ¸6ØþeÉHujãxä ùšù¶xX³…¥¡òºÛbð0^ùÛ¾Æb׆GF‹c$wÛ²Îï Ïî·>­óòóð¸Ê;ÖØð™z+!I:6ñ5ø“7EL“æ¥_÷ñŠŠ€A‘q(¹÷w_|ÖœËÖà—$†ì‘Q;n­Å€´ØC†VW½ŸóG;Á-ä¤?Ú܈}t¬à:"ÆmÍìeœãFÉñ^]q3ôÛ£:_B¾ü¼3z‡5ØluÍg9-J†œ¦§8 Äc_•¤¶¥‘<1ö7w\H2ß&eúÁ/;ÃiÍÊm¨/ðêë‘ÞQÛns2nw9¨¢HraNŠAO*Œb36Ÿj_½N›ôl»¤EWO·{ »¨Ý›Ðbl×î# bE¢î>èѶûH€¦±·{ãHé¹vƒàQ‘<&àA«‡SDnbµ¹VKÒ ãi«¿žÄ2é‘Sÿ2à͆…CþÐìEpF5˜ä“Ä50©0lB5¨PºOÓwÅÀï«“Þ•´(¨l…¾`lð4’¡Ó¤M“f,¥·Kņ‡*Dæázu­É³]E›™‚¢U£óí¾.žo³ÊƒhYÏ©ÛÄÄËo«má¦ÜÔ¥a£Ìaå3ÂôjœX ®‡õ9ÁØ@/pluÒ#”Þ |€TbHе@ÅÐVM#Ðð1µi̱6a—°;ä´étÍ»÷þ¼aw$Ãp½uDÜÙ7ar¯Lx’íˆ;aÜÜÉ‹4蓾°PqŽ5´‘ h¤:¬ô ‡õriWm?CT7¾y¼ÎáŠùf¤ÒBtâ@š§e–`[ûf.ç DªØ`èmœnYŒqt `„€÷5²b› ,-ÙgEd*ø^åô¹ˆ;IÌè² C²-dvßJ¿SEÅŠN@¬`«pߌ 8 òi’‚CÒrà§ j^šh;$ÎIi‚ag¤ †MI<^šèh†n/‘&ÈøÒ$ÝHœ¤‰™”&Åf23]hóE×LK »Hš¨Ø… ­4Q@GÂ"%2èÐJoûR_,M( %;8îÝä˜Zòà‚¢HÈA@ö(šŠ é.7/R€B%_þ9BjgpRX`Ø„°ˆžJYîâ‰J“4hÓ`Zþá}O‘ùþ«Å‹À–l ‘~1ìS [5ñ¢¥Á@ÅÙƒñå­}†¼u(Diñ&tlí,O"bÅžò&(¦]•ƒoÙBûš#Õ^ðm‚í‘2ž| n:@éÝžù¸ðó-¡IŠÅ°3‹aS‹ç+Â÷»¹ ïsNtt¬ŸAù€îP ^âTÏñƒÎ÷âg¶4JY޶ }áÎûr¨ ÄCÅÞ ä©üË(9hs•öîÓÛ·lu•sÏoæ Mš ¥±ñ SáêZÌ•QŸ!–·Sâùƒˆ<ô¿¶’ ),»•†ÃknÖ6‡¸}><:üyzô'Éßþììtß;^-§*(3Ë@–Ê žI7r{/}Üõ-Ë‚±4øãùx EÓØtŸ‡>™ n-ÌÃ{JáAP“˜ºð€ hÌCÁ2ï‹í®Õ³oöùÚ÷Çükñï"Xlà·3w“¨uw4 Zw;< Åÿ°öù†H–endstream endobj 591 0 obj 1815 endobj 607 0 obj <> stream xÚ¥ZÛ’Û6}×W ²™Iax©½Tśęªµ×k+›—y¡$hĵD*¼x<¿ÝàEhP”5»vÙ%Ý@£Ñ}ú4¨€-Ÿ[®á¿·ðïqñf¹xýKÀ„dËíB°þ Kë”GR±åaq£xÈ5¿]þgàZ)"ÅÞ—Õá­iþQ®³ýûrcî77·¨fWüˆ§¡vVÞЧcŸž‹òXç5Ê<‰…Ûè><.~^.`Þ(Õ<쀟c ³¦l¿Ð2ä2ަzéýb·ØR§(–ðзY$\jaùS^¬÷íÆ°¿°ñ9ßý͵ߚS„8z§ó Ù¤ŒxœL©])"®èÌ7D@ ®&~2u—ůY±ÙW< "DDžÕ®ðÃíŸg0ŠÁzí¡<Š"W` Æz‡rñëÈØC;dÏl—ÉpQ‡®$)ì ȸa+c F“`&M…+öC"oöÏ Û´U^<^ ^%%Ù8†Âß+“5¦ˆ<ûþÕ€ ¡"Ú àhoq×?iº^âwê–¤®MK4̘ÓpmÊ=®ûÌ6¦Êé¹Å\ÎN*¥ä&“n ÇŸíʺaëòpl!\ žۘ-ñ?äÖ†“zÖî›ïØýV˜æÉUØ:á3Ë6› |Ìç‘3H<ä Ï"§#Æ>𦭠F1OðT±O0QqŒÜºîóV ž&f°Lœa QëäFeí‡Òs”)—‚Û$É‹ bZ·€@D®î€´38 qk²Øõ UuhÛÃÒû~|ÇŽUÙ”ërÏLñ˜fDâ=aŠÇc Xåz)ô,d×G³¾ S眔$\¸«|Ú¥j”¸*§€ôùžÖ‚êÄ÷¢³|Ï•bÝúÍòë" Å^ :aI07i*Ñ\¤ŠZº9Ù§Š®ØUTQéªCG5âp˜áäA/}%UÔPãøjª¨’"º_•‰îx QN$N®/«†x"ˆ¦®,¥‡"‚]É3“ÍðC`» Á•§üðÎßH ’i/9ýÓuþˆàQïÀt|ÒØML¦‰Rž„³ÓX‘?¦ÈV{óÑ@n³¿²m¶¯§¦A·’ijs®ËËÂ.«~èŸ4_ß|ýØ9ÌúpãÈ<Ü—¸± ¡UHݘ=Ë]±3ÜØèPÍ´‚P…„š²døl±®)ÒÖ=ÚÁ7ôRv-$­ÙϪh+OÄÆß~ú|ký™MÀâ$%Ƙ¦†`)šO_жˆl5‰»H¯ºD·ul Î ¼ÝË_ä•€s€˜Ž4e‹y‘&9úY m7àÄ#"zÇrˆ¬`åqÐèÃj*žH¹}¡—Üsm½7[åíóKN·.[ˆÎ´”ß…©6ÐӶ¢n¹TÖŒ1†gìÇ6£1œˆ3°×¦ÊŠúÛcãì ’;J¿„汈ÉÊÀ¿îºè…Å0ªî7Æõ@}Ö„ñ@y&ôÙF©¿Ù$¤\+ѹìMV)Ô±(tua“•Y{Ì€eMkClŒõ%rÕ¾ø½„ŠÈx¿]ðøõ!’uä[síB€.Wîb/jÀ—!ѶíÂÃí]U2Ö¾££d<Ûý¾t7žàm+ð4ðöòhàÐñ[ý\7æ€HvÌ×À·Ù¶2Ò‰vcÐ%Ò¥¨ƒá9ô8®%ùÞf£õ²Å,©´K\e‹¼¸kæoH…)WdCµßçÃNú˜”Êo¥C=b]¿Ùÿ·ÝýÜÙ Þ¶˜RÊÊLìCië¥cÀYËióª$RØÕúBÇ ¦dº½¶,þAoM‹`8v)ÊöPð:³OÌ£ÆÄäì×ÒOHˆíLùD¹PshîqO€0°)wÜ»ŒH‘’îì†{ìA­7¿y= GA7=gƒ ÁDè|]¬+ëiTB²*hÝíÖbt”é¹RŠQ1@dÉ69R–C^ ÝO;8ɶ€È’´5f³¨Dç—ëu[Ù+ Œ¹f×ÖX a (öh Hk,†°Ýòp0Å) ÖtÎàŒ1"ü ˆPލ³2özìãÈ»„miWÃö¨YÕÀO¡ZiŽ/gfÅ #= æCJûUF¦jÌÞŒ!åŽ\Y‡âÎÐzŒ!áAJŒ¤Œ¯ø·… +…½î?œ+»X z…ÓYõD‹ÁûZ§Æýwœû›!!€~Bä¨4ã…×¹â'!$‰¸í” ïÍm¶YÁÐÆÑÞ2vÆŽP‚PÉßF[$‹Qꛃ„çúˆÃ~Þ³àÁN Ãûl¼C† ÂZXz8 $C„‘«lhK¿*!'½°C¢ï·”´>…I6¦Î{àéogð‹X-Nm¹]iäškÈZ1{ƒ@í¹›¹=ÇwxÐl;Ó€Úܵy≾ü2eR¤ºH´ y1èP¸„,þMÖ§°­ ²uýÕÐ=AKâùüÔ¦wÅ(Z¶¢€©äÝÛÃí·x!8,RdÞ ÄÛàˆÛ8«Û5 q½m÷C›oƒ«è(€‹é*Ì´%Â×WbæEi :Ÿæm†Ò„Ù¢ƒ„§±v%¿ÐûZà ’Œ›âl`Ié×;pâ}'àOIûrÞ¦u•¯z¢òórÔØ+ëj¶¶/#ûyø˜¸¿›|Õš~ák§öï ß,É]QÆL+ì¨Ñ2‘NLq-‰SÁ“´ÿU(CoíüªmúÀJÓ‘ê,?û6AéQ*†qd.]à…ûOÞ%¾d%RÞ-¬q³GDÿ¾foÛ¼{£Ûü×âjàÿD æ­Es'kn'ï>›(8“í¿³Öù/‰¡´endstream endobj 608 0 obj 2950 endobj 622 0 obj <> stream xÚ•ZmsÛ¸þî_I?Ôéø‚ߦ½Î$MsÍt.—&Nï‹g:´[l%QGRvüïû,@RX’ò%É$# »Àb_žÝÅ:ב¸^῟ðïþâÍõÅ«w‘PøòîB‰•Èb‘¥JjˆëÝÅ¥‘Z¦ø÷òú¿#‰ŠŒ,RF&>ÙîØì#3J†‘ý›¯ç2Rl½ÜmK4?D2MR’øÕ;µ ¡.$-ƒåzSµâî¸_uU½£ur¼zgD.uȪ’TÅø»æh=õô•á⚋ㇴÇÕʶ­(÷ësŸ›ÒyÈ{WnÛ3'Å™–§ö'Ý…úŠ‹BX¨Êj{l¬ïB:È,M>'Õv+êÕêØˆêN”½ìÉTv(HfÓÑ×7Õ~ýz½npíå+˜,“‰f7€]MJ–DJF)í¡ZÛ5ÑDdìÐÄq6¿);±®m+öu'Vu1 µèjÜâùTad¢Bær[­¯À´÷rǽܗ7Qñ«\ÞCIkñþ£(ýMÅ]݈ncŶ^•[±©ÛN´OmgwÒsâÄxê™â%6cìd“ÈQ21†Q‰u³ûl»ë¯¿ì·Œ8Ïe¦ø–O7—7/Çça‘æ‘,‚ÀͤZ ÜL|~Úׇ¶rfdžå†ÐÁ¸¿øûõí« © ±sŸÓBªBl/’XË8K¾ðÔÛ‹ÍÅÇšY˜¸ýbÃd$̪ýj{\[ñ—=tòúPÉÍ_Cù‰ÜÄJOþPWk†8E* Fªö‰i “F{sÉ R(}a³¶Îü¡¿µ,8%ãœÑ‹6$¾š^Qª³žrþç¶®·ü›Î]b¶MŒ`Wß± "aoWÝuÝ_¥jñ£puóòÏçÝ+‚_0÷ŠÝ+ om»jªsë‰Ê(Ôñ)ŠSJG‹Ÿd bá·Õ®êZ–^P=…í4‘&b;–;À*“9Dx\¶ìć_>ý kî×¶iE=ñ) æØ°M¤xß ¨µÅ>Ò>Û§jï6îÕÇɘ C=¤Ù°Ù—·E[¯þÇT¬N¢$$³8¶å½¥ Ô»wr'[¸Å·M¹o!Ël«8O„¦[Ýüÿ3%Õq€à”7/]>t0½lÒO¤ØÀóeƒèB!1Úþ2¸E.Â}»²U(•ÉQ&dyàËáT(ôLI#mOuè¤|MÚ'IJ²í=“É(BÐ0‰Šõ[Æ{Ðs.|¨›Nì»[Û0ƒi-MÌø¥à(°ò<$¸ÞÛ+ÊþÝÆ§g¸x÷D©ºµÝ,ÈÌœäðò?ùX˜ë^¹ôî¦(¥™ ¶iÅÏ_>_ »/o·Õªl;Ÿ…ϸ–ï¬]ß–«ÿ‰‡ª„ 1oÉÓ<8oFæIÈØç‚·–Uq2¡+Ûî‹—æÎnX…©4d •ÒeS•C§ÀÂt*Ƈzm!Ê3§Ôžä9Á)#V’FÅTMZ äuãÀÊ0> jÛÁ©€-"û»²6Ûá5WS*#¶ü·ž à‘ ¹©üì&¨´žlÜ€ùníܧ´Fød!ù_Fø0‘P¼Ý>yÏö`Í4%2)Br,FER³í®áR‡cs¨[+ê>b#ôÐq<5ÁäT n·5O’0>²Ó@Û«eÕX8.u(ò0øšk@îšzG10VÄCNYG”Ü„§cy„æFÍÖO² è§³ém£'‡Z¹-wvbä(çP,A©p+)Þ<‰õ$NsÚ" É(PáÅ ¦3ŽÃ‚Êw »rZæjìr¦ÉÈ XUšû»U‚ÉY(Æs%ìT‹êÊ€b¢åB抭Cxº¾¬È'6Å™%<ö-Û1£{‡¹¹l­åC"Ñe¬¾Çèʦûìxf †š) â’.Üð‘E]„¦­A@YŸs©DÑÈ‚)Ç¢ò¥¾»x1w×\!Ù²ëO <ŠØº}1Oç T ?Ù+:RÓÀ5ùµ·õÑ7—Ο{WÜ×¹3¤J©ùÁqV(ÊÃM]Y†8¦8é1x¨ÅúXÁ¦¤W+à„)q*l¦fùpv3RgÌ'}sá4uZ¦]6T"}Gó,½v‹4™ lŠVkwIôÔgž úw4×™¶åL9o”ÌCnAþ¹³Ýz­¹IBÂ+¯=Cdÿ3;Ûg ã;ÿФ©ÓÌ&‡¬JøÂb7e¯©tŸ7K¦˜´F ò⌤¨""€\@ÙëñôŒ0{õŠ#4”ls'çb÷‘£o‰tHìÎÍecwu·àc¸d‘!ûôÔÊØ2ëå·$”Š4cE+vçäšgË!½)½Ô™xDsQ1=af!).TO*gë@‘jßvå~e…ó@?‚ýø’ñ7žÃ7|,aôdòb×t-ŸÓÖ`ÊÓe{ãxWñÓ"ÜþŠø|°ë|¥JŸ4ÖR–FR. Ï~;Z×¾‘æom÷h‡Ôý¢ûê²Ú‹!©Ê!+“Œ½îÏT7 äPáÁ<[ ï@Í,'ð20¡Ç6dð€öWžRb™El½ê6½!+õѪ7ŠFhõm™`ž;Š‘: i{»rvÿdÁ33>½]$!Ï•×é´òt•–a”­ØÁ>Õak{Åe§—‘ÊŒQ_¹ôæ²’V^9 âÇG\\P(O¼+¤éRéü“õ2ŽÐµuHÏ=”¢ín1!ZÛA~vS8lR~…Ã9œÄã…ç ª2ÍNà Lv; ¡Zìô¶â^ˆo.© =ÒWó‚˜"¬×U<íÞtvzq1xóR¢pƒÓÓ6ËŽÖ<&à}˜i"gëð<×x»g)òÁiëL°kŒ y–{g¨›þNóLUw–0_µ·J¥‡«¡¢ñzJfð¢Ó†Æš‡*•uõŸö7Ô>q¼"#ð¨'Ó&·¦2ˆÃ9=H@Å$AÅä+]-ç[£Šc¼‰Ðo£Æ ¨_|?ö0 #ÕÄÐp<öóˆaff 3” (9&a˜Œˆµ)Ã}±mT„ËìRè%r”sÁ²eíêP¶ò„ˆò\S¬œÙ”\T°CD¦æ`ÖìâÛöx Óùž¡u“VÞKü?ØPÃ2ÍÃ375Ò}šòJ3p2*§~Ó¸0n¹ƒ U”©Ñ!¹«c©ÃQ-Rlµwyι±OªO]v/7’ô/†&Âû{ ·½ã!Bxžtg‹Í]·ï»é·ê{™xú(©ã‚# €`“{/r“†îùÝ¿Ò /»Ïõ oE3¤K ¬Ó~| qÊÖ)¾µã(ýK¼S¥³…{#.‘;ª†¼’ iÊ‹³€‚ªS ¨@8¬'çå®Þß/µ`Z@dÍmhžëâð%7*è%äuÚõí9Cc!ä“¿KcyV£ôT0æYz"M†r¹·ë1&ú°õÏKò옇Êr>æYÿ‡dÏŒÿC²¥ñ¸>ŽÿGBnJ¾4Ú”ôæÓÏþ'óà<“I²º3ÎÏoc@¼ æ·ùâü6¤§{vÏç¤5DEÎ)x‰·l4&0O¾<ä ɾiÈ« ø2?ä"#œéξ詿qÈÃu³oò’Õòg‡¼!żDž¦¢Ä0†É¤¹(‰v<7éͨ™côCPM‡³äùùï™ ­ÇZw‘Ù†iæ^ ŸÛÐ¥#±Ú”ÍŸúošð×7ÄH›ÍÍËhvJ‚S’ï=Åç»ï8Åà”âùS¾¼ÿpÆ-øãO!Kãˆè¹i55ÝF…q²8­ɦÓêÈ¿Îýmš<š=ù#V"-`xìZ*Ü [×Àè;ׄ7d}—´Ní2¯Ú\¨Ø¦U=Ž|zd­©x éùrîÂà´<šŠœÏšã“@ME<0ð )M%t°ÊKOCCÃÓ"R»Kaç u$cm†và Ï]ô•…L“jD/*XÿÕÏì91b˼H˜Ü蘞+‰”qœÞ+ûÑìs¯‘™"ÌϼEⲪH¯zG«ïžù… “(©Òп;)¡Wê§Â ïÄ3òh é+§Û§S‹îÌ}j ê`:6¥þÑ9lØ4? [%‰Xù_XrŸ‡yø‹J³AÈ~ÖøÑóé>Õ½¹æfC¥Ž®Æ€¸AÍD %Éiòþר20#zO§-|á¨ù©ñŸ§2jŒÉ°>þœÓá[žÂrøP¨æã ¶n·ôôÇVüt¬Ö¶¿æ¿.~» ŽþÏÍ n‘8qg_DN\O~7c6Û\ü*ö8çÿãc|Ôendstream endobj 623 0 obj 3282 endobj 636 0 obj <> stream xÚ­ZmoÜÆþ®_±p?D.dš»Ü]’mQÀ©›Ä@⺶Ҡ€€‚ºãù˜Þ‘ É“¢þú>³|¹¾ÈJѶï¸3û2;óÌ3à ƒ(ס¸Þ\„ã—oñçóÅ×ׯ¿‘Bbpw!Eˆÿ¥ˆ•ˆ­ Œ×Ç‹Ëw;ÑîsQݵEUfñòúgè‘‘¯$#…ž^ýë×E¹}³ÝÖyÓtJÓ…d¡ö•Dшætww(ò­¸¹ÌJñîƒÈº9DU‹}Õ´¢Ì޹(JÑ´uQ~»ª>Þ¼¼r»lªÍ¿i­amÒÀ²må­x(q‹ÍÝ\Þ¼mE aZI–ñ ÓA‹æþ\ø3§:ˆ¤ôeîÙpHˆór<ÈÃ_Š–[Ýå%ŽŠÓdb“a_m%Þã@ŸÚ¬n?曜-)H³¾jÉ ù²µ;%l7Nû)/·Ýã@0cé0ÐRûÚ×8÷Ê…k“F_zvåa µ³ê²“Eñ ùß®ÅmÞÝ!”ájâx:´Å&Ã…v»¹,v½Ý2o¸WèN™ nkh­ìPlÅ¡‚µÅ©ä àhx‡ßÑ<¯`’TÓð)L "ÿÊ Ó¾ÿÛÇÆ q­uFÃ-,cx²¾Úõ§!g$W>Ç¢m=Y%2Ж©Â•á-õÌIdØÔäQQ  Û:[Å]Æ—ŒlŒÃO–lÄ6oÚ‚œ×mõ.ß—¨þ–/oÂ0äA 5WŠ“ 6l¡Á•^õ—Æz1ßþ24žÀ™Ô©/:¹”PV[_À] ¢±br‘ lÈÖ|h:7¼;äÂÝïŠMw1§¦÷h¬»ªtŽ·yÍŒc¶˜­~%n™D_÷Ô š{[ìXü*ěҾà.¯ó²‡RÞ…çðÂ&o.)–¦à •¾Øƒs‚°¡Å€Ë`Ðf‘lÇÆ ‡¾˜”†c'¾Zãî锩S¦%²rÕUU1Âp¶È\ïò Êô0„Z ŸhóºØ”„|¸Ï-yͦ*Ë|Óv© §>Ñä‡GBgÝY¸Üvš²éïùx$šçnÜeЉÅ툒SüIÃ@E¾@‡>ÏŒýÍpã¯) xü)ò*@´7·‹¿'ÁP&ŒçÛ™ƒ!ÐÎ&©/yO¶\¼Äa$ù´ðãº:þ¿€."c˜{}ÕåË$M§wbÌs!Î}½²ð›ø‚_ò^‰ô®™Æ=1 S¶6ÝÞXV»Ÿß‡’)ü(öÅ™·*q˜°ñ:;8ÍËìöo¯fØ©'‹|Ňff;ÒÚB!]Ý‘6H¼’ç5˜BÓfå&wH›T!¨BMR•Õ#*ЦÍKrC(O@\*Ð*«}ñÄ{p¥ëjDí3f9­‚ØWãvÕð8ÉÆaךxŠøñí‡Y„EJ±J™|‹Ô?sšÂˆ•z²¿ºÛlN,×\Ê2S ¥-eɬ˜Ý¡©pãÈ!·‡Á®22KÙßFc"‚!¹9R‰RÇø"œŸ[¸!FxcÓ«n"§^O:ȉ¼ùê%ïÀ„뻢èHÌd[m•ͱ’*ÑèÒ½;ÌCX¶W*˜ªcGn²õ1{¤Ä:WÔYok€|OHމƒÂ©É)yµ½àB—È…#ƒužmû3Ú¾Š­’1\ïŽ0NÓaRŠ Ø"iüµ¯÷§†Š<ª'Îj¤E™úÒy»Dpl8âî@¹;VAއ£LMǾÊ}±Í·Ag&mõdn“ŒøðÕwn§®¤Ã¿eEöÞº²5+yöC‚ÿðÔ]IÛ´Ûœ¡ƒ²à8l­ ®0^¤T‹JΓCôGÆxUõ»÷ ™6Tƒ›7þ0‘´.£®%è›èÜÒ™zibQ©ûÔ‹YI™&Ee¢}iž3f‰fã0ë’(ì^™Õ‰@K²i†Ó‘%ú·¾…¾‘ß_¤‹š{(Ü*&ˆ^YžÚV'ü_5ƒGuV6z†t^KªÛÁ´/ÀöäÞŸØ4Q`Ç…é\?&pqÞsÜ®iãZRãy§w«‰A*í/8mp,%U£¼b¢›ªübãCáx¨µ<í ‹QÈê’ €Å€4àöŠ;œ'DhMè3e>“øJ³Èçº:Ý5}7rZ›ÐÃSGM‡44)]Zeêh;$:Or›#›ós%A(™L¾’˜ Þ0É){ˆ4â1ö%Ýf›§RW¬Q,²sÎ:Ã+‰Ì8÷÷ƒ YY†Ê‚TªÅ…\gûþ©¥´E1í±áÈ;ñ&L‚”@)\I 2 ÅÆórtä'ЩœøôwŽÅ®ÔÈPQûJ®5rÚlòž0")=eŒÚ¦¬ááœlSÛ®84¼|S•?ŸÊ _WX¯]­@ ´?uG ÚÿW¶y½Ë6ù× /N,› ¾+ÒF8Xðbm2ß@ +ÙK…Aœ0¥«>7éixj3‚Ó©QnÄ¿Y·óª·êPs#3x“Ozæ@xÉÆs¯±PæíO)*¥/^ÕÿÆ=’å9•B€'ìPõèÍ×¶+×:U÷.b ¼ZŸY5½2Û8xuȱ¹ÛºØ~vΩáPP…çY¦3È-e»ìPü‡¼lו‚ù¶ïɾþ&œ¿³Ñ°ñ:ZT,üáI Øb™˜ø˜·§ºä¹MƒCj&ö>NÉÆ³Ã)_ñÚWÈ˜Ø Ñ²Ï¨úÂ1Ý&5;¬ûªnóáÕd‘(Ž‹9> ¦ï ‚Ü—ψ¾+GVô¬œrÉʾ˜øôXVwÍ@ê’8ÑôŽ·ûðùâ¯×4/ òG÷YG\úpa`dÊYóôáb±ãoŒõdFA§§Íü®(7‡²äŸJœÿÍ]ìÿìïŸÄ‘Ý£¨¿­ªƒ˜tgR&±jFÞ;”fj7—|ÜÒëïù¼€?¿H“ôzÚ—øÔÕô4Dfâ^æéÿåû¬þ}ÿ¤ó0vóò«n¡àJê»…Zr _L¼Í›M]¸&GŸˆL׺X #Ê¡Z£ç¶¾éåv±Ù÷/ê'¸¨\Ö_d©ËaPÍx‚°Õä. x÷AŒÎ0)Ù:ÇW&ÒÙì‹»žíÙxÚ]‡Ç²7û)üϳÜÖWŸñ<™ Œ“Yã"k™ä¬KÔ5A=‰Ç/U” ™¤ìˆÏ'z%c˜îSLB_/.ô ¢¤øÙ‡NÏÀ9(Å¿û0v3½Â(4'$Ÿ&ú¹rïªû‚¤ïx;ï\ð;z=¯ý ávøŽsê¡hãK=L`ÃÂvLà~ÚZ×!Ÿ¼Ûˆc&pEé9ûÒG13Èÿ@þˆ.£‚ò&CR‘³—Sуí]on‡ùE†Š*÷Ë!¥#ЏÊäêÜq¿Ä¡Þh6)â¨qú³ïòMçÓÈ^bU¨c‰5xê8ñ¤ºÔÖÖh_å¥{-¸-6-Xâår |Õÿ$ž™ o*gïq(›j_¡/D§ (©‡êË­`¢r/<¹)$ö(ضøî2Gäªìs>m­£\"T:O4tÖq)Õ6ÿÃSBÆ’šâŽ@(ðG¾0{ÐK?“@H°f-C¾—  †©Ý ÕÚ•x1fUù¢Ï©þZ ýV@.cïaY@3“÷ ‚`an JÁß|Omñj8“Ý%s¸4Îó0Q|¡¢w¨"WÌèæ²€rgìßÔܼD"¤☕p$‡¢/Öú—R!žõó ¬•øÊý`ÃSyAôá‰^Õ ½èq-ý×}‡æ¾ÈVwKÑ.àMw6óJ/&F±Å4^8R¸DBñJ‚¸±qñaÝçácâÅÅü«1ü{„¯^Ô‡Ï×çuT SG±ûW]+9ÛŠ¿“8•ô®¢ÿ¬èçÕ8iþÀênGãçéž4¼±§1ûAÜ[ÎÐ ë “âÜ+†l> stream xÚ¥ZÛrã¸}×W &ñl1Ä…TR©šÔfv·j.ÉH›¼ø…¦ ‹»©%©ñøïÓI©›"5Rb—]2q4}9ÝpÀVÏ‹€­2øõü<-þ¾Z¼}07 Áø,–,ŽW*d«ÝâNsÅ ü¼^ýv„ˆ@sûbÛC]2Ó‚M`ÿ¦ã O‹ƒm&àJ8yß¾ò)ÃÃÈOxÇênã¯de¡¸Ž1Î-̪—ïí{Í®ð¢Bk$xB[l ",/×y–¶¶aÍ!ËlÓ°çm^X–NЦÁ#sƒhJIx€ð›´hfDSaÌåŒpí6má—eÍÞfy7_öóï‚  KÞÙ5Lnm½ÁÒk#¸ Ò¤™eÏ 0¢ÊÔŸè}ÀCP1œ)|R:CÄg*㟗x½ØÀŽ'úLÝœ†Ó"_sjˆ¨PÐj›7ls(³6¯JöœK 2ö u‚ç×IãD®ô¥Ž|æ,¥Œ¸2dÑy;“:ä‰ÂX–oØ.][öh7UmY–l5o:š‹èöSUï–mZ·K[®mýp÷ðzzw-"+"*«ê¹´L¥'wúb3›½´W(žDD—>ÞLj… E„èçjd &ÆÃϛЛåi˜FŒ àRáa[Óñ˜Gxø øRÕ g°K_Øfl>Æà i^¸óKKFí[ÂËk9+˜”!䵜}O¸¦Œôè Î\S&ñx­æ†pðœ·[AÜ;³µm²:„ç[[[ÞÁa9 Ö„ŒHêc2Á(—$\ŠˆÀ˜·Û.—OF3‘§¢(áå)XZÐÅáIHqlùRVû&ï³L'ÚeÃîÃÓâ«…[XÄð;ÿbª0¬X„RqG:t±Ø.64·žù‰_,-^˜?åeVÀ¡ÿZ¿Ûç|û7û® ªþXU l&↠NŠ£‰|™àîÈxºO&jˆŽ?§åº ®$„1Mð¬éÀoÆâƒu«¸ÇŒ¾²ªlZ–mÓú‡þISê̾[¯kXíáõ_fO>4 9y9uòÇ~ô»w¿OH’ÂÉã˜r"Y4¶mºDê¥ei'.ƒÌ–þÑýò:ŸÊØÇCÑB~5<Ü9kͪ½­S·MaÞ'§KÕl«C±†„àœ±ÛB£¹ÈâÙ>…м Žh0Äv.tY{ZIQ8 SÕá; ¿tQc>Y H8Xšsu²’½#Cæ^HVJ0½Ñ÷s•‚x© ï”7]VnªÉÚ×î ÙS]öì·*/j]•vt¬24è-·‚Ùµ½ïtE±Ó=Öx¨$ˆ:ÊZàqÊ“àt#< Ò¥û}áØ¡³ê¿.W@àÕÜ+Ìr¦‚ÒGí&{þµôý)Í~¿ ÆHA\ «t2(qcíú–`mn®q%§ß¼¶Yk×Gî€õÅÈ`ú~Ùʽ>œR=§vF38péÏãóáHœ…#5Žnºb7%(Z0²Â˜Œ ¦{ç¨fÖQ]è_c®d’À6 ð»5Ì?B3.M’Ç’€o,œ$„òðñØ©¦o~±rêìqZ¾ÿ¡v¢Éa8¡PŒÌR'GÇW=d˜å ¨Œ †|×<$ã]aô©jm÷BŽŽŒÂ6ÔoãIì—³\~ c|¤¨y‰­[/ßõÑÒgÐåGÈ…–?ñ7Ž+ÃλcŽLbàÎbÊÉu|Œ&\ýÝ I…ƒªÍ»!ç$.‹ ©—RŽ`^“û\‘r€¯C-w:«7„)M¤zcž”kmx R.&I9† ¤|µúp‘”k_ã†xéIRŽqW‘rkžˆŽ”kál qð³=úJR®¡¼‹ÅÕ¤\A!›K¤#NŠ;'å7IÊϺLÊ1~Ž”+Hm‰š&凲ɟJð]ÇËý“¶-.QqF'ÉyORqŒSq$j6w¹6†N¦˜ø•¨£ëm¾³÷mu_Ö$…á‘"›Œêo÷œŒ[ÖÔÛ÷ᙟ«Ð÷2Ô7@\!,D6!è ƒuÚ¦OuºkØ“-]màâê ûôùËG¾)-5âWeS¯â/å Y36»‰(œÅžfÚph‘!Ë:² oKPP¬Cî&¨ÕvÅÛAT仼¯ÎÊÃî2àà.¼ÚBˆyÕ¥¾)ó”_ö@ ;’I"°m}ìRJj§@pÕ~¥ãàë]¨î¨œ3¯þ4"3êv) 3ú¦ß£ÍË'¶†Œ¹·ÎßSÝin‚Ï ±ãÆ”„mä[ºÛöãg)HéÐþqH})ỡηê´lv¹·‘¦k§BIêO4ÜVTTŽYZÛ”•¶5.œ/`ÁïCC ¦ú€Žns÷áÝ'W;oü>ÛʵªÝÞ{s¶—¦«ÁGѰ×TG TAÑ„€i܇´¦]5àÁ:ư'[³1wÕÀ3Ä©’^ @  …!»9rJüë‰h¼Ù}*¨¨:†à,B*êùau4&)¨áƒ¹}4×d|(I4LyçjÉòH6›jg‘«õ>™uñÿòû<ºŽHãKS L×´Vr0µWNÉí8ã¶*Ö¯Fú6àÜXàNÛ 9ß—ªS¨Ù©Ð½9†É¤9ƧˆeÅêJÐHí./s·a›S_6¾¼B S®;ÆCÆ!8T‡rÖ/ã '©„œýR:Wñýkíû”BT™)";8…6¶m]Ú%w§LŒV*=²Ý·Ì:›t>÷\hÌßetŒèØà ªzÝ×GAoÐ2¸Ôä²ÀK'ð†ÏÛXzY—p(‡ê[Þ‚s§¦\&Ä3¨Ñ%.Ë¢Qëãá|gAê`Ì®&; 7ßYÀ¨©ÎGW±â9“â$æïb]-€ßm,8aÈÒ—  pCÀ7ßÈú ˜ëåS*àqLÞèbg!äEÿ…ê©£,Z­ÍQO`\… QÏeØGGVuÔ(Øщ•¸€@‰ä aŒºâº5ò·"hÎèºU¹†2¾æ¶ì( ñ¤K·­à\ àöëV dEã%n¸n yœÄdûK×­PäEfr§+¯[‰Zæo[…9Fñ©ÛV4> stream xÚ­ZmoÛÈþî_±¸~8p’»|C‹Is¾ ÐĹX¹öƒ-­l6©’Týû>Ã7ÏP¤.-šËwvwvvæ™g†rÕêéÂU«5þùÿ?\¼Y]¼ºv•‡‡Û O¹øÏS‘¯¢Ðs´Ôjwqiíx¾ã;/Vÿe<Ïu)§ÞÚz]eû&+ u7hÇW×ÞÌ:q‚°¸zÌjµ=kš©ê½]g4ÿÕµßO»¼s]·{4¬tikÕTé®V¶°UÚ@æþ¨>Ü|zOk¾tßɞ܊~4,¼-«Ö"ßk¿Z°”§cÖâk×¶®q7¿¤Å&· 6s}'‰Å,G [¸ˆb.°‚º0Ò¡£cq°•7dQ1~sû?]Mì;^(ôm¯f꾿¡´Vø–\PÓš7mTª~8ÝΛlWò­Œ‰72|«§T¹UûtýE&žãúÂD¶©Õ.=ö¸šŸH qÌ]Á †I;[eMçi®~=¤yÖ)JnÇ(ùµ¼…K7•M›-r´Â6OÒy#'ö _¸¬¾¨åBÚ‡#Í…h‡ÚQŸ’µªËL_Ù­…ýJ•î÷9¬yŸ[`[¸íîe<$#Bñ“¹z¼¢"zWϪ=9¡Ö| éŒ7¶±Õ.+l$VúœvBñIß`»¦QÌÚW¶é6†ÿ3›Ý]f[<7èâj¤ÊGØyî® ‘g¸$ÝõSÖÙæPjzmúM Ð9ã«u—e¼X/f™ÐŒ‘ôNØnüU*¨ß ¹` ¸±îÔæ )#–nªÃ*z¡vL"„iÙ|8 Àg—n,²ðWž×„t‹~á _â°÷¶I«æÖ[Ýå,ÜÐ=Š#±=0xa'ƒô…ÉìNŸìÚf_Ïíø®#ÍâŒ05Í ¡?‚Ù/"åâ>’ˆ? LM >,1!çk>l+9Ž$ǯ#e=\ÒµÚJïId66!Írº>Ь­³j9n|Ä€8çÒŠLl¸è„ðzJ-z¾ƒ¨R} ŒHïO€4H'‘~‚ónÜÂ(Sí¥Ûæïe¹¿O×B[.úåÙ#fM€Lx¢Áß¹DÃåÔí±(÷uÖ§‰8Š U=݇‡‹ŸV´°WÔ®ý@•_°‘P<}ÐIç[YC­Ä-j2ÊŠu~@´þ¥€U^ï3çñ¯\ïÖºÿZf Z8—Æý"ý̓rá®*âhÄ3«MH>/‡pK\^‰Šàjz’Q/9÷ç¾,sù$ïÏñSAÜðîÅŸ—]Á (®0[šr¹iiJ ĈÑ+³üÁĨöL’°­ž5¡à&«»ÏÃT¹§ò1Õ1¥nÚrn)Ø5¨žçñM¿£ð2·“ˆYŽz·]LÄO‹“IÛ\<wÞ2‘æÃ.ÀŽ3©ÇçÄM°)gB ™†É^Í{vW°!ö´~DÂÎKY½àŽ _ç©ëôH» T®(! •hø Ÿ(ùèC(ÖÅ킸ˊÏ÷¦›j‡»LPTéö©ÔÚ™Ðû6'±W‡új±1`BoD ËÏÜ™ ö»/Qj¤pgY¥»„ÌlºL".1âÃ6?žÚÐTÄF.ƒB¢­Ÿjp úLiòÔøT¿…‹ÛëÆÛŸ_G ´‰áR°>¬^Ô»¬ 'T§ʆ¦¶~$KpdÑXLîkÁ.‹è©M2útG–±b¹ï,-K¨®¹|Ëh‘w÷rC¶‡ÇÎC‹¶nÔþPíA-ê®ôlûÏwYË-Œµ®9Ù¢ë&Ñê”è ‹å›²wœÐ¦ÒÑsÂdT·SgŠbᳫm.ÉRƒO|UÿËäʼn»bÂ)ÍЛ f‹ity‚hùˆ/2Tù\Ä=&¢¨—NC峘*=ÎÈímAx¾­ÊÝ©ðuÈåÈéO‘ëz±„³=¿im )†&ܯßÁ(%ûL *<>5=äͨöÉŒPÕ7úKÔÓª1æð%XÈR>µùÚmM½»Yn0ן&ûÙ—[n0p©¹ ³ÙOÇÞ?!œç^¤úDTÄÚçzJ¡Oü—Ÿy¹©i€´ž¾"S³nÈïê~G^l¼¥FP.¡|v¡Ñ™z ™-‘êÓÒ‹KOîxÐÛkuw¹)‹›qôî…º.»ŽÔ£M7ôê_ÛbõóÛ¯ÓG/Ð"qö¦Gü 8‰Tã½TMïNÚ&+Øî:·i nÈ럲ÚJÞwìœLEÜwº½F%™€/ܽ?Áº}Ck8^÷õ$†a¸X.púz‹ê-#´oßnõÍ;iޏ¯gÉcg‹)ZÚ‚Ù ²ð¥šÈlôÛšÈzªò¬ø¢Þ§ß²Ýa'i ÔK@ùٜմóùbœÑEõ¹Èè-ÖûÕgx¹µ^V–Ò¶4ÙTå~O·s-AkÄ9¸ò]6j—¬èŠ”«¾rJ¦>áÅ#|ÖåÎD”½GFª'x”ß&âSŸ¦õiðajÄ·áöìUäçòÏIJ@>Ø"ð,B!…QWìô ‡Á´ŒP¤Bª®ë!Ê S{Tx½í‹»¡õâM‹L/ìLÚótà$š ?§½p¨§/äMbqù¦žì‹åŽûŒ:ÜGYé#ЏÐÕLüÞ]fŽu®&yu(5}Nª€. å¨jQ˜¶+ë¦u} á,9W?yÁˆUÂÑœþ÷*Ñ´âéPÐ:?Šf}¨*uõ@NÒ\µÃ"X×êæöŸýúëØ”¶›Xöû²ê\’Êñ±ûšõ ×!WãÝÇ߯¿¿}wû·›ß~ú4žr–Ey>Ð…MˆYk.Š-ÞÞ|X]zýóBÎÁ¥‡ŸrêŒa±^.÷<`b9[îq¹årKÍ•{|ü|¹»ód´+óêÅDNFˆÙì3i<¢¹Ï’ê°§°í_>,½F P³ò™gx‘ѯ#NvÙNój2™4Ë•mo…Û æª—¸oÝpaûyø³ÂíôkÈï_»yº¯ïÞ¬Ä/¨Bpµìµ+š}}¢ ×%’'ªÿܾ{ÞmæA+-„¦Óhü<ÕÉÀ©é÷"Éø~º%Jo'en*R“߆aGWŒÛœpíÇZý|È:‚cþzñï š±Ã¿±ÔE1Hêžÿ׳endstream endobj 673 0 obj 3058 endobj 682 0 obj <> stream xÚksܶñ»~&ý¹•_m§3Jb§i'nj«Ó/šÉðxÐky!y–Õ_ß]€ $O§T*"¹/,ö 8`÷OW»/à×ðÿÝÕ·÷Wß¼ ˜P\±ûÇ+ÁøŸ`‰dI”ð(ìþpu _ù›ûÿŒŸ³Œ+{ ïÿñá'öQ×[ݲw§ºè˦îç6àq$‘ñ7ïÁœM¨¸L ‰û½f•muW´åFoYY³~_v¬ÓæËÇê™55üêfw–qsÔmŽ0œQqÃä•1åu4Ê"·¬ù3;æm_å1ï5ëú¶,úêi<ŒPx*²”ŽLÞ ¬;Ö´ žZ]è’ò¨£˜â|ö>Ç’+A?­$†BåED7M¿·ZЬhê^{‹ `Q”À—ž5,·Š9¶MßMbvÝB1*Œy˜QdܪѲsJs-ˆÀ!µº;‚ËMˆ¢7] ͺGÕÀ®ôyY—õ7¬ì;Ö·yÝJ#J»Íû|¶gQÌãŒr¹G(ë¢:iø`Óõ!rS*v¦"JfwkV4[Mœ¥à ëÞëÊÿjØŒwo¿µoQüiQ7h%:?° å'ÉÃR;=zßÓ·›|%|t_/3)g~'ЇJî(<‡à|¥Pì}Ó>öyë›cÆ“Ì'×[·}¸~x3²Ÿ»i p㈰Ÿ ŠŽ=0öñ¹n޳ 4IûÇîêíýÐbؘðï8Ìx&XuÉË$^¾ ««ýÕ£ÂKy8—9”<ÂÓïÃa®A+wÇ’ïÿBåGpò ²à›\Æ‹x1Ï<§ÜAyž.P‚üpíy”.©Yýk^o+ψe,¸T<~:Šs³Æ$¤lÁäÇ­Ç@ J–‘Ÿ²îú¼.ôÛ›™Ê¢,ä"\bŒ?'ˆ »bxÕ€÷ŸÍé,ÿã1/ô‚h D“×íöMÛ“Þ¡ó~wZMÀ‚Äkˆû¼õ$­šâÓ*ÉHFÿÉútø9oËþùáÍŸÎz\›'ÔãäšÇQ0ö½É™G ^ÖéH=ç2o$À»Æ ŸO ñëŽdC“p;–»„ðTB.®ñù¨‹ÒJ/â×AØWŽß5,ß¾ g„Rð,RD bŸ>‘)+9œ °Ÿ Óãêô}¶Ëžöz¨ \uiyUé-J•¡žàdXQ=ɨ'šÆÔ YÚOù`k‰HâgØkÖŠ=ª2øNwF Læ-R¨·ß@ÞܵÍéÈàW½½…äÈúò€Yçáú‡~Ú†š*©d÷oØ£ÖÛM^|²°´b²™©±ð# SY4 j^ä!@‰”@ßýüãrÍqÆAizk>BE€+Tß-â¥LSž¦÷¶Õ¤tg:‹àbÁ"b‚¶óö38ÿˉ„ÕMÿ óJÄYÙ$!y‚N'jèA¤àiõ¯§²ÕÛµJCAx³HX*ùf‰6é ìˆl“¤}R“$!âÀcb³ P¡q!òjÁ@9 ƒçÀ GaxÄ<:C:˜Š’Åô@ýì½À|<ò™   –"£Ðå{”¼°R BZžŽÂðH—2rqbŒd Þ \ÊÈg‚N‡ŽáK ãI¸¥àcB%/¬T‚!§]éRF.NŒ‘¬Ô{KùPIwÅã„6 I$™v=ó!/¬T‚¡¦]éRF.NŒ‘¬Ô{KùPEwÅã„K@d}0A$ð]cùÂ"¥À â+㣷ÇeAPPúÂ,Åñ—âK¡œ°ÃŠ©}Ù§…Oá¡–<{txÑs±dæM“«::³Ç‘ËÇž™öä7ŽÐìqdsÁËfv6±#4{Ù\0ùÙ¦OUÍ-jƆšGû†žœ‹Š—¶{‘ü¦ˆ½ˆY—Ãé"™¼. .BÊåh·ˆõ¯‹w ¿Œ¡øuáhá—cÅ"R"'çúΑ]lp.éž½4úr^u/¨Wϰët#9Kr/g½EΧœFsX%ÉYz9)-R2å4šÃ*áHÎRÄË9c‘1)§ÑV ÿƾHhÈ º‹ 5•ø·÷Sá¬bkZQÆãhj3§®‡î-o^=,O Å!àyUž-”¥Ì8/_5¬TÌ"ä©/t<~·%SžxŸËæÔálvƒó>¨ß±[„%˜º¶oÎI©"Á£8žKù]«¡ Y—»Qk*q¸ i„5_ŽCPùa˜µE‹É‘·¤n®*è¥XoªG©BÁÕ|Ì|»Õ—Û Ô™¿ß!lˆ2‘Ì«“f§¡¯Â‰ð¹)°âŒ`º9Î/åöÌžG0£(ì ~µÅ¶Ž ³z\f;=ôØ"Q«{Ýú°´fÓÜÁ ²?ÌGí¡’°7”àgÿ3D²„~ÆV­Èk¶…®­èíœ`tìQ½º…;ÑÑÏÌBÉv†“…$u£‘`þ‚Ý@?¯Æ†¼ÕÎñäÑl4íÐÁ:¶-ýár†©ŒyÔ-´Ä쌡‡Úì»Gx_øµ6ÒŽ ¾µ†P=e]ë0€)ë²/s3XœÖ\Ú!Œ7¦pª ¡Õ¶$ßùãlÁcA?ƒÅi0‘@ Ä—üp¬ô ìtÛøÃ{hë³LPŒÁTëEsk/òÛýY0„ìe A6Áð¬îœ—Äü’îDÛÔÃðu¯Â„‡""ß­òÁijˆ>>lZM¨Rš VX9O•Öf›†x×7-x8®Ø®Í ýxª î·ºh<‚R’Œàù±-JyL©‚M<\££7§gc§Íeq¦†ù;JãstCÈÓ*Œ=ÂÎÇÚæ»Þ7}^±î¹ëõuûS¿m|ÝHfû©ÆužÍAaâ|¿Õ›¦¬ý̬à9«ýA¾LxQŒ§sö!C(ø zÉ>dóÈØeˆ©¤ßm&9âù™ 5|ÈoájœÆì H…òÚ°ÍR‡üKy8 7šöÁh`·Á:7ϽÆíéÝÑã8XÕõªÖBýàmR(@Å@dzÒcÄM]Ä ­(Ö,(J ”bmâ…‘*ž¦…ôòXI’xx’—×~±¦x$èÙ?(‰Š“râù¢l 0åQ7'³‰á˜—-ƒ-ëµK±gÎwcð0Á8©lŽ=îÅhÑMKk‰(˜Ù ceµ% ®£¬m@töpfV¤°Ÿ’³¥SÓÆ¦ÇZ÷Os%&‰‡Ú´Ÿ`«MÕìžÙtùTnûýï·ºÂm³=á;¨$þ4?G"–ñ@¬jªŒ²jºÎœåeUMÇÙ¤z[ú?–Ä _Bæ¢2à æP“SV•‡²GmõMúøÑa;ú^3°‰X³ lˆéÇË>};œ.…ÉêÒ!ýü‹¬ÃPªŽ— Æ 9zÞôSnlúp^aœâhÉf¾¡ ¥É"A¹L¾§(°´E¨@_šà?—Û±&ÑÚd6šý«•bÖêœÓ»žÐõ¨^?§<óùìJˆ”x—5A-~DˆÁÒÂŒ"|Áº¤t!€š2ËFÐð¶mŽGPðö¤ÇJ4tqQ­ÆE™Ò¸ 7}Üfî“R¤|vËA =,צò®9µ…ûÿ«_)`%‚cÄ åivÍ%6€Ÿô¡1Æú‹|÷O™0¤‰pƒ‡@Ú÷‡§ZUpQø=3$¦<’™'¬©*s¼úböüÑçaÊBŠ4dY%g«]™ŒaæŽU³XƒG‚ÂìΆ‘¤&ŒàË1ZN #Çäß¡ÆÌŸ›\×Íù»„:òäÿrÔ5$XˆÑ£›Í‚’é ÐCIp¶¾‚–Æ›ÌgÐa¼š$4‚äÄv<˜ƒHÒûÕÈ1®š|knàøÕȹ–öálŠê!rµV’a0H€gy¦¬ýú"…ò?%pÏ–ÝÀ‡íuŽl_Õ~ƒ¸³»SŒÍ£~7¬ãëó ôIG{#¹Mq®#Á|Š2ëH RË|v™;¯ºÆŽ06ôo/4×ÓvÎD2çöSw-_î®!d¹=Y^ÑÃŽgX\ÑÃVmúŒs6·šè1˜‘¹œW›ûw]sÐÓ‰<1Íwüì ,ÈLõ:±B£øåýÝw?³Ð`…|´ŸA’k¥q&ÏÇš vËê –¿Óµ)ÌÅËájŸ©û=¸üòø>Ò4¦!ÎÞc\'B¨Ÿ&˜a4ánOŽãõË"J¿àø/‹DPZ¦EÁZg¨\e¼æµ"S(ö3ññV˜Ø3®ÀÏÐ…«˜€;+lÁèEé™v³Œú+{û”^–‰ÀÔ'è7‚4ß–æÖª‰ñŠ¡Xb#ÝÐõ`• ¸öÞ„ñ§±FHåš¹ˆÔ9£éQˆþù– 6?¯À1“(È$àf*h®µ˜@|ª λ~¬ËýN^@Ï7~)¦°ÉiB¥ò&6öno±ošå†Bèà Ë„kwÔ]Z–çó³H‚ÕHö-¡ÏŽAX-Ô¦§Ò nó{[yäþ€i«Í•1pˆŸþõñžåEÑœ`ÓÆ&7oÈLƒ˜gÚ¹àg”a×isAÈÌ(Îu P±È8#”.&Ìþ¢(œ½óG°)¤ò”ÌÇuaŒw6áÆu/ŒºÖ~aDLØüþîþî\Ø„N)¢³ÄëÜÕäŽÿnðäç¤ÂÉ#V¬¸‘êßþííw÷¿|¼ÿðöî§3ÄRL{‚C6WÌÊ.aʉ á DÿÎ889€¦¬Á€^éz×ï¡ý®ÄïYåºÑ_¶ºäÐE‘}ÿ³_5Ùî»ÓSŽ›Èf¨jü¾qr =´[©4ëÓaƒ³n¬°teÝóacîãÏr#Ï„Gphj®ç³…m¾Ï˜Aâ>âXÉÞS7—Vofç/Q(]lÇ;»Ë°©Âz™é(Ĥ‚}€æö#„æħá*üpåþI©5™Ðlu‰Þ:^¡Ÿù?ž b;1jL«¼-8¯^3‘"˯æ Dxñ`"ýr†Š]ÕWPÝß|zxó4†°†¢ÊûSëÅžeݬ0Å„´'ÕJóOŠ0;CÉÀ”|7esÑ´¶ÛšÚó«O_ñ1 ¼Ž“v+‡ÐVØ+õæo÷'=_> ÷<\þ²7îý³k ¢ÆaÂ"•Uª…‚eþóê×+Ä8ÀïT9q³Èˆ»xq-<}·@ ÄöWÿf5ðùk|øbendstream endobj 683 0 obj 4132 endobj 693 0 obj <> stream xÚ•[ÛŽÜÆ}߯h(–M6»yAì’-ÉÛ‘ÉËw†»K‹CŽIŽVë¯Ï©n^ºxÙQl Þ!«úR]uêT5ã‹w¾¸»ˆ¥ÐJ{a*øÛ“ÚüŒ”(/z©VîåI_ üA@qàÅzúyq;W:˜ÊVËÐóeÄÈ8šæ¡º—ÔÚÄ4¶¥¡»úɶâ<°ô \Ânea±•q–a+ã°ÃVØÚÊ8+1nE¹÷[‰£”†8ô6¥Ÿ‰kóÕl³ôÀÌi·2þt·2βv°9{@[ç¶24ü·oµH¼Ð]” µ—†ÒÉ(~(þÊ­Ê|*Á†UàjˆcÖd‡¼ËR8Ìà“UÛWñ ·'•CQå­Ybu:Üä¨oE[Ÿš].ÚÇÃM]Îl‰—¦î0½i®Ÿ³Ý'&Š  ÃȕͻöúLt86EKfÊý§Ì™ÙÌ žïkÚÅb0Y?ÚÃ}Þä"Ïv÷O.YF‘sM³fQ´ât8³Ó CØ2fŠmnT·Ï'L”ÎIGÜVÄN'¬<¹¾ÐR€lÙ<„ £T³‰—âÓîd“À•~6 .8‹¯™q_‰cS#,\@²Ž›~,l…þj>@"úQú˜F¦:µHg…u¥Ý »}²©ëp,s:J›/ŠÖ¦Œºš‚›'y•x~ ÝY,ÛeU‚²7Àókß÷¹Mž—%(µ;ž4N—­ú±wAí§¬%zÖ䈴޼ÉZ80ÐôP´­%-ìÔÃÈGÍ.} ¿,0”‰+šw×/€¿»8P¾å¬9õ”²Å‘ÊŒúx›ºBœú±—hÍæ¯6‹¡ŒŒæŸ+B"H&‘«qé&´ü`³‰‚ÀF†¦d"Ö“>sœP^‡LŠb°hG¾¢–Pg¡N:›é^*ã3YÄè&¾ãÊ"Gø,À£˜Æõ OüTó¬IB‰+ôÀq_Â’ |æïáL1{o«Ä©Ä‰¼D1KÀ9rº cªÔN6´³Òü*y4#ï$1;ª/tREµkò¬Í[‹42\EŽ9¤-îªâ|ø$:”ëDj‡9žÊºH²¨3Ï9þˆ¸¡<êhp¯ 7|åät¶ÎώDzØcµˆZf{Oyà†2CÕæ Jû(©p6îX]Á±-@ša|„vä#ä#¥û$z•Òé$ž(¬Iy‹ÛÕ°ôµ'‘ùÍsyT¥žô:€ÔÓÀD—3D“`·JÆ®0·<OJ¶p@ü¡ØGSzVy÷À‘41‰ÓѨ›ObA•AM©¸vîDY·-Ú¾°çI|×Ô§ã``?ÙÄ6ëɯÿeAÍnŠ’"Cîò¦jy'~êí(¾ÚÛ™vCõqò-ø2<Ç|Z¯Ó Ÿ‹=ìB)§£ dJØ/m\Æ~¸—Qè’´>³Ûä{"’g#p_ÜrV¤n©«~›¦0–>í%òüÑÚ¢Èñ«k²}þ²fã¨0ôT’°q J'Àðh³¬ÕzD£&ÿóT4¹ÛFQä*‘Å$Plì ´¹³^[_XÂà)LSöp‚&뫪oL¡×;%Ùa»¬«pžJÃØ§v×ðkÝ>ä` –¨­ú©LÇÌôv‹© ç[ Ô J´Ð.ípj;r¤¶«G8Êõó6Ï·JeIŒƒ‚yÉ,ºvêëç[5ƒƒ#¦ &Dç v°æ6öÌy¨AMÙ ‰–5 ²šO(=_ †:·P5Àt…ucØT/ÌæËAª›{FïZ"+»Þ ³˜FªH㪯R&Fz…€#òê÷Ÿ‡øæä3AÝžëˆ~éh¯ûYdÂlíéhzÔÙ„!ËÔÌR+Ï먹CÍö¥èŒš®—Ö`¾Ng#×ìŠÛÁDûÅ ¤2>ï¢x >Lˆ±+ò%#ä²<Ó ð¯«w¨…ŸmæäO„‚»(Àøc±ß H¹’«<ûв$/÷æÔŽÈÅMiŽoÆ”j•±=sÆÄðKö^u‡ãÅ©Oó3ÛÓ ÷î˹õ)ãõÊ-áéì XN|.šî_8"êP®kiGÜ:‡S#æ8SœÅ©8œL‡;ë¬î§€ïÈ7³žˆq²1ë¬?ïÈ"z|ê§÷5²¤$%:‰œLØJÀS-Jê:2”i'KS’ï‹ä¶I=´¦ .lWvr–Y QyÄ‘;zŸF‰jZt ¡ò‰‚¿)À„¬wJ/ íK¸×Ÿ¸mbUÝ,þ""t’þbú÷ã}ͺ—)8­«uÖG¤B¥Ì&š3#à^¬]Wwüv'0{u²¢º´Œ‡ChJ÷ šoÊBèí©ÚY¤4ÕKK%x ì¡t@Y¼qøÓ<úÔ–#mòì®ýÙ®IZú†“8àÐàzì|å¥ïsDMÅì(Ębbÿáï©ßÂÞ›Š¥w’(^ïxbÔn,΋ $2Øì˜Ê°*i¸]sÚ¨ŒÉõˆ¶;Ât"Ù;Ý0A]ÚÓfiùa¡{5\gœÛ¬lómŽ"¹´‰‡f@¡É·^” $ ÃÄÓ¨U1JýT®çC¦Ò”ð‹!MB©w*uËÆ\Ìô]î9y§KFÄhÛ.?¿2]càOc+zsÓ;+”èNL!„}*”ÚzÖÔR¨ÀPö8bt‘1$ySg€ NU_Ï6£¶Ž\mìÓæ7PÒŠVh{–¥©’Î'Ý;²ûÐj ‚¹1â‰l>_G+Jaè ^½þQ¼¿³I@E8Ž#ÆûÕðí¿7É Ûª£À„u%ßåÝ›¦©›ô "ÄÑÚ®V uí/&èaø'„L™o©Â‰÷9ªíR-\äyTÎ)Ó¢Ng©tÀ §:(Ïø å]SpºŠ/5“ùL6=Ô|(”ˆ’MŒ ’¬o%%Kï ÇV’È›†wSB/‘ü ›5œ#9ÑÉýèëC•=eèÁ­·9¨ßTäŽ7T-x+çp L¡VÛ/ä,[žVŠI‰­úl%…ðâÀÉFð¶µl䊉U}l‹>•$tÝønøãîâÍ}…%#B@Ÿk‰C(÷¹Å+l¿õñûÍ·< l§‘SÀ‰oÍö· ¿«°åWÇ»ÿ§»z'ô<©.ö ¯S¤'&Á-Ç›ÓH~|8ˆ£@Lh1Ø<Ц,y’Ë r—óD1ÐK®üsS£"bÿÜ5Ù.¿=•â{aàõ‹lú5¢|åú\óWLü˜·»¦0½©¡ŽV›¬B¢ö“ñDî'”0ß"e]ÿ5’ÓL]´Tž(S¨~K%›æ|™·‹}¦ãVFsè’poGÔ¯ÁàsÞÁB¦ŒB6b†ÚàÒ½}§‹ô„ÍF¢VìÕŠÃ!ß©GRä]‚kWôKÑõ㛽 $¡ªûŠžúôÊæW¦p¦ZÉ £JºOw•œ ¨ò¨O±ìâöqø`¨Éwùì³'àBèŽÁKfÔv>[—ý¶‚ˆhÑ 7ø šdnã¡`o¡ç7/Ô¢Ðrdf}¹Çøõq {ŸÓ5Þ³1ÛûS·ç_ÑMµJؤճ¾í{)òŠ:æ´°Ën0ÛÖÇ3æŽÎk˜y£©†‘2ã8†N„ý’ˆø¬¦k ?ÒÌÔvî?©Hç=Š I9uˆú!,¦îä°Üòq~ Kõ¿3Ìå9? ƒÔú:³[²5&{ß{ÜH€›šËZÎO|*[Ùn(þls*ÅÇ•t¥õÜq4èTÙfâµD`¯]ÉW›uXSèJö½ù ß(µ@u¶ˆËÍ¡ãÔÓ1[5á>þòÛ¯~ùøáͯ?¾yÿñ‡_~ûðæÇ­ ÏÔD6Üi_´€õÝ=õ€ïsÛŽx"FÊý„›ã¡"3›rð>k×[8lï0QDmWæDÐy\­Ì]±'*sWl­2wß•ùjê ¤¿ž:±k„@_!ÏnÉðŠØU5s˜ý€¡ b¾xð´Øª™¿‡?÷ÛðÅO²ßaÿY¿ý‹¨Üë+V_Pë@겿_,Å]IœôÉxÿ·œ>C7Ÿ/³Ì©Õÿ Æ¿çk¢/îUŒ÷¦><´fÞ§oš)þIÝçûì}^˜½¼;ûmþûâÏ Ò8à5,7Õf¹‹¾Y®•wŸ-œÁî/þ+*Ìó?ðÞ‡endstream endobj 694 0 obj 3933 endobj 703 0 obj <> stream xÚ¥ZYoãÈ~ׯh ž^öE6‘ ÀÜÙ`w'™Q²/´D[Ü¥Ž%©ñ8¿>_‘”ÔÅÃã`5CfWW×ýU5‰åÃ"Ë~|ÀÿûÅëåâ»÷‘PZ,ïJDø§D¢EâRk+–ÛÅ +­4òjùë™@EJ:k•øi_m?çÍò맬Éo^Ü\ÑŽ–y4dnb™0WöV¦1#ŸwûC]ÔDIŸxKt_îï– ð½“ ßÒ÷D;©RQ.œ6R'ñøAO].6‹;n+¼4C™•—Ú©V˜?»Uy\çâ¯;èüêPÈÍßBùI”,LGþe_¬E¸žB/FÁLÇ,+[F{ó‚ÄðÀ³º.ö»¿g»uÉB©=£uH|=Tă2é)ÇŸõþx[æá“мõ—YçÇ8ICçë)ç‡dâm^¯ªâÐ@ÊÎÿÖ åïÞ«‰¬“‘n7.7E-턞M-šM.š*ÛÕÛ¢ÕZt‚º¡ËµrÒ9r«zçŒOÕÆI›0bq󢨉ÛGò g¯ö»5Þꛫ›+QÛ¢Ç:_‹»}ÕKa|mÉÄ2•:ïîÖy5-Š%§l Ó·¦ã:#Æ©"#†¦3æ´‰ìt_°¨…_¬ i¾°åþbËù¬q•ÒÒjv^=ŒØ±j*I¤ŠÙ.)Þ³ØA°êØ„gÛêžÛ‹›(Šø/¾²Q …eš¬_’óyàìïzΣra¢XZ•„~úøéÇ_>¾þÇ»7Ë_Þÿûi e”²â¬À芥sǼ}µ|5#äÙÆk$r¥JÚô2‚ ~Zè×y“WÛb—wµÎš¬Í|‘5âaS¬6‚D‡jßìWûRláÞìÔðoG|hò]#²*Gvìš+2|xæ–€"T&/´¡!>/?½{õcóFùùÂ¥çè3¦·MÑ©ºÍ¾Ûã¶×¶,÷,vl*-ì°zè3œÅŠƒÌ¥(îZ–ÙáP«¬-RUÑQ÷íJÝTy¶%£fü:INqir:ŠË’¤Ò™pùuˆ¤¾™à¤ÊhXF ‰3Fãlk½€æ _O‘l=¯àò.˜ö­éвûÕêXÝ\I4”^(:2ÑírX6AÐÔE_û¢±7CkxV0¦eŠtñIH ˜“‰aËyµÉ³5%:fzšW5%î” ÅîÁM¢WûCUŒÊE«4B Çê°GÉ“¬/°¨¡6r¡?ãˆÎó)® Ë{22¬5%WI³ù.BôÔy>—@Úz`ªe,»žä͙雎祳U/ÔçT1&7W×­CgpÀFHrÃ4™YªÞ1b‚tx£ê£é–*Is-nC£:¹õq¸íØ–¸hhÎø\=&,¹Š·yMYÛõÕàQü~,V¿•©ºþõX7ピ’³‘3~Й©Ž($ŸòæXíXô(«ÐŒì?|ÝËH±õ¬<æõ´µI.•L7R›¬»=ômeàUÀ'Ò%áÖöŒ‹òÃAæp‹¿ vrЩÚAãó › â–µÓƒFHö¬AÃjØ0é 뼌]0WŒtÔÏ4¨KÔ³ kTÛwµ Ü5ã\ÃX"øC*f>F›`Ø`¤ƒY#‰¥ó#^ó³ ÃaHÏg§Æ‹. =xàºÉ1!$Ž «“Y¸7h­oÄuUäÃÔ%Ã-ìCsl½oŒou9uÛ²O †„㎠(33-tíè·1rÌ«Y¡,Ü™¶>ß‘[o@dCâÞU/{S:Óš’C¾VÌ”ˆŒ~ד <²9öŒ\¢œ¤! øÃð†žÄZòýÿáÍj4çq2éà RTùxÈPƒ!#_5,&ú†ðwº” -ÛÓ!m˜ÐÝP\ïIà|¸¸}œµÌ®¤øˆ3«‡¢ÎϲRÙîDé¦j»Xè`@pi(*>‰ðP4›)ì4H€žò÷#7`ºá´3WF£¸A!±l£X¡óžGTc†ÅcQC²'5$›BÔpýiD5Ñ|É9û䔊yœÕÞJ]pÖMâlHu¹Ðû¼_1b4Ò1ª]Hü[Þ¼>ÞݱòºïcÎ3¯žÄkB øÍMãuHö,¼¦‘^›¯µCKx?訟‰×ک̳ñZÓ!=¼ßî‘©£‹Á"tAoânø9޳žíá ­é."ž`:Ú©’Š‹ùô¡Væ|1*æ?G n÷;êhØ~n[e>ÿ}²P'N˜ìB²‰> òóc¿ŠSX}œ“+Ls˜(Ú+:ŒžTþ2´½»—ë|ç ôX>Ù±âÃcŒ,±h‰}@†lRÑ„½!Ÿ#?Ñál°|Géóûƒ¿ýçèXè31?µU àÑV›C¾*¾}C† 5ç^@wæt ¡\Òõœ;=L°ÁžV™ö‚(,€¼MÐÚ!ÿÓ–ó3&å'– í%îf.sSJèP¤CVe[óŸm­þV,¯‹ –úÄš/' #Á¢$%‘(x(Ј‘øpý téüØôÆ?¼ÄSÖõ{~ÈX)ñ轂Õûó ;Že…%Õq@=Ô€ÞKxc ®B6Ð]Áeý¤AÝÎÔH¼]¾¢KÃꑲ/[mxKnj¥ ÕaͯÑ4t„˹Ø÷›1¬ö×8Ý×mNFéQñäŽ µ}Ù×ùth\cN±ÈV9]‘×Ô©ÛN•”9Tˆ¢:/¡Y±Í» ¡l\-b2„…Ù­¤Ÿ‹mQfUùÈ÷@ò8ØwÝõˆ82çãƒI¥U> äÓƒÅćËtãE®9ÝÅ¡ öå†Úæïv•ƒ ÓsÄeQ6’LQ X^¨ø°¥0Œ¥ár>P$½ÅÅ'2Ç1&ƒøŒ]‹'—õK|N…#5;˜qgDÖ”ð1—ø¸¢È¸;–×ø^7YAàØ†èå2LÓÂØÓã…¶!÷¾køÔw }´FÀ¨—¢(tŸBÇeƒ tgË쥩‰ŠŠ%_vFž—õðÜ)q;F_¨8 åÎv_!O¶‡}Õdèz8n'˜aô˜HcVeå…!¢3Âåqô£Ñü„$ƒè1ÕM…‚òè1ÎJŸ†ëçúü´#1ÿZ&ûÀ•ßòSWª¸£NW!nèþôYÝM†[!"͈e‘ÝeÑ<žÞU _Èøk2T(Tð3ñŠªK°º/ÖtC>r—P¨ÔϱI”Œl°:v–¦{û8Ðfä,ØÂ¬Òi,5 Ï£`™\µçá@uZ@cÔ.8¼úöEg(÷æÂàs=Æq^£Š²½hÚ÷ bPVù;té}'ÈpN÷'›‡vdªSÂQá´ttY”Mº( vŸÃ~ø¢L¥–óP·*_:iœf2Àcøõ"jûºiàQ.ÐOŒ[R g˜ I0_·æÉE$^"œ«v®ŒÛ璘>üC“ѯÎñßiØìöÆÎ×Ë À5ZD ¦èîJ]Ç#QBIˆŽÎ¤ÿŽjhÃ?ƒ?h©ùƒØv¿e²t3”`=¡nãü êm>hŒcTÜè´uÄÖó’n®þ\‹Çb÷jþkñû‚vlñÓÛ“¸È{wô jÅíèÃg£ ³Íâg±Ã9ÿB»Þendstream endobj 704 0 obj 2771 endobj 719 0 obj <> stream xÚZmsÛ6þî_É}hÒsXør×ÞLš8¹^Û¤çx®37žéPd³¡HU$íú~ý= R–µîÄ•…]¼ìë³ „âæñ"7süz‡wßÞ\|õ6_./¤ñŸ‰I,ƒ(2âfuñ\:0A¼¸ùuG"Cd1#×¶í6•`dZ™fdÿáãiJ6ž—mˆ& T¨iÃ_½•G6e‰ÇÍ}шeWÍÛ¢®ÄÆí¢qÛøê­iù¬Ò¤A–1þvÓÙžz¼ŽL@,±èÖX¤éæsÛ4"¯S )£,æó.ó²™XI%Yrê~¥¥/®(L‚˜Ä¾§Ê‹²ÛØ@üT7M1+íˆ!š´>d«zaQTó²[Xœ}F†Aæ³=ðQĆÍZ[I˜±$L‘a›hló²×±Q1éØ×¬JvdPè?!ãrJ?J©Ï Öù&_ÙÖn˜•Å0á0ö /E.æyYжžT`ˆC&>Óûz³úØæ›öÚÎmñ`7·Ïo_ßYÂ|3¶µz3µR$5VRG—úh«ÅÉ…² ®ÃxÅ}ÞˆªnÅ“mÅÌÚJ¬rèx‰ ´÷N’/±¹Tå.§ý%íùÀ4dd™¦>ýÏ‚,b㧬Cš~¢}òY·\ÚÍÇâSÎÆAÆYÄ£¿%c'}o¸+I¤ƒ(Ž'O¡p LãÛ*ïëÖŠ¦^YQ¯í&o‹êN4OMkW ¤ü„èó[WÀ½òÅ¢ p”—ð˜×U5œæùm†ü€Ïïz¯k4ì¡£5`¶]c¡åêeÓÂCòÍÛšbGá©ÏMö0–“fÓ³è¡ü†Mµˆzi‚~ã R£À#’ÅJï2G<Ê20H>•pÆnÛ·eÍH$!'}|]Wí†! ’Œ/[—{9’Ûbóñr[Èc¹Í'ŸªzÝCbJxϻ퇻‹«› šô+÷YÃI2Q^*‰|ÑS—÷KžŽâÍ¥2Òmæ/Û¨ýuÁ½ZÁý?üý¹ÄQOþPηÏp.F±—/ߺdâHc¨Œ1Ü>gtªŽÌØðø½ÏuxÊèEã_ŽO‚2('~uGÙÏûYîó6Ÿ·õæöÅß'mÂàIæÛ„:f>™xc›ù¦X“?A52ñ$`1± Bu°Ìû=Lˆ)‰" ÷ÂPøüî4ˆåy+0âÀÂ÷Æ¥ Ñ+žþ¢þ›h†—³œ¸’¤š£ H•ú=n·¿M/î_³¶óâóÑ;xÿáúÇìEQ/;sÄü‰¶+6c³: "hIûLÁ*M²È'¸áãÈ¥†e*!‚8e$N¦À¸A äM´—)OjFÁ™,êͧFÌžÄzÃ,K§>凑ø^²q[¹TFÊ#•lm)_¯ËbÞ§œå¦^ [ýÖÙ΂vˆ„ÆŒ’•p‡I+¶«TRô†E»É«fU´¢žýjçmCx£i76_‰EÞæ½‰s!h¨61þ4uW.ĺãY‹ðyTwV<«Ëų©¥ï“p|än‚O6móªÖÍ »Wリl;ù{°R¤ô“ì&óG_/àÏ ›H™QÆVx(Ú§ÁÅjä}œÄ? ß-þ&p–ÂÊ©?åA|œ˜IèØg¤ ÓJLCg-ìC¶Ú¯®?_@GX@1âK:HåælwÒiäð…7ÙΆ ÒŒ4 yÄ+;¿Ï«¢YÑ!írŒ{5M½§^Ú±æœ2ŽvSÉÆmù$E“#{-ñCÎí˜ÀyòžþÎn&UaöŒmðL+…€ç3 0 MÍ'pe:ÂlrNÕ$üfS3p©%Ïlï]Óþa…j @¶µ}xœ9—˜Áª5Y6Vm¸KU.1 )²X/ªÿr@ú²®îx„§"#L?Ãå=”Q±Oѵ½å–#5` T÷%©qþf<:§A,Ù¬¼¦h§²_Žò½¢ðÁ7>„:¾r˜ÓêäJ ¬/R§–‚»eœâr¬y>‡ÌguW-úV Tæ/è=£h¹çà㦷\8èèl—Íú…Ë›hÄ- ƒl!C¤>óÙ¥7¶€òˆñ^N6"@8þÁ:¤–k[¨ð¥„:õYË8ÛP«Øöæ÷×$“o.¦×ÒÊAs¶Ô‰—Ö)å±õ®ûõ†&„ŠGÊJw™ùRÓô–$üNæ1\ÂŽaŽB/Eš%>áÃÔ%š#ôÞ¾peû ¥´µ À7?4´÷›º»»_ë‹ŸŽ´F¼‰üùȧ¿^Ø2úr©=‹öþ¡¥iþA1«ï4¸Z-óuœM&–4£Ë£`gË4ê#'ãÕ‹¡6¬G@ý¯Ñ€ìQbúD'RÔÑhCg¦…UÈÂöŒ£6§2®yæÑäãh t>% e¨#æ!mlYä³¢$U£©žœ+Rr$ Û{³p¨‘g=2W¦ SµD!i¸®™´Nc/a;ˆß°H „!úéhl<:Ù——“ 0#ÁF>ñ™j“ÔH6ŒsW{Âeæõ â°0*gþ®upÕ (ßæ]ž~Ò±*󧥟ÌIÈ +»E¾ìX`VÖóO¢^n0ø±|¢]!´¼÷{X†u…Ûíó"°Á¸’™r0À㿳 °çËvŸÂ]I꺥}ÁD­ˆ÷Óµ"cÛØÐÞ¸­~sØ¡_Šw×77øßíóY>ÿT/—ÃÀ_…ì„;Âd“%¢DÔ·*]-G ïÙTî—òwì3ÑêS=…ÌÝ!xÄÏÈö¨ò `œDaôîñØM[±½»f„@b*c“C ¶6 œRÞ×B‡IßHWÎ{ÜLx©V”ÆupžózÖ|òX>‹ú"Üaïqÿ^•IŸbèž,‘…ióÇ[a‰NÆ>Ûî€~?˜QÛ p\öEH[i;âk…¨‰$£Ê»²å…‘THEF3"F0ß¡Ÿà7úŠþV†®\©OÖëuï[ÿÜj.%\Ê8ií)ëÉ€‹¢Ø§FÄ›²Ä £®D\§&ï{G} ÜB?5†~.²ê ÈÿyÙÔ¢X­K»²UÛדvÜM´ñ¹§eŠöšC(^(ÛÛbþ‡p0,ªfoâ}…9¤zw×ÂÔu¤å¡?¥?Í…ÎiwùæÓ4Æ5 1ìÓc~õÓw½=.t" üñPè”å¥XCU[àóab2ŽL¬ wm/ºÃ"ç[×MÁq(…´TéÉ©&Š6Žø5ÿTq™›$@©î=Â%îzÝCÎuIhÁõåfvéla×w¼«¨ ì‚b‚7×ÐÛæ Hs`‰júºfÛþœL$Jíóœ¯_jò&FúÌÐoýX´÷𜩺1 £3¶,|ì—÷Þ\á×û«‰ ðbÆ&Vv5ƒTQÉ@Nõ‚ŠäÆuòú>N.ž-»²|ÆÞ_ø“»¸ÊÚ²IH6º•ÉÞØ5÷®£X¯¸í'†/IA†Œ“†õaìÓ=$ÉÆó’ì ‡>HK*î/£=â?yU¦Æ¿û}[ßWùaàÔNùÎ üaÙHÆIâÊO½rÐ…&„ñ屄®²]Øo¿®g]Óž¬èš…qms±IÇ1M%»È÷Ý’ž×Ü"*X‰éÑ áÿj¦ï°÷šî’”>{r!Á»:Ó9‚䢛ÛÅ´STÜl•s•Ã^CÆÙW:vÜçVL£:¨²#ØVÓ@0XûÄÓÍzC˜9dÄ[\KRBµÍPkQ¹èî)ž­Éëé ’ѶríoW1N‡Â˜¼þ¬.~øö_W¯o~ùxs}õêljhHý„Èç<ݤ{ÎÑJ»^þOØû•Ûñ‰F¹›âöEo;;ÇÚÛ¬/3³ ØŸ3äT‘ôöfÜ?ß_˜™Òg .ÓîÞ¶¯ŸƒÉr¡ôb¯&޾ôÉN¼ôÉŽ½ôÇw/–|*ôP¼·!ôïG°=M Õ­1ý¨E¦?Þ£–ä裟jû¨Ç—6AsZ*ôêêði A3ÒÏ…§OÊü‹{Å'æ\ôê#ÓN¼o¡Ü³òéO¿o‘€(égÞ·ô?³ÞÍ~úÐy0c¡¾þs3æ‹_‘د©ñ𠷱ûXÂv…P¼”TøŠùð؉>o?¦ìÕÓøOcøßþìù¢Á`œ¡ è •']é@õ=/•lÊßS’ÉÅ&`,Ú¯{ä Ù[¬ÿE¬û½í>»Û¿E€‹éãûg›Tÿ¾á…+RqdǧV Ù¸-éqáx× ;óß¿]Ç ¿S½ÝnfÜv¾Ýv{zÿ»o²û‹ŸE…uþFõåendstream endobj 720 0 obj 3463 endobj 737 0 obj <> stream xÚ¥ZÛnÛH}÷W4²“Ãf7oØÁ¹8™6Él"ì̃-µ-îH¤†;Þ¯ßSMRì¢HŃuC«º«««NÝè‹ÕÃ…/Vküú€ÿwoV¯ÞûBâËÛ )|ü“"DIO©P¬öϵ§½Ø ¼«ÿI¤¯½4bdâ©×U~hò² Rß“:¤ _½—3¨Ô #Ë¸Úæµ¸m‹5q Sd7;S‹ëçe%6ymÿº~!š­Ÿ>ù(jSlL%ÖeqgjË‚MUîDy0Uf¿¹/1Ô¦®éï©ó»"kÌFÜ<’p„“$œ+R"/‘½zŠÄS®ìIâ%‘t‰ûM~ÊŠÍÎt\ÓËPy‘ϸÄ!«²½iLÅôšÆ^ÄeñÄ{—"¾Ê¥Àao Šñü—8¼«Óz[¶;݈u¶Û‘ 4d¬ŠèÑ”ýqõô¸:Åqèn÷©¬ö/‰ü%$ÑÑT‹2¿6YÕ|µ×uýüúÅ‚jTäÅÚe}ŸmÌ¥¸aª‰SO*¶AÛœ7ƒuVС7E¶Ïé ½ym^õ–µ›¶Ê‹»Ne[Õ¦³Ý 99˜¯Ž ¿¬ð¸—'~¾µ‹Ü3™í‘ËšíZ#ÊŽtÁ‚ õ’ q¹:©ç„©ûŒ|´-ÒåÂÍ* ·–L¸¦j6QJ{‘bÄ—çu{]‹‡mÞ ƒ ý`¢×(•Ã’yClÇ«!/îÖæÏ6;g¦fÃÅn³]½¤²îÈ©=Áœ Öžhíüº5ÅSO|y‚VYÛ”û¬ÜFªxª…øˆ‡½¥f›ÿ´uS‹ÿ›*+ê}Þ¶3â&«¡!‚:c67Ùúq[•{Q™µÉÝ“¨ „bbw}f¡JáNRöÜTµµæ›²-65íqºý6sÑ`K›h¸ ØsœÀ@¡µi$ñéJ¢#ä\dÍÒݧ¾§ÒÐ%'„újšÕ·/õ=ÆJÊbÆß‡{Òîö¦hÄC¨¬Ì>Ë |Ä}iz]q#Òª8a ¯@ž;\±5»"ª(­eøS „G¨kòNú —þùµïûü@ÏÉ nEV0‚2qWzëmFfLîÔÉoMôô’ïóLd‹ð$`’үщç3 ƒ‡Å{U‰ôü˜mú}õÛï_^¯®~ûÓëO®ÞÍï¦qÔåõz;ÓiJZ&'¤DÈÕ¶Rî=YØ»}\D8j—“™Þ²Ñ¤=Î ŸªaÂÜ2$Bž$I #á­YÃÿuB¨©’ê*bB´²­zA§!0–“Ÿ c:Fâˆ(êw¾DšéÄ.ØŒt6KŒ‚#þŽ!mkºàtt7g"¼.ŽÜΙ^Ĉ¹+SZ¦#&碸"m±5ùñgŒ¹eÈYx$?b…KùÔ#+ÙçÔNØz;ZÖÛβ÷I‚Þ}|¤òðÞ™!06Ýֈݗ1Çhµ.‘ˆ®)!·qËÂí4vQFlÝ{þ<rGîs艔„TÜ.ùlÝVA÷.ßç åy'›h䟡Œ7ÑšJ¾Ç3‘o°ê“ ùRw¹Ð—^ Ýå¾­ÍÁb¦ôd8úƒ£WÄç±0ɉlÝPBä§>iæ þÃLê€Øî¯»ëSÌ·<ðà )&EV÷Àعq¤UWç˜$ Ÿ„¥FEàòÑÙÊ›ÚT“Ü:‚uD.¡-ïܘV1ÝÒC‡ãŽ?O=?bϳjC€8dìGó=ͳÀƒªÌaåi’?á²N²ª¨¶Âj»5e°1;üRp´é¦Z,ÄÃøÏEù“vS ~—k¸yz~;æM„Ò7†|®³R\Îà–\5.”® ¶HªLÓVEw¥KZ”ÎÎ@6öáû6¦q)çì…^NýyÝÔ½RU˜LÒµ0’naÁŸ$j‹dµ­ÎyJ-C`ÙêHÅ­ßÇ{Þ§Ô-Ûls68i©)ãþnp‚ÆBÎâ'»óPïnùÊS~´x…ÊMruØÀZ¶w[é¬2»ÄõØz˜V’¡>‚*åRÖ,«©Ÿ‘ú0.1ùÙ¡­eÝ—æÀ›ûiÏÅ^ÆÈ“Uyç`Xˆ˜<.£¬+yhÁ²!“ûÁ-,Ó]W!Á‰ƒ“óª‘ųº½#ÌæY§¬c\%ñ^¾}+ö†ô—×{O¼i›KÑUÛùþPVMVØÌЛ¬UÂÉšûìQ”Õ€*~:(8¢Qb5*np¢ª<¾€Ëy±îúN£rzlÄÌvwe…\ao3žrÏ­)I½$d;=¸s ÄÇ)Ê.+Ëêº\Ó–›!q‘Ó’;”ÊÅÎ!fìÊl3¬R˜æaš¨5Ö²úcÚ¡ ÉZ\"î =…4À!ù–í;Ó…åY½“&«'tnûÛÔ#òÐ…°¶õ²·'ybOþˆöfºŠ¤é¼{]™êCYl€éX@3tκJèoåaѽ4MÜ¥¹÷ËÀK4{n°vŸ—tl²uhÓÙe—Áp/BäÝlC¹´h Ç¾Ü ¡záGÖIê4õ˜ÃÂhÙÕkå¡r9î‘v]ª«ß~¹úòóÇ«O+vËÄ"]Ž×ÿ€¦¶êÂ6Ÿ>óvŒ0k—g%¾\½ýü‹¿»z×u¶Ô#"¤àÇëîTéiE;]Ð!!tŠÆÑÕ&‡ ¤ô¢ t¹é°õIK˜qËïS{¾Ï³¼Â®ËýÁ*AþlšE|'þ8ô4_ng;‚S×ÔZ#$°…àšâj~È7(=¨þ˜k²è±GP–+f\©ö’Ø%Y½ý…·WP¢¸Ï/íu\%u{ÈJ‡¿+§Ñ„®8œOzQê>66 ‚OÜ>ÁùÅ÷“.M{>Ûî¡f£RÑXÂ_?Ÿï%Ä!UIáêÍ;ñ²Ÿ ݘsɈÄÖ¤ä“&ÊÕºøÚ(<‰œ:é~SKÇeÇ@/Æx:'¡Ëð ^Ÿ“5g»5€·È=™uÇD4’f2K¢ašDŸ³i9³©¹1›K&¾Ø¼˜ç4¨QSÍÈþÍŸ'¨õÙsJ±úå¡ÎëQBãÇ»‹«ÕÖ h2{ú¬ ÷Tì.BÔdj²“/zêÝÅöâ–O^ç fÈP‘0Cº´kQÕÿXà䯹·ýÇÄ7Ž€-ùM‰¬“ÁŠF1£@žß@é|ÍÎáG‚È gVœL@ÇŽT1zÁÆ¥—“Ó\÷”ç6eKqÀù¡àô1/NÖLpõòÿY3ûvýâï‹FDÈa˜‘ÍÎÊ]²é¬œ²éh±DàÞþœ7"«ûü 1]ŒcÉ“¾N= ,¶ùz;öùf:ÈnþÝù€N¦i(ýÁÉyQ“D¨n]‚Š]eŸ[™ãhþ.Ÿ6sRÆv?µËÄ}jŠÅÒÚ€ñôA”àŽª¤GÔ<½(œ󷻿ò‰ º¢CáT¯2>ªÚ¥€Z®]) 9!¡+@Iu8¹4U/45œ$k“gâS#ÒYˆÛÖô^­òùÎ}|Åí"ÂÛ«öRçgi(&?qWé½v©OƒÚgô}!2T1]kËÕ¡¤T¬Ç\û¼È÷í~¦çyýüæ@¯˜PF¾dUq×îâ=2,t×qO4ßqèj”)û6/“'>ýD%Ó:MB)þøê²Ö¾†F=plÉÔCÑØ xŽ©)éKÜ•l°¶Ù‰B«ÿ5UI|•ÙOì EÅXyÂi/”ì9©0bu•²šYG¾s®iͬq;¼S2wýs•N_ÚÉ:í‹.Ï–fÈ""—ü{‘iM@Žëh.ÅK|y)"üÜó—zd# ¾à,ñ¬o«ÚFïÒÖ¯è‚OÀP—›ë‡÷*Ô‰•DGŒ:5ùt&ÄŠ±>  2}A‚F/‰K¹²ö×½œÐ½9@í†GÜ=~ý•qe"ÿä-Æ®®Ï½†©KÞ_æØ£ë[tg´M¸Ø"×/Ž/ù c¥™uAŽ÷¬|;Ær–‚)Ö¢l›EõÐÿªfý´!§Þ˹bVê#Þœí/[óðôº`̿װ˜ûÈ`šûÌ0.Ù™Æ%›+`Üçdžœgy¼AeÄl|ëJ˜zy|Lí¤Ôå_~;Š> stream xÚ¥ZÛŽÜ6}Ÿ¯ f2ÆŠHQ7ì°q6»±ã8“½šnN’n©#©=î|ýž¢nE©Õv°Y$k7‹T±XuêT‘¾¸}ºðÅí ÿùÿn.^Þ^|ýÚR‰Û‡ )|üOŠX‰8L½Hiq»»¸ÒžöRïÙí/ƒ€ô¥jíH‰·eµûÉ4·Ÿ^e+G8õ½8ŽáGó²<ëúîêîÉZü©Aä¥AÈt-ð[䈉ŸŽE¹¯óšä|/‰Mmÿ°¹¸¹½ÀºQz:;ús¬BO¦b{ªÀS¤åô‡Nz{ñxñàšM‹Ä ¦:ËÄS¡´Êü)/VÛÃÚˆ¿0Í‹}î=þëOª¤X"hÅ?–ùZðñûr$¸…{ º–Ž¼Ð™qwÅÇŽM''–¬ë¼,þžë­qä“ȓڑ5¾v¤é°W阭žÿî.KO9Rbø§†ì›ìÓõÔJqâi9>ýÏ¡¨óMaÖ"/šö—ìԼɋ٪V ÿ¿U³OwÏþ¼èÀ‘ŽàyÜÕ)æbâS¯ª|ßÀÆ­‡¾¦¨ýúµ<ñrV;ïö1¯ÅáXÑDRS‹m¾ËñÍcÖˆµi•TÝWw¾ï·?õË^²F‡Ý½©ÎW4e“mí¡ˆòAìM±Î‹hª¬¨±´(ï1+|!oxÿ-Ö˜ø”o·­æJF¤9×W¾Ùv[rSÀÓ`qü ÷F˜â·ƒ9Àð÷G«]¶ßoóUF»ôb¡±=šÚˆ{4o›U|í@ÃøÉÃê#>:\7qõ;˜Zì ¶j¿kw¸¯Ê¦\•[hµÉ ÓaŒŠ§»D˜u»€-įNL‡^œÄLƽÀÙ5eu´6¯›¬1⡬ð57n¤ôü€¯þ1/õö8H3õgB d3C„@É¿¾ÁÁ¥Måš8â§šÉÁ àM¾3âîjmzW8ìál0MÂC„IÚÍïT´Ð!*ìðî™xz4ÅôL¼8ƒ;Gþˆ4[ì£; xNÙ¨E:¯!³õ:§•imr¨`j¨§i¬>G˜I{Œø“R‚< ïawŸ!‡øpûŸ?þ|óó͇›7ïnÿëÆÓäÈQÌfŠ¢l7x>[ƒÔž“”‚-ˆ­f•bQ*ö­O¢ObWV¦=EòʬLîúG€Õ5›âºEH€É‡MU‹úðà%K¾ßSÑA¬oÖÈ“š+·©²5ü·0Í“#Ežö&XV¿|‹öT»<¯’ØðÊzt&ì27ÁE&a`}–“Qà:5¼äÞ§ÅÅ>«²Alimk—}Êw‡#@djpÆÔ×äŒ-âs‚¾Ú&j=™õ51G*@ÀK.õ1_÷‡ «aw¤çº³U ƒS8§Ó/(G/[ Y=A"Å{f¼`*ÔU±Ïåí±/,.C„F˜ÌV_<È©”Ëaáä«™$?ä€è4N9ãÄ ü øâÝ NêÃ#/¬ct$öî Å˜4I'a¤“€a —]6ð”k1¡z~[zŽ“7î0jLŇ³ ÅX]‹îü;¾²ž[Áº`©iL¦)[îl©Eââ.—Ö„‚t° çÒžxí‚7”c&>âÂ;‘öˆoòS¶Û£äì°Ë!!Y$Öü›‡mÓž‰%mýžàs:–_„>…“v·L VÆ §- *_¼!ÔÎ`¢¸²và+“â‹>­A²•fÒç}Z%¨6".O:%dÂòä•Hq]žz(â~ x϶îImäÇ'³–A®]ãkñ˜921•üÓ®K%X"âÃP©”c‘ô¼hZ}è°Ï`}¹Òƒõ€ÞÄ‚Ò$Y³™±"¤w£2M<`õ¸¬K޳à©ã¨±«Áz •¬Æl*“ª 2/A5‹zÛöèx6Ì?zÝyµžîVÇ h–r%=b¢Ÿhy\z ˆ™@ý°µ†-Ä£Kd42`sQ{d… æÀg¾úq8BFVúOÑ‘ªS™²™~$õ¬ÆQèÅSÞ<¶ÕÓ^…úD@Å"‘xþÛJ&>ë< DÚî~&‹›à¤òµr¹)LRAHÛΠ¤J”‡5ʞÚ0ž„Lø¼¯…)_{Ò`?p-| £kðý|õÈz-.©œóÄxÊTún…HªåÇQG#@c°AjyMQú)P?bBàpä.xI•“¥ÉP‚FñaÓÕá6üqº½ßOl-"QàÕÃŽn®½±÷TóáŽÜ*\AŒëv´Ô‹´rìŽ~äö:Šz“õê{C1ã§²‡í·ecÚ†äRATk6ã3Û’åq±; %<Œ¥ ù퀠ÇÙ-¥VÄFªf^d‹JY$?|†Zy`ihâsPœTfUîvTØ­»ÆèÿÜ~I(C/ Øì²/´Â`š2‚¡g6žKÞVÞ+ªÞ€˜Km‚(°W:lêtM‚×ß}³@H,Uàózï¹u¹Ã'÷¦jËÙúX7fW‹|·/¡K×̾»20®x÷lžu4QSÅ—Ÿ¥îg¾÷c×BŠÔÔßÈØצoEù†²Ø(%[×ʼn$öÐã¨=ã²èvä_ &]nDVå¾Ê©WL o²ÎYŽoûΚ­~>°©é®n”Ÿàõ!·ˆž­VeE6!1R ê4J{â»îz#3·Ú_%vTY_„̺Ùųö¹üf99(¨o:Ê~¦öMC)—'YÂ?´}ÑéâKÆ%¯R.ßkK<×-Çž°ó ötÀ'=ÍZ>4š3µø˜W ^ÛÆ*:ŽC·]OÌ‹¹Õ‡6Ú‚gcÿíy¬³&®cƒâ+2@¸Aõ|>œèÞoû.ô6·ái4èЉòÆBY ÅíÛ÷ß·›Î‰è›¡žî.Ì‚)• †ŽY}ØïË &ÚbÝ"s/$L’“œnïIÀ¸öùpgýY]ùÀ!”ÀÁRŸ0²Y—-T‰ËMUöâ—2/.žÊMwy÷äúokÍqryØ®çî7‰‘IG±Ö]fºj ¿7­‘OTâlºêz‰¶OîœÚ©>b0öZw\Sg«Á¹õ™IêiG;p‡UFsNwkž“ ¡æSéòù½±ìé›dÆÇ³ˆÄÉ'ÐbœüâÝwÐì&ÛÖ¥ho¼jÑÞvñFh{{5É®_Ý®¯tØ'z™³=hºiOÂÉ&žwH9MPjhU}á6‰©ÆlZ»C{IY[ð¹Ãjex~ãº52ØÖ8r§¨G‡œy¢¶Ð^2Ñ–ŒN°"L2tt/«ö¯ímÍk{Ó;j™â_{[Ê%•Ó“c:¿¥ñïöUäOîöƒSwû\L¼7À´Â½›ÑDÔ±¹ã‰çKgÜ^MŸ¶é¤'Ÿ’Iä!»Ï\z6d_øpñ3¯†¬Y/=ÿ¼gx³zÌ*ûK6ìåÜ ‰:-WP']ÉMŸàP†jŸ6œ 8éSsré! JÏ¢éhûì}C€²ÀwrÉ) q#.iÿ”ˆ°îåR:QiìÅ*à3möÍ‹ÛKm…£vfˆÎ.ÛÊuEC5I{5»¶÷`@IñúæИh—¨f•f’ô«ÝoËÕ¯žxyœ6§¨Ù#»Œ¢¶;uw•{Æ»^äõô8OGÎ,îã§Œ‚ Ðçßùë’  ¿šIúKìp‚ Þ=»î¬b‰UðÖx6˺ÏOfïî®Þº­ñÀóC®ï w8%ŒbïþY£6¦wóúÑ´3G½ðŒ¢îA¡6 |œàаAdL塹& Ô50éž¾,žÿnªÒÍ2ŠZGÿ¸-ÎÔUad/GØŒÉáÎÜÌZ:3®ùûLKì@ü‰úmÁºÛ»-ŸÆEŽ­Ÿ>ŽtÐKûâ¹Ô(Äʦ…Èþ¹ÿcÂß‘Îþ Açï”<ÚyãsSÜË[‡cEA,Bí)eUSéL®2ʱb"hš?uÿ یňt«ÖðgRŒëDu:ÆxÌA(êrÇöÂIMØ#¾è;ãfKÝ ¯jñí!oa›?^üvA3vøo¢{ué.êÎ~ð­º­<ÿm6-öxñoQà;ÿ N5endstream endobj 753 0 obj 3597 endobj 764 0 obj <> stream xÚZmoã6þî_Aô>tذ¢H½á¤Ý—E÷öv}w_ŠÍ$jeÉ•ädÝ_ÏP²Ì‘¬4-Z8ÖÎË3ÏŒ|H£B±~Zb½Y]y~À÷«ï׫ïÞ+¡ðøn¥D€•HB‘ÄJF±XïV¯nËzó»¨ïD×äU»¯›NÔ·¿ÙM'ÚúÐl¬Øæ].ZûzýÛ¸CÆ2R›û­ºVܼ"¹ïÞ‘JíÆÔ*ö—ܼúø¯Ï¿üúöz}Ý/š*ªU _#v¶mó{ÛÞ¼OE÷ º å:Qv·¶¡{¼÷ÃD]“iô\[)|©(Hd²K­Ü>°k9»ú&4ÙIì|ö`²ö¸»­ËQWXej?ù[ô áR{lD7ØÔÛ¢º½wŠVlmg›]QÙ­¸=º[÷6‹¦†6¾áú¹M¾ÚËf6i ÓŒ­û¼Éwt$- ¦W×ÉIðÐB¡§[‰¿Ã2Ëü%ëf÷¥Ë›î‹­¶¶¹yuóú²^a dùKų¢R2Lüçy+6yYB¥»ºqFº/ØŠÔà¦þŠGþ8“‰ñ÷š™Y“r©/ÛÂÛE]ý˜WÛrÁÒ:Ž¥aö“ξ2VS«È B3Sxí›:ßtìJÊÀݱ/Ï®¤¢@fÊlËãU‹`ß䇮&GÝñ±Ë–",ï¬3]e;æ•¿£ŽCç•óŽGÑØeZiX23‹ZéÌÈ$cZ5â#KYʈmpÍgR³[ÿð3¥ .”o žýÞé¢.&d¢™.¸OYä·½©™žz'Ð'a‡šwP¿¨`±Ž¨Ò‘ŒMì‹×Íïm\eÍD™*f;?Á7›ßyÀk©¢Èò•u $û‘mF±Ôäwo;Ž@q"Ó€ ðTHÈËìyç\(†Là¨j;yçèC^u.Š\lØùvÛŠš{B¡ª,ëDžJ§:=Ø| ·÷žRI:ñTœ)æ)¿¾¹/v…ËZ)~šû/ 5êÛäì¿Ùh·Å¦£@%³®ÌRã/äñf2Õì¹-]‚O<®c@2S`p8’r+ö07, Ä;Š2oxɨlå=âº>TÛ«®)öCY3ÙÌ`ÉXºìså€?sÈÀÙ<ðpóÄ›§I¨‡Fáܘ‰ JàNµá!ÊP¥¾à‘ÒŒ:e(êbÉ‘'òÄlwnú%@±ç¶9²nl;aùi_ôºlë7¢Ñ!‹6u{Þ2"ºDLïCw€ÚÄàñX ½D»£ ÔÝÁYY}†® ‰tõVrÌÏBWï1¶»šß"ºjd]•0;D¨$X°´m˜Å©˜ï;$~0Ð0ý¾nì¾Cšåå<ijLÆ:eÛ1NöuU†áÕ!MdÆ×ðò@õ%bÏø™jÙ%6G#ò“ŠAÍÆîó¢qîEŽÉ!_b=¥±Ö~¡fËÓS_$/.‘H… CðÃV ã>¹„»L)5_âàuwh;qKÀC’+JnÉ%Yóþ¨)èS¶!øís*è(•&à*ŒüÑ)óA4:•qû«¢sÜÅv&G”cŽTìé_D…Ľ6…xÊüÇËQtk_ö1Ô†(­·Hö‚ÁüÒGëÈI¡¿‘h–´dÚ⛈ˉ϶;4•à —bRÿåw†_öœ¢¸½|Ò+IÎÎåîPm(©Ä¬_ÕÈ,§7,š9/ugœ/NVqhΗWüêAŠÒ31AaõÁvX¡T8Ri¾a×½kQüPÎÍÉ%hpkßJª‹ðäÄ—cUïÛ¢íËAš Ó>œ>ܯޭWØØ€=k%vô9ÓU™(WÈH˜Äó/érõ°ºãÿ,×Ü~(ª Q¤ÌߊjS¶Vü£‚i®÷…|ø'K¨’…p{/¾­Tq¹c™ÆLj´òÙŠ¬Š o2)[ÑÏ Îè‘æ[~™&_¶WT°L»yý÷EMJ"æÂð’ }9ñÖ¶P(Šé¡¨Çá"4“J"Y³lèÓ „sßœMC½™ã|§µ¨B[ r܃Ãí="':êÙîÅÍ«ŸY D<+PLÿü5¶¸Œ{Qà¤<áGÎh4øªÿØWOAµxA¤ùà Dã“/8³RšúC&Ì­C¥ÿÖñλCÙw¡û}YlrzÚR ›0n Ù~œõAó8ñÛ&!¦k˜£ûC³¯¡«3NÞ’Ö4’Éû‹¢e^Ô‘|·ÙÜ»i5 jœ@0»zS—ÂV÷Ee¥xÏôCKCtÝÛ“Ê5¡¼¤y"_óݾ´oÐ øÖq¶kQæ¬#ª¼ÅJ´L”¿ÇSE*Ûúе§Q—ž#¨Äosøà„deg³L}ùGêÿÀÑócKŒ–3èŠM±Ïi\ˆèΓ¬‡\" šv ï$7Küðy½þõ?ŸÞ^¯ß½]ve4$e+¹M–È€`Õ»O%³=§8)Næ ƒhj¾ 8I"Ä:Øævyb–ÊÔ_4 êGûµ{÷ˆ³ž›˜‰-2þ™(¤<*ª-ŽíIÚL‘&–C›UÖˆ£žÄeú¬Ó»#çõâí·‚#’2hz#_~½NÔ`_»Ìvht6Aê‹lÇ—[f;¾Ô%¶ã?Ù@à ×Æü5Пð}°èKÁ\“é°¹ùh=W'•Ë÷»sÁ˜´³Ôà±M®Å$´Ñá)vºüE¯ë1úÇvfÉèßQ5<Ñ+4Æ mLÒDÜ“¥¡wo:$LqG WTœ¹¥‰ì-™PJ|ÏÍËb{Â~ñu¼“É¢QƒH>KìÌbk·Ë“í{™¡*™ñ=9CUØ1º°ãAMAPc&Ï ê›ém4$³Ar韌{ÿÜã>Ïq]ÄbÂE®ëËM¹®F‹¨2#‡èäØÚnÂtÏÀ™ÓÚ ˆÈUì ÂÀè[ º&!ù»> stream xÚZmÛÆþ®_±h?ä\œr¹|C‹öÙq‚ÖŽk É—ž´§cC‘ _|V~}ŸY¾íPäùÐiuÚ™ÝÙy}fV®#e ¶Wlwwúëþ;l^o7ßÿà «÷O¸ø×‘Qè9A(¶ÇÍÕ—ÛÿNK¡öjš·Ú6I;nÌh^¢´)Kg·/¸ÿx^â$œú”ëÄJÙ$܃Tà„ [7.T¡„™“H×w|?´im'9¦gËIŒnumßk½¿Kw¿‹ìxÊËt-òì˜˃Ü~® GÕ»4|§¼‡ªlO¢ÎþÔ1¾]Ÿ\‰¶÷胆òº$ÙicäL÷\'AèÄ>cÒU“Õz?°’¾M8š”N»ÓÝE±ÁÝY4UZÔǬ& ˆ „ܨÊÅ•ƒØÞô×]Ak]ìáFöÃåãp¸| f—“1é8‘Õ"çNâ*'Œb›ð‘û™çxpkýÚÈ3S‡’ÛÊÀYF~`")IX¤ÜIäD¸µ®«ÚCä¤3Ù%Øå´PÑ]Ù"žá'$fQ3ÊVˆ¾ßY® ÉùÙ1 7üYWL6…ˆö6¾½Êí\;~ÿƒ±ãÛUBEÈŠ©Æû¾ùú Æè8æe%@Úv)Ä~oêÐOÆ*e[9SÍöjRLmTðÍ=\9‘òmžYàû„­#žÊU¬œÀWë»ÄPU¬ø.EÚ´H¨½m>üüéý”„3¤hÔƒ“FІµ+½Óh$^—\¹! —¼2Ûœ¨dÑ©æÄ.’–RNŽÙmŸ6©© »òxÄÿ×Ng.÷„pC”Ø”£5Éá1ä:§Ÿ44Qð”®p:£ú…I!bë+êe7"¹¤Ï¼â¾-vFi¸€fŒ3»Eæ‰Õœ1]^Î ’Ä ¥š.?»º;Ò ™øPVÇϺyÇ‘J ƒØtMó>ýz ï_Õ| •Øš÷oIó6ø|.ÊSÕ؈#xé»áÃaóv»¡Q{@4Ÿ‘)¼Dä›J‘Q¸ðEGo6÷3^¤Ú/€JÏó׬Øåí^‹ÐÉ«Sæ<ü“INø~Gþ¥ÌöEâ^ŒbT­QSEB³ŒøöŠÀsÂ…ÍL6ü!³<"Q)%§GdYÄ×ó‹HPF=åÂ?û²½ËµýÍ¡»Åí‹¿¯{b>J˜ÈE°èÄ]ïªÌ$…„ut1ŠTŒ"#¢¨ÖMmUæï(í~ÍŽíqŽ)dˆ†'X;-c ߥäÁÜòøô¥ì‹m ÐÒXÆDv"—ÌwC–¦ZcKVtI²ÓxpQÎ|è1dç×sY¨i”¹]ÆÅOà¢ê{Š+[÷EOvyA2Oä‡Éé/Eðàdƒ‰ JºÑ< ©mUl^SoÒÌRë]‰rÐã×z I\Âî¶¶€Ûº‡€d%`Éf„l UøQWؽbÁ¦xqÈÄ?ðuG­§ÌQ÷Y.á¥N¡Ië)q©YW•øN‹†Úª£NkTィ ÀjBFÜšÛR¢1U1ã†-ÑŒÝóô3Èõ&ªàCƒCøôïÎ!óì®J«3¡JX¶·‚#>k͈åœKÈ­?ÅÊo{´>Õ˜ ¯Aá·Ø§øßOYdê(ÛêTÖàÌb)mƒµ#|£×ì‘€V߯à %/RÞ"ܰéÖá†Mµ7ìõ§á5/‹‰òÛpÃbýÜðc¸KlÁ µ7l²§à†M×49Y PĦ)ï¬ï˽~–ø¨ð¾m!µ KlºgÁŸ’˜×Á_¡ž ¹ü¢£~&,ñý)øÙ°Ä÷@ž<Kl +è>V£ù€à=dLžH4¢Hª—»®áá1ò'àɰ¹› ûŸ6_“5ÆÖœhå4?…XdLð9Ç"b±é戅Šb¼ŠX$åûç Kɪ—Ýä1žÝÍÌJOÔ •4)î«òØOöæzxô†–_x±—„Ÿ­eéfg„Á¬VI´¬=å2Îñ@`Ññ,C™o/åx’ƒ²žr¤t©VXLŽøX‚Pí ŽdÛ›¬7V‘©|/p¢(°ùNÜA/…ò#0ž ÷ˆ!Ì×fÈ(.»)í·Ÿ~~ýö·?x»‚ö ˆˆ±]ã‹$\¯ÑRÉ…c>¾úüù§_VNòBes^›ž}å>^ Ç2Y>éÕÍvõ òÕX1Îèž~‰Ðã» ‚,*z†ð3ለ]‘ß‘Ø=ùȯ•Drù¢ÁbÖ%ÁBR]Ÿï,‹Áî¡v‡äaÝ—‹tæ²õ.ÜK™©9#ûzʳ]Öäg‘î~/Êù”Py6ñc®÷Ä5á¹è®B38±˜½Hõš^"ÖtäòëÝvZ¿áTä$#{ÏaŸtâ„­¿¹½º¹YžÊ‹ ì²è‘†ë:Åo_t³²µ¨…— –YœFÜW7ÿê E€ˆY-^<0M‰ÞÌÊÓªo[^>¢su{:=|5 Ôò/<ħ7ƒ„mλPrJÅÖÑu³ãÇ,ÏÇ4ÿ˪±ÑŒ[8@'O›öÙn—Æ|k°*NÙáp~y7{Ôe“£ùAM‹ù(ˆÞ¢:¯& Ä£7;‹Ô˜æCo›…¼ƒv;`Œ^@NÞPg:ưÎ~ÔÐ=2ej÷Ÿz|y&È/Ç—’d6F¦› r±G’µëHå¸^Ìøž™OÓ]„‹Åy‘»G8hœ2zÚ6%ZµlgÞç({<> Eà^`|lª2ïÍÀÒ°Ü‹ÆXžt•Fœ§‹•zTPëõ+G¸2ߤǶ7£7ë]¥OÏ;Ûdþ¼çÕcϦØ>´õuwëË [ò_?e1•Ð .œ‹ÿr)J¼pL —Ðý©–™ÆˆóE#8¨€Ð‚Åp¯wÍà®ÒWs±ü1ºº_R3jQ6\1ÆcÒ•–Žˆž.u>¾9Œ˜—/?Ê>»ÌÛ£ÎC€ ñ%£1¾â¹çÉ1Œ›*½ïô'{ý]ݺ®ËUzµ£œ}x&]Ç«ðÚ|RN!0dñVGR= Ùž Ò¨îF;È?êJ[é 6 Ié«{…kVq Qá½æÂܼ3ï3àe‹l*¹d Žùa±zÚzʽGúщ7œ^Dïs±Íõu>q ¹˜µŽlc*9ÝÕ<8Ù×üw¡KC9‹½m–û/_ùæÜ"\úe [ï!Ù¾Ô}Ì0ï÷èG$LO`3… \¶{ÎHØzê*záíJ¦íšjÝèt¿|KëâÈæãÀ“rœÏÖû[Ò#xÿ&/O§²jÚ"«‡ò2Š» ™ä»æ“H Æú®|fm78-`£ƒuLª¹Ž’1I<¦ Juƒup =óá ½ù»™i×å‘~©€«][¿Þ0ߎJiΦ-å?Aý c¦íÚªî¦ã³A2uüàÃ<³"–#¤®‰¢Ë¬æÐG„*²ùPͱJìåþ‰A3×bO¥¦ÿ]Ê#ÿ™ÅwõôSÜj6ß§b„Ö6ÝS˪¢J²o :íÜ–”ºŸ&,¯Ûf´mÿv;žàŠ—¿õ…æóð1¶F|—ÿÛÇŸŸ?N¡×[+±Hxn$ЮËnë{òØâD@±q"úÏ’FaÓ‘ _jþE¨:±ÆÏ$˜-“B£d|7uâÍl‡ Ÿ³$8Ñeë:'xó¾k³ý öÿlþØÇÿ«AÜ$0â^|áq;zû» k³‡Í¯¢À9ÿéYí¸endstream endobj 779 0 obj 3146 endobj 791 0 obj <> stream xÚ¥ZmÛ¸þî_A\?tSlx_$ - lrI.(’KãîË­Í]«gK>IÎfÿ}g(Éž‘%g‹&H`›3äp8œyæ‘^F2VN,‘X®/É×wðïañj¹øñm,b¾_Ä"‚¿±H•H“XÚD,w‹«UU¶uµÝúµ(}ûøbùŸ£`¬T “®ê?„/™Íd*ôµ¨«rç˶¹í¦hDµo‹ª÷U-öyÓT_¹Tš˜-ò•gjl„ûºº+ʱ˟ð3•׉•¼ÀìY{ÑT;/î|éQøÇ·ªwÊÕmEÝOƒŸ®ÚF¥¨ýú°ÂE`¶ZU[”ŠÐ»Ô‘&;º†Z‘&ÒY:Êöäb™ÒA_o|¾–AœQé ù¶(óíö‰N–e2ɨ :Ý‹nOV8©éáÇ*îÜ}’ïù¡Z{ì&ΘŽXå%xS4¾mÕ/fÆ‹)me¥Tñã/Ÿ?üþéó/¯Þüþñ—o¦Ôq$®‡«øm±ƒý·>lŸºKdâbªÁ<®3ˆÍÆ;§‹Û«¼\?;0n_ˆê^à&B4HgãÊí°Â»ÏìЭT^.ÅÎçÍ¡öxWàZµEíùÙÆ°­4qTKŠ÷ew«Vy㻳n|¹öµÈ÷ûm±ÊÃ]Û˜’_ 'O§ú†âE»} ÇX@Øû¦-vè`Ø$·Þ€%ÚÚ‘ý‡§óD’š±'"=ˆžò,FàúëÌPáU½ûâÛwuÛ¾éí¹½º}1›p°YÊôÅý¡\¡¤øâ}ç«á§ƒr±öͪ.º¬[Eóö‡z_5~øŠGÄ×|Ë\­ ñ8¦x{Åt,u213ªü²û–çÁ8‘·ò¾ïÊ‚dÚK~çϺ:Üm=ý¥è÷ô¡(Ï&6˜‘ÿï‰óo·/þ>wVA¼ð¸SSqGåÄO§üˆ¢,­V˜æàSd ‚ÍÉ”aŒDS)£G™ -W<»*H{ΑNÁ $Öé¾@á”[Vpl!£ã¬ Vš¦Iélì›XK—°Õ|Ù%ýàd,@º˜*4ã;wIpªqTKUG‡:…¥n„,ztc_‹z§íÛ¶ØóˆŽ¬òD퇚 5’ŒûFì}]Tëb%Ú:/›]6ƒåoÌAY‹$`¹×~šq:‚{ÉV½½zýÔ—?€ E» ¸£**„Úë¼Í™==¶ÈԱɡn‚” }‰xÜÀ žM 8)x°A^Ól†ß6C@¬>`œÂ_wQÓù2‡«¸ЫézØK^‡Ànûã5îx¼ÚŒíNôÑîråñ$Äg~%5$†„ Â]è‘ÉêP×x ·è´Ú¯y X¬6$Áýõ"žN íÍ]ŽC% 7bã=oØ£±QV+¸ËD|ÔÄô]‹?W¼Á®_SÅG†ñ¡:Kmô¬¡˜‘ãLsC™€B›0ž°sPèϦ8-~~Wl‹öiàA(æë|ß!ÆMŽiéó‘c Ò0l’™º¢l*]JǤU2¶ÅXÚ­ý=gŒT ‰T=ÓTu‰Ñ|ÂålÖ¿°…?#ë€HLçrÖU2ã¦?#ë¦2M™Î8-èŸóæ…kQH/¯»¶©ÇòÛP”˪»|í¯Cº›Ë¾©“&bëÂ…¹Ò™†Øå6vPz2Ô´>Gúf飧N²ÐmÎ,¢K¨ì䯇n§àL¢ ±¨§»§ØAmdfŽIû,0ýD`žûŤ=bg&¹_*7ÏýR©)î—Ž_æ~•›!r¾ÏýÕïp¿ î_L¹ßd’û¥b÷û*_ÏDƒýƒ `!âsU÷÷o§H*“¯Úª¾Èë*$ñè &Ó¼.•{¯gó:^Wi$A{öC/ýL^WVú|^Wbry]*q:¢?ÐÅÁ…cÞ2¡ ø‰)g]åÀå†É_&t¡N‚«¿Ç»ž3®wtG—8×8…HÊXLLr®Tn̹âµd¶‡m˜àü~~l8ñšÍ1M„ùLQÝóñ[Éø½àЩ¢qD"¸ä‡.VÃÉ$ŽÍÈKvšûr³""³Tö<¬vVºŒ*q8ŽhSsŸ,/ZpzqÌánìÓÀÖY¦Å饺Pã©1øû¸×B^§PW•ÛrqÚmø¤™×E-R-Õ¡EÞcH!Ððš˜a¨ö ( ¿þÌ·Ï‹ú„o9_­Z䍯’<¶^s$k´d–ûº-•`õ܉à–yª?‘—Œ´c†"VÉ {éØbÈFÎQécÖ»îŒÅ÷%TÆtF…BذqpÃC]öˆœR^:ÈrM‡¯ÇŽE›±½L@b €ÄXC¥$ž oXBÅŸÞ©Ôši…tpêÛðŽÑ6å—¸Á¸ž|1ôÌ 4WDËÌb>­`=&;€¾Ó)8ų: ^¸ùø¶v‘H?Ã5Êâû3L‹^_Î}ìòoÅî°ë8Ñv“·çñe0J˜Íü%I`bÈ8rÙø²ÔnýÓÀwD®'Þc=~…]T¯Ê2@cä…ÈðÍèì‘È0dú8¦éß·©`«µ¸÷~þ;>‚¼ørŸ×íÐ^BCî%4M[¬N:Ía¿¯{â»õ«MYüyðÇ®Q»)Ú<;¦^†üR| BØ2„‘©ðþÓIà[¾Ûoû—o†ûÈ1dP8¢“Ê † êè0ø)œÍ‘ ŸëáÆ§pͲK¥çìêà³8“R­¿½ûÜuàÅÒB„GIÇ–¶Ôø@^åcÎJg€#˜ÛæÛID:²ÿ­¢‚¡š*ñ"hðíC7‚ >•¨«Ph²‘x‰·ÅŠUÜIø<|thŸµ–×ðµÓÓG<±øjÉ$:ÖHÕ¦Õ™=ÔœòŽëßñH1 Yr⇠ÍHLgÖñ3Fm2€TM ãì]=€¥kãC &5z[VŒØ¸ßâÓS¸ÇïE÷†!lóß‹?¨±ƒÿÌÅÆÌ=û! ævòô·32Ùfñ›(aÿ0”Paendstream endobj 792 0 obj 3207 endobj 800 0 obj <> stream xÚZmoä¶þî_A\?ÄØŠ(ê- 䥗HRôÎm¿(ä]®­Z+môr>ç×÷j¥ájïÎA»Ë!9œ×g† ƒ0Vw/W¡ºÛ\…Ë—ŸðÿãÕ÷wWß¾ÓJcpw¥Uˆÿ´Ê"•¥:HRu·¿ºÞŽÛ«ºl³y{÷¿…JGšc”¯ªj†V OVýö÷¿ªÎʪS‡®Å } ~nùü(Mƒ\̱b<˃(áãÅpnÍGm'†‹0ˆ3>~£JÕï˺Våæ™Óš8 âœÓ¶;1ž`ã»wb<ÇËÍÐvJ°kò"HÄe=Zµ)ÇÒÝY»%®T?„Uµ ÍIW\-q1O‡ ¬ªA«¬àVë"ˆbNº³›¡$& ²”“^u¬ƒTóa«Êf ín:[¿¤â®êŸU»;ñ^íuKœ«N_—/C#ðˆ%ìÆVRJqÇ#!F…`¬S];T_ýaû€ˆoÃ@G©/¸(›§Ü÷­'²0 ’"æTåXª·ÃP5tJ"ÿö]¬rhš¹ŠNŠ Ó)ŸáD컕Îâ M-ù†`ViNñ±ÚBÞ$ö¶)j»j*Nàûvk;x©‚exÂÉU£œ¯ é3Á©—'Û¨ýXß:« â0ó¨“ÅòªMÙLï½:´àÜJœ&'±æ|îÝúƒÝT“œ¢£œ®ïÃÐÝõ¦è|0”v¿·Í¶‡_P…‰ó Ë ßØkw»wÎוkø¶³¤ã’ìtÆÇã^6‰8ÑA‘Å|FzÉ$bÄÀB ÚIcã„ì "¨ÎÓFhNÎ}RbÉÖ³:XȧNSdœÕ&2dI†b\†ZR³ÉÁ³È­Ý#l•‡C]MºìÕýõK5¼6í¡¯ú)¡å æOó‡Ç«¿Ý]aá„Ü:Q{÷ØBª¾JÀWþΘ¨ë«§«ÐgÎêÖƒõ&Ú1ó' §zÜZõ—bûîPOåü9aH3‘l«­°ªYBP,ÒŸÄëÅó”&'¿¿–öáâ|=‡%~FÈ®­Ô#É!#¾ñÏ’PB8R®þM_=6– å0ýò8åþíŸ/Bb +„!Dk†ÀéÔ¶ßtÕa8BjÀCc J«—„ ÒŠÃ N¸· ±Ý7€ÝýPí p¹Hæ!Ùi7Ì3¾žŒ¼faĸÀ².Òv \äatqY“¤À˜b|ÉTÉbJ©Â2œ¸÷`³p^ˆYöÅÁx@ˆr–›*·^Y™TÊa¨ú)&–÷r:M8VÐÈ…£¡8ÌNûÈ]e%Gyf|Âþí¹†C àG*Q³+.ú­š üí¦­ÕR/ÈŸl ‘™•€* £à~C°?Á«V±/gS†­ë3ñäɼïŸÊÔ“·U?tÕƒjtjø”Ñ™úfì>úU‰Bd„Îè±.P[[i÷ ¾`Û™ —~ðJ@„$t¶ÌíÊÉí Iâ¡|¨j0Ym.WÉcÿ¼™YÎk7OMõ;ð á`'¾¹Ú˜% oQ…ùºÁ Ö!ƒFEÊÿ‚ý8…ÖbÆ)>l[KÉz@ÒöA‘–Gð* ¾HŒ»âÈLÒ%„bA×½ªr=ÒöÐÏ8ŽS½º-ÒG–ðQ‡avˆȰíÈ¡ÿ}ùØTåµÉ°å0–5b‚B‚){æ;ØÎYs³±sÝžœÕí±1d¥nרÛ•«Û/¨•:#:Í9ù—ÂBj‚"3–¸0{qÕ_‚슊"³õÍ~>e„‚Љ؋º.ÃÓØ;Dþ"œ)u.ŽÞvÏêÅ¢¶!,¡0(ÎùèÔsTÍY#g4iÊ×ñâsèÀŸãØQiqâªS| SM=F®¾h‰~SƒFÂlM¦v""lSÖƒ«ÈØ„¾!¢‚ô­Ç\ê°d¹áã¶«_ývHD…2#ƒw…BûA–bJEx’ª«a€ÉîÛn­ºÁ!€dÅi©ú…ò&FªNÒìâaÈ‘Îåa^¯g ñ¬DiOšç—ÈÚ‘¬ È…hgc}‹„Æf¨ÊÉ€$DªÉ N«}¢žîª¥bJ¡ˆt"ÿÁüb6 Ng馜ùlf;ÁgÉ¢)Ëœ&œ—S #½4ŨÂS*ùl3P?Œ]YÕ¢ÞŒLÄ(Ø:7§D³í“¦/9¡»?¸6H9- d²º=8§¾…ÆâˆY“•ZÃúkšv 6Aí:dﳸ@Í(”ÒÕÒ8 1ޏ°n‘6AÆœö;ÞÚ´c½0Ü…ðy—YbØä—ÂÙ<•MÕïp£¢¶2 ðN¯ž¥Å0 #µ àö ‡F‚ÇOÄb5;¢Æx©ÉdKD:²ØÊ”ùövÿ÷TîßÞ ]ªjàMÒ ~ìF€;/“›ÐÕÏle,ãDtL°¿½ÿeÕšöå«.ȼÈ4_KvOtCã«-4“ž"¸ ^Ã(7+8ÕÇjéH/ö|1!CØÈalöÌ—\ ÉŠMP,Š<¼²M9h©¦æ±wË€zZ ž…%P!áÃ̰g¨Þ_n%£úEêj+‰Ó]n%qªµVÿ|+ÉDf½²ýr+‰MýB+)*`N9k%å«­$N6·’î>½oe}R &‹sA<öƒ¸z‹ÀJMNâÚ¡Ÿí'E€¸†k(_ï'qº¯ê'EbžúIQJ·=¬}tþÃDý•ý$– Ó_ÝOŠP„gÅçúIœ‚«€D¼´”OIS—Ï‘M¥(DòKW½ÔT‚ëkÉæç›J`Pn>×TrKCiùÄ¡>×^¢3D‰°‹Õö§óÛKa}±»¤é~3?ù ¢j {j.½é< Ë )6Giô’)űN8;Þù×Ñt¹Ž 軪E¥1ÝÎM!tn5éÎ;íí‰^ÍŠ3óg^x™¥ï<»)aN}´ƒªaÎygâ( ¥|.ÄQ¿Þ"7ý(Ýn߈#нaI÷†ý¸yRåÅZ-&ûÍù´ÊøõGqò8¥ͨî¯ßýò¯?ÏÑæŒjºƒ`ôÕ¾:Ö$°—Ô/zu.J9á¤Û­ýò] õTç#ßËG«Nò=¢Í©ÅD×f€[×UØ´uM×q@)•|-@ý¼,lÉ„GAŠq*ôŸ¨;‘›œS½ÔvûèPÌ$ _q>_€©€9ŠÊF>Šq@*ïšÚ Lôc4“9/¶Cr¢¬z˜ð2{ãÂk¼£N—òÇw/7êAÊa*”Ùn#¤^—Tgvm½ŠÂèÁÆ‘¸òjbdhm88?¢l‘óQÛÑí§l?¶z8à ?·êŒO^iÁD€!pmFô¹L”¡¦ÔÃYÊYi®Åp"Így°¢4©àn1/7f {*؈.4eLNýtNéUºpìɈ⺭K߉"TçõJÉ\Oçm j‚èÑï"ª§ù™ ö峄þ°w!® 5ú­d-á}1÷cTÅ¿·íîV˜ûypÒ^pQÑcD¥ó(cÂÂquÚTêX;°Ä†WbŒ¡ðœs¢Sˆ™œ+N–½Óp…¢1µ-¶[÷ oÿ­=“ (Îø®†×cÂM|‹Î—¤D:{°„§mç€\Èo âÀH/|Ö§¡ƒ·Qì‚yËîð;§¼¡®Èq`ÔÝX»˜kS“²Ž-»©·ãèQˆ]ÉÈ<ˆ 6œd%uÅIDÈŽl3ƒŽ3t˜z{©©öYÉ, Äœ$1£¿”Yª%4§¼«æò2Ìý`œ‚µwYC"—ÁOÔ¶ó•‹D9ôÐ/ôÑ]œ^.0Zè ¾³;ß MBè•­x´ÁíÀS gaE ¯ºøÝºC hž— Õ-> stream xÚ¥ZÛnÜF}×W4¼k/d†M6oØ à‹ìõ±½–’샀€žéÑ0æ’cIûõ{ª›—jÎPV° Œ†ÕÕÕÕU§NÇ÷Â4W·g¾¸ZùÓ_oñßÍÙË«³ÞH!ñts&…¥H‘ÄÒ‹bqµ;{Úm‹V|{võÛøoºbUìóªkEÞš¿E½ÝV‹}Swõª.E½×MÞuu.ŠŽ4»}ÝtX¹¼#+|²Ÿ›ª²ÑŒý¾¤±¾…U[´®ºò^´šÌø©§\ tkt^–ÂQ8 +ð¸¨DnÖê¶…€GšŸû^$²Ÿü4&§s[ƒdØéRwF­úáM$R/äw }éÅŠ/èî>×_m÷&_uuc—ÍoN&¾'!Ï–‰®†¡Î±ex*M¹”97.êUsk‚À÷’ØÑû\ž6!á‚ȱ\ìò¯ŽÛáïP:ûëÖÄA£×‡jmn»É«vWÏöQÒj[yµ6— ïQÐUkm zCž^û¾ïÚö´*:]Þ÷¤‚pL~72¬9@yI›íKMwï‰7ŽÿTâ)_ñu#´#®‹Üå¤î\ÜÝVìë¶è Ç)aâeQÄW¸±ª/õçˆÔÕתv¤’ZœÃÜ–z}£wÈœ¨,õʦ—u÷ïÝv”~+1L+K×µ›ç½ÓdÎó·- ë_aýF‰Óh$J¡)ÕûM ެ S/ʸ&k¬€;¹}ÈÛU^­4Š/÷æËLO\»¢Ì{Ãr•F^¦\û¹8•Y?=´[¤eêØg§Ž³ôÆ`¼un>P^¨.XJØ­‡˜îÈÞkBÈÑkë¼Ëݨ/Èwía§×žà;„iè¹–\¹3f³Ç÷{xªœys¡sÂȇIEäGÅ×C’ç“%NF"-àLxˆ3&º„2@°@qÁ¡ú ðp-¡»öìRÿ„-Qâ…ad*OyfxÎ%J€˜+'>ëîÐTb‘#õ³ó˜<–8Ï gÛÓG"»Â1k¯¨Xm•ÉV±Íét8œ1Áó41›LKÍÓáƒù&•Ο¹GGM d숉u³{S”ú¢BBôõÓëg‹ÎÒÔ˸s3Ožr.——÷U½G¹61ä¥Iªˆ Ø7gWg¤XvC±3Ÿ“ŠEy¡$ñ‰/¬ty¶=Û¸tç(êŒ>ß "iŒùSQ­ÊÃZ‹¿U8ö‹}ámÿÁí'ñL*´âä›_~®þhPºe Š=”͹8s¥ ‡Ò ]éë§®@ l9Rwi Èñöa aaþi¹øùüd â à¢X¨*Û¼ù ÿzƒãUùîX7¨’ÿŸî¢ÚÔŸºFü]|øéýû£€j*zäðÛ X\ 4º;¼×vð¯Ÿýu1ÌU–"<0N…9—¯u»jŠ=å´EÌ-¦¢ˆ>Ú8´ø>ñ)µØP1åu…Ø+UÑv:ý}-ð‘aº •!L©ä1ƒÛy@Pú)[ãd:mXþRuPY‚Ôfk(øŸ[GJ¤¼[©Uõb—˜û%Õ„fB®#êŒÜJ[%v¨l@^çNA¯’”ëv±–Å!¬Q÷KûÆMt„ið;õ¡ :M$GãÖô£î·%²”WNÚGp„«¿·@­”¨ Vµ å÷DJúp;«Ö}}uäJ2«ˆQ—”È@z) n½ÚêÅæ&̼,æz 2>2–Úš Ü—ËS3ñN7ŽaÛa {ÛRKÔmç^’u©›{n…r™¡—rÏmÞ¡©ÕÕMQé‘HÏ«d¿²Ñ¹¹qÛ€O·b]€ÍP÷ºiêÝ#kúŽÁí=ÈöN´`dùMÿÇtˆst'Ô6Äéîy#ÏϘÑߊ5‘FÚfÖfª(55Šêæ^€¦»$]yAÌd`ñ·¢éy9tki<´ÓY:kÙTõËž€OçEl«ÖõœŽ§“¼}BÇJk0Dcu[ïœv¢u/8ˆ•g1ÓðËÁ .Vænð:ð(ùÍ} Ï\‘ÆÖv„ úänˆÍ'«CÓPÏvëº4&²7©¨›¯ä})usÿĦ°<Ùá*9gŸû‡V¯‡A #΄7ôqÖÀ^TÜn Ëj€û—RÏš\Š ™°4¨M¥ËËÅ–‹S¶¨¯îK%W1i“+Kª}š©FY?­:òá3®™àå¹õe„cÍ2ÖpÕ *qÓ;ˆf-m[¯ ´vKUL‚÷JÔýI ¡Å¯ï>¼ù¸4QAO¯øÓ£›à È1…\3†ñ³Ê¡S¦†®h—߻Κv7ÏcJÞ˜IßêegãHJr ™·}ÓN,±œ0psU7”5uÔ@—…íp’im«ohÀqYüw¡‚>ºÅ—Ø ëyо)€T|ÅrsúñµI…áÞáa{™d+o&ƒ¯§çt3°Ï8Ø©n@ :ƒNý,lÇLõà(AÀí§»›0• 5 ŒŠ¥b ÆPD”z3âÌ?S¥¯íGevÐû©ü,ÏC`Yÿã’Tæ0n*rǤ¨‘FGÛ||ù¯‹WW¿¾y÷þ¢Oó$1ót¤Æè-Òw‰*®¦ð‘½Ä5ðá\üøîÇ‹çÝýÞÌ»jxµ1ÍG³³B·Ûbµµ39´S@\K+ÔÚ©;*‹@¿cf Sw ¶eü1AVWŸš¥Š[”ý½nPÿ·†Ä?ž/™A6ì7£;;GÕÀÜÏæCµ0äÄB‹–Ï‘IÆ(hh§E·y{& Þ^vžœHÛHyûΧOú'ãóU¾Úê'âK} ð¹œèå_¤Üä± ¡ya4Ÿ’†ÁÓ—º»º{E;½4û<ЊÄfö?-½~f`¤êÃy¨îð¡âõS³TˆýÀs°ž5}eqä,Õ®ˆéÚvP±œ×¹P)óå^䇮ޙw:HºÝšë¡ükÀptÕ/ÕaRg‡Ý«QÑ+«ç…KçLÎô(f{wTý©¡Q,ë‡/]<>ÀÕÝg¬]¶:’™fŽÑ§².ȆÌ»švyx$ñ|ðprxÉå–‡—\êÔð’?‡—ˆôP&‹5=ˆ†Üx±8èÅuâ&ÉSS´Ó™á§|¥®t8ÃO 1gåÉ4ºTLþdÇYÆÊ‹@R˜áŸÞ:ÐNI4ëûàÊöi‰™ÒlGãê샾¹\ 3Ù9¾e/©-Blìjš&éü+!纰Œ¹0¯ž[ÀÙ‡°”jRõböK_D|¯ïý""èí[ÀÛŠw~~ñþÝë¥nJ_:1qØŒ7MíŽÉ`^ÌxâS?…›9×|.™åÁŸÁNƒyŠÊtê¾{'¶ccóÇ^ô3ÿá=lÿCú ½©°„‰ºd§Ð΄YqŽÍÛÃæ™E¿-¢`Š£[=œ5HçM†LÜrFú¨ãb°ÀM![ÙÊ¢¤Fì|øÂQ Ñsk÷­‰¾ ]Ú$Ëþ¸k€nqµµ“yó£ŠÙ[„ -ˆC®¶‹06 †éÌÛ ‘ £ƒ`Vpe4à5{\Ý#g³Ù? H#¶ìEÙZx6“•÷ÄXò}ÀeŠÍC3Ÿ QÈ7¶äÁy^è§4õ¤Ùû‚™#šQO‚w+=Ë‹Êz5Ž.Ã#ØK)!Çen|ŸœGf^Ê7š¬ü‡‡DÖí:a†ï_\¾x.Aa#±2oÇcóyø˜²·âÇBÐù›^™ÛuÃËó—Ó>(¡è½)/Œ9¡:2…[’PÕ‰þ3X”b»øÂH»_ÄÊZ4~žÛ„æL©ÏÇ_“™°íR8°—0r¤Ü$̰£ï<×%xñÛCad†cþûì÷3Z±ÃÿS5˜ ¸%s¾ð¹Vžw´€)Ûžý"*ìó?·=s…endstream endobj 809 0 obj 3366 endobj 827 0 obj <> stream xÚ­ZmoÛ8þž_Aô>lzhU‘¢Þp/@¶íîöÐm{­wï>(›Žµ'K^In’ûõ÷ ©R²Ü{)8ÖÌp8o|f(Ÿ­î.|¶Zã×ø{ñýêâÅ>ã‚­¶œùøÇY,X¦^$$[í/.¥'=á{OW¿ ÜO<Á#‡Œ½«êý«¬Í^—¿ÕQ]_^?%-ߟÊ"/ B[>wWྺtìÓCYš¼!:ßKâDÒ.̇ۋ׫ ŽÂГ1ÛÓçX„OYqŠÀq4ÿ¢£..v[×&’%^0Ušc×!×Êü)/×Åq£Ø_Klûê{»¿Ûú“*)D†œlóþæ7µnÊÊM¡œ­†‘E3rË”6µ¸¸Ô×—.Aär&î“jš¼*çË‚;ÄLÿ46ù³éÎÇ6ù™ŸuU6-[ï²úÏö×lïC[ÏDlj'ù#EË&¿-Õ†åe;ýV•3ÑD‡Lë¼ÜVКý½ûåíÛÙ !VHÿ˜ò´”Ç þõÓ¿,&PD‰Á§Ȧc¯T³®óC ÇjR1•„?ð+p$‹IíÕ.oØöX®‰“)” Ë%Î’IìÉ$±9o÷ »«¶,;Š|i{µ¯êÖ²µbÛªfm•Í>×Çîòv——¬Ý)P¨unL :/¯}ß7_õ:_†ïÞüÙ”Ÿªm)<‘Á‘ôš5Ó|˜Ãv±´™<¹VA·¬e†gV'xÂ=‘„6—N¿6«ÛOªÜ¨z,ŒÓEz©txÙÏ¿|Z±]æd,ª/mÓ"ûâ<çÂK\»QªCí¦~xqê Ê«cS<°uV°ë‚ûº Ä<™•¶|ãxlñÆ×‡ªn‰ð9b4ŒÈ_–“”÷ä•.™ ÛgP¥¼ –ÙôAÓ¶jã1·&^Œ hÉYíú=Ì¢B ú ‘ØÔ]iZðèüÄ¡g‡¬ÎöªU5ÛQ5 iÆ\ ª%‘Ôù†*$?ØÚJÇ{V«l’,½•ü„¬„O~$è·í+wB»Ì‚8è`ÈìŒ|éqœç–¨®ˆ.&¥³´e„¼ÜöˆZò÷cV¶yû@#¡z³j®ã¤äžt” ¿Qj#p«¶ZW…Éq¦’± ÅC¼—·y©ìiö~Wç¤Ï&¯Oïm]í_@‘ŲÔT,oÊ^¾§`ÅLÖk7YL› b˪íŠO2åp(…ûj“oØõ%Òd£^Ùèú©鬽9Öyy«¿oó½Ò+°n{”ÙzJèJñãš4ô…Çc[«-\dªSuå©TH‹¥2ç‚ lŽEü7««8'ÒÀáÕÇ@öØ‚¿v\ð¤Ë×'ŽŸÍ\¥+é»÷Žy8 Åý¨ÉªË895M0Ö‡Á{Æ›@ å­q`C‹µp«=‹ˆq\{D*Øè‚U!¸íµÈïŸWÿþüþû¼~¹úüá—?¾~uÚ¬2ð=òÈÈLùsû €*wãˆFÚ2¿¸öC¤öcµéí—D}Å ¦yʇ×§?ìv›»í9HlÂ/.¶á^:Ïq¸™Ã‚umÏçm£Š-sq´Œ¿Ì¡£Ãy“K]Cm×µÂËMÓã‘…Õ‘z¾/mîFi¤ÿ)ÿï–l?qxŒW;¨¨sª¤0-¾”WԦơ-„òêy_rRÙ—™LS$*ü£ 8aBDßÄŸ0a ò'ö¤sCã:ÀíÖT `ŸÑ ³} t¦¡-ékA«~bs Q‹*^¨m;@ʱ ~Gø  ¢?<öú>ÛLëCSˆ¥r-£¡º› 6³ˆ Ð1¡vY,_Ù ¹ǰ:–B¾¦Élî”|uµºZüyîð±}~»ƒÙºqŽe¯çõõ³“xƒj— r»×ºïB¹&O×m9”x&w»|½Cá)âe7E‡ûfDz¨èð,_Üç)¬ê<‡JÖÞtŠNTãnV2³Õ$Ny_ðÅÕ$N¬$vž÷V¹Ûá`&‡bÌÑŒ§V †Z¼®(D[å±÷[„űn€ë .?T8ˆÉB'a9!cµ¿Ííœc|Òa‚Ò:ݲ]Üi—t—««FnEH#/qˆôØä±ùØÆOgçŠï×4ós#òÑrs›ëΜ]óŒµhóC1ö‡¬ï²»ÉKg™'Ãóu¶Þ©'ì¦:ÒÙpùP…N¥í …Ó);âOª]Ý¿¤µ¾×+)ÎHßHÚ¼ÛTu‡A¿%v|}Idµ:dèÑ¢wSj£6à·æNErx‡ÈÖÆôKO§Ú­ê Z±c[!º ‘t«í# ª-ÛY³‰@x>€¿%ÏÌlÛ—ƒ¤—FвUXE¦Žlk¨¡çªØ½3¬€Yœ–l©6íÎ9ßKéEé‰=¬î?R§{ñ¢Z¥®ÞCÚÖûûz‹#ÒúLF¤Á©©MÇ>ªöX—““€Ü¡úÕß^;ϳâ¨úJðåk †,¹Z²*À´$gˆ`ÞJœ^F4§rM‡Gûƒ?ÍQsªn„A"˜cLŸ?ntH ûÈÑýÃÜš1Ÿ&ƒ8Ò©oñèÚ¸ôŸ ·pRyÎǹDIÃ-šÏç@p؉ÛÊDÏ5,=i3÷t»“Ž0õ"?¶Yÿ!:dàaÉþ†ŽPDk1w ‚Z+OT"RIÏU´Jÿh³-êo7ðw¸'ö¤ÙSê(ã‚tù¾tžwvŽwB€wYRÒäôa§G z¨¶‹¢NS¼‰R¬oèºéÿéœ9ðe’ ‹¥ciíþ†>ŸÔ:‘ µŽ–FYÊòò\»Â½8²¹Êã®B#²%Àt—7;¥A_­¶ãÀ¹C?ÙV¡—õ‚Ä©£Õ· ¦$ÚwOß4™òØ›R8»éo:=†EŽå¡™þžú4OfÚŒ¿±Ï33Ö'/Îí¨Ÿ¶õ³û£*”Zöä!ÒÐf&÷lk¥¦×)tUÄ6åüÙ¯á\j§ûn.SEUPÉ莢MB¿ÿPAÝä¦ ¡öb'+4%î²d]±I"ÆzaQÐYx¦chå“8±9ìNîÍ»_¯Þ¾yµ4S SÃá8vêIpŸ¾ã±Äd¾w¢Ã·ø®ŠÆTm=%ÓYºuw ŽÀY 'ßž½ø‹%ÒÏæ9;7¤›ç$µÉ­k¿‰%Cº;·(ï×@†@ÑåI?fÕ0¡ùÜh?±¥^â,5™FŽÍüI.Æ×t´Åô­(ŽÎHøÖ[Qüä[Q6™NÖJÇŽ9ξÅih÷,üô{Q6Ý£Þ‹âœ^¤2ïEÑ Gql½5ÿÂP?ò½(àœ~/Š‹‡¥!¿©ªâ„…ÜI8÷ÂÈá:û>“ˆèBß¡?ó6S/-h~ý]-® õÍ&g] 0ÄÝ;;0zÏâ³ç-SÈÖÚø‘þÜLì—Ñf‚Ðù›> stream xÚ¥ZÛrÜF’}çWTh†š a\ ·˜õnP¥ñZ–4R{½Œp€ÝÕÝ£6.¢¹_?' ·¬êEÇÊaE •uËÊTõá‹jo0Ê'=ÈÝåÝËe‹õ£7ŽšÓ8õ²áÞy™·yVÛ~DL4BÿtA²GÚü!ÛÀÆZ $Ôõ#ÞóQ´94Ñs†6«[-–qr‚ahÅØ‘KÀ–íèâ´eÌû ÑózŠž½R¯„ ~ ß³Ž]«ÏkÑþc'MÞA“ˆÕÿŽ<âËí‡Õ‚ ¤¾¹Fߧ芛[½s3½}ÿó—üúúãOŸÞß®nߌ!VS¿³|%’RÁÕžaHë!$¯3x‡ª¿šÊŽ|LEV·«ªXwˆˆ:ú—DêêXç`*ü̉'¢µ?GüÀâÔp2BouÝÜ•vÛ8¹7_°Ùyûãä zr8&¯dIèœ×“ ¶—`<ñ"{b7å0>ÁÉ:[ãŸ÷UWnˆÈÊMÈkEÔbC 1oõÇkæ•剰绥1€ØØòRiã-»Ã}¿AËQ$`?Œ®££hÝ '0YT`m?L'GÐe˜oCú|bqÖ›èéTÛ}×Uä»܉ B ã·|ž!Ic7£!õHâ&‰½èdò >Ý×<Ãz&Lµ±aBFNc#&Klò¦=jÇqE³¯ºbCÛT8ŽlKQ?°ö¼7{¸Ì¨eÏï÷ÄRhíqð§qÆ‹hµ¼ë0æàÄ´µÓ‰ÎÀÌéd>ññÈè?%*;“#[ã`‚&-b 2¬YÍ(ñÃÕy£úÍ#o“ŽÅ ÁemrFÞl²ä™Ätà[wuMFo„—c•Ó§j6c-O³Þ+s½ÈÓáwyYR¸_v@-†øv÷Ò*Â@r¶úöñ¨&l[8}y6Uý²ú|{óÓÒá{N$yOq"XÃvµ®&/0j 4ãœÜÝ]®^½×£Agâ`å³:ª¬m^0†Iär³C‘ÒxBø_#€©w„nh×;‚sõ.'>«¶«KaV(°^CêÌXkŠö¬@Œ\Oö¼ñlÌ”Édˆ7&wN"Ç• 1 m—| Ù™¼G[wKt>‘À”Y×zïD)cÕàj3û(pü?±8¬®É{l³¢Y¢ñ^ìø¦ôé궆Ÿ$‰9|EyÑÕðO|î^'¨YCtƒ€Ã躰ï´ïXî:ñvOîØ'­ªÇ^Ã(?]`&k?r’Àh×¹ÑBÎæÅ2åâßNÚ|Ê]£“ÉÛ‰%„ÒØ®õ9¶’F¡±“œ\q€ LPýÄ.Q:Ÿ«ZQ&v6 )ÍåcÓP6Bà5Gâ kã8 †&µøÁÝåõps'efãXaðÓÏŸß-Ʀ$uM³Îw/ï^Š!:Yº ÈïÂK÷ºƒY›Ó¸ÆÐ™®™¨/2zÒøt/ÏõÐw8ŽxWg C™r¾ aØRäËd­’22  —‹ ME[8äáãQ•3 =ƒá’ˆ,ÇpßñÎa8—_ËêØäÍ­ÁÞ?v·« H¿8Ðoézt†ÅEè×Hö‡Aº¸Ø_lÍ:û¹_¤Ðbþ2BÄ”ØõÍ1wöÿiÅà –@Go±ÐÁ“"° [|֤ᶘ 1„ï.M¿F8<3š]ÄQ!É\¬ÐŒ²ï•½7ðé æâ˺²Éw=ÛoÙçûn»Uõ—üÿNaÞó_ûÁOöYý7þ9/·Õ§¶ß‹?¿2Äáÿkõ4Á{àÝ÷½{ù÷E;§|+‰ ;?{7Ãåì»Qs™kdÓg*ê §Y¾8!®Gjîþ\@82æ=‡ümD;"C:¬«ÝÛ9hô<ù!×+Íûˆ~£2Lú†gÜOCòso$¼ Bde}]AöªÓh™H.OrQäTª¿ÂB¯û̃O†ÿ€õ‚§ðžvæâ¼YÕ„ö›¬ÍÆÊ¯x¨©æWö4X ‹¤:ÀX¡ÈÚE.?Ž'uhõ³{5ž6”U?W®oIZt›#õéîâñe«sX}‰°tÇa‡8˜yž~ÁÂÕr¹A† KïªSy]ñëÊÇØïÎ’åLÆBn¢?|xûqáÌe —ŸôK{vmvLA‡S kee½Ó3—BŸvŸŒ\5NU’Ã, ލC9æàïû˜p®L(a)\|N¶GÜþ‘¨NÑ5ý5ÏXŸÒ>Ò ?¥ýI~Òþö‰êËÈžåY0$$á=Å!ßí©F7p÷Ù®7êÛ'O¯<ŒRq,º¢Ò†úúÍpú¡í‹rć}¾Þ÷Õ…þ–¯‡“‹"/M)ŽÏ¿Ú—c~ÀZM÷ÖÞJRU#%G`Rõ±VíÂ}"x°ô—fÒ³1Ÿi3~W™±'}œ º‘#·zôÚÀx¨Œúž}áûéÃ…awmµ®H‹;*MÞ›ÊÙƒôÍýº­}‘ëG¼}K÷¤útÏC-™hUç˜ÊºÍÐÎY«c–›Al*„ÒÞŒ7bÝN)5”7²õ>7ir?IØ8É›™¤L4,ÎÍs8êW‚=™Y"—7+ á<ò´©ý‰»DD,DO¾—™­-åK‰Î9ç¬ÌC@PWEáÝ`Œ¡~>hÿ¯x1¨ø„ ²Í(ù²^œ«êûnhx`‘¨N·7ߤ“&\Ö,@?€rÖžÕâ>[ÿÆŠÔ½k¿0KãD‰[±q±ú1üµÙž¹(ÀO|u1½^ãòU=¡®¾5mã ‘Ó®X{ GÒ+òâL˜Ï ³ÁogÁSHOYãëA|rÀ8ÌxtÊ+V, šâ @Â˼9 µx{¿Èz±£y\ … xµÏÌ Ádþ <Ìi [x™>§S”÷,”·Œ+tB6âÃT–°Ê‹Gl¦›µ]3ÁHo=§á_øc§gRâcЫ™¥I Y–aª±Ð X«ªà¤p®J§¶cÕä­õ^!tRàÿÂÀ2¡âoV×ÐsiiÑ×otf¡‡ééNbßÑuk/T¨ÍNú§:7v Í£5M¢¯¼{‰C†ÂkÕ˜°FŸÒÐc«}7\Ç/ŒÝuù&¸ÑÎŒ8ÞBõ‰Ö±È])<Ð…{† Á>(µ™ñÚNdä;±ËWmªî¼M I{àÛq‡ÊÙC>ÐÇ´ñY‰x§JŒÊP\Lyº+à͵ÍRè¾qÚ©zQ¯TIà~S­  ï`U£c 5ÂëÜ®ËÑÄå³­FbsÄQW!«AÛy‘·6lı¹QëuOêH—+°kES 9èy˜¥ö`ÄhzÎð7{Z‹?vô éaÂzØáÇž†¬=«9”X1ÜA„–Ó²VÄ)l ö(^ð%µ+A^À› …µ–U¥£xI6oèŽnGŒ=}¥·[öÑ轺êŽÃ32y þˆÁÈX-#L)ƒ˜ÈN9⋾唘ÔOwt™h0ö'ìƒïI6à· 5p¤±¼‡ftfÀu¾Sµ>ÔÃ[+z/E…äŠ\”PÔ´6.Áybß7vôX›/eD¬‰QNг]xè6+ åÒ:CªF¹¼À3)®zH> stream xÚ•ZÛnÛH}×W4¼“ < ÉnÞ°À“8™,rÛÄ3ÙZjYœP¤BRq¼_¿§š·.Š4œ &PÔU}©®:uªZ®“xR\Ý­\qµ^¹ã¿^áÿÛÕ¯W«g/=áat»ò„‹ÿ<ù" ='ÅÕ~õdâë1[ÉïŸ^ý5y^ì„JÚ’ç"=6å>m²ušç÷â¬Òõ}±>M)šµ.6ºé¶Áßõq½7•N¿Ô"ÛšñôpÈ¡Úde!rm/¦üÄ‘qb/öKåø’ë*½Õõt^RrÉöYUÒ+íu]CMÜ”Çb“V÷¢Òë’: œÈ³UØ>¼È¥ï­aI¶:mް…(·âÝûoÅõ“ZkAŠÏ^*;Ò¶¾{¸%{ŽweµÿÔÀTû·iõå²Ü_?¹~ÚjO¯NF¡H[ùú©C¢¿¸Žô§÷£q‰FÃVic ¶>V•.‘í¹ÞãS{'ýö³ZltÝzCW[‡²jDYàÎËö^7»×wbe/Ç/Ïœ0±‡á*æ¸â@Ž‚;Áêp®bc¶ht7§Çñ‚~‚´°€Aýľ_²}œ8qÚ¢tà?ßÿúïËçW¾¸¸º˜7»ÂÞSeµ´ŠŽÄK˼|ýær~?TN$c¾ÌÍ_zÝÔB_úˆÙbá¦J‹zŸÉ»,ÏEQ6â†ÇT:RÙsÝfÓìüÆ‹äÔÒ®ìuŽE“帚“K7øà+[–‡Š/±ñáÚá`뼬õÆL%‰a7¶üÅÚ5‚8UeÅ­Øó&ƒïvÖtë²èýºµ®ßY÷ɵëºÜàOrýl“6ikŽ-¼ðÓoïób>ÂdÀœ[]vú²¢nR˜&EX ›i×Sß¾ÚÓ˜xo½¾^p9±´uDZ‹Bë lÖ][à™xÇ'×üí=‡É$òu¥ÉìE ;ÁHõ¡,6dɳò ‹3A€n< €¨Ù=û‘ïD‰²§üÆÇÝ^bSP·÷âˆÓù¤RØúâtÈ&e0™n!Ðd8®³ãZöéêãåÅÛ«@âZ¤­+R‰¥8R¶…Ñam# ‘š7÷^ ˆª²)×eŽÀEÜéÝô©¥ëa…ОŽ[Ä ‘’Ø8%Y;0ÌŶáù°Ûcù‚ã.D¹ž=ÿÝWß²”v=ÄÅÌ%%ºÿí¯àÝåç%Dõ@/lÍG¡ã§Xé:1Û"î•nÞéïÍå7 Ä ÖwÅöÕ%Øg/ÝSäÈ[IVt|ß‘GI*—CH€-ùï“úƒ ÃWƒˆ§ùQ×}â÷¢önfˆ^èr±˜=8€´EÉ^ïMâù ~Ûrµù;tc¦H®X™óÁÕîv8à”ùíÓ{q¬F „Km¸0O"B¶÷¯ FÕ2b"çZ:W;lf7ì†RÀ±2Õ2ƒ8±ñ¦„Rg ´8 Ïl*¶FšgѦÊéqY¬ù@·ÐlÕï$š5È)Xv­ó–Ò¶Yÿ§šgú^IÐ €¡5÷xÏÍÜËnød¦ÜŠÂ»b5‡~A4¢àhiW üŒÆ’6q5 ćß?¾º|±à`IàxÓžØÌÓKØfxrõt7¼·žÉs0#^ž)@a ÙDÃmÝN=@±²¼) LpãɦºwDŸ¯gc†¾_ºþ8F+fisý¿´×â9± ÂãhiÀRšË.âÁ¿À--±×Í®ÜPy—5 ¡õŽ ²¶%FÕ…í¹º¢ðýKƒÅ³]ý€§(…4ÍÏôCùįÁ­±¼$™+#<Ôú|zEç@;]<‚yd&`cÖì,ûœƒEÖ¹ã%ûøTÜÛû£û£Î56µ|wŠŠi+Óõl+M¼dZ4ø2²%©H®ËcµÆåb›ž~ÆÓr3Pž…@2LÙ—(‘±¿/¨›¬JL æÌaÜWÄÊ”=×…˜bdŠK‚r!ñšÅ‚;€o͆Í_¿ûãâÍë¿’1e ¦;¦8q<ÀWUYq‚ÛŽøPÀoP"lmÁÀ¥°d¢i–«–n9¡<‰XÌQ½-ÁþŠu~Ü´àPôúq<°+»;î(À`+82*$Øt¡”‘>~do£-e¨í³Ô¯Íc?§Úé¸}D`fÕÿŒ.x§«>£ÄœÈÀ/µ- r€RÕe.…;F¼ÛºYžâ¶ÎE‡ïg]n£×;}Ööˆ\pßQOüÅeü€(/×à@ pí5ÕTˆ*–åd œ8‰ØÄYy¬Á†®€!QÃ6»¦Á@{:ÖC#OâîØRAíƒ*Æ…6阔è¸Ï8°õ.òºzSBšÀÞr«xTÊÚ+%uÁöʃ“ˆpàÈÖÉŠmùF NæÆ°-.i•";!åL,‰,®lÉïkÉ–så%ްàùŠº¶ÞÔñOΠPWÆl©ZßR¯íSö¿±ž2¬j–¸«d@à<ÃŽEˆ?•ÄJÔ‰ŠI ëø`Ó¶˜[ŽÏ©3fŽ™"GÁ¯»ÈDÏ9¶œøt_”‡ºÏ§€_EéöÃíêòj…‰%èä÷ôYIP½Dä«Óûà'_tÒùj·Úòþö\Iª|œ:ðÌfþÖ#ä? ûâ9»1t€8Œ$e+þ­™·Çœ‹IL¬7 _?áã!RçÉlÓbkÄ Ÿ¯«Í[ÙóÉ9dÁ¨œûsS–9ûâ¶J×z{ÌÅ?Å6Eξ~ú÷EO îs”0Oðç<Á–/t½®²ÃÐG™,–« ®?–oÛc±6Œa—æM=¶ëÊ?º~âã³^סYˆYé&”߬Mض^Ÿ0&|³t,ð!@¯ZrVO™l{¶ž•åZC¹ <¿IУNš¨JÎi¼å¢u]®©¹é)÷™Ü¤—I 9…Ó8ÕX‚V¦hí”¶ˆž¸ÄH‰kM­™lJúp5¡pnßcÊTûàÂ+Ó0Å~W¹œ¼ z¥åíži«Y²cØ~®²æºì…H´>Óm3Û¦w-\PM3_þù1€;`›ä4Àjl|(f<ÜÄmáǸ$‚,fJ<‹Ë0„s)[àŠJ¤È& žÌ<xèúìmõÓy­;eeÒK†Íë†<*tTP¦Èà–`Ïé›êFõ/lo|®iÈNûÚh άÈÚVüY¿ó3QïŽÍ¦äm¥Ø T`¯rg½Ò‘8µÆeÕ çÈdZêHê+ø“j°þ´êöÞiÝ5OtªQü^?Ù—¨ óì ¿?âál:¿¿~Š ‹^ô€:qØ2íV®ùÑr;×OLú‘fM›Ù,åëèšbª;@÷i‚«÷Å™ G‰½$.ôP• “ö ¢÷Qi‹~¦zýd @¢ÈVé÷2¼À,'2BN« +*´:ï_z6¤x mMrþcÀ…Ø–=?miy Ñ!Þ’š¼fÃ~ §€¢JàGž¬DŒ0~–âlüê¬FÑÚTàërcú¿K­¬(èÙÛ2nØ?Ï¢ ‰½eÃG*õ¯ý”…»ŽÃÔB¡2xe)q Qrظ^îuzØpHö¥'Ï!Ïß¿ýðæòj)„¤ Bå± ~,†Ú.[:wT¢ÔÖZ:ªò`mÅÆ©K0^Uã=¥ès0MÌ~0@+ô6ŽxOÉü. rxÿÍö{½!ÌëÀž÷YAÔ…œxÚJõ›÷ö¤•š°ñ´ÚNÇ<}jÃÙ KœwfaR²qó–‰­ )Aô€o³Ó¬/µÝ“®ñ­~®¯G¶Tõ–Û ê?®žæt][uÉs ´ÊR{ü#=›¹SUylúçK; ÷éÞÜ«±rQÁ«pñp L;Lظýjü©<§–2LÌŸ*ßñb¦õÔ¿i›’Ó‡{_ÀÍo«­È欇¢ÑólÅÅ:ùÄvžïP²U‘Ž è4÷‡î÷R¶í&Œ£žÒšå7G³/Âfßm¹å7G[jîÍÑÞg—~ç°Pº™ßt=SޝqD‹Xªfå^1s7¶zj¶×a‹‰EÚ?c\O)нÀž¶×aË=ª×Ad¢kuxÒG lu6N¾h…Ùéð|úÉÚ£; 5J¼îÇ=ݯ¼²îG3# ©OfËN¬È*Ï£7s[š7=p%ŽòO¦[lz Àð˜4ëyˆÉ‰ÀÏbù@Ë£ÿCï¹XïÒêç®rÜ‚O[(æµàÓ1ãÑŸâ¸ÿõ¾Ñu×AÁ½÷³ºâO!]еq€Ð|î?ÆÖÅŸþ3ø¿%þÙêÉÎAfâé)CzÇ¡ß$˜³ÈèdSöž`iê¡vŸ³ÊZwæ #Í¿U»·ás·»±ó€ˆRÆÙ[°x¡§å± ˜/Ÿ‘}—ëœ^/~ªÅ«c¶ÑÝ1ÿ³úº"=þŽU¿]øŠ °é®Ùn+ow¢`M¶[}Öù?eȽ¨endstream endobj 862 0 obj 3374 endobj 880 0 obj <> stream xÚ­[ësÜ6ÿî¿‚ãûPgf­ŠITï1ã¤NÛ¹KÒÖns7㙌¬åzÕh¥­vÝ¿þêEhW¶ssi𬗠‚ ðÀøìúáÄg×)üñüwòúúäë·>ãðåæ„3þã,, ¹'eÀ®w'gÊSž€ßÞ«ëßFÎ}/ tì[S§U¶o²²@Òsß“Zâ’_¿åG–±„–óz›ÕlÓ)²2SüÞšÖÔl4 Û”kª¤¨wY]ãðCÖl³‚5[ÃÞøù«›Ê$;VïMšá²_¿ýbg7¾ïw_ 럙5»}´ÌÝ@À´']É×^,¹+^·Â÷I±Î ndŠ´Æ„‰í“*Ù™ÆT®Úá{Bj—ЪÕ÷"_£ª\‰hRТ¼1°Ú%¾m7›nÕCA9¬JB> Êvmݰ[ö/³¿iJ«+{ðÆúÓY3PÇSz”:ôüÀ]¨hw¯S/¨PžŽËŠu–&À‹+vúR‘œë‹knŠ»fËÊÍ$}ZÂ†ŠÆcïËÆÀ×`qi’çl]¬E ûÎËô³ÝÕCßW¦i«‚e»Yg°tþ螣â C²¦Ç(AäÅAàà!ö³ÞÒP{¾æ.i’·fÚ´%eó ûr`Àm‚~oAW°é[T3ìxŸÁ9mªrgÕ°¯JwY¡àÇ;Ë}¶ÆûA¨"îñÈ%j7t<ö™d3™µ¡"ɇ;Jî1YF)5›†.£~f¶Lí±7p„u·\Vw†!”˜é næÈ58{Æ`Îu›¦¦®7mÎÚ"‡OVðNÞ¯êAâ†J+}P݉©¸Ò× [B€j©÷I ZA_—ç¬LÓÖº´ÎJ÷½¸ce•Ýe ¹nKRÌm=ŒFÿþ±2û$›¹ÉlCwrºoë-Û•ksŠÔ¦AµQ©¹ò|_º“'ymØÍÙÚPB—= a›7+˜uðêÐÀ ÇDò÷eµ»²ò]™æGï²Hnsssvóê¸@­ãC§$®æ4 G_²6M’åõÍ+ýð"Å4UkVà­€Ÿ—våÇ—Ê]jÚÕÇ*kžØŒ%ì†ðvfÙûä¹E.ÕÖè7á䱋¨á@ࢠä±òŸ,úh nÓi1<ð2ðÍ8ó~Ÿ£KBûB¤K–4ö§´„(^h_â)BXfwæ»Ïʶ†‹0Ærˆ9ßœ W‚ß)dö£¹Ìjô·çZWå~?Å~ À6eZæ°n³¼g}Onƒ 9¤t<òTLÆßüóü6©AžÊäYr›åYó8E¢™£†Hçù.~tÔÌÐs,„pˆþÀÃÊšŠÁ^@GðÁ—1"À &¹z“£¿ìÄg؉H¥Âñ`clUæ+Ôqe]]î þI9 28œwø °˜l׉ÌqÜ“²ˆÝ­>* Þ<ŽfðPuD"©­z÷1ó¾£Q|žúÄ•dX~o¾ƒÚ…A·«h>z°Î–!–}@­}éÖ¹¸ªBwÂië 8à¢)ˆ\<$ëße`v ×¾„«þ—µµ½~Ûe_îÃVdëõLóÖ«vIõù)·x\æû{ *‰Wà%ëù‹ùx‰9 °Ë…Ö SÿèàzH‡žVÊ%F©.ïf. oÅ5 9øF¼ÅBÁzIŽt‘ýÓ§ëúé—Ë_.?]¾ûñú?Ç…`õœîբߥ3çÒ{b¡_/Þ\¼³°‚áHÓ•:ƒkô3ázuGx ÊÉUäœÃéŽo¾)o3éÒÙ!œKÏ^Mæë0$ô$lNÓ/É3¤.Öˆ;—² kÈ ŒÃùv?XñŸÊC%0 0sw² ™{ØšÂui"…dýØÃL€´³{NøÂîà>ﳤˠƋ4dU=XÚ¢|È>i¿ÀŠujN¸i ”p{´P.9b &ã`?¬yÜÛXÕ›cY"I66ûupb5â©Ñ'O8¤ŠžÉDH“ÌÉu@0YØ&5$(„Eƒè ,2ÏÍz†dÀL½mk¤™‹èlö¿K>•EÕá5σbnZ£›SñƒbÀ¦^ ¯5+¤†ÏÕ/G¯nóÝšõI\ÒzeZÚs]ð²î/ª|a¡B ~ Ãìê´V86Ÿ¿9;–ý#zD 5§ž¶±T¨‚P.£øå‚+Hø' 7¯ÀÄàfá®×ZA—{œw2-ûañ¿„…p‚.3›!Cˆò’Ðè¨#Ok2÷·vc‰­±ßeäD ðøáòÄBÇ^Ìg/¶|â"t‰Ÿ/J¬“jÂöyÆëî!Åò¾€ U„áæÕ_­UÄÊÓÔZ¶ñ]º#m|.ô¢ëX>æ:Ó¤­±²èôPÙéóÕMÐÒéи¡Ýÿ¹Ç·ß‡[äÈþ‚?XŸ–„éx_ÅÚöØB¬Ðw€>5™ë¼ÇÝK©CO³ƒ¼›´¡áظt)VCs©`W"âÊe!]¸‹¶)gNð ÿUÿÉS­"+ÈUˆ!\.%“ (A†ËÏó.*'ãf½z!zR2ö4wyg e€:vDZ¡Üt„É ÊÊ9ôÄÀ©ž-ŒÓæZ®»Œ)MÛ]›'!lž·Ú4Ã<î÷6yšGÄxw¦0ˆ¬`†¥¢,œšÑ$Žuß^\_,ßÁ#k—íÀ\’;Ó•a À®ó2YCŠšÔ½¸Hj–v Ó­MÝvßOßA®„'á­ÍÝtp•ý¹p9ŸHi—Çy$Ò;¥Úc¨¼ÞÎò“ª¹²EÙ'Z ²"²*VÀ0K¤µ2I¶ré¬Gìz±56¢vØ5/6†rç?ùaÑÕÆçYŸÁ° =DX¥­Jw„6Àíð€0ÒBK¤!ñ!ã¦Úšdí±ïiã ™Œ" †RxÚWB]aË™¬D£) B°²ØÚv€}¬  xë!Y½e´iŒ™5›kçmÓm_ëóZ¯à£»/¸}L‚eõ‹ã`=âäLØà*ffÙP¹scËiþâ‚–ç] °ÁßûžÇÕÁ fŽr#HÊÜÙiÅIƒ=aꨱù“q¸þ÷Y²pQ“þ‘øóLàé;4«=°%ÿ< +m\¸v$°qÈ‘cÂÁ •Iž*ucçYp²£øí˜OÅzÄd»6ÓÓ³ ß韻DóG\N>¨Š¢½±ÜœÕ­Eظ,hßWŒ Ø€cæõͫՑ ¬ë¬tÐ`‰DD%é^"Q?¸ØæíüŽÃÿL*÷]E|±u ´kíNøœ‰ãÕ>áp_9ޝ–Â=¶‡%awÌíâÍõ¢µaí_Æ„óÐ_¦IÑ?¡;ÔY89Êyå)hȱ |—âšþÍ V áü\¦a/MŃÈšŒ›êã~oÙýOÖî‡BdÚV~ÓU>÷eõÞó3¯7J)W~÷lÁ]zeV&óÌßt @*‹³Ù7=š*f3wÉ"›MêmW<ê|·§¢9.Å ˜?Ôí WHd»»ßõ§6M$ö¸Ë¿bó=¡¹sXÒ!:¨ c¨vÆ]×µ˜“`÷E‡„ÏZõ›wß.¸N{‘OnÎì¸y5Þþ¾…›Ð8hЫÃèTì:#¼Æ\³jôÓƒ•!¾¶ïЉ¥Â¡A´v˜,t=:Ín½šÔP-Ç>¾[pXg9Sà…‘;ŒiËfzÚWßj%YŠXpݦØ…U‹tn‚Š»3Ù«4ÜÎrÔ¿¹ˆ'°O/°x¸Ô`1È„»KKsÒ£Ó¯æti1CÑU©“ñÉ¡…“÷Æwýj ’ƒ¿!+>ZøÇNç¦/!̇\,nÍÖEC2nNÙ‹@ÙÁ5ÀÝ] ÂáÅ2>xʺ «ÝOÿÒBX,&_`fOÞ¬I—æ“ímÖ3úKÒͱaq)B¶­ÀRœùž‹„øXŽÄ?®»ÁÅ¿÷Þ_.¿´å”oåü¼ÈEÉ(âVaèñ˜“-!f*í+=,v«Þs?p•>"ð¾çåæ|ȵñÅš}–jKm·p”ø`ÒVæ.¯Çù|vÎñÍ,KmUؾŸeÃGíTƒBò³„;>Ù__;>Ex!ØO€Gbe—ú@W’®²îkÕ0ƒµN«ùÂRÓ/BÕI4~žË¤”§Tã‘ÛÏcßÒôªûy B›;nrL‚¾ªÙwmÖ'ló§“ßOcj5ˆ —Å=øÂ·âvôîw ÎdÛ“¬€uþ Q’CŠendstream endobj 881 0 obj 4048 endobj 898 0 obj <> stream xÚ•ZÛnãF}÷W4¼k6—Íîæ{œd2 ™ÌÆÞäÅÀ€–(‹ E*$eÇùú=ÕÉ.Šô8³Ø@«úR—S§Šºö=Hq÷|æ‹»ÕÙµóç{üÿñì«»³|+…ÄãÍ™>þ'Eˆ(”ž ÅÝîìân›‰jßæU™âòîW({ÊÕöt»jYµë„§«K•àLVìÓ:ÝemV“Ê KÏ#WðJ`÷wÕîþâþrÁ±a™öý¥ØTuw%»Ž¿Æó6OÛþÁq‹{ß—|é‹C³ÍËGhˆT4øTdbs(WÖ"+ØÓ®AáÏ´{ ³{]“’ï©@Mí¤¢^±·)¶94Y#>þøÓrB¶{ÈÖöFðN]ík{“~í¦MëV<¼à«jãM™È“ÆÝ`CᆋÑR îоïù&qµèŸ¿¹¹»™÷ÖÚ‹#¦1œí1+³‡]ÃÄ]Ÿ|•P»†ÌpÎj¶$Ú¸"Ïä#8èðÐd¿²²ÏuÀ\ŽëŸóvûÚmƒˆ,q¶·ýö‡›÷·Ÿ?ܾÿ|{wóÓÝüÅr)ˆ˜òÂ+}䤤­”î*wÛ¼ WÛ´Ì›€ËYÄáÌ~ÈŒñ”¯PIËÆÆÙ€“®}¥í‹D?´Õá¶b)ß;î¡:”ë´~u¶âÆ^dÜÅž8¾(/tŸfXÃ"Êrvq€ |i%…pò'K5â× á‹Ó×ÙuóR®ÈÝi]»|}ÝùÝë’Mêd’la"G”¡hÙ¦­ØÔÇz+6\ÊÃr‡"­‹ 7Kñ¥cœB³}»øúßíwŸo¾¾ûþçw ÁëÄ>ÓDí¢d‚›®€ËäšæPØ|ÞUuÖ¡b¥­VUÑÀøÑÔÑS) Í5xz2qžòö…,TŠCsH‹+ÑT@&ì´;4X/ýù^Áä[~'ul5ùci1yíy–«Šd­q—Mm[*¾éC^ØSU¶gYGžNØ êê°2µC8€U“ÿ ¬EÆe¬dûXÏûcŸ­d^ç.ÿ”h„ÚxJ+ á!=•Ç–”€LNü”µ‡ºd€ 5ödR?³Ç ±çiqÈšù0¢sŠËP̶i#Ê adðÄ Kd7UíãåƒÉ&&I¼ep¸|ȯîÇÈõ‰‰±Îßfí ‹$²”fÒ@«o ¤ßÈf\`¢ÐK\ ¤ç\àʉۗ²Ú7yœ¨d±&FÙ}x<{wwF “3ØÙÏ¡¡D)Î ¬DáÌtq¶=Ûp~z´žmŒ´‡ù[^®ŠÀü_%Œs³Ï½íÜó“¸Âªªò5‹÷bÜÆ½™­ýŒ)Ý_pgHß“U|ø ñ¹`‰°$?æ±ÏÈ—‡B1–¶güP­¹,|&c&+ðoÓËÞ_þs9.pÇ(aqÌÆ…#'¾ÉšUï’«í8f³L f² ”«çÇj›­ß\dÎÛÑÀµ}—·=³92p,øðâ0œ“~FËØK’È=ßÔ3”.¢"Ï”æø^ BWðX{ÔÈÕ G™¯^þŒ«"Ó2Þ‘IQÛп,Ü&}“!³õ¹¨ÊâÈAX@)ÊRénù•©¼-¨´‚4ŽuÝöj;£“È‹%» …ôuß'uM«ktbGÁ.Q'0wÚt"Fµ«vé‰ï*^#€€$Gè™W7°80Žÿ8=•rçù´£%„fWT•›|Cm^ˆˆ<"`v–. Q|BðÐÜ:KÜ|úþ¤cUB,av²+ˆÛ_O*b-Y™>CGâ‡'qŠN®Ï”ÃjÛmE7x[Ä4MT«Õ¡ž‹ @€PÊŒÛp âÆì9qè6ßeö›CQ¸ñÉl…V,ÔL÷0i / ˜ÀÌyÒa(p(­™%¨ÃXwl{)ðIUÐÑkÏ/Ôš-‡´ñWÕ6Ú=ê&úØ3JMzM1Ô©à®ú²Ð Ü @Ø8¹BÏ&ÃÐUìº-ðéÞ_üvím5GhLêÎÓÞ 2ì\嘛PG¼]§#ÅÝ„–ä߸ê~VU Ò¿¯Êõ‘­¨Dεz:à˜\Vεx ¢¼¶³ŽÝ.[Ó¥¯ºð:ÂmÓ@~Ò­j»; öÛñv€& ¡t%³ú>E W¶éþx@M§#Z0j›œs4ÅmûrÞõ%9Jkû²ÇÍ qþÀY Ú&Š©QÿPüÖ] ¦´Åu'ªÛSñTRÆ#|sô[Deyš+”!tÝø¡É`Lèìû®…"ª©vf×sM‰öˆƒÍÖSâ“Ó^–²ô(ý©‚«j/#/ÁAËâb±4E1O@û½ËÈfFèü¢ˆiŒ|Aôœv8åL¤\e§GþøãÇ¥9‰=Íõ®–§Z1@7XØãÓÍííb#®í6ßÜ©Ÿh©a¢…¼GΓ|F3¿6Æt65'PHŒqhò8!V2N°Œv¥ˆY-m)õí(¨ËÉ‘[-z*ðb-\æ5O²„Lï¡eõöÒ},¦‡²€ Õ;œÃ?eFÌaíxâ>c|Oùb“¸€æëEî ¼Æó4%wt="Ü;Â²Ì ¡9IM ”Ù"_HMí+øŒi¼òÂAËPϽßÓ„Z'©\MKûŽ~RÚLÑKxiùyÚuK“‘’°„Ʀ‰RC7j”‡ö -Y0‘§b¦ŽÆ#mÓŽÓÑüã!Â49n³’ÏŽ¯8mÓ m¨NÎR k5XºÓÉA7â¼>”íù¢¹Ñgi~?6lPàÍbˉöz¨}M¿¿°#ï}úRT麔+]­_M#S£òjw9Ôv¨º‡Ab@R«Ód4«»Íÿ\ˆDeüî²£ÎX$î/M‡÷¾INO|ßAšg’°³Æ,ÄÊä/Clè@EŠ­fŸ­òSTò'¨”­¯fsö-H64vPPcšÇ[ûaá¥Eº^çÝÛÊ9¶ üM]¾F¤f ¾ÀiâÄU´†úšw†Tv\™ßpçÊ}~a-½ˆ{4Za›Ž  :5DÛ Rèjð ÕÄ—îc‚ÞÚK‹BŽÈ+ûrF=}3^ÞÎ<¾]ÝÍ•mí¬³}š×}ùh–ÇÃA¬§3¨Ùñ°+·<v¥æÆÃîó×ÇÃA¨æW_;ª_ );ãáhv<ìŠññð'¤Î;4îüU”o©·«Ud¯ˆ±I©ã9fĮܛÄ2Ô^,»qàk*Zã<øä‹£ôÄ2‰oËâÉkbWbÖʳSZWk:!kN–]žƒ*0i6 ¾šÞ'¤É8ñ]ü÷P¡Ÿtÿí‡ë¼6–¬Ð°˜˜»rÓá0Í;ãÅBÝý¦d&ÅVUÙÖUш-ßE\J»zÏó34ùQìJÒ í!Û¦AÚDŠÏ6ö¦3~…Ö(vÏÅ'ü4¨ Üí9©‰ðÝ=øt_!ѱ¯¨—YêI.ö£ô4OzRƒq¹–w¿úS8m¨Æ„ŽÎò/á4ú|¥]Ùã˜ã‘?Ö‘DÉ’ŒD縳þE`ÿÐÌTkì}ÿò{6‰Vù>ª\ÍLH³P“u¡½Î›UZw¿«ŠuÖ´Ó©eâÙŸ. ž¦—SÎcàݤÂÝ_LÚ^C\|Ô˜t½>Qññi×ô"àÏ+G|Uê5}q-‘ŠF¬,e íçþcìP¥Ó?á+üÙé©QÁ;_Ý9• ðB ‚׎®ªää<îqÀK¨Q:~Fg¯-g¾°Òü‹PwÇ>ÓÁÜ3i¤˜ŽðœýÎÄ‚ƒÌ0©§i |ö<+¨½DU|È»¡®ùß³ßÏHc‡ÿƺ?.šx:îɾ=n'ï~w¢à,¶=ûE”Øçÿzвèendstream endobj 899 0 obj 3365 endobj 913 0 obj <> stream xÚ­Z[Û6~÷¯ º;fXñ"‰Â.È6iûÒtÛ8M ÐØôX‰-9ºdàßsHÙâ‘¥?AY<$Ïõû¨ÜE-"¶\-?ÁßÇÅ—‹ïLÀðf!XK%KÁã„-÷‹›¶ÎËf_4MQ•¬ªÙ6oXi_-?ŸåEœq™eá¤od<Ñ\h2nkö`mÉúÅÛÖ®ï_1·²]Û5k+f˯í,k·v´ŸŠÏ2®÷ÄÖy›sFÄ l+ȶËm×°œ­òÝ·@éïÔÌpž_+Ã%‰ïªzÿ¾­m¾ÿX­½¿¹…“Á B4è´uvV°€-é1²Œ •…BÔjœÒq°Ú†ˆˆ”«Ô„"yáN¶ªÔCšË4 FñHéPl¹-pÕ6å¤ÜET/ 4öùdÙÚ6E?ì,ÛÀËüpØ«¼…ðiØÓÖÖ–-ƒU÷>îUÝæe‹ZíŠÕ—Ý·ŠxÆæTéi»µÝ¡F&ái Sf‚'á ­ã 8ÄB>¤ üòu«aG8˜m´µ”ŠËÈÌn.¥áQlèþ¬Ú­á_·ÃSñï6ÉYã‚lÈIġÖ[43 §Ô‚X)ïví…ó´Ly’uÑwÎU#«è4á&"?ªƒ-íÚ{IH1ö’ŒOÂþ0Œum›CU®›!ëâqÖ‰DòDªpþ¡k¶oKŒ$?gœbRH®éf¿vù®™Km©ÁY"gl@|nýÄ@~iê™BÂÀH àfW@Mk\éªóÖ⩟¶ÅjË –‚|€BT:÷+œÎ ž²®Ggô±Á…:×êÊíÙÛ½ÿµêÀü˜`a!wjåådóŠbµñÚú(LJC^ÔìPW+Û4ÜÛ'º,q DR±Û]s¬2\qšYÐt¨ûݶ]]ÒÒ£!ĈÔ´€ÁS2žï:ÛLû õJh Ûtåʙܵ/Lg§­¸&u› SÝÃáåxCÈêáð†=2l cC'ù9oÈ1šMLÅsˆÒXé¨ÐñÔŽ¦=$%ÏBALOz(cïeuhŠÆ'¹IFÀào— X86à ÁöøœÁ¡Õî1VCè4/zéÝb»ØPøq‘¤¸^ŠÆÂ)ó¢\íºµeÿ.Áv¯ßþ'Ôß©¢!.¼øCUíHhA.eD‚ºÀ™øH 3b2ãþ†ø ‚Jk.–üõá³]µ?CRêÕE“Ч ‡3›^‘aÖ…=øšžàþÕ¿fýCMcâo9åïP޽±Íª.˜!Þåq”ÌšXG€L&r Ëôÿ®ñð4ZhùPYjW^Np¯¯P·¬9ØUá"ûnî£(¢y}ë=Ý 3†Õà’K Ú¥aÇGÑ€ïdF&±C^ç{ÛÚ:´X P̘Pî눷”[Ò‚ƒÉ{¹¨ÐMÃÁŽôop¯!Ã0ZsÈWP§‰û0ñ¨ƒ$­b ʈ!ã ]Qo°!ä­3d؆·5Ý +ý¦ÛA‡ßç_´À®™åìË0Z™˜§& gÍÀè פךÌå®t–$Wch~šªvëí…1œŽ=0¯—zAyE\¢•‡W+/Е™ ·±»Í8CFv–&ƒÂ’„‘ÿ@Š­1$÷EéüuË(ÏUuÎêZ?m"3ÁÁ˜’eO_T:Æo1”Þ~™ï€N_Ûï\ßt”Í:@¶f÷7õìl=Ž˜ƒ_ÈyL¸Å`Ô÷¶ýßï=ÐO²Äù”È Ñ Ñ}×2Rc*¡3yN§÷mÜPM •*[^i** D1 åF©þ¤ãU±fÕ˜HÎÕÐ…H±‚å=¯)ÒQ= å§Ë¬0h  ÞŽJŒ³o«ÛºƒÜ@Í7ϵ%x†=,ùî×ßù´üóÓoÞ~xûé×?¼~÷ÃÿgÊ€Œ“Ù¿W`‰¾çêÙ£Òñ¹’Ö`¶bt—,ø6š‘ G¡PzfýXPÃ'<™]E@Üé˜,S24Î)e+5çY™†ÀaÀIVÊͳ²PjŠ•…ãgV†Wé,„ÔBNCH@xIG-x Æ`æáNØnæª4p#ÉN•3D_F<ÕDØ5I,“xIÕ È•¶^‘ñ4MÃyÔ)àÃ&&¬;ß Lá1-ýì ÓLIGçñÌM†ã@(«ðdOEcçÙ­JSé€Ýf“ì6 Øí/yýåmµ–šªz[¦Ù45 客¦ Ì*OM•–<½|᥯¤¦ úk’^MM•Ü3ÙoØý/¨i(qa¿Ë"Lä)1@/c}±à5Ä4*D&^ÃKÄÓHŸgˆ)P-.RâíIbʉ)bŒµ™²"SÉõDUvV lJ䟚‹,„ô,Ê5þ²'Ääjð¡®ÚjUíÊ<¥(Õ.oZÉ™êQ—W-ÆPT&Q¯…e§½õ»3M3ž‰`‰—I¯L Èb˜\ÏzR‚:XÀÑP[éuåÝÚ¾Ü^KXdHãѲ‡ª+×#ÈC©•2<6ï›\\øKmÎît:ÝU›»Óâ½}ÐS´·Jdë'Ãlzu+Âa¨ó®Ì;³Ê$=ãìŠÙýƒ=³Œº:ÔFH¯Ö©õOýþ䡼†.rl±yÑè‡^’’›°xQ>ǧðÎ< ç8õæõòõŒó£/ù³«mikm.œWUÙæEé“Â…4¢ÝCc‚–íè&ÛayüD©ñùËë9ÏÙ‡Æzæèqóê "dÏï• T¦ f¤@¹‡}¾ÑazÛÚÓ¹®­öpTÿËÞ5Çru:Çø âT,þ†œ(lãÆçª(ñ|÷7``P ÿ\¶‡|Öߨç;0ÚúˆQ÷X?{-/²h\k'`(7C©)Ž?-/3Y _¾•f¾p)/48` 4©)ØŠyØbÛr‚»#Ms¼…€|Õ‰Í%˜D5¡ÜU¨È ˆ=¨Á%"`˜‹^øJLƒßš£ìjLc¸û¹Ûö@àdړ騉¯˜PzŒgà¹XÍ%ÄÐä†Ïu ´–Pü”<^ö…Á”'ùˆÝ ,’­ü7 ÷|z4áÇŒ‹ŸqL£åý¼ŽœüŸ2è©R†Ÿã¥èB©P§è¦ÉXÿ,ñãÁ°ïÄ 'M_$Úëv~îµ¾(AêÆÏy]ÝyCmk jb"E»j†_ÁɸÝU[ÿ³a?u…¯’pÌß_8cÿ}R7‹}ÌŽ_DN]/¾»˜,¶]|d%ìóœDÐendstream endobj 914 0 obj 2681 endobj 928 0 obj <> stream xÚ[ÛrÜF’}çW ø²R£.¸ÅÆnmQÏŒ¥Y¹w½Œp€Ý c4РEóï÷dáVY´”ÇŠfWÖ-+óäɬêÀOâD{?^ý‡§«Xz±Ný4öNæs”úIê•W¡T¾Œ£•/zéòêxõxx»gúg0(Æû~wõÝí%¾òvW ðŸðD"ü“~ owºzó±nNŸþ™ï»¿dÕ¡Ìßîþ9‰ËHøR3qÏ«-áϧu‡MGѵÿ=ÔuÉ¿©¿äMSòå¥=zÿáuÍ%¿ûï4òw0n`ï€æPÂ×"4sh_û*ð¥o¯CˆÀ¹œ÷>o÷Mq"Ñw1i Ÿ‚Hê¾û V& R?ÒfŒÝ±h½ÇKµ§A¼öœï‹~rèöæ>‚þ«q¤7yëeÞõ3[^œú:í¡³.oNYóû56ŸUí©h[šã\Uçe÷|,öGïã§Ï?{m^òÆ;7uWï¡Êúœ7Y¿¢c})þ~ę޻”Ó.¥¢]Z{‹ÒxZ€·ÜŠp¶‚Ó)ª'šyŸ·ØVuø®ÆBê¶è ¶¿Tù*Jíá¿ðöÄid·ç^¶ÿ½ª™íÉÄâÄ–z.óÃÓ)‡J°ñ2ïÏ{…†ŸØ ”–~"Ôæ ”6ßÛ ¨„®Ë¨0ñÓ„ ·¹9žÙ_––£á¥Z†v/ßû`¯A+ø±bZÂNúÑ~«5†‹Ù†È~ûôý_ï~Øýöá§¿ßQOB“x‚‚U{Ž’p:óê°5_°{XÂötïow·ëÛ@)²ŽÌ¢Û¯;æ+6#ãÀé´çŽ_x;¾—¬}ÅfTÃfB[ÊØLîÍsQ–ÞCÎÏ#ðpÕêûT@òÓ 5¿ÖßÃA„šÂÖ|¬¦ƒ6곋Àøûút.ó./_Fmu]~ð¸Jû"±GÙaUF+ÃÈÈhÝ9¿f³J„~¢Y'ïœ5Ù +k¼Ó¥í°Zø; ¬bÖ)+‹öFy]ç†k: `$v/E}iË—wFÊÇ1;šC$÷M¬<Œ(8(ò.™oÙ²H¤){ yŠ2¿«þuÉkÞÜ¿]׈Œb_¦v×›­Y$vÆî,ï³.ûg!„‘ŠÏ² °Qx‚;Ñ/sútΫíy4Œ‚MsÿÖŤXøŠýHJI\­=D¼"O-<@OÏàÈ/»Ïw·?o ‰Œ|ƒ¹ ’M©jÖãˆ_HYûZì ‰Uh[j5öpQ¡ð…Žì^@Ö+N§üPdäÞÜsR?˜Vn¼KK!–ö¶¿4 M×ï±g-«P5…ƒû7õ£=:ްÛ¼óêGïTÛ|Oc`žÞsChSÝ¿¥Vƒt½oµÆ¤¼ŒL“?æXÍ>÷‡Ã@Jg-"´iäIí¦[J„ ´¹òíáp»ÿJøX¾æ™8Ç@±ÞÞWâ™Dü„E¹“}ÎO Ÿ¯™O×FIÄçkrœÀ wʪì)7ê+‹Ö(zËob å‹}Óô?zÒxÎzüÔªa(ð _À=÷5¬¨=×ÕÁØUÝsH:~î62ôÓ(Ú]"8&‚µçM‹í‚›’xÖhÄ‘ÄþÁ³ë5Å]F…¾äóþq.‹}Ñ!.Ã{ŠÅ„ûènÔÎ(¶ ÈØFŠýj¢;XºNÓ@ Ê%Ó üNà„°€ÖàÞËåPLE@\i{ßûXwy¯Òî¸Í(%KÃÄîÉÍg-d‰m°Ù Vüôþÿ|¼Û°ù °n°ó"Eµ//ì°¨&›÷½ŸèÛÖʰԔ{ ª8ª‹'ÔÛöDn6iɾf݇¯‘XÝ(KØÓḆ"ðNÁ–ó͆2eD°nó‘ ýØÔ—§# óñª¹…e¨z±ÁÏŸ¾ÿï_@ëoØ}ú¼̉DFìMV—ÓCog¤rdÀc&`ë=Š-½c‘ÕH(ô“4[º¡œÎô°Ê$S{˜—8›'l·¤l^F¬}‚“cÆ\^€ÈBdk$%?¬=÷ªº›(õ«+‹ì\”–i tPd U¿Ð HÇz<5yN ½ì{÷zü“İòžò*o²’<” £¨…keaÚ“)—l;5C”I±ä'ºaAÏE6; _( Éõ,Í+é"€I)»Ý”pÆŠÁÙLk'§Ó¼ôöjõäóÕábJ3ø4”Ë—ž ×ÕSMb=»µÃñïC   L«8óCÞ8i,XÉFõ\Ÿ™gyäµ!”™e¹ ‰<ÜØ RjS1òž¶£KŸ¼¯ÆJR‹‚?%#{¨ù~¼Ý(“HéÇšõ飖­1ɩҚÉ'¿¡öØâ`)¿þ½ÒµéÕ\œ¡SY¯ŠS1=£´„¹é2†’µ¯_,2±-µ~»6b_ëÇ –áRÎ;]Ê®8sމC!–dMýk&‰Øú½“BlCîõHi­£Ç¹Žbœïý…ë@A,bâÏ–Å )PѵyùHðHI'ªóW3i³—Mè’Œè’ôwÇ D¤MEñŸ§yx§=‚S4¦DN²)xŒ RÖNVgJnõ ‘I€om!Ó Yû6Ñ "8÷ö²”€çgY#Ñtb=jø²vCfÈÄ’ØGg3󌄞u˜p¹¨'ƒÁÀªØØïþs¡˜0 ÙVL„†¨Ú›iîß´=úsH”õº@.o'Ô\ãYñx¶ÏDúJØž)uM]¯]¦Ãý+Iü8 펕dãd’H`áü´#ÐÃÈî`VИ X2òÐæ„iÄ~qD§ì`p{ó*TšÒ“5…¹“Í»¡ü'ݲ†šk¿Žuœ¯P­þ.Ôê4Vlí‹Â•4°¤ÐîfÁuC[l;ž. ·ªV,ÔȤX h·ÆÔ\ ÆA ?ºyc¸ªüLýÐîò øÎ›VTH3)ºhî&“¸Û¸LÒ>q¿py5©Ím˜Õ½QÛ8¥$õã€õšŸOp,̽Š%xÓç¤T¶Ø63So•lz*·ÁJ@%ñIöRˆ•[z³MÅÅ¥HØ3q…`ån|º ¡zNÑöÖ/H‹´^µX"bذíWvÆé^¥î0~¿^Ì èÜ~ÛŽÌóÒ—7—›°Þwõã;F¿¾åÎOøJ»ed9§îl‹¦Öݗηl‰°Ti{„WØ’T@ǘõ"kß&µ\Ô‡¥f¾ú¦p¾nGBZf½ûXØœ|³ÁŒ oÃh„ª†~1mv jPeæ/nª•Û[ÃÐíI¿íNnºÈšn"ÁºÜEVa™l̤­Yg›Ó·æ¡°?÷o¼âqíe N&´§åœ$ýaÍkÏÛàzqĤ,D1à&Ax”0éIk´I‡t»¾½D‘+ó5úï‹åp (7ÜÉ9‹¶+"¦ r=XAUcˆ›?—À:d‹¨ÜØš¹¿¨è¶Í)Ýß%X}^᪤)ˆY/ëÕÜð&·®Jso,±ËUÒœøOÊ¥¶ IÊèYQ6Åí©fÏ&jhJuŹ€U´ŽZßR­ÌšËpPü‘Ghhp{ÊŒG»’>iwæ’€wKÖ <5õå»kÒð£=¦ÝUSï½óZ–N—I9™f X{^=éùñRôWlØæ]ýëŠzœðo¢Ç妡Yîâ‹À,·—·¿[t°;^ýêU˜çÿ®0'Tendstream endobj 929 0 obj 4281 endobj 946 0 obj <> stream xÚ•ZkoÛÈýî_1H?ÔâÙá<ø@‹Þ$»]l×iµé-QŠTøˆ×ýõ=3¤¤¹©¨1bÈœ;¯û8÷ÜK ¶x¾l±Ä¯ŸñÿéêÇÅÕ? H¶X_Là'`‘d‘Ix(5[l¯®5×\üõâ?‰@Ä\!cwU½}›–ˬøDdÅELDÓ6«·iýåáúáµuGã#¨'ÊøG"ÜP9öñ¥¬vMÞX9Áã(Öö¢ý‡§«÷‹+,&‹±­ýIÄWF*.£ðôÁ ]\m®ÖTmšÅ\@1&p‡ùC^.‹n•±?—ÐÌí.盿øçwGÁª¬ª‚ùã îE$<ï5HX}ø3®©@ÈÍÉŠ³¦É«ò¯i¹*2_\ÆÐxHäYã ?¼þÓ¬õÂ(ä‘!Ö“SÖó娻¬YÖù®ÅVôFpië³?üLla4Ob7s±É¶îʥʖNG KK²a˜pø­?í…½z&"qÄ#¥}‘½¢_±tù¥¬ˆ~Œâ:ð…Ÿ‹lõ”m³²euöµËš–µ›´edââ!9GÚ°]Mt¯bÅcMNò-¯º¦x Zö-O±rÆzõŸ8¢617šlÑ[ºuŽsÓGÓêÖר–{yžcí"àqì˵¿®jw¶§œ¨6ЏJÈߨê%—šŒgåp?3¾_À¡"ã 7c/>=´™ÅIÀÉPó@’k-p‘¦MÛ®aÕzäPJÆ<0‘/þÂî>Üÿã/³œšŽ%Õìí¡n"2žÕMï<Ûô…mR_ZÃñ¢h^—Öü¡¤ºpÝ‘ÄçDxX ÉÖ]aÝ×Ú)/a.ç¦'ábsH„7ÕCûe#õζ««%°ˆeiMõ­â,ñà³ÙÓÄzœ=ÕTöôåØ}ÖvuIEGÈø¾Ô¿È0€æ§ÒÖtŒÙs…fÍVVÀ=w‚°ƒ?i¦Ûâx÷1õ4*áB{ÔSNRO_ÌQÏÛ½ZÌ#*µº]Òƒ!ˆÄ| 5wÕ*;KL ÂKùÆ‘ÓÄÔ—»ˆ˜jäŸ(ꉩš‡ÇCO ÒSD<Œ.&¦é:2爩/Ñ«ÕCµÕßXÏ&$ò#Z D6údÁy^KqJKßL-B:9.nù q‰2BQA6ü+ð9¶«mú ˆKL²]_n‚íTslWK— íÌOdK(ï!Q¼qèå°°?­–º~BÐÀ¾FbžaXRáŽü]˃Ê&¨Uˆ ”DÜ)]­°…ÅVœ©ÈA‡A¢f²¨I¡ý%¨¡NwÕ•%B±G‹|Þø|ØÃuÎ3ÞëêUêÜÖYùUžR„£Œ¡¹_ÁÞãá5 ®öl-á(_“•+P„j—Õ=Â0ámc3YÞæ4õÅXŒ,J)îe)Š7>‘”Ò\ Žð¤¼Œôp}KYá±UÕQøí¯¸…—¸ö¼ýbßœVÙÚûyʉ¬Þ„ØïwCƒ(ø¼I#Þ£ùÒø6 U.†ú%&ôm™ŽògQ&b¤-f¼á mKP[h™ wAL×YºÜà¼ðë1ëÊÿ‹G >mU@{ƒì––N…€Ö`†,?*al’ñ¬x¹™)bˆœWÄŒyŸŠÂ™îÍ*û¾…JÜoYm·ðÞž»ê#}sÀ¤Ã¼÷J”쇰‚Rr„)ú-@aò˜êhãO8‹Ë*²$Û“fÙ×.u|w®‹ 9’ «Ïw޽ǯ»÷s˜áZ’iw ìoYöÜú™Z:à‰&œ“Z%Y¥k6€î};c ÚJÀnÏÊÛM]uOpJ¤Î¢˜Uh§ƒû?þóãâóO·oîçš  ™ÊÊnûhsÚasøõz,ó°±pœòDÆzJñ´†6}ObÙZƒzI¬áìÔ\?çÓ÷§EÔã´<%JPmVˇÊ p¨•†/·g±Æu'°EÙPEíOÕçÚÈPàpšnOa,A¥Èxå5» É51 ¬µë§£>žv`­ýy‡>ž•“®^9Kp@ĸóÖ~iÏQ¾ãŠ =çí†ý\¬œâŽþÞÅš ‘È4 +*4Ö¿ÒyTÑÂ6=BÆ9XÑÐkœq–•é#|Ò]&êŠ6-Û>2…Œ{Ï›*L”ÉÝÿþüévñþþ·Ûû_?¿ýðÛßÿö~ñþÝ\’ÂÜÐ_®Ö^o{à·¨|Já­+› Μå69âáš¶"¸6ñöêZ»K›ªèÚ é1mš®¶mŸ¾s׫âfˆ?è¡&l7´Ódr@¿Q瞬‚È –FÚiò‡4pmEŽ|µ+2¤uVäÖ<®3¹ëyÊãekÙK·;à¢#Ä´] @C©éoqì‰û¤…9JB ›­ä~®U@ñÅŒ@œ+rÉ|Õ·!¬ºúXcÅG8´áºµWjP n¼…'¸ÀžWßbJùla/ÉFÏNguU¼rä玲zTØ€iOœRpðZ’ñ·¿Þ<¦¶Ž8– Ö«®×2ªPk„þ"¿["“·$Ë€jMvüFÇQµ%d¼o—qF#x”ÑJÇ$ µE¨| ¯ëjëÒÃlǶ™M…ÈPwUëE Š©}þ˜+Áá „ã.—@¥¶WTdÚ¨D”Æåkÿ~+î²Í'Ò P 6¾´M°Ù€tA0Ö›9@de“òC‡" |ñs  M4w™Ú[Mž:C$½ç˜iÆÚHCÆ§Ê qùRÓe³»ëËö„ÀæTœ.KÎÖG¬ÄÁ§ÈºÔ¤u¯“œÿÀ_Š´&÷B”Zx:J?eóU Å5“U_n¾±êKM5VýñCcUð(1³m)¤_Ú<}kµ™e¬öêoz[wsevã"Œ€MP¯9þb5GYÀ=DHæ®Ó¢™{å ž„;­ 2BçQL¤Ò¼€ŸÐd¢TÂ-P U% ¬õ)k<]Íbw_”9 k±'/›n}]ȳˌ|4H8d«êK}ª…H`†-SZíÁBÒ¨Lì oç¶9Œ³_Ö—÷–³¥£IxLÎ|¶tDeùÂdž.ê°$ñû¦oE¯²5-óQú‹¬ó­ÿ ¹^ë_M¶þ}1×ú¿‡î©&}ÙàË}Ëh÷_ºlLD.jþZñØ5Ýü÷å.jþ'ÒVê®÷o!MD^«ÿäA/|aë?°_iQ·þa å^ü[•¯N[ÿ¾Ä^ýV¿“Ý÷mþKT (ã%Ï|)µ&ògºÿÃêH®ÒœmþƒäJ"7Ùû‡¥ö3» 4ÊH¶t& ÝçýÇØÿþÐÉŸ$[Cöóö&u¦< H=•1ÙûŸ<9”¦( «‡ï9a2Ôæ}Ïéô“¦BÝŸíðy8}ka<²ïxö¬Œ½;}lˆÔé«`AƳÂRâ?6ìç.ï ×üÇÕ×+;c‹ß±Þ× Ç=y Üq{yÿÙÉo±ÍÕ'VbŸÿ4Îo.endstream endobj 947 0 obj 3001 endobj 964 0 obj <> stream xÚ­ZýoÛ¼þÝ—aX¤¬ø¥m·M»¢kú® Ö 0P(6k‘%W’›Ãþ÷)Y¾“¥$–¢-É#ïî¹çN Øõý,`× øõþßÎ~¹ž=0W3Áø'X$Y ®”a×›Ù©æ>sÉÏ®ÿÕËpCåØ+[/ªlÛdeáDŸ\«ÐmùüµÙB%Ü„~æõ:«ÙjW,ÜT¶´¹mlÍšµeõÖ.2·Øóײ[âtAûh¿ê©]²ö‰a1Wx#Ä<‰ðfE¹´o—t^ZÅ<6Xš­ªrãUɳºaåªÛH7RÜD‚§^•ÕæêÍ”\ì¾beb ¤ù.fWÃyï×¶`W>¾gµ-–¶båÖVéþî°ŠtW/\Fûu@tÚÕl[ÖY“Ã*ÉA¤¿ÑñˆG!·,]Ü%‘ c†KÝçvyk7¶hØüô Kå|)ÄÂ/ßÍÏØ¢ÌsÛúhûÿñ<ŠÈ^µ­kØã/i±Ìí¸©´4Ü2‹³«²± TÚ°luP.ÍÛûÚ´®¤‚3…0OqG>ÇXšzˆ.#ƒœ‡°“ u¶ C,îèËÕ‡W—ðëêòd"*‚ˆ+2­ÓšÝXðÀt¹„ËnÊ>DÎYÖÀ÷’mv/7–YâÓQÌ£„hü}›g‹¬É°Ênˆie¸ Ç'§×:àÂí&‹uZÜZ¯Ð=–7 ¨rYϼ­†q¨½@c«MZݱcÛÕ문…ó®Sb!“ð@à%¿eàÊà0K[g•]òvã#VcŒåØGÛ쪂1 >K¤þN5Õ"2îQfÜœ^á¶=À¶s‰¢#z ¨ŸÆ†+gú-g—Ã=Àò¡Ô‡³kzru áˆÅ˜ƒÛ7¶¹"þ&Àß­‰ä÷æbAàŒ1‘¹c:잟ÎϦ-$*±…4£BrìÓ¢ÜÖYÝ¢DÅÚ¥âöÃíìòz ›Œ!ØÆ}Ÿ%ò™‘ƒ¹ŽtÒùl=[ÑÄ®G Ç$šK#¼2¿ÍŠE¾[Zö§.ïb›ñõŸ±þ^çybШƒÉGñ‘¤·…»ëý]RÈRðœù)Ë ý4ÄêX¤ ¬CõsvS–9xemö‚­Ò¼¶ó³?NÚÔÉ#Cl:J|°Üñ‘™$>Ò]Ÿ¬ñœF'¸†ÆSh`pÙ[£M•Ñ0H€ØL®“ï¡x¡–€Md)Á é„Ç莌‚á%¤‹UÇ[º“^““Ô{s ó¤ec›4+ø¸󃥘µáeÐnD¼_{yòxp] »³],—_>àÂQάìtÖÓ—[b\)®C,Jï|O5l1Is5Ä Á²O`5J—Ñ$ÎÞ¶T¦ôΜæ“4*ŠxHöó6ÁžÉ fÛ´J7Àò!ÖÌ…&ä픺ƒŸ”1žå¹M¹êø­m„‚\î'5Õnâø`䄈ž#ˆ]Vàz“ è¥TxÕÇâBÄPÈ”aöŒ¹ ø›èâÂGÜb›x!Àâ¬ÞÝÔöëΑíEšçµ»ß©Â%ËLôPå#øžvyhˆl²Â}Ö¬÷5`âì Pz"3iÈE{3õ7äkqe~À×<‡"ÂÒÈÙ:OËšø×Š’€€KEvIwù¤}ðÄm|j™€>-€c‘ÅЧ¡‰ÉîÎÄ÷Yž¥7mø‘<-…K¯dÃ.18næî¸6§ÃÓ‰jØ"Öä„y²6`©(š>¦¥ŽÁ1k¨ô:ïùx0t•Xî§ ¿ç”ˆÅË^ "IB$,ÐAÊd8C ‘‡&ЂiÂÜP%Æ!žEâÓWîî¨ÜÞ4ˆÓź« \Èà ¦CDF“bæªúí.O·Ä!K·®Äò½ÇÑîP+¼ÍOä> ¼4F“$¾t×”Ï*ùbŠærë«/Áå°Q¡uù]:*«Dä*C$Ø–Um.qÙ6eˆ.âZ½q”‹Æ'd­‹_ß²ei]9Ó€‘Ò›¼­&·Uy H² ñe¦]Üu¥ï¶ãéH«ðgüG\ÐY7Ö¾§…ÆÛ|ÐÔ6_¹KèÉMÆŠŒ¡xPxkzÂz]îò%»#WG.%£IÖnYS¶Ž ÷ D¬„-+¶±iQ÷Ž‹¡‘…Æ;¯ÊÐ}±«*Ç öÀQ7i³«O|Ì8ìùÃCu© DÎ×¥*NÚªs_†?h¥ŸX—*@Kšpîã 6ÁKúRÏq½®¸Ã+G’kÑ®|¿Îr˜A£ýæÚ§7<²–î*æÇ  ÔIWrÂK¯Ú'±,Å_ú`¤?VâèH´:ì´­ öYÍOO.^¾Ûg–¹[ú]¾cĺîÙr>/Nðçl™´™Ÿa G¶U°mg–ÿôŒn@éFË\庲T¥®J³ƒ w}ÕP`Ùûa3:ˆ4?h¿-Ë%k²=à°ómzè.³Vva)w éš”;)Ń0ÂãsXHWŽF¦riâ¹ÞÕ®ÿñåóÅõåÇ÷ß}yùáý¯½¼¾|EÉÎø%-í‚|Bç»Kó®W.|°?Ðbtw˜fÇh‹ËM·±ÔX‹` H¦˜l•H€öîø¤×8Ñ) 5™rÔ*Ñ ?Pâz’犊PãYö9 Ô•tÊ€ì‡.p hYpÿªévà° íLLÙÂŒÁì@å÷5ËKHfû·DÇ„‘ò…Í@¹‹±ô"µU&ò}4úÆ2‚MxC‚mtˆgýO {´÷,¥c¯¨÷lF{ÏXìë´÷y ,‰aÿβH`˜f¼³ŒåžÔY®OÔu–Ö>?ïöñƒVú‰\D ð°'w–Ý«‘09$|œè]x$>È¢$À ¦âƒæ2,)—œn.kÂXž‘þÚùØê:²&F0WñdÝO±§qÍ%ºp,Wÿ$¥¶ƒ;ºöCmï¶2&7ÚöÆrö·àÁ¯û] «±®÷×­²ýë~’ºï‡Œ] ²Núӯ砾Y€Ý\‹ì9Þã·ß *v÷vØ…v0.@ÆGÞ~»—* ºú·ßþå÷á­v¨cé[½Ÿ• Ÿ¯š}8h½/M¦ÕccŒVi}»ù¼¿¯é^†!€Cs'Z×¾hXÕAÿ)€´‰‡§[×JJŽ%ŸÒ¸ J4šÃÙÛJœXAî_@ƒƒY  6šñ} 6pï‹]Íš¶­ ´FÈžÚŠA Ê(íä¾Rwº‚’ÖÇqŒäջࡊÐpyGñNpp 4Þ•¤}Ä´$ÔWs%¼z[Ë:yî/Sd¢Ð‚pÒ‘ÊÔ1CH‡%× ©œ:²«…Ý;Gt$„þo ›.#C–ÚO Ø3(skí{PÝ—žð1Æ/D¾’$ß|mç©>™íi÷/‡e"½eŒö=)…êH)¬S”'¬û,]«ð°ïÈ/M„ºÕ­ÿì´Ã:ÅÑ:‚ñÿÍ`/íæ€Í ‘¢”32•ØÖV@ßì²öÝ,óo³¯37c¿—wêº1ÎøÃW·•ÇÏŽ& ÅֳϬ€}þ iN¹endstream endobj 965 0 obj 2877 endobj 984 0 obj <> stream xÚ¥[msÜ6’þ®_Úûpò–Ìo|¹»½*EV¼ªØ²ÏžlîªTå¢f ‰9!9Vôï¯|CƒÃѤÖ.'C¢4ݺͷa ˆ­žÏB¶ZŸ½ußÿdzWg?ü㿇3ÎBøËY,Xñ@åöìü«iÛ¼|dí“aóðfõÏ‘‹4HxâRgû¢e»¬Î¶¦55ûNÈSpòboÒüð“fI ]6—A˜ºÔeµ17›ŽÜgZ(¤±KÍþÖ¬f#kð”ð}ûéËÇo·ŸÞ]»¼ý¿Ã3H©$½XmÚ}]6,ciÚ¬Ý7ay¹É×Y›W%{¨j+¶Ê•‚ŠtÄD DJ*ƒXvSgEÁvuµ6M qèPãFº{¦Ò¡ÃeÑT–"΃º9„ßóÍ>+–v€Ë4ˆ¹Klxd©KímR‘éqû¶Í^ؽa¿ïM› Û7ƒº-lŸ £¤èt[ÕÛÛ#¼I‚v¡ÌÉH¡˜óV=À¯ ‘£â‰ULGŒ¤Y€&*·ÙÔ ¬'kÙ³© l˺Øo`¡yi·ÒßFývµqNT Iû÷¼Ú7l ÊãWKâÂ]LÜn(¬ËÍærý¥vw~÷fÁª¤ ™'ÚU»}‘µÆnRcÊ Xzª :ÿï` v\†ªÂмi{…MD䯔ëaÔ›gÃEÏÄù]rÊ×ù¾y‚Á€9JbU6˜Ó1Ÿ ³yÜš²,‡å èò¶o@ühÙnW ÖúúäÕ WdF¶®Ê¶®Š W2î ê8±ÒÊG(Çòæ ]›Æ´v¬g²X¥ƒ0VnØz›Õ¿±¬Üœ,ÆQ0wçÑ-áe*oÈ|¨Cp2ü:Ì»¬B2W¤óÝ–w ÜUecÔ4½¡4ÕÖtj#b_NQJ„†=eD8!ÂŒrÉ( qà'%í†yÇš"z‡"ËA™ú†7û;Qª@r·Ç31]JBY'< €–jÚ”å °/k€Yû/ZÈ*ˆxDxŸ[NÛ˜âm*·mÎ[vK0/MN¹tÛA{àì$íW?7ÝKÍýŽGè|¨«í9¸ N&‡ÐÛcÐ`AÚƒ³†•Æ ô¢•ä%¨o½ßµý«ÎÞî_àˆ(MÝÑ^€t—åõ¤Àv'ªõz_7#¢‘€}±v{¯žöÍ3Ô+H@.¬½‘vS"§¸ùm>XK¤}¯ ŠFèþ3z2îüm]mw…A!ÝOø2‡ J Ý­Wµúßo¿^®®¿|¼üòó·«O?¸^]¿[‹X á Û´«˜P£*×±5·Xž•޳5è’ðׯõ´þÞX-\`[­«Â®p›Áa•1Ï(£ B«›FÈŠ<«ÈÚÖlw-âÁ¬¨ ¬Çé@} ®‚D»Í¦óñÔk ØÔ¿ÑÛ~¦jÂ3ä[µÎz)ˆdª{Áû¨M [W÷ô@{¤K¹oÚ†½`”N[téZ€‡Á‰ËK_ˆ|©Kž‰Ò±ÛûÛ/` ÁCšfºaÏO âEþu®$º¤Îx¦x«n©°4xh„ª9˜K³ns L±7Þ÷¼}9ä—Er„.Ô˜{ƒÌb2p# =y —þLk6p ""ÈR/`J‚”»Íˆbô¸pXI¾8žœÌàv\;)]‚;ßÔÕn¿ª}{Áš'ØæÍìàÀCkêù\ªµë»7AgÝá<°ŒJ¥Ô–\K0Ø@ºCôr]:0 Œ²2 ¡úÕRiysÚ­?u€/Œˆó¹Oö¾0}pç1`†f:ä]œÐ;õÿ´×«3QŸ‡Æ~BÃ#ÄœŠg"' }îFß¾ˆ"†¸MOOg~§­}‘¸Ãj°”|nòBÄÑ4¾Ð"šžMŒ3áR4]Šö—¢ý¥hg)Ű”~„CKÑþR´¿í/E;Ké(œ¥$îÄÃRR;ĸx”„Q÷…å*õ›ös#ôd)Ã,#ð#£î »”Ô_lêÈ0q'î—¢! Ó®àcä2J^ W}JÁ§]Ý¥Œ³ lŒÃŒ’¸”q—‚»»Bf¥ćØöšŽÄ¾ ‹{yöKÉR†YfÖ@^Ø¥ óŒK‰ýH܉[0{Oñ'«ÍÛ{<Ñ=-œT|È{ÔT‹– ÂS‰I߆¼ÇqšW´ÓÛŸió ó½iNC½™Ý¿I3@> ”ffù:bÌðò4̘YÍë=ƒ³ÓLz¦Ô¯ÛÛ mp&ï¨ÙΚñ…‹àÇ!}v ‘™´?“öO¹Ô?<wvÞ™†}:8°þÄÙqàÎ4îÓÁÿ$^ÍÐgz ¾Dlàè¯P)¼$øqåä}Òn÷#‰>fºöH#~œâ.zD Iì¶›r)ã,p¤„KÜ'ÿgaûo*TèÄ;ºàÞÏÊR.¼¤-øÉ(À©‚½ ë3øtÉ*†ËKV óá‰KV)fåÉ’§,{8ÞÝÈÍ»£ùÐV]V-aSþqÊÈŽÉØ±{¬\lÜ~yõó·›Û\~¸±Á:xù -þÇóÇú;¹¯là‚î0[@ëBwO€M‡ìhšGð¼ò cwÜ£Gw •òlùPMĺ|`ã'UšƒGsp07+ñœXØn¾)݃áóœîöÞÛ÷p:ÔüÉR¼Õv)¾{ÀPº­ ¡û.'º»Ë»ÏÌì=ø9ƒ:ìÆêû~7ø³î‡DøVM3Æ© tJÙȱªÝ+ƒPAˆ‡îDõ2|±5kˆ´óf‹NÅ¡èdÛ ¸ck[¨œþ.ÈëÀ[€`w펠> stream xÚµZmoãÆþ®_±¸~¨]Ø,—»|C‹—»$= ¹¤±Ñöƒ€¦V{©ðÅŽþ}Ÿá‹4K‘>;É]ÄÖÎìîìÌ<3Ïè\Çõ•¸}Z¹â6]¹§ß¾Å¿«¯nWýF ‰ÕÍJ ÿHz" ¤ãâv·º¸Ý‘ì÷y–&MV×ksyû?hyƒÖÅëºýGãF…Y‹´Üí’b-6&iÚ {äyIbã)ž8±gõT‹?üô=?®M)ö•¥©ÂÐñ•æšÙÚˆºÜQ¶Íu¹¹¾§£ï.ž²f+*SïMÚt[8^Ðp[u>¦ù®µhëð.ß“"Íò<©ÝÛ·ÅËaTïŸÎ”k×ÑqL¶à'é)ÂBn•{’E§ºi ³®p„HÖ댶Mr+%¢Ô£L?é¾ýñ³é w#£&Æxˆ_× ¹³æ¸ð[àŸÙy«5BÎ÷­“ìuß #Ëz¼iú©°î«ag[RO¹Y÷pՅɱº° ¢#/cžÐ%jÑ›¦EôešÒ÷‘2’«7Ukìäntµ%,Ú=©Û4E-°‹™§”yË7#XØXîqc'@ú2…$˯SŒPBü„\q“äõ‚* ó–ô!ÃX³lEI%¼éð¦/ƒ|@á€5*žf†:‚X¹7UXw(.fÑ^脾äšËjwÓ²oºcï.î.ç-ñt®Ž¸îÝåUgH¯àOOóP#¶NKwëïLñÐlÎBW˜–>¤pˆ üš³®»k >p-uãÓ/Ü\Å>RÛºHm¦ž»½ö#$T̵®¨ KÜ–mNìYOù˜•m®—aÐ;AklY_¼Mú: ‚î J;B¨9á‹7É^?úú„/¡..zXb‚Â䪤Éßõ‡žeÁ|BzŽ`¡#çŒË‰›CQîë¬î†(Œ41‹þ‡‡Õ×·+Ú/¦¤Øu?#e,ò•ï©®?ÿ —ÎWÛÕÆæ)g™AûExHºÌŸ²"Í[4/`øÛ}ælÿÁïß]°¬zñÇ2[[pƒXgïg—¤Î·\þîÂ_ŸmxÓGñ?±]nçIvb‰wù·e¯¡¹ }Ëkެטœxoê´Ê:ÂÐ;Ž2`©nèØs¨ìаw„çÆT»¬@—_ »Á–\ üdš±T=ƒÐž8Aèsâ‚?¿ûþý:«¿ûðîíí‡>.!Þ `é‹Í@½ËzÔèÚ'»/FèÙ"'§iOiàJ.4¤½È t\0ݵüárãIˬƒâ vÏÌG¬„^Ì…ûX)Ög©{^s¥£"KW¤`ÛŽxßjèØ¤>é¶* ;â"G#Q™æa =GïÚ”i™ hV`³me’õÀµ¬±êã@°}´W“¢q{ÎÌ:‡ô% GD*÷Ûĺ MäÛáñ¬p­uÓƒi’ÓM¨N˜pƾTÛˆg<£|éD(¡Lá\=+/:y¶´;çôôÀu79yÓ4*a9qû_J‹Ÿo¾þx»¸3zÒ£R“}¾Ð *»AuÖOHGK¾1ö]h ß Oçò³<ýlÃçy:›§^öjb‹Ä}}9HÎÿi ªD¼D-¢?÷ífcª›}’šçØ¿´f6 Þ\(p±sò/ƒ`‘üSŽË`†üä·ž2Á?×§ÞI"¹“óFAyhxP³Ø6úy>¨µŽìú]›jÉÜÍÔ˜38šòºž…é”Áâ%„ >»?<7Oõ]4O|kÄJ?0„G¦í¿D™Ŭ؛¡xž¤}O ôêÉÎ4“èh8pAgÒ; ñ¬£o—èÿÐFXn’aW’™:DÏ»&T Èº.ŽØÁ#’4í*#jë­Sìö´@Öºý 4½ •%pݱ ³z2×– ¸ôbM_?ýÆŒ[dàD–«˜wMmÞú €Ð±•ÅY|z0¹Öin²Wã083)Cf‘µL»Ĺá‡õŽ;É.ù£4„]{ãK"@Ya³&š7Zo4aUh¿ìõò“%o{¶€Y_uÔº,Ö# é…WU^_͸jh½Ý`úÕŒD,ûí+¶Sìà Ðâzš;^'䊷ËH £Ø èÝOÒ å†(Z9AsSžÓÓŽ-'}•ˆ<Ûr–=@&»²%¿YºV€Ôÿ×\ˆ2-v}ëB4MIÇTƒʹáÒõ§ôˆy–æRÆÝ<’‰Ú½ ‡^VYëDño’Næ襎–w bÀ–µ¾TQd:öNãdv)Áhjé*®ÁëÖÐ+Ø‘D_lÊÈ:e˜uUå‹Kßz…h¬ûy?ëD8^jK‡b±D!•œŠ|¹:-'•*>Ue«Ý /f‹¿Ò° Z˜æÉö$Ê4º§“dY}"‚”þBã²§lÌ…ñë6mºy ¬ùd1ˆÒçiÐ>4Az+ă©²]È$e \ bjoÅ:«Ó¶Ÿ~ÑĪJÖæºÜØÄ‰.ùu7x§º.Óì÷n<ýGÇbÓQWS‡ï$z£Î3€zE4×Ñ|ó@.´Ç—ûÖ¬ÆCýñcŸI´{¢®»¯YNëQS¬ 2s“Žóßi§©y$ùźI•PQÑWÖeÚŸÌ AUÄoý–úǺ¿ÙgÊbF“Èçz+W³ú҃ЌB®¸I?M;bt??FŒÐœÿ Aëw¢?½ž:òx|ö/QÅ T(|í »êúsÿìfüba 4Øx!rŽ>óA'mèþ‚ÇŸéŠ_ݲj¶¬C¬ÿâ[“ï'ãA<³oIÙAˆ,ð\kÝäôwÐùÛfýfþkõËŠ4vøo¤ÇëÆ~wݳÜ<ÿìLm¶]ýG8çÿ#¥Xendstream endobj 997 0 obj 3076 endobj 1009 0 obj <> stream xÚ•ZY“Û6~Ÿ_ò>dœ3Að¨Í¦Ê±'[Ž«’—©Jq$hĵD*_årƒA«²)×å^”GSÙ™¯„Ýϰ •„ž¥î6îùx⥒›B4»²½Ûaû<»Ý›óìâ=û ß |MsE¦Ã·”yÑàŸÙxâ—BÔåÁˆuV›Z”[‘‰}V¹ûdâÉ@»sܱ1ûìñÛÛ¬Ø<ä›fGÇÝ´ëFà‡ïÊJÔü¨Qê%>›‚5½H³qS ~rÉB?öÒQ5b_Öõv] "Ñ©bba”xZ21´[×H 5)’ÚÔ\H~*K¹¹\—íqo6°ˆ ÙÈný‰¤È޾çûl–ÏÇ}¾Î1µ&9²¦’ͤ/С;ÓƒX—ESÁÐ`¬ï?\ÿzóœLÁ±`ÚWeÖ&g²T§Sw¢{>{![ÇTâYe^ÔÅ:/¦¤‰‰Ç÷T':W`kSl ³¨4öb—âªß,æ¥ý>+Û&»3õ³óæ{coª¬¨y]CúµØVåoç‡2š]^ üÍŠl_Þ•mM{Ì;ÉO%îâ«W¿‘ ³&ÚóŒÏ"Õ@ÜäƒÝ‰­;©ô1iê’eù¾­ÌÍs¯Ó¥?5¨(•žRÚR‡žöðÍãs†^12qmš¶*Øyd(É#\²ßùxâ!zºãÙ¾5u§6Å‹E'Wy)˜i$‘©Ø% )Éè»Ó†cç“2ÂY¤ËÑTíRlV‘—$Œ˜tZÙ³ÃÓÚ#¯n×kS“¦7K‹:ö”¯Üy¶Ù¾^X5HDMFÝ­Ä­¤ïÅ?ºÕ´Ç”¢‚Mºd+kÅYm͖ѦÉtJëÃåzÝVð‚õ¾Ý ¶ä‡¼1›^wjìr‘>ùjýX7æ@^U¶ÕšâzGÊëM…iXLñ5¶à²—Õ'${…7wÈLCzù«Í+èekƒ¾õL¸ÓáÐy%·<„+/TlœüpU¤²‚vŠT‚¤†t ·|qrÈs”tÏžüx&ß‘jN.Œy‰s‡' Fˆ¬‹èR‰÷euøØ”ÇkЦ÷¦º¹¼y¾èâ:Eþv\<€“ϸ¸K&>>å±Î{ÿLb ”·Ã‡»‹7« š7„ekq°Ÿ“ØDØ_è@yAÍüÐQï/v[¡Â¥ $JÚÌ?»û¾À±_so÷ƒ»"ûUG~_ææ)¼žQŒ¥Ç„GžNùÍ%#H, šÌ×™Üψ{žs£È øû숯ÆgÑ Œ{ÊÙ?mQçwƒ€žº_î*À‡ßL•—ñ/áß<ÿç²5‰§®5³Öà‰×¦^Wùñ”—ºÒÅ€­Ž€1ºhƒˆ¹m ›ÑÒcm?;è°NùM pU5€ ÇÎI3Ó)HP”Ù|67ÇmHy¾f㦲v' 5Ú©óq ‡ÅÑã|tF€ØÃxD}4ëüËXÚº}´Û‚ν€r‚h˜êa‰ƒiF°%$‹r(<ñã#€0@‘Ÿ¸d ÍUS“Ù'*r©ïÇV%l|ä7I ‡e/—2ä‰s’Á˜oÄg²Uóæ‘òl~8˜Mv„ß]¶§i(ÉÎn>ÄQã4YÜ|¨|/ “åÍ#x¨.f7Î]Y5 tÆcu%jàÜVl7—†{U€K¹tŸ×æØØt…Rª6âa—¯w8+c#„šh—íž§LdmÅÆ¸5H__i–k[NÔØ* »®YB2*HÂܵÈaÞ—smùÏIhê7)¡?‡ó)ÄqgJ|¡·ÿ4þÒR/Is}„µ1T a€=ÕϬ¾7tì ?0uÂN€œaî,>EHwxä+‘;|eÅQÚ›-ÖŽ@É^ à0:qO¨®|Æc)ägðMfP€ñèhù¦ƒETp² †^È÷ó0_ã)‡tY^ -É @ŽeÕÀ!$`ý¼€³ÎÅ^"ÕX:=K1Õ9À!ò$µNÊ‚ãc!†Œm5”n]Š¢ZïagºB*ph)i!<:R—`uÂÀÓv$µÕ¸x¾hE0_84ã±–Ç2s&¿»î °ÿhÒ1å|b(µ;j­‚më>䉵ë` V•§Þ'ï½PÏóî x{͈íI¶£ÕŠLnC óÔߺi2¨ 'Ž]ÙEæÞA¸Y£'‰DÑâIµÔÔv†OâÒñ¸6Pé)Z[óÝ#jË.óaË#¯•IdáƒÃM~K=¬ÝÙxûÈ»ÔÌ¢2@ºS<³ö²‚ ž¡òìJåCS‘uµÃ91´)lLcßB_«Õ"Ð /B-åpPü}ÝVØ­O’ήún±NÇ’MN|V‹é&—CÇ(ô'}6îÆ˜;SÐ% ì§à(ž’”v¹mC VZ[ÃBrÍòŠòUi먨——Õ¤Jyº8‰‚‚ Û)HY}’{T¬ŸÈêXèÖÔ#Ø4„¡ËùÇ€‘& PZ)FË à!ÔÎpK+sà)‡ú¢œ‹óèR6N½À.HÀï gsâ¥þò>)îÆ:ä­—ë#ÉY~}J&ž)GØg ‹ƒ©kºj€õisÁ‘ÈVP©:}¹€ï‘hÎ,£[! hÅ>s˜ÑUÐÌí’9Ä<{Sñ²q+P|¹­êææù•=?Ý íÜw{É“ænF”>ÅÍc gK,M>]rZæÏw^½|÷çõ›Wo~ùýÍõŸ¯Þ}øøæõRAÓu•3ÃH˜ 5EâŽß»×([œa2Ë*1Lc»D]e8Û‹ ŽBØnÃòõŽštûf¯w\²'®w\²¹ëwüt½3Û$TKMBªmв¿f¡Ó„ÀŠËj×Xn¬ÔHÎu5ÛXw©ºÆºi®?¿ÊÖ£ÈóF¼3ï¨dx²÷PÛב¿šï½»d_Õ{¯ÙõÞJzÚiµO訿²÷@Ù±üêÞ{€<}ª÷îR¸îÈå ¥ð9Gíw̨gf\ê¾°.»ôOwß*ÕSÝw·_ïPîÐ/ë²-š_³ÏOuÞeJw®-ÌvÞ]²qçªÇ®.Ÿõ**[ÂdÆ«jº"˺W”]Ò*ÚÃ-B3²aÙ6uiFº¹<û åñB CuÕ°³Ø¹=W/u1âãqs6WrC ‚Ã0*¹f}6>-þR#! ˜2:s8n3@"j5òl"1yOL7„𹞊›Ä%{Ñ#€[à0 ¥÷ecÎ÷œ÷ãG,¾f̶¨YJ÷ªëo8䃩-ä'jäûŒaVû‡ìs~h„Yj³n›Ñ› xvçõÓ#w ¨/ð±–Ô=ûðše,\êö'É qK”5¸ÈDeêG.5•±ã;Ž(ö¢Ä%¢+ŽqÖH©¹èÒ¼o.û¾žë&yma:5Å͆úC[±XÏÀ4;Ì“jQ©¢§=-¶X÷„^ÌÎ](xdêÅ.å¨P‹–Kë"lµû ɾn¿öÙ~:L‹O~Ó³8Wµ*–!ç>»—G>)ìLØî?u¯i¶pŸ–0ðÕˆ'A2‹ãiD¾íßYu'êüo ž;r_`Mo1à€¡b›µðÃÿ~ójõçë—«—K*¤úÙå;¡v˜ ²[c«Ìþ4•Ù\õBóÓÓ+BW\?Ì¿¤gPH[›m»·ý®,§"ŽôÕy.ŠÓã¸]~·c¯èÂÇlì‹QûƒJ’ßy5øê÷£gsWöùÚ“7šJðÈe.«O0ñƒq)IïNÞŸ¶¥©'~ÙΗ†2¢¤¹lÜs£È‹B6N¥á†A"5Å6«ìuÞw/Èú¬„¬Pæd’ ŒSîÌ32ùáü¦EIñŽ[é).v $˜ÒùPj="t‡qD2ŠCÃóÈó»3šÞ‚:S~8fdúý}r³«èEæÞaCÛÿù¢/ :„{Þ‰ó ¯FFèo·0s2 ]`´÷Ó¾|xÕ͵|s'céE/5nxÛ!¥n`ÂÂÆÆwSTóFÒ!~ÀÞy"ÆtÚÝ+<6øðíÎø…€¦ôÜ%ùšxO qßÝŠŒ®èQ.‘îd¾x!µX[ØÙÏÃÇÄûÓ¯Zóï _;>ÕW¶˜€ z¦b¡íƒ‹[£É¦Ü=c{I*úÏ0¨ÐYwæK͈Âno§ÏýîÎ#ˆ P2NO·l«àõ÷CÆšQqíS>öٸٓ»S‹·mÞÝÆá˜ÿ¹øë‚8øÛMµÝîäßn·£w›08“í.þÖù‚riendstream endobj 1010 0 obj 3730 endobj 1020 0 obj <> stream xÚ•[ÛnäÆ}×W46Þ$šÍnÞ8€×»¾ð%»Jü"À 8- ½rLr$+_ŸSMÎLW“ÔÊÈÓÕ·ºœ:UÍ„A¢SqýxŠëò"<ÿÛwøïýÅÛë‹/¿•BbôîBŠÿ‘"DšÈ NÄõîâõwbØV½xxsýûID†:±våŠú`äÊmÑÜ›(îÓ šôå·Zdr·¹ RÉöù©ív‡¢>˜ÒT¦»y}ófœî0Ê’@)6[l‹^ÜÓˆ²¨k³¹Õ «ºmS?á0îéµTJ¥;ÿΔƒh “ÒPWž¹RõÓÕÆ Å;³k;#$•ºÚÓùqFošéúKÑ·£ûm{¨7bxÚWtÒ'z:2þºk;#~úùÃXJpO£¢0µ»ôÖA–»ÃP~»7]1TmCv©šj¨ <•.X=J¡×ØN×A@Koõf슡Òá¥08&™™ÿà~!ó3¶RI$Iºn+•&€®Ô·•Íð¸Û§Á@eï*^\€|i•{“ ²úDÇÇHœátžã…§œÑ?õƒÙ!Z› ®…T„㯢óöóz¹?ŒÜ¿Ÿ%ê(Õy×y·G±á—ˆòØò]GfºDGÕ]/Ú»¹ÆÓ¬“­;Ó8"?e\á:Œ‚ÌßÕê»'ÔA¾y@¼‚žd¯ãugŠÍRsóf½ŽÕIèqâÅ:Ö{¦ŽuÅ–êXwüTÇÂ'IqPygšS÷e‘^*–éõXÔö«ð)‰XqæÝah%">{r„ÅaM¬½úfÖ<\/‹ÙA_ƒtä j8ÛɃxÂÖ,ªúЙ@ü‚ ]ÝÖD+ŠžÐ‹|̉I8›OSuy)$âÂ:×K™ôÑdQ|ꕹ6ŠRCíjÚÁk9 씌]ñ¢®6—"²Ç\Y&÷jN˜@$d9a¢<³qÓ½qæÕØaz…-Îíž±/2ˆ'`Šëžð¬úX¹Ü³ýuŠ˜S«Û댸7Û½9RóËÅP—'¸À~ GC½W53”¹’\•2 @’œaÒä*õP1Ñ2GúsÌCfe3^ê+SûÈË!œ–¶÷4% ØÉêu)jré›f½U¥rPÚìܪŠ[U®Ô±Uõ±Bm±Õ0”È‘r04^n5¹b/j5)Do6µšl;¥ù£ô [MJç¨^_ÜjRÄóQü¡Ü‹µš\‰E.´šÜ9‹­¦ù¢Ï·š\ùç[MT3eê³­&ÛVcÿôöR³å¨Vý|çꇟ®UÄ~Ù¾35 ü¯Ä•|®yE히9ÙbóÊ[h^ErµyEq/eWT¶~ªO“¨6SiÑî­«—oP•µ6¾Ì`¢œmÄûø*H26ìvÐl ÿj´Ø|} (ŠPX¬­¯ã(cÍ×Åë>˜ÎuC8³ ³ÚÖëý(‰Á ØeF§\+^Ü wjýõêŒ0DÛ·ÎsUJ˜0aašt²ëCÞ§Ý9^Ä ƒelœ¹§u ©¢ŸÇ„ ϦUZ ÏÜVFð3PgÞ3d[R–KO=1zî”øŠúìóYz‡Jí¶(?™õðP?ŠÙù 7 ¦MT²3uUÜVu5¨};?Iì©Uñ9m³wQ¯¢&.Â&ÙËJÌö_yÆl’Dnšò5x “ée„ÚfgHc]¢‚8ÝʼnEüöóÛ½ÿæú·×Þýãò±t Â,ÙTúÆÀx™=M/±¯"ïõ,A·2WˆÏ&ˆ‹r_Ýé2nRï4vGí"PÀšèUÁîÌà–XhùSwÆW«¢)¨lâŠ^É5CT1Qð¾¸ ÙØ>ä¬>žöí¡+¡Íb(DÏûh °¡bw»ß!êÆî*•v·¯áAõÓÕœzÀ9?ºG=TElüÔψ3ÿ-H&'@',+Û ¡ÅmÝ–Ÿú±¡`#lßvƒho7å@¯?„¨û¢§GÌ¡½éÚ/lì£JµÛ·ö¥“‡;¨b[{]_…J&@m_퇩HM7¯MEˆ5Ý+ ýDK½¸#=X° TÐâ¿4¾dÃÙTïá'‹,Ós¼‡Ÿ·SLàô˜ðl¡îOŽ"Ø=µmw¦ØýL­ÐÕBÕF’°©Ô'{@dÿ9êg@ˆDº38ìçð2ÉÆgîP|KÏÚ’J-_ uµ1z>›:Fé\¶Q5ƒ*ñ=CòÈg›ù8˜ž3Ú¢´YuÕŽ2¶øõöÐ-mN#úVN³eÇ ïÚGšžÛ\±‡ ¦{‹<‚"لϦ ÁG$;õ`*I øÌ]LEös'¦¶KQ‡~* ç^–Sjáwåã`)‹îiÈÜ2gûÀB]$&@¾6/PèF¹^=ŽN¥oA€Ü„Ÿ÷B¿Ê“Ñ)NøJ`]·c¹?¶ºoŽe ÿ” ʃ„ì{^Çû–@¥¨p™€›–®óªsrwÊ#¦Ø”Ut]å?Ò†#Ë”*ËnqCÉbúŒÑu¤4†L-Ç“!4?AÔóŽ<µO½†b3†.ˆïMSšËe·“YŽT¹³½zB!ÝøDdõ,ÏIt?~eRØ¥ñš¢¹åßç©÷LÈ>yî{_˜°¥lþƒßŸ‹Ù|#¼ºUYÎÎNÄvô8/>BûjãI ú€¸ÛUÍŽÐTµ;ìDsØÝžNäƒIvÊy`ÐKÌ­(ARíOVqÓçSô4ôE/ÊCgï'/z*жélŽˆ€Ö$wv}ðCþŸ9U÷ø­u‰ZÏŒ= ´SJN|®–žPt•ôÊÈ’„t%•æ™3:¡±UƼ$©0w\Äž-ñ™C=äŠPù‚†`%½vBÒÛÎlŽå¯ èé-t/:Öø–s|m¿¨vê|~}’Ådàmåô/ý}ü3c_óúÿÇüßþuœ§N/0àÛk'#d¦TÄš>ѲÍûtv÷8iN$ˆéïÉÔÙrá+ÍHôx¬Óßt0÷LZZ§OOÿŠwÆÿ¾”ž§©Ù¦QÈÆMMu‚è»C5&{\óß\ÐŒþ7ÓÇãR‹ÇýÚãŽòîo³ ÎbÛ‹_Eƒ}þ¾¦Ëendstream endobj 1021 0 obj 3796 endobj 1035 0 obj <> stream xÚZY“ÛÆ~篘r"Uí˜Wå¨ZY’í$–‹Ž_¶Ê…%‡KD @à®÷ßç$ºqp-•l’ÓÝ3Óç× Üúž4bý¼òÅz³º¾}‹«wëÕ×¥XÝ­¤ðñWŠH‰(”^Šõaõƾ]ÿoX =•ÐÕßÓÃ1·7"O”N*åv"„i~²¢Ü GõõÇ@Äž¦{Ê@zq@éïïmž¾t fÂÏg [ T¾ô4;´ßQŽï­üÐÓ%ÏYž‹cUÒ»)x±¦dOÙÖŠfoEe76c´‰ö$ùÄ—cÏçÚéñ˜g›´ÉÊÛ7{‘”EÇrtï±M›TìªòÐâX1“™··<Õâã‡oÄC^n¾8bçs ê&¹¯u‰óàÿ©¨Oµýíd‹f!²ZrƒÆ^,™^ÊjéÚ $˜ðO?þôï?¾ûLJoÖ¿~üþ_æOeò;SZl—6131K»¼¿[ßÍï(ç5Œñ¦ó%$·q²”úLã§,ò‘m3CŠ RÜ,£Éf ÊùÈ×cD&[‡«óؼ„Kà~á+˜‚­Û%¯T~â%qHi_ñJ$¼X1†‘W‘§ýˆßy%¼§Ù§Í¸Li‰2ÅïÒ–©¦J‹úXVÐãÃÿ€ë®&?@p›!Q@Õé(ì¶³ŽŒ’±uüKñk³)aÔQñ‚/#Ê÷˜±êÅKR’;û@½ÞŸ ²ÆÝ¶(¤£Sšãœ$nDS¶µþeÖ;\ÕŽ Œž€­£PE>[y‡‰¤g¸„'¾…s ‹Þaà«F±RïðºgqdÏ×ëÈÝŽ®¶®ÑÚf ï!áM„…ñçõOî~XÊŸ¨’rž­ò`]‘8ÕHb«?sƒn ã:>@üÕsß ™øÉ6§ª¼bK9ˆ’ý—¯ J¶îTRÏ_É˃³á>»SÑ¡“}ê.OkÏÀaA G(k»Çpy5ÞDI/Tærùptuxƒ1ŒJ|*«ÃgÛ¼·»ô”7?€²uó)eµ\…À!gürÿæþí¢å„X!ôäœ(™øüR”Ç:«»¤G±qMO÷áqõa½rrQÞ@h?C;2ù*PÈÌÀ$Ó:ê|µ_íx 5q×V E ÛÃü)+6ù Hò¯ôsw̼ýßY<€JѺ#*³­a„Q,©™;ýÆvÿ†¯#Ä3r[Ëâ;ÔÔ|”£QI¹@QSâ›ñPF=åõ?e™ó_l‘>äöþí_–½X#J¨W¨Y¯ dâ½­7UÖfñ¾–‡ábú |‡³g‚lSMUæu‹’·vÇË2à|Œ0;!ÛìS®}@+MÉPñÖolå0$RS'½n²¢C¹€ª‘×BvTÞ¡O6]¼ÞY»}€³ˆ¬—>ÚZ<ÚÂAés õͨ‚ô =ÿó¨DÕd›ìˆƒá (Žî¬½3xâû]û} lh&³³õBþV)±Û;=85µ`¢:¡±øêÔ…€øÄ.:'¼w\uðºúÍ?q™¯œÔî@[¶EŒ*s8³Q…À(t‡ç/ŠÏ=Àï6\!í¹j‡*À™VTØfõ°mÝÀ0%ÍV`>æ`¹1šÊKóÚŽpIˆ¬aJ„VŒkHÁYý쎯GÀ]o•4ñfmhÁ aëÎî&›SU9¬Õ©IœoÞWá”ÝÌ ÕÅ艜Z_¢¡ÔÀ¿¨W‡cõóôL¿8,1ïRÇ^'Ôw¼£ÈÇ1]ãb¢û7£¸w0PB6÷÷ooF*‡YÂdqwkE†ï>jZµ lœKév[á#ŽuÆšèD±}{ÿ¾öÕ\l‚ärÞNÈýÛ¶Ÿr¨ûF<ðÁ‚kCÊsj:Ü6¯k7’>Ûän¬´D±õIÞÌ$=°Ehy Ïzhpƒˆ­Ï¦½±6û;ô®æ›hœM4Ò~ÖÔöL¢ûëLSžª½XÉ»óüaû齸¦‹k³ÍC8GÂÖ§¸k,Qö bðb æ³Ó\Z”ÊÞž£K^Tz’¼ô%å‘.Æõr qæI(ßÝŽúÚÐõÞöèîzÛ{”ív™j ¸L&LÀÓxáûì³^€v°máGìV4RîWÜ}QL4I;ê’«˜"‡; ]f÷G! \uRzìú=XäÚ •d¼(M¢L¶™œŠ»<•Æ¢qnG¹;šÙ%žò—ªpÒÄŒNJÕ·Ù;¹E¬ øè¢kO|øÝµ³&?Bƒh>ÉKÚ«Ë–Ãr(,dTSB®isØëFZT`ê ZZ}¸ZQŽGâ³ÝŸáÆöÐÀßÐo5.iÔÖ.¬\·m˜*z¸Û%ò08trÉs¿œ74TcD%Ý4<¦L.ã#¦ùØã"N÷<ö¸8aëéK}É4}JíŸg ˜{åò±?R@ ©OtMÊ×õèØnDäì²ëwïÅ­8r™vOH·P€ŠÃ–Û?7"úä$¡4wÿþ^”m×€ðéÒŠlçV¾hØßPV>·A‡óõ¶ QšÀù›bJ±}«'†/IþRí½«Ã€ä¬Î#'ò ¡ë™öÆ Y ª¶½ékÊí³Óæ¤×1è‰×ÓÎ#wD±r:8tW®eë.ݤ…+Üä.±½y‡ä»aY¶U•m·À4OYJú˜i ¢ZŠ©Ôê§rk¬?ß^fcÔ`Ñ¥ Mû•PuÑBÊ54¡NyY±Í„Û)¡‡w»‚cïåy—võÔ³ó.JveÞEÉææ]týú¼Kk9ߊ¿>ï"¬¯Ì»Útó®hvÞE©5øü° ñ’8®ëÃ.ODóÃ.Jö‡†]mÛ-»a—Šb̶¦?tÔpØ¥BœSþáa—B‹%׆]”bVÇ|Ò凞 ÓhÔ…äÓÍIιTŒLÉ¥õãèÇC.tëׇ\£ ×ëã-år`@ý`v¼Eɦã-$‹ã-™(Ï=†~m¼5  H/3}×!ŽQX5•ú4~"öÙúõQ”h¹ÔG4*¶}Z"ê£Ýd¾T7÷¾?zŸãÍæ 1Õ³KŒÙ]sÒŸ¢O}gÔâ¿MYu;oÛ1\yuše\kS‰ƒ³,Œ´âÞÈX†¡ÖøñxÂv¸¶p×öê˜]îÚdMGnþΤ»npéamܽT@¨Ýìmá ­{éFJ¼4¤s/PD1“{Ç…¡—÷Ù¥&#‚ÞàªÆãžB†ñ™sqÚ¶ø´›#É×4ÚúvÄȇ ÞÒÃxåÆQ1åÙ¹aÞ‚ëݜڟ­=‡ê9ú¯<ý×&Ä4±ø8a™˜öE$&¥UäÖ6i–×sØGá™´\Ρ7qN6òîN£å§«—‰œÏåšÐáM^2|÷ª¡XER3ñ,(¢dW@%›Etý:(’r!¿Š늀Îd¾¸u¯\bÓâ…°ý|þœ0ýü»Æ×ŽO÷pâÝšTà‰ÀáýNÁñä(ô$¨Èè:Eÿ¹}ÍpØm懖šÿšîD—Ïã3ƒôa=¢›Q\ÇõÍ$¥šÔ;å³u›»7–þ\‹oOYWpÍÿ¬~[9Žþ›óqÝ{Y8îä¿=nGO›0aûÕ/¢À>ÿÕÇ·endstream endobj 1036 0 obj 3155 endobj 1048 0 obj <> stream xÚ•Zëܶÿ~qýÐ3àSÄ—mQÀñ#ê8}iPà€@·Òí*ÖJIëÍæ¯ï ©‡Òž¯ÜŠÃ!g8ß ²»ÓUÈî6ð¿ïàßöêÛ»«oÞ…Œ v÷xÅYÿq ë4ˆ„bwû«è ^Üý6ðZ)BÅ>4íþSÑ¿)³cÕ:×›»s„äA¬#2§©Ê ¡Ñ"œ®~¾¿¹DfŸ¡¿O©ÔÎ>¹·S¤!c°µæÐ•Ò…A' •aÿØ^½½»¾Q¢ ßãß±ÐOYu¥… D-? ÔÕÕîꑪV±$þžyÍÍfþRÖ›ê˜ì5¨ïÕ¡ vÿt÷[I…´ä_š2gîx rŠ•S@-Ÿ‰šy(Êøþ†¨¶]W6õ÷YW…K.Ã(#BÏ:—øå óˆc‡ùúNSpAˆcÝD{ÿâïM#Š¢ N]Ók¦á’±7E·iËC;·Ö¡R…>óÍ;¾²€ÒA(ÌÄ»]Ù±Çc½Á™ {ß±~W°¼x$+ư"šË<‰]£@»¶©Ë?3Ãà°pŒDq¬Ü™çkv슜vEÍèyhÐ'ël˺.ë-»¿iZÖ]Ÿµ=ü¾?6…˜5¬yø­ØôƒgÔø‰H,åÈð±mö,ƒÙû¦/@â:/Zà^EðÒ ì¯YßEØqXí–ÇÛ’l$OÄ¡ˆÈoÄÓøA‹hâꯉ« à€®ZSœßf¶%w ”a˜®–"Œ+L" <'œßF„q™@M"$Κ£ù8J`µ¿$QòÚ"c"ìzƒ ãO"İƂé¤f÷ƒ‘bXebd;Iá®sÙ˜¨b盬Æûù¬ãõ$”XùJôÖx–iúÇôUÛñýåYÖ³PãW×·i\Æs›ýÂm¦ß®Q>i¥¾g’eFiVÙþvä»®5WhRT3@N­^àÐãØÆ{›*)°»‚ð5 1œÆá$Âã4åÞ¦®ÎÍ$@¹ÄÁ"HO»ŠÂ‘èþÆÃ’kŸÁðXë- 'å®ùáÇ?üúé¿^ÿúúçß~¸3¬ÁEëp}Ú‘‚R@øzjh*ƒ3ÁÕfR FQ]‚ŒíÙèu@&Õ}VUX¯jJŠ‘Ù®¨rVÖ#¦Ɉ†Ø&Û@v^9EðæDN§¢žÐê,ǬÕWïßE@$.@:„š*ž ðžÂpš2 OMáàa7A šp¨iñ=!ã ޱêf¥Ö DJ¹©µ.èAÑQä’¯šØRXnAf.k©!žQáά4X+›Ìpi;à{X1Ù“àqâ!ÕÿÀ 5ðu€ÓvýŠâ… $T‹7ªx‘<"ãP<<PDabq&œLq8”Ýíx€™M›—uV1ÔöhâÆäMÛ³2‡%ʯ V´­†mM3Ôî"ò–¨qG‡¶é›MS!ºBÝPÒÒÒ”' y°#g*Õ|GÄîŒCij¤±L Ä¢b £ÈnôUž—h EÎ4~‚Å&„ôåš•6†v6v f ¡¾Ån‡+(øÖP¨jüd U‘x‘BÀ1¸«›ú¶-YÙ^r5ÕWD§W{óêîÕº‹õAùïN`{¨è³maûÍaTŸQý¡éÊÞk1¤ààdU¯Å^E Êú¥“„Œ.$w©æÒ túû±èzls )Í>™øÍ†XAÁOØÌF-'o%á¶©œ)]¡•‘¤ S¢/ˆ"'šÆñ$éÙµùpئ±¬|UΑ·½o¶åuóîík¼¨7MŽ!ù¡j6Ÿ1Ô/»=häX÷9üh2A"ézõà¥^Õ &Eçœ)M'®kö´!¦bXÑ%3ý… Ôú^£Û@q¹¤^‰®@sJGw¯×HÊ¡ð«ÚEªÔalâ»Ë´´ŸƒÁ-¿šÒ …CÇ´ñ‚m%.Ý¢ 8Gû­²¾¸ý­)çNa§×žÊ®`×Ë Ì½ œ}¦±Î&v—8_3?خ¾Ø?@ß•‡¡I.-ô¿$ŒR"P ¦¢ù¡€°Pþ9DZǾ.唥Œ´+ ÒhKº”ž6Sp2Žgl߈yi“Í`eÄv »öZf)ÔÚeu*ëÜ&Ù Vù„ìЈ{<<àÕqu¶«‡giÓ ŒR_d1…xbwAÈj›C‹vpQ1sRA¶a\ûõoîo>ýôóÛ÷¯¿¿$«CÅêŶ-n×â¨ÁÜâ= bÃkÆG6ÄT(v4`]•Ûz¸toåŠk!=ŸÇ†¢r™Ÿ–Ž.EhBD] R3<Þƒ•`YƒÙ^hàÜßt` CòÂ@ ñdð1éXRMEÌ` ,„ÞÍ7™Ì™pºö¯j8`L%•KdAóW0ªˆ¤¹tækÚgg ÅòûñX7>Ö&)â§}ÍÖöšdn2\µ^: ¯”fP5ãFÌc&²n²·Ñ{ŸÕP æ9ò ÜcO!Ã#AôÁfO`6æ†{‹®†k¿x(ñª‡ó)&ÀKäՄĘÎ/àp¼S–dR/û€Wêf®sŽfdíç¡9¢ ƒò.|p˜qëî޾5,.Ç#%^;óÁ“ ]»5Vq Å/ÊŠ}•’ñ5°­aÏ)TB—Ø`ÿ9d|Ĺ¡ßîÁòp ±J«0?­3.S‰9s§hÿœ .À;bMæƒÖ Ëàs‹ÎfX»í,HaÓû<ïÄhÃ\Ù©C‘µ&2°ÕfÅV,âßî›ö<4m˜q”„ÇÔDÌæp…¢1In2 ä⽡È2ÂçS./ ˆ4d6AÆÁ“óµO¶~ÖÛ~ÕºÍ%Vi—ÖU >ût]ﱌuêT»4Û²îÖ2‘H¦È7õ×F ,cßúÄ\Ëÿb%pßÁßua©¦ÍD|¸ãÎôz:HÉpó™b] Ú/ò'Ë ¬°àÌxn×;Lì‰Ï3 C ˆ Q„IØ‘\¼P‘ štïlõ[ûJ ×ZÓÚ_šG8ŠÒKúT± THÆÁ<Æ<¸ FÄÜd¸øàœ:vIÏtN‘pòò3$¼X¹ã&=c‰Æ>}ÿãÏïß /î³áÿ#&½K§ë€k—‘‰døôë#ªê >ï¸Çd”â]›3™ ›ŠÃÕ7wS¨Ü7wríÍKÆ>ý±­™c¸dÿñ_°„œŒgÕ±èÖEÁ}…Š(srþhÁ'Efž·Åæç©fYxÿÍ,^H9¿™MWß̺TÞ›ÙÙÆg%)ÛÏD~hòâÉ7±ûÎ!¤ëob]²g½‰åö™§yË!¹/`¿-í3_ÄbÒM£g¿ˆ5 7õÔ‹X—b¡ãQ‰ËG©î4ÿElHn…ï¥'±Pz…”á“Ob-w|•ÌÜ/ìU‚%…”š1VÏÄëطó3Ýr0Í6æô"ó÷øgâ¾d^üÔšþ–öIÉð¯9Öå…»"€¶XÙËe•.6åî)Ƨ[éðâ&s徸^~0ÔôC¤ìÞ¦¿‡ÝÍ0 ¨Ša<;šÒ{SøÝ© 3)¬’ñ¢jEû׎}w,íY˜?]ý~…3öðÿDÛÅ'‚°ÝŇÐl×Ò»ßf»«_X ëü¼Ö‡endstream endobj 1049 0 obj 3680 endobj 1063 0 obj <> stream xÚ¥ZYÛÈ~Ÿ_Ñplã6û⑼ñ‘ ë1b²`ÀàHœ×©¥8žL~}ªšWI³a[$«ªëꪯš ÄõÃE ®WðÏø{wñÓõÅë÷PpóöB‰þ(i…JãÄõîâ…•N&R˗׿ö$*°2 ™x›VU¾¯ó²@Ò@†¡Â_¿W3 ˜DºÐ3^oòƒ¸½/VÈ)Y}õ&ëì–­9ZKÓûm-žéê{^܉]¹Îž‰ûC¶›¬U¶Êr*ÁèH†.¡~ cyók¶‚EoËÊ/|Ǹ¬Šd¬ ãbϵ–aÄžÃâHñú½±4ÔpkœÔ3â`÷ßÒb½Í¶±»\È@1.)¨.pÒ&nìT$yH BàW`Ÿ†|Òys»-©Ð8”.)ÅC˜‰c•8Fúƒ?¤ }žU"Ýï·ù*m‚^î2±*‹º*·¢¼9„cQ: ! –ʸ«² ‰÷iUç«|߈ʋVÉ}šWb_•+p°?=Šm¾Ëk øÄ„2±Ë8¥däF î{÷ê±{•ëêR”Åöÿí>;Ô‚ — ùÃ&_mPfº…½æ,ö(Ò m„˜=_U ?ŸK{IÁ¸1ë/Ÿ³ˆÛ ‘†)Í3]Y©tLŸgh )#³à,5YÐÛw_Æ#­}‰èëõY`:¾"«¨èª¥eõ]lËtí÷~·©ÅMã–ü¿à ÜÐÞJ’j «Duà{ÈX-þ†?ŽeÈ”ûÁl¤‰èã4ߦ7ÛLÐò„>Xmï×Ù‘÷Ýõ˜B}uwð[jç/M"¶:qÌo„&îè ØHa–—›‹Û1ÓÎ߈©X§ tÈoÀnÖÁÎS´‚' ãJhŠ1̸ä¦Ð^@Ã@)tkJ+AϘҭқ҉íM¡7¼)Ý:…L‰éÂ)ØØ’Á¸ ™¢ô†×ªaà~ÍA‚¿d¦t«ôjtb{Eé oJ·¥è}Ó…;SâEìºô€KŹÜX¸aHTºKfJ·ÊDlŸ>ô†7¥[§7¥Ü›BW:²WFÙ2¤b¿'F—g&î(tC^ô‚F—Ý2'²häÇ!HÛqFËœ·¥'I}z¿MªÍy;n’s§·Ã¤œ·!&)q:['{WU·Ý´ºõ7hÑ8^E&5”­ÔyoV°Ó£=}|“OJ[©óÞ¬à'îÁI•@œÒØ´anèáI’4ˆ€SùÞ÷¶EY‹ºJ‹`.h¹¬WF1c)Ãc‡Zt4€ñ‚A!‹ d¬S½êáÄD­0êHÇÀP]`ïé`â„=PÑ 5Ù u;øÓíêÓçß®Þüõß®>]½k†¢À„óCQ¯°µZÏÔoö¼óïœó´ Ÿh*Åkù÷«÷Ÿæ§ë \Šqx¨žuƒhÓòóa :,—­³õ1¿4ò~Cµ¾}ºúùßóºõëÀ«#>žó˜”®nB v‰ÓJ‚i°?|ósn/ŽÀ.‰Fà}¶Ê›5uËöâkÜ/²ù99ñ”÷còM¶a(]HE¦Ã<ð×ð jû·ï\ ãczmPc|$0Ñk˜÷@z»wŸ*`öš:cd•uTî¤U†ÖPM¬Ú¥í°æ,MS ޹ éÍhŠcìÒ„€Up³¢³ªÊ×kýýÔq^Wo ?<…±ÍÑûÎ ù‰á ªäUYí®`­/Y}ÕÌ%áê닯/ö¾… ffŠ#¥ÅióÇË}òŠÂ‚¯ºú7Ž@d{ústR&”°óÛe—±üTPVÈÄóC‰(‚Ñ>ζŒ:aÀÖቋ z)y~=w8¢ò™» ††v@u`ç"Ï8©âÁb„ cæÂIË™zÐ$N2ÃŒäXûüqÂ:?àà ƒ²¸»O¡\ÖYÖ„NÙd»P÷£ø-ؾÍýÌ‹Nð瀗"ÝÖ›òþn3r¤5Ôo¸DÎÈ; £fÏ3¿Å¡Î·[Q§ßyä S †ÿõ´«GŠÒ€‰éws»ÛÞÐâ>whÎV{ø™AeD‘V†A<öªÎ#`r5sZ¦bCÏ"”<1x…1{žU‡ç}§e!ì6c,¥þO?ÑÝ­5ûŠ•5°­ŸCù¹\L2€ ¶”ád0\Ä8zÈà]Û„ëOÁêí©Û"¤iÃÿšxšê'P‚ C_ Vãóh|ꉉ /{j¨ £”ûųûý]•â;Õ.œv«$„†`© b¨ð ˆP ¶Œ§ŸžÚä©ç[ÊëRÑ¥XÃ:«¹vSÈ„ˆ$•lG8Eª¯»_ò]¾M«Qß d1%»\8v·b.Ôš=o‹çj“wxYO€–ÁØG˜<ÒZ±v@Æu8bƒÇÌŽñLpçÔáT¬-Tû„9•@¡éðˆúwÁ’­É^­±0Ršë¸C³õ›÷\ã@A›@ü2"[й„QŸÞ‰€"¦ì³æÅZømð?Îù;(ø{qä„2d•fÀ'ù0¶ƒØÌûJ£÷•fî}%%Ÿ³ú¾*x|,ÔlËÈþÅŸÇ2Pìyº…® ÇcTaJO°&7ZêæÀнçžÃP<ô¯ÌÚ·3âÏxçÍ>—›¿Pý‘z†é‹Ê|ͲÚ]Â(æÇ-æì[$cúú‚GCIh‡sR‡WÆr(.MøÙ²!½œâ‹+"xAO€™ŠS RA¾¾üÓbZ|˜°´ÐsiAé¦ßQ¸x‚sn Ÿô-˜³a\ü–ÁǪ)-MÂøO F‡!M5!DÃÇ¿Ò'@Õ¬^Ôç­Û©-P£Öf  ´ Ý<’®9éI"­fôË»™.h±y1|?Ÿî²:«øô 8ÏJ8¯ÝXJàƒ;BëÄ€Á Çà€Ê´cÏý9ÍüÑNF*/¡>ÖSM€“}ÌÜsûÆO ãÁ,í!î$Ó,$SzÑB«4!{ŽƒŸŸY¥ø’-#"0ÖæÜÿ³2u6¸ñ‡ ¢Ór½ÍnÑKç¤È„„Û[žB$úýî?é(Á©àIO¤ÎF*xè%Ç ¥X|9bñôŸ²° Vã±S°‚å3ˆyÛçÐJ#Ú…26§Á ¶F,Î+ ?Ðs,3fÁ ¥ƒ%Í"TQ®m| ªœAtâÑ‘è!È0…?†Û—UMÞx.Äqìà‚HjCÕ+oºÎb‚ñY€”ŽŒgËLTˆ)ÃÀ¨jµ¢„#€FЊÙÒS€¡ C°¡D¼âW{~ `8 )ï(µ4ä ´ï°’7E§ûºek<¡¯ÇIÇô;ÚúÀüÿuõAÎÙM,}¢§”ç¶ôw÷x…'HN¬|‰ýïîgL¿«˜\:ǯMûáOó«ét`_WhšH@æè¦Éº`¢Õ j)¾–jkþ ËÌ Å?Áí7JÃoÔŽêd-¤XÏ#z¢u£i¯cT›ãä°çÙ¶ÜgÕóƒøpŸ73ÿyñÛrìàߨvê&Ϋ;¹xuzzoÂ@„m.~¬ó?/Fendstream endobj 1064 0 obj 3091 endobj 1083 0 obj <> stream xÚ•ZmoÛÈþ®_±@?Ôœ ÷/hQ ¯×ëµ šøZ0p ¥uÌ;‰TH*®ûëû,)J3)ëX–¸3»³3³Ï<³J$n‘¸Yâåü~]¼¹Y¼ú …‡÷ %"üS"Ñ"‰•4Ɖ›ÍâÊJ'>Ê7¿d”Фãrâ³owu)˜˜M¤cRÿbÃÎH—°ñ|½óMyõAMØe2éâNðæ¡hÄý®\¶EUЇ¼e%êÞ„ïl‘4é9ªvkÈ~Hèñ"ÊÉXÛãæ5ßz”J­b&&>Võæ‹oßùû|·n?ûm^Ôoª]¹Êkª«ÓLF|…§Û«Û[ÆŽ3-3-ÕT ¨œøòTVÛ¦èÜÉ4ImwÿæëâýÍ"Llás'6ÝûTI•‰õÂi#uO<è¥×‹‡Å=O+RiÆF'Vj§:cþP”ËõnåÅŸK¸èõ¶¡öqgþ^ü{U¬Xe±Ì˜ÄO?1W›XËTo¯˜@Ø“ž˜»iQÍËÕÚSy£ÌR&/DC¥¯§¦·OŽÓÏlL$³˜) Ÿ©ôí‹?Í'ŠÖ2ÉX¢èÉD!râo–u± '(ˆ¾Œ`q@bòðÅ‘ É{zøòõºâ§‹GLá±íƒÇ~–¾à‡ÂY*Êofd±q_‹|»]˼[¼­Är×´Õ¦øŸ¿÷FÅׂ;ÖÈxvcRi[ Ç°WÜ8·‹d+*ÜŒÓåÔuVY™FLëZä­x|À˶*ÊvÆ9!‹ãyÓ`Ä©˜;§G=×CO*Ê¢-òÖ÷Ë~üôùâ#szŒ ŠRªòš'!µÙøÛŸö¹*¶uµ„OÄjWå×ð±­–ÕZT[_w“X"gxögŒ¶tÎë£y'®±‰C$Ø®¾óñLfŠ#oï‘Q¹lì¤$Ä™G’èIG™?R yFGßþ¶r±wJÂ6óáý[±¬€†wëjù›@Òˆ¶ÎËf[Õ­¨î~õËVÜõ§½@‰˜‹R“Ò…°B\‰½õ368ÍÞq,U"-3³[pQÔ1|ƒ—ôØK±„FA*T÷­/_}ÛËßÖO¯ú½vYÞiT÷x2lù±X#A–Ë+–1´‰¥ËáÜ Î{¿ò«ë!ä7Ew÷H¦Nb ²1¸í¾ÓêW—œ±èX¢2áëVþž—ŒŠ„JtLpD¸®=bZ®šO3`¢áj¥è4õIm8cc™ª%ü·]¾>.tR‘MŠ"N5‘úåͧŸ?¾{ýù?¿¼ùû§>ÔÈS¦*ÅÏMïô^DÇpGÛ %¢ÏH Û›ü u£õu‰Ï¬njÔ?ÓY¾óñLª„{%ÚF2±Lâ…ºmƒá³Á°(¾–ê\ +㔩]¸`æñ€|zó·÷oof"eö¶Ìwî"2ކ> à‹a ÁaߦA’(pÔñ [Õô¿?ç!²»²-Ö]¼qžk_¶§Øú÷á¤l¶kß"€Ãnr–å¸(³œÉ¾„ÊÍ÷%Tjª/¡ãçû›ºijô|_BTŸéK,Ú¤(%}‰™ìK¨XWj?¢à€1Ï7%¨nÆñùÏw%œÉÐ0˜é®„Ê]Ô•˜è¦ú®Ä‰cGš“{é »«2™¨‹»’@H’ì\WB%æüÌIƒ˜1µQG‚ ¢¾OÍ{ÚŽ¤b²"ü”áë©©A‡RsQ7¢â–Táwt#&F.:– “Ý•›èFTÏv#¡ÚôÂnÄÆ)U8׸4¦¢£nÄJkØø³ÝHX¨ÙúeÑ;KïwruEÇ“«%,ÚT-ä}¹ò<£}¹{º{ê&š©^6CF³Kì yðrïÆgŒäÎ5. }EšRi±Íë|À®¹‡´–Ê]ÖßèŽêñJoo!£”ÁÏ´.Æd#ˆ«aƒ:ü{—½;u6¦–Mõ~¾/¾«Ä¨¯‡d\w† ¨Ó…À'8w¿qå"þó‰ºì»ßÕ°¦†9m^¬ÁÎËκb³ÍQ‡aØÀ‹wNQƒÃºŸô$†™’*¥ßG8:ꇖhhsžºÆ`[ºß­½8¡zá´Õ» y8Vs\®ãHÜê ¨œCõSTk:ÙM¸i³Tnž®èô'é •›§+TjŠ®ÐñótEÇ3Øù<]!ªÏÐ Üu–Ð;IW¨Øøõ¿Ÿ«»1³±:ÕÚ².Y£[DÓHEêU}–Ðhpƒ”ÊN*w¡Q¡À%=¡ÑرR„¿œ<ØK_Hh4àY%Ž…;Gh¨ÄD$‚§;WN\³RÕÉkÖÓ¹Ï_³Rù3·¬a_I8î„ýA5=©ÙÞαeƒdY2Éj¨Ü˜Õïc=Kj”N¸f]í€Î褪²­+à÷§6ÈÇTíQ \!)[4^誦oÏt‚:fËqàM-°cÒþšf“Ã…øM‹:ÜaqOWn¯šÛšk‹rçªÑû¦í·Ž®uTZ”rà ÃUÙ}]mzÖD¦õŠ N™¥Ê#¨Je¢Ù8zÍǼ ìýƳ34ð1m;‡m€¸ôyƒ¦Tp"ÈM©ÚÍ|A2±î*ÝìÉšèõ èWÆÔ8$Û@vRæÄ€É¡Øûzƒ¼ç‹ ¤Þ1Ç<Ñ$ãÐDfÚä%»ïÌd”ÐqÓbƒÕò™|SI¬gSަ»Û\2¢Ð¥[ã×÷/ÖǹžŽL"Eµ^ó,§‘÷³·Ãµå>9C‚í¶áâ8“”mœ*Ö9T¾ŒIS%äíàLkFÎM"´Ïk^ Ô ‘]J†Z‰„>Žßt“ßI†/2"E— ×’ÜÑà›˜ŒÊ„„ÒÌTTýp7pTÐÑL³€Ä(Íöðå™K7•KŽ…AÙKRªuî² ”ËÒý¾T3³ê®‡!“îÑŽå€ÿ"CÅü¹/)p€ëˆôèøÆÒet¸kpžïqÂÙè{t ´Œ%]øÄîKr!½¼Åþ®"4¿LPÖb¢É¯Q”Q›£èž $óÅ&M×a Ò®»³ÇƒUÞæUØÍí )~ìFѦTu›‡+Ä ¼´ Îî¿I Óƒa †Eâ%Š1ˆÙ²ÿB»{?¼MÙÙãÎñÏ{=s bpë›ró¢Ñk%¡ü÷wNØCÍI²äbÿµÀ’%'tÒüAl{³ïƒaÔ&Ô1 Ip ÷ÿË¡ËÉwüÎ( 7“âu?Ê÷ëÐÿþ±?ìŠÕàö.¾-‚Ư©ÌÍ\gîɃ¨3·—§ÏNÈd‹‹ëük¯dþendstream endobj 1084 0 obj 2510 endobj 1096 0 obj <> stream xÚZÛ’ÛÆ}çWL)‘\«1æ *©TIÖÚÎÅ’³¢ãûú[+¼4b¾ž)ÁJ$Z$±’D·³—ï«zû1´óÿÜU‹}Ó~›-Ûª¾yÿêÕüWÐVBETYùX:K'YÑT"[£üQJ+'SËÞ³˶uX†œIºXzï©ä#‡ç‰aã¡Õ.ÔY›W¥ÈKÑ„¶ÍËÑn‚hóm€gm¨Ù,Vi©4[vV€BÖŠ¼û&¬D[‰¦‚¸Êþ!tJ(÷:’Q¤ÐÚÔ®6= 7¡\ÁJwÙò7:­R©4  ­hë¬l¶yÓàŽ6Y#–!Ã5Ý¿Ìe7ÝÎóå%8ˆYÐÀÞR:ácÞ>u†¨öíý+)˜pœÊØQéù,ðâ þbÌvÎJ­¨ ˜t2~ßÃÇj ëìƒå"Ôœ‚LWlçŒFÛÁ'¥ ^jE“Å¿ßÝÍçâ+Ñ¿À _ ”•*QT¥e‘<ÅZjg¨ÚÐRÊÚÙZæ›}Ó¹¢bªÁ¡ Ay+#ŸÒqˆÝ¢8zH,ºª˜óý‡».ÄÄ çüäü&­¤ŠÏ/~ßçmT*›PÁ7 Ó"kò†çM!7R6óÏ›Pž‚‚.NÏ0+ÊÀí¥2TàdɶjϘ؈Uh_ªÇÊUàld”ŒÙöE;$°JQáú1bç<Û²’ØHìÁ pÙ%¥ o¸O¼LøšórtsÖ$”áî8„ÇNÆÜÆÅ¾[ÙD€ÚÔÈÔQïÜkSf/Ù FAô11®“²ÒI#99Fˆ¹TNÜ…v_—š-  “úvm Çí6ãÀuÙ„±á)‹ŠË ¢­[Â#§‡¤{ÉYµ{ÇyózømÀö¼yÇ·y`Ù˜‰‰!* y'õLƒ”×VNFƒW@eÌKÀõüõ‘ŸÊjùßã¢O¼Å´ÿð0»Ï`bg‘)Ŷû ìªRQ̬MC¤_>襋Ùf¶þ|Aë:BWÝbþ—Ëb¿ âÏ%ØïÍ.—›¿Ðõ£x¬!6zñÇ*_±ðJX˜Ä$8s(i™ZÏšçñÊóÑy¿ÏÊUÁ OÓ…8< Þ 7ã@,9ˆ]ÿÕýÊ¡íþÕŸ&ƒÂ™H&) =TN¼ ͲÎw˜JǪO'‡ª/JÒ¾"ÉG•J¤ÏùXC™”—÷m_€Mñ»@Àý瀷ְH%¢&2¤\ý4/§pRC‰% U=ôSïÂqø¹dn5\Ä&PŠ ;œUÎÁ<…]²å>æ+¬Ä{VìSÐÚs_HLkÓä¨t$ÏU(û†âëoõaU/ï£h€÷/Á‹§«Ö‡uy°>yEÉ‚{ÄòÐ Å\¦:Û›óä‚Lˆb*'ÅÇ|xŠ2ìE&¼ýÛí7ó_Þßþ]!¼²e@›¾«+ÞðÃ,šmê?‡Õ¾Æ4jöËM¸PÖúdè µv5žòLQY ï„Š?7•‡n3fª_Šü Dã™Vt¶+!¤–õTúÌ#õ§·Ýå]ê9zºÀYàÉì®êŽÅ»Ð)EV×Ù“øÔ×(chµ£ÓòôQX°ñ°êÃjw„:Ø<ÐAU*ø1J¡|h7سÔöÊåg‹ul\¬õtö# Nœpiär¦p4 K%èE5¦ÒYLŠ%å24Íz_@*nwE@Oß\[¡…0²&žZáùúeœM>ƒHUgA|Ê‹-·­VÏkwÀÛØ{ATö~†Î»,Xů Ö`bX ìg—÷ÕDÕ‰ ÒÕ–ZGÔgëÔ¶;þ¢â×ïf0ÎÒRüu}ݬP‡¦TƒZ5š6¨Ž†…"åKl™‰ÿ†º4 )^^ÐÉñnúsê£ñ›þ¢úžúòá;,ÞÙ<à˜=`~ÙƒªÅBvb„êqnëB¯ØTÇ~Ë$Yy<ϸ¸P)!…¶¿.œÂX¬!a¸Îxcs²@–‘aªè~p®#èÈ!<ˆ¯X XÇZH,ŠjùRÉï©€ÐDU‚ûn*SnyÓµgd°× qòRÐöhnªuV4“¤ —¾…è‹· °Ôox>ƒ`4¬RLê©æC·OjLÍÐuþÇÕzÙ¡è‘)îÖÇÕ¥’IÌÆ!øa[-!"7$ yE¢påÞH+DWO¥¬üÓïÞÌo§.)€J=Ó¾+„…X±ýZ5Çs¨s¿Ð9 =^pÄ<‚sšÍ›œ€œåc­”¥£Ì¢PaÂLTw$¹Iñ¤'2T/úºè‹jâÞa=KÑv©ÙTûbo߀§U—Ð=u MwUß[c_¶yq ¶a#£â_AkpƒÇp‹õóXZihàS®ñN |‡8|Ã+þîø²¤ƒ’†ƒIs¬>¦bÊ_Éqx©Ø¢ù˽ëÎ3‰ÀñþªÇ¤‹Û5§¤7–*¼Y­rt^VL–õi‚¿s :_[.‚ÄOÙ0Ô^RÕ—¤ªÜ‰d&£H6Ø ýuÅè®j äúغÌMWb#¸Í{y(Œ-}!+v)¦­úôžÒ~x,2zpIå¦.©ÔØÁ%?\â©J¬'ëÅãÇ*x˜f:ÓÚ )ÔQ"¡{"ú]ÌMŸ0ãñ€ƒ‚•h´õ~*â]U!–â{þÃÀ/[*ò) Ó"N˜ßAжgãƒSuˆxŸ2›>§¯ò*žmvµÇY­ãUqbÍ"ïbç‚>m‚ÝúôŠ­Ç(å+>ÒçÑ×vx¸ž`¾Çk(<€cV,À^xœ£þúãþÕÍ…ã‘’dÏó~ÆñxN–(K®@±^ÆL˜ÂØEÏÑ9BŠŸÊº'|r0¶bÜ ^óS“á¶ï_b!7~z¨ •8™âqx¸Y:<8>ì:«Ë.)üÑŸšÕãØ„‡i'xrê§€ù›?üøÛùí»©³1$E¢þeUÀº&¼Ÿ&Äk¨žËî î>?zrðùÕ9þÝÀ×^ÏœîÀ·oç$$µŒM"ð—xýœ¾X]N’*ìòŸ5d yåȃNš?ˆm¿¬Óg\]ôåN–ž~Ñs¾`øÒ1©A²Á#6 üuçñÝJÏÃ6ÿ9û}†[ø¿·Ç妮[îѨ[n/OŸ](É6³ŸE ïùÿRZendstream endobj 1097 0 obj 3139 endobj 1110 0 obj <> stream xÚ•ZYÛ8~÷¯ ²›ÝñÐ…],Ùt²³@&³‰÷xh` ¶é¶&²äÑ‘NÿûýHIvQ–º{0ÜfY¬ó«¢¯…lý° Øz³º>ÿõÿݯ~\¯~x/˜Àên%X€‹%‹#ÁÈ­«×M[›ìÀò’µû¬e›¬1·o®ð‡aÙñX䛬ͫ’²G¶©Ê6/;ÃÚŠiËvuup”Ã&YãþúùÓçìXWmµ© ö˺¶:`§MVoÖ¿­DbE¥Rét”êUmšÇróÊÕoÞ\1ãz+$JS¦oþzÄ£Ä[7%Ëw¬4í%”AÂ#Aéªú«½ë6·7oXVã‚ÝÎòüð^Ê|}AÿÕ¨ßכܔmñÈŽUU÷Ú¼ƒä_«ÜÚyv—yûȪͦ«©: ¸Ôž8ûi‡S7{–YJXV…jª/ŸôåNzŲrËNºsç4ó¶¼ÃWw…3eáéU‰'1ÝÛS«’÷6uvoX…CêÞòyšðDJÿö—Ÿ˜uƒf¸^Ãz5j–pEýTG ×iJy®êÃç׃VB[­àSÆ6¨~d82~1æëÇæþK›ÕííëÛ7¾åN>£žJ‘Á” ò‰Pò4¦Ägñ>˜ö3"äÓnט'”qÄz:5[³íÃlSyúÔ’‹DPß<:‚Lš®Ã,y /.òûòE@¶{»±É=ÔÐr/î¬q[åí»ÃÞælÌ-ypJFÔB\ë}Þ°­9šrÛ°îX•Î;ˬíeÕîÂW­C[ñgŽúá=¶—“Ì%)¤vgirs/+ Ø¥ˆ<2v6q/E„)‘ö¸ˆUƒË!û¤*¤b_a}×£c_ËêØäÓ#‚ÙëÃøá~u³^Ùa%ØÁ}±qÊŠU(‡+Í|ÑS«ýjç… o¶ûi('N˜?åå¦è¶†ýµ„vÞs¾ÿ•߉‚-TO~W!ÓÓõ÷ò(f•Üú‰8â:ò˜n_{Bp­/výt÷›Ù´ÿ€§ø™L¦‚ _ÌÁzÚÛ7Y¶d‰CÏ~rÖ~„޽3ͦÎÖo{ÊHÚp˜-Áa¢yšœcbו›Þã·~CÄ'ð9BŸ•ÓWZW…«¯$xŒ¢ä6¡uö2†§$¥ÿæ¯'\(oýTîk³3µ0[v÷è¶ïõN}K%1ס· 5Ä|n´ Ɇ*abǬΦEJCnt­Wt†“ÚÆrärùÎe@À¦¥ûÞöµöD $ã’ø–±uIzëY^¸ªz0Mc«â]Õ•Û¬~ô4ªáÅ©ÇÆÙGŸ!7=ìØšçQGyVƒ¬ ÝÐüÙ5yyo{E¡~ô9ÿaŒ£õcV½©OM ´A*#üþí¤àiê­®5\ŒÚøöuÎ w8>ƒóûꊖ•…ƒ~¶FòrûêœvÐÞˆ9eNo¬"ïÆ}ß¾áÌ¡áQ¿-šÊ*º„.‚ÿ•V5À¢]Óãæk~-Òpö É…ė8Ë– {#lgí¸³Ÿ¯ÎÔ©˜ÞGžÓ*…È]ÓÎ÷8}@-@Bj‘’]Ï‘dár)¥xx¬V!»®vÈzRj›ÍÚÒ+ K5¹—G‘¢ä¶(ø6ÓÀ¢ZhJ´Ævƒ/°Õ8e0ÿiÌcºhúšè "ã…F5:½ºY*…¯&§èô=i–“l?@‚—R”õî„nÑù‰ÉBÀ#°r;Óž"§Äèh–.®aÔHF3wG¦éã S¨õ)ÕsQ?/y.,̶>tÞá¹8ЂRï²¢Y  Ÿ”ÒÂ>åX5s9ÏiöUWýX8y_£Fe'Ÿ¶¼s \«s†ïÛ•m^€·éîó{gKóDrd²‰E¿~þ߯Ÿ~üçÍß׿þû—wo×7 —DK e¶à Á­¿3”q¬šÖl—G:Hy É( ™P2öl5˜Iò*‰ CzÎl¯Oé^Ôë+[ûTßë«XÛ)å¹µ¿ü¢§~a¯¯"t?ñ‹{}…£®lúlRT:—)Á'Ä õ§+¨É‘Ç5éû#´|±íR߯ÜÏ#q߯d„"íÙr¶ï§tÓ¾9]› SI “õf¾ø*=_{'I_èŠM‡_•CÁCd·óò0ÀÛ윑§4åq ÍOrÀNr¦qInÄnIZßÄiº$¦’HÐ “ž¶6›=;IÐ2pµû¼Å  ŽTÝç9/ÄÞ‰ âñaºÐ7ÍÓ©¦D)Öƒ7Ž®UÍ·éA!:ÏÄUÓFÎu‘ûÈÊ¢„„N€Z×.Ÿæ¯nÂÿ™˜rÇšÐ;ÓÙÑÿC'°I8T|¦]ï;슒~oJSgÅ­7ÍXp†ÞmŸßïûGà+šÔiÛ5·i?õµîxšûÖ÷=S¤VåšpZϼò¡…ÀcŠÐtm¯…égÉÃ#‡ï€HõQD˜ ×T[³mLÝf¸²wÓ‡}îÞ(šj“Ã=YSÌ\%•ö­â¢‹tÓj?ŽmïJ¨¿ãøA(iîÑi¹£ú"AÍv”n¹£ Ts]'…Vj±£r1©9õlZÒ\Ù0^Z;Gßoe’ ÅÇÞ™f8ibyÍÄú‹ô2v}áÍ:É0aoÒ@')ξ4n 3ë1b 6 oSו…nMW· ·§\‘Ø] Ö<ç!×Zy$ý{\_'ÙûÁƒ e²lC);9:ÚÐ>ÜØJwg¸õ5fCß݇(ÊÝjZ%BtÁè!É)¾­"ô˜¡·ŽŽ]è°u­Âa¥mBÚ:+›CÞ4ÃCÑX|c=ßDLr¶­”ÞV.W³-hwŠrû«ºe•SYã€÷0Óïá%õò>È*iªèÞþ}`È8òÎÆ}ܳø]?²iöeÜj¯&õ U»{œb‚Û¨¦KdžH à&=vÔPšèK'RéHžmû'pH–—0ê¡Ïjøw2IO”®(ëCñx}9Ò…DJ(Ýdê)yœxûÀ›N¶˜N‡%2)!} }Îè®F“×—SD™ Þuíq©ý"ꘒÏAÐ9ð¡§ŒÌ\Ô©â‰ôn}߆‘›{á–£;Ë cÉø¤qW©š£Ù¼ ‰àáP«lìµL‡ö‹#N@bÀurôË4¡ìsIà1NL‚F ý!®æ@6[˜Í0‹]œíÙiƒ’Ý|t9cœ ¹’ŠôGºÐq¾–ÌÁC„2l:$GÀ&ߺùƾ‡(cšr8_¬Êâq®fT%ÓÔB#²›UÚ¯ŸÍ÷Öiã‰)4*jSÞ+HP˜¦ñ}£ÑÿhÀZBøÝúRn«z{ÑÇ“@M‘¡NùÝÍhŒYœ9À‰"áñž½ï³;÷‰_[ÀÌ2ô˜Ç‡‹95ªG%óG=éèЉL=F6ÓiO¾£gvÞÔÃ'FJZ‰©€ïóÂÜ”ð”Î<1“´?ã‰)ë•%D¦O<¦‚ô.k³gîép^=õ‹šÄN@ôäœ~|ð Íæ‡!å~c4<,,…žJ廌¼M´ \€µ¼·Ì7ëÀ®Q†Qe7ý/2ÜçñcB‰qñ'½¿íè¦ç;q`‰×$°%TÌBÍe/l¨.ä¡âÄö•(eÃg *MŽœùÂQû_DºëôÙ FeBÒÖ¨oqzþ‘–ÅRį̈öQ*¿ò£ÊÀ[7Eu4õŸö¡Ë{„ŽkþkõûÊrðÿDâùZq/¾œ¸==ýî‚l¶_ý—•8çÿiÐMrendstream endobj 1111 0 obj 3220 endobj 1134 0 obj <> stream xÚ­YmoÛFþ®_±À}8p¶ûN=à4NÎEj·®®×Z^Y,hR!©¤þ÷%)q–âJÊ¡HÜ™Ýá¼<ó̊ј'dþuÆÈ|9c÷ð÷<{;Ÿ}÷^‘˜J2_Í8að“HÈpª ™¿Ì.îî~ú4ÿýÓýÛo~˜úù¿nÞ]ÎÿMN8Ê<2TÇX™e“u¢¾X0Æ|ý‹eÚdeA²šlʺ±O¤¬H³¶¤|üÃ.÷üÉ~ÞÚ-¬lë¬x&þå2Ihd<ëËêå¾Ý凴XÚ|q±¸œ6^Å UXõŠl‹ÜÖõ•“gÎmØA*ÙÉ¥ÏN`·s*o9+®H oS}ÍjK,æJQcé?7y¶Ìšü•T¶UxãÅEmmè…”TI¼ÃðÆíá7–BRaÝÅ%íDaYŒSBhj„jå5”SïMøM)OŠ ¦|°Í‹ Æ(múº±ƒ­ld«“e‚&R#Æ&(šOŒüúZ”›:«ÛÒ8Š•ËüîÃóìf>ƒ} „\ròÒ~N`ׄä3 ¾J‡:é|¶ž­Nב‰!Àš·Æü#+–ùöÉ’à—ëMF×ÿÆö·¦(*%Åqžñ³ÆÐ( ë=,6žüâÂ0TªÀ†ÿI‹§ÜÛOrC™ok_¨ìâòû` 4Ò8†b*†XŒ¼³õ²Ê6!º0­\5&´;@0šÄ­â| ¸±ÚË[–iA-ÀTTSž4¶zúÂ8Ó€çHç›)p‡bE',:pì‘ñÝõN9B<Ãâhk˯ó‡›ëŸ@@†ÆXeqIV=¨»ƒHS¥E½)«fñO¶8§U@ø_Û}º}àB©©â>¼eòDˆ xä)‘MZ¥/.Mp‚*SŽÅ(ñ–•¤ —X`6U€*€Þ#¦²`¦ëÄì”^¶uýbe+—Ú)Yn« ¼yE¾xµAép¬—æÙÓA$h°xu¤FÅ+§Š‹èAÛª >|q ™ŠÅ~ó×cʸ·žæ[Ûc¸Ò2ì-¦‹¿j­¨‡ôCïPè ƒã­<ã„‘Ðç¼õÖ‹ã]k²Cû U‰¡` Þh&×J"šDžâÕÑ2ÉÄ!m™¿&Ìõ¨Îµb^‡1‡C#ˆ=…cÃ¥[°4~ßch"„ Ì`ÍQÌm €±Àu‡å_üÐ1*µ'æòŠ”« ¹J:l¾»¿ xFࡾEäk–ç®u¹0æð0-ÂØ‰&¼-¾ÄP<?4^=áÎ@Aaüþ·w¿]¼ Ì‚µ¬©†©¥fš25PK1I-±Á¥¾-V>¹LàÌØS(RK‹65&©%;‹Z*^$;j©:ø˜äáƒNúLjéÄDgSK×™¢ž‰>–eîUk žÄؽ¥ç¸‘°¼O(9°àh¡ Ç„R8îâ[x6¡T€ <‘›$”XlL(Š‚µ¤`TQßB(³UÛgj[Ž‘À—®0‰­ëxPaŽÀüÝZ—<ü>tœs„P+þŸOaò+µÍ$ùÅbGÈ/›"¿x‘_7†pJ:~Õ“/¦ÌÚ~ýTÓ‡<“ oØTÛPEÂ8ô É:_î)N>R#‚qP<‘ý§“xtÒâHTϬ`ÄL=p…©Š¬ñÅ¿Æ4æx9Íòô1·ûAõ|¨;˜¡ü¡0J¨–G"¤ª ´ƒ!–7E¤ØAû*Íë@ˆÚÞ>HzñÙ_K†¹Ì(T™›ÉIn†¥ük¿nÐû åG[<7ë£ MZF¨üä4CÃbg14.†ß24h{®Bvø “>“¡ ü39›¡ éî :ñmQgÏ.BõÚeÕáíû»÷§O±8tNOktØq°ém'¬ÂÒg36Áa°Ip$'›¸Œ“ rhI0–~ã`ÞúÌÁb{’¿ŽàÄÝ´' ÞÞÇ…Ê[ßJˆ(€4¤q’8¾èiì9ÀâÐÖ§—í„ó u(¹§£S½žZõÂAžØ]6Ùby’æ w!†÷<ã.ŽÁ`c°Î4Ës9¨½½ÃÝ›ëh”t“Ý‹éÞXlª{ãõ}÷v—-QxÌàPKû¬Åéx„Brà±2ñtO$2 ¸§±K +’Ay¼6¶¾:VP–€€HÔT#îaõï멸qÑÉÄîO3 ãè>Z?É€\s ,tÏÍ)t?$8¦?Ef@Œ2O÷’@q=«0ÿÅK´?W!%?^¸«5ìš>`îrj[÷H€îˆ¡î¶aä ‡iS“e÷+Zûy÷1Æ¿ž|ÕÚÿîÚm§·» y;Gr‚`Ç¢3W«S°%‘C¾„ôŸ¡y+tÚăVÚ`TgÑþóØ&¥ "XðOæÐ³üa¯=)˜LàDæ­Û¼ÜØêŸ5ù°Ížlÿš¿Ì>ÏœÆ ü«¹‰nÍ=xÀZs;yüì@m¶žýpÎ_>Ÿ‡éendstream endobj 1135 0 obj 2127 endobj 1147 0 obj <> stream xÚZYÛF~ׯh$;^ÈöE6±‹ì]ã…c'¶öxÀàPœŠTHj¼Ê¯ßj^ªâ¡‘3†vUwu_”Ç6_WÛÄðë-ü\½Þ¬~¸õ˜ló°̃‚’&ä¾Ôl³_ÝhîsÍ_l~„'¸ÑšP±E¹ÿxÿk×o“ú]þ€¤ðÐR†âîæî…#jðÆ(Ÿ‡Ê ÄHÍCŸ±Ï§¼8Tiåè訳Õnõ@u¦™åj,³°\Ñó}šÇÙq›°¿æ —W‡”ïþ†åw¢„°…jÉy•>æÉ–U»¢¬¹©öy@ˆÇš.ˆª•àÊ'ôw7”ÀçJ/løc”o³“+ás ËúŸñ¬Ç·³ÀŒ–~â]Tþynáþøð”“½˵¸rï‘jÇ{¿Oò»YôCßøÜ?”s~ˆÉØ?’*.ÓC¹#}éqºÈƒ^(]øýp+fŽR†{~³Åf—Vìá˜Çn‡4©X”“ƒ}Á­¯1׉µ×˜ø¦ð-÷CLúáã§Ÿ¾¼ûpû±åK#…ä¾%"yä5‹ªªˆÓ¨ÞÝÜŸX½KX•äÛ¤dÑá¥q䄾{Á¾¦õ®Y­Ë(¯Nù­Ã°êÄi{²ìN¾¹ó< s“l;õ §µ¹°Â J;éîû»›ñÝ­æÊ³˜¶yúôúBk &L,Í뢹͡$ñ&BÁCC„yJ· œ}²/ÊÜ5ŠV&àjIÃóNe÷$ÈŒäA€÷8üT>À˜Áë°;De´Oê¤Ä¤Z(0‘3J>&Ø€< êÓ€"ÐD×}ÜÌ+O[‡!᠒²ÐΞؔBôÄi¾u>ïÔ”%ù#¸Qñ0Uš°CkÄJ•&B Ž×ÒZ{¤9ØÎàìÝÜU€)skÕ5)e¹ÐÓ?£&e%á`ôYR¹‹Gy#U×Ç([ kí`P呸vÀèyÔ"ò˜0ì7hõ½f‘³YÂá€>4A*7óœ Ô³Œq|,©Óˆ”º¢°!Øœo}6ýÂý!Csa‰øÏàš’&>þŒk4 ¡®ðLøDR4… ZÒ,ºÏöP”-&^ r=*‚õˤ>–«xg>OÏážÇïý‘x­U< ðòW’Ê!”ÅËO4“y\*¼LE@ çãå5Ë‹:qÎZC’­Ó œf)ט·±Ó§ÿ~ùøúŸoþ¾¹”‰éÊÄêN½B¯mrJ=•KV|—Iœ¤!ƒ«E­h/ä­à4çt°ž)brëþ®à‰Â:ó·d0dÞÞAá*ÄG…¸±>&¥•J6²Þû(ä>0ÖïIY€>ªcV·|Ÿ ¸fÄu$„²\>JBuèý¼œ€êWA ²!Ùî¹ÀõáwœäÕñ¾J~;“ìD¥m%ñ²ô:„îBÌ)Š·†RVò•ñg’çäž!°R˜WÚ•+ÝÏMФ± !Ü,ŽÀJ1$¸ï±jzëòê>ͧpZ#*@ à-kD¥ž³0’õ“@ž‡ÂŠˆ×Y¤q&â?Z¹X155†È'ë«á–Ô~m¤YÞ%Ð5È2jm¡vÖ„ìßtÝ6:AëQ2vU$œ°Ÿ^p±¢€J¥œA éAÙg1÷ÓxŒáâù¼Ü»×R…n¯D{Áµ”…Ê#CX}{e1qQ\cSg1MõÖNR `¤ñG£Ã*Ïmê.Ñ:~IU¾k“}¼ós䙦‘AUuצ HVÎ(ˆo”òU“7Ñz›Í"öá_ïßÓ&D»Ää…Ð.DЧkª1À‚§q‚ é‰ÎÏ]šn]]ŽKÛáš,¾Ð–¸ÞTaâgšÝ^`0CS@:^_ºÂ5­Ñ¨´·vtô«¶Þ =¢!ç5÷F^z¡ŠaÓÿ!æç’Œ'ÈízqÐ u%;%5ø0˜{Z&è:g³ ©RÝ»™€¦nçü卨ŠÁÇÄC¡¯‘!^ý_Z91ï^üáî‚®ñ¨WCC'Ш×ÌŽz1õ~N'&uÍ(Ý5¹8éÕRC•dÐù³“^LvÕ¤×5ØV´“^íæYx°;yÐQ_9éÕ=Áõ“^¥œE³VPYB+yŸÛ)V1­ÆÁ(Úúь׃œì/l8ñJ ´&äd¶{i@êŠi°ùf¤˜l< |sÃÜ…Tî¢.;3½”o*P™+Ⱥ9DN7BúãÃÈ~r·4)X ¡x@òŽ'//÷|Jy=çìhO@hi…É8s×h¢:š[eQ9.Y(ÓÓã’ªRaœSœíZ÷Ûwïß,À-À˜ #«O‡dͪÂ}H]7Óª´¹E–Þ—Qyê<"—®iì¶/ IÜWB‡(ŽiÓÓBÅ1šš+ ¤“žXX_UÝÑç‘…åàQ®!+dMé¾â²¨Àåž÷›æÍÃ1Þµs’â”Qæ¬:¤ïÇæRÓBE.ûØ[æÒ)Y28('É]QêòOÂùº¯âZ×Ã*u0ÑžòÝ‚õÁ†Î{΄ßo“dÔ1=²_ã_>ÞÞ~~³ùòúÝæ3uJÓ$Dïë¥7PYBú‡…NŸ¤g©!ÿJ")­4 ÔiY²&¥ÒºEZáæ=ˆls)4 È±äÞÞgBBA'# CÎh×:SÇE¹ÊN´ƒ8ÕSg;2¯š«Bd¨{–jW³­CÕûñ¤)˜ð_ ØVMGB£y¾Õ‘ã"žþñX6ë&5ÂÇ· 8¾%i:3WÁ©ZX¬šTᬲ4Í4->!fŒˆŸ7ŸÞ¼úiÁU[é#Öõ9_ Eï.)¸?ô¨ªòmÕ/«ºL¢ý¨Ñšà-GˆZG‚æEˆ;±rõnƒÁ³žáÈ=}ÃǾî N@Ëœµ£Õá%W'è¸ög<©ì¨x˜#`² sL67GÀëþ$Qzñ%‰Cd½j•×UÛ¨Ž†F¢{ö­åùzx#µ¦=ú‡aÄž“ÎCQU©›:4Ï«bß'ôj0âø•ô†0Ü‘‰À1Z~%V/Ä«IÛÄá+¯GX]‹ ;k¶-Øn4hQ®›Z:Wz­ÁðÁK,ÀE &}nÂbB÷®1Ì¿rà®Í¢ˆ n@ôŠGƳ–°^ÓJõÎîÏ6Z˜Š6Z¯{üL¿Ê¡¸µ„ÂÂñbÃ% d tþ|Ã…É®j¸\#UÛp¹/­ú«éƒ–úʆKnŠàê†Kˆpø&Î…†kL6Ru«KZe®(ߨñ‚kª…}g¾[# Ô„|®ïõö{ þV‰5ûÍçþ£Åß\šü „äo§û–¯·B£ýI¸„= ½ÝL¡@Dc&Ba™‚PpÛà ˜ Ð7¬¦júÀ×­lÃçNº³–!êtë7çÑô•´”?2„êiòNË#ëIæ ô?Uìí1më1¸æ/«ßVŽc¿­îÅm¾\àOx¸-=~6a@›íVÿa9œóž–iendstream endobj 1148 0 obj 2804 endobj 1161 0 obj <> stream xÚYmoܸþ¾¿‚p?ÔF¤H½ EÇqri/ñ³iŠbƒ¬åîꢕ6z±ëþúI­4ÔJ>§0lÈâ‡Ï<å‘åãÂ#Ëþ¼‡ßíâÍrñúG¼Ü,ñà‡‘“0`Ô÷%Yîç‚ðÃéÅò÷Þ„y‚ÆcFÞª:­²C“•…6õ( B=áëwlb?¦20—»¬&›¶HuO’&¹W¤­Õš4%Y«FUû¬P¤Ù)r¨Êm¥êš”R©T™Éô?ºñÓíÝGÒTIQʪ!åýï*mH¶VE“i‡^¿ãç+Ïóì«£kç0Ýý“ÇúÎ#i}—$¢þØy·³ü”ë\¹#ö¡ò ܇’*Ùë…9! }‡RâÄÔ‹p»¹¬XgiÒ¨ÚD£h÷÷ªÒ±¹²ï’†$ÄP]±Eñ[ Š^’Ç*†H)tð²™t—M`ú´ÜrXKþdFÌ\%b§ãƒÓy4N»Z_’3ëqçèyÌòœ¨ïm’“ßÜá|.)“η« 7l¾`ÔÓ0ØŒâV“¢lHÞ×uRe°’äpÈ!–÷9¤]Ù%³ Çáð|7&-›§ƒ"6Ä8u˜ïÓH2ÜS'ío·oþ~s½üíóòîæêãtqîS;]a¿²tGÖ¥q—àEó60Œ±ùƒÛ.©àN»" ùãcRd"uö_Eɧ3“‡²®3-eÞ}¶Ý56†~ÄF1 bvœ?Éë²;ù›6×gÿ{«*s$É™9Ö{˜¬OŠºIšÖD¼†W:Óí\’{g÷ åLÔ6Úëu©ì¾'iZ¶EC6eÕŸw7×Æã±·aZ•:$YE:¿`õeQ@p¼Ú'OflÀ«u›ökèjsH=• Ò¡­ tŠÚ Oàp ÃûS8ŒÍÈjÚªp¡Î@,³ºíõ˜Óžä­ª§sQûå÷‡é AM uÙV°êuÒ$Ä9Ëè”nøV:“*ã¼Z!áã©£}HÂQ@`Ÿ…p¬ S«ý­qí:)R•¯ÎW³!—QDcò²©c3òù©(uVÛ4ÂHèúj¶‹›åB+ ¸ŒìÍs£Æ$_H8ÖÀéô…µÎ»ÅÆ­Öb¢ É*‹væOY‘æíZ‘¿°ì«CFwÃþks gÑ·æe¶vr%hìXŒ£ç"|@e䘯Î]ˆ7çnz¼¡lö¸„v ›\bW™ß8ÑPâ›ä,ØlÌY^é²7OZ¤±‰¦JÈ~¯ÖYbª`j‚d‹0Îo}>’—)”±²NÈŠÁåR›„Ô•¾ˆÁØô‹¡¢º¸%bqô»›hS•{¹R{ â;Iýò©:²ÔUŒ’ÄCØÇ :ù9¦;N=îtš¦J¾¦JØlTñ¦ƒÀYörÞU?Žh\ç‡\2¢‚9Ⱦ­ˆèFolI»BÄã͈ø±KÚV°SH—S ã[&9œÒI‚ë.û‚J@%Ôõªp Ï1ÐÄÍ"vmiw·µ§TºÐ%¹6‰©™$ÊúŽ4s9^,S7ͦR0v[äš¿ëñ»Qwv÷ ˜g /«Ç¬Öùß$@ù{O::f&~È”x'`èGrH≼¹3ã貫WAàt†ãœç”|1nwû3^&¤C×aì¯^^¿´lfÝ}Û8»#cªÀ0\Rï`”ËQÏ~ê]ÙækM›R  u*˜%sv\„<Æc>¸ÍgJk–ʨ)$D‚x¡&ý ¡Ú:ɦ€;ÁÌ1Q”Ï‚$sã®|09H!q’lÕñ-½™še쓵%]SœTðþL°ÊÒB:Dv=‰K;ÍŸ“B>ƒà±\!Ã5CÍ6ûþš,ÍâŽ=9£ Óˆû³Ãê÷Aè´«ª¾ì‹Œ;¨µ8–óƒZ‹„ fÕÙ}''Žë&+€øîu7(Ÿÿ\wñÍÝnÐtS¦e>{ܤ­>±Ã,FQ]|;Sc Ï#Ïé°:ÿü«[>˜còåæç럀 îµBÜ*b2°±¨•ÁzçÀIð‰‡¸ûSÐQt¼¦’^†¸õ ·FÒœ‹¡õúd,*˜<1âØ ψ‚ |Ò‚íXD>]¦ÃŠºË79¸†wÇáQ¦IPÙN»$Y¿Ÿ•zÕÅ Ž…ŽŠ&z)ŽŠõ`4r#ò‡ØÀñ^3?ÀÍpBM‚êó¹O¾¹¢0ˆ ¶JWé2tŒ¦ÕjÇxÚèïYŽp0Vœ’ÑÐgxXPœÝ¸û²R—Ö£$ýV”N¥ Ü‹qÇG­B‡¥Çco²pÀ×áRf S5;“«¤NR•Å!<Üù X`]¦™YhÓ¬qâÏC}cƒ;¸× !2ÆÍêt>°hæLj—¹*4Ä}u^«Ù*/@Ý †‡ÐEþ³j¾&úº0©¾Íy õ]]Ì p6Å“›=#À±Ù”ÇíÏ pßçÓRDó¢ìtôˆWF!uƒºê9æ•¶ïÅÔƒÒŽ&•6¶"ó\k"¶< ¨bM+mlö"¥ÍDÑ·J›˜ ëÓÖú…J›pbÂ+m2>”Ï)ml1ŽÞ„ÒÆæ“J{z¼Y¥Í_¬´9‡â›TÚØlâë‹g…6‡ÄDrŸY&]Ÿ=Gõ­rÀ4È h£ÐL÷1 ØEKĈ=™kH…1Ónf¯ÅTÕ””qöCzõ}4øƒK*|ù¸YuqäñXa²˜w6Çý™RÅVQ±·”$/‹mWñ²JãujZiýVvªÁÜ…êÄq³ý&ýÐE=º`At\«NŒÕyf>éœߦ››"sí! ¤ÒJ%Í´Jo‹&Ë»Õõêiø¾¦ù_,Žü/ŒFd†É`")ôý|ë~2ƒS+A/ö[˜Æ2‡gî,ãiŒfXþëø!æ—/wïoÞÎ LÀM_ Îš[¾àÎÌ®DD®Ñi¼„õ¹»Ïh€—vÙQÑÕe3ÄþŒD{ f´¹ö‚)FÉÄiÜ‹·g‚C=†1A¾ëƒüéæëL„aE2Æ=(Â}îÕèõ4 qºÚ8xcéÊü#„Aà“¹…F±AšÞv´ÌëÛ¿ü|³œM'€1?FÝušÏ"µ??ÕÕ›Û»Ù‰4ëó#<ÑÕ~äƒÓ®?¯š/•‹qá@ûl|¥Âø£tÍîHG˜ÚÍî<ŸD> stream xÚ•Z[ÛÆ~ׯ ]Þ1çÂZˆÛuá¬S{Ó¼,p©ÑŠ)E*¼¬«ßox‘ÎP¤VŽ‘„âœ3sîç;C{\†ŠÝ[yì>]y§_ðïÓêíýêÍ{ÁV7+Á<ü,”, ÷v¿[Ýüº5k¶†%û}ž¥I“•Û%ÿ}uÿû‘C„!ز™š%,Mòœ5%³´oÞkqE’Rs/”í®¬vŸ7ióÅ4IV<Ü<¼ê¹§R*¡xè9ÌlSV8õ)£²)íóÀ§dÏβïqgÚöúSqU y(%.;Qÿ™ëÜÌ‹©¥ä:t˜^ϘóÀÚºÛá>‚¸ðu‡ŽGæf›4KF1—ʧÔ/Ë'tÄãØabŽ„ïó8¢ëIÞ–,)ºXsáÐØÝç/?1J$•â‚ÒüðóÇ.JjÖM–¿h*ôxäªxM i¡y8l4Ðr“Ôf9Ò|/æ*rM„H³Äp–O¥Â“³Ì$a$lGicÇ8Éw–޽9»+Ã:ÿO­ôÓ/_罹’±àžïˆc¬¥Êª2õ¾,ÖYñô’ÝT wù!Ýã;즣‡¡ÃÝe¨IÒíê"ÔSëI$î„˶Mj(·6:àšò^_G¤ ¸çðÚØ.«µ©ì›Ê˜I¤+ă(ÇÕ‡º1;Ó–m•"&n2nøk¶3»²:<¼²ù½f‡ÞƒK+x~4µŠÛ˜!y]²âèúªSÇú.Ásj²iê˜r»©lÃKÓe3HÂ{JÒ6åe Nª§ÊÃÒ±¢{@ù&xI]—i†§5û–5Û.H—òÑwH7±þº+׿Tªlj k–ùåË©Ñp™=¸‚Ù!Sm ëÇr3ob0hén÷ì®Ç<ˆõ£Éêr>‡bÞ¿:9PG·ÐÙñX;µ'‘DÇ¢csÇæúÔC{S”¬+Ïp^[}Ä-åLˆä”ó”4Lóµ3Ý…¼AÏbÊŽ`…1k³æ=‹wî· ¹B·ôš2qWÍãÀ!c_:]+ -x¬²ÿ¸ë6 ëÖ,õ¼*V.}LæûmV³M[¤7mñ)ÊÁžÓ£¾!Š «=㤻œž!¤>êO4G@híP± ÕvƸ~Œ^NŒ‹25g\JƾŠr_g}ìñ(Œ´…†ýÃÓêÝýÊîëÃŒ‚íºg(-b–¯|©€&ƒ™=u¾Ú®6.Ð< Án¿!Ñ!ÌŸ²"Í[$Ìß èýÃ>ãÛ¿Sù-yàÁ£=ùs™­¨ˆ¡²Cqf>×}]Rú‡— €G6<ªS­¸t%d=¼úë²çTÄCŸzNÎzޱMVÙÞFiï<á…‹õÒEqçñ–»}nv¦hêKÛ¶/Šè>ßÑb#ˆ-æy 8e»YÛ®Žc{m×ÙœŽ£Ñ%"ÀnÂ} vÒv†–ªƒIõ­£%T†Q"¦$.(‹x éêòˆ ÜàvG±–=ñ¼¶Jµ»®AÖÖâü`v=e_•M™–93ÅSV[žò²xBŸ«ÌmVY£¤0M=6þCÞŽ˜KLÇ Ëñèc­’=µj¦èÓÌË0€…7UŸgõ€ ºìä ~¯º{áÿ%5³/XÒ‰4ߊ!I5•uc ²=Ç”5Äkk‹àg3 æ@Êd*té¢N6ƒ…ÓÃa¸.@—W ¤„¦û}.¶¨:V÷(ÃBXuCdàÈÅäIÔ#ÿì˜oÛ¬ÇßS¨¡ƒh$P7`'<íVMTy´}Bûœ•mìuÉüØÂDBö?kݬ9K„Ãs–,ZMÕ‘è;.”Åt”wŽh Y·îÎÂJvŽP²98B×/Ã-õ|¹~ŽÖËpDpxúGPº\Õ#.1æP²¼Ïr|x—ì.£§Ķ¶4º'àïÒ]GA4À…¦‚>Î_ôÔWÂLß<¯†#JÅðhOþX–ù9¡ë¹7h@}ñ‹„À"ÑÙn‹XÄq÷s°Èë©„ñ@8÷OºMª¿ÐxÛn6¦:ÛK Ÿ© {¡ìfO6ÿ³¢é^}ZÀEZQÂÛÆThú]§¬› møu?¹Ž¨Lü7žç¹[Þä§¹toÒìe†ñ6Â,6MGP§=§»ºð— ŠázàÜ',ý¬ÏËK§ r/ö)ó)Ô-rY¬Ýr@“f»tŽì/¥Ï1 —@¬ä*ry<4ˆ @!ç‚DŠÉÆÏÙúdl‚2¸{1€iƒðÝ_ðF¬+Gå—ï!e&v²Ž¹í‹mM1³ôåHØ;o×ÖöeÓ_%“þø<Ž)S’ÚÜ@iŽ¢FÉç ÚŒŒ¾Ã8¢§!lÎö‹£ŒòíWG; iûüö_ïþqÿÛûŸÞ-*…1A;Œœ}ì4I›6É»úÀÆî%‚3ƒÂmç€Ø›mÒ]™D‘E "ˆ(GFKi¢ìØð9Ñ¿Ï"D[u8PÙl@44AÑsJ(yè90o"—iÚVn؉ÞÙxzw}U9ël™–hµz;cNÅ€)“ž©&V–-#ëõuñ{ªm?v¸7€õ¶lóõô;”¶%áÜïPp‡tyP³ßq&)÷ÝÌgÃ}óU’Zc ÕpöŠ(o<ó›ýØ7 E¯»5&TˆÄq6] G¤ˆpv~©ˆKÀÌØáXFíöš{Ô tó°=À¡rQ{KMר]pÕÇÝl硜‡=n¯‹"Z®D&üMÕ.ÝØùÎsˆY»·á×öÓ¿ Í%”ÌHšòn’¼^*¹æ—º?i3`?Œ(U’åme8û¹¬ëì¡è2``ñ¤õ¿k;޵¶Žén×5…±R„”oyš*è®9!f§9Jvœæ¾˜â¥aNØK8šrb~˜£tW sb÷³œð¤-§ÑíìEO|å(û0ÞåI"Œ »šCò´“%èžÇLjÈpþ„Îo…Ÿ=Ÿdýk2–> stream xÚ¥ZmoÜÆþ®_±H?T.â5—»Ë´( Ç–ã±RåÒöƒ€€âñ| xä…äYV}gø¦™%i]RNäìëÌ<ó<»çÉ(ŒŒxwáõ>]„¾M,ãPºÏA,£XÖ×Òƒ…½uq±¿Ø]xbó€?RøB¯7¯®ˆ¤›Ý…üW¢ëÙ—±Ubs¸¸¼¯ªB¼Øü:½3‹U}¸Î‹ì6+“CFMUÈ€wwwÉ B%ƒYg7÷¿fiû}Rn Öo•ô#f.*bû-5ÆeX0ŒÃ…iU6­H÷Iý—þÁVñÖp÷â¯ØÕ«kèÈs÷F+i”í:52 æ$Ùš”'-·o²&­óc›W%šzàÝñêZ-ŒàÅ20]ÃÍ>oÄîT¦ØRÔÝ7¢Ýg¢ŸŸ?´¾¼ó<¯4vxYdâÔd[ÑV¢i«:Ãå¶YÙŠ]U“.fþ×0ÿÈ„tonøåæõ?Þ~·ùåúý‡·|¤©aŒ g E['es¬êvp”hŽYš??y˜÷ý#Ο¿„ýRªß/»®AŽVNèÌg©À/¤8&5ìk›Õ<4µ4aL ¥à‘ô¢ˆtîJŠ¢bQ« ½Ú=4àË4Ë™™±ÒDlbŸyð{Rkö>«Er<yš`x4èé>DÄÝ%øøÀ¦¡ÃXêH­ö¯##}ÍÞCÌçiîËj7F˜KÀ•ç+l\#Ê,Ûf[)0àúDQžFÇSoGvìâV À’úñ¼œèSs`îð”õ,»@…R[öþìÅÊ6/º´#. Þ´¶`ôþ-ó¶xüÝ©/Å5ó  !í6€nj[Ü—äpTMVnûäÀL4ÖudÊЂ…ã!yp­ª&ÃÈ<á¯uÔÁ½Wí«÷¯o–óØ·!µžÐ-iš*Í“<ó·{‘œ<ÁD5Ëã[³‰}η} €™W¦Ç¼ü4ìHpö'PcÓ¼„À;ô¾ï²Õ‰@Iy†6ùÌ߃s,{ŸÕ‹KJÆ& 6›ißgð©"à ^D­Ç*¸²ï>¢;kð âp‚ŠzŸM»¾P]Œ´Š5ÿøó‡+Ei43~ £ò²óoÓÖ°ïâaŸ§{Ñì«S±íëË®+P8‹¢GOÍPÄLEj›5y Ý—ίàšû¾zöP‘T"ijºIë f šÓýË-´M¡¾æÁº¢ nn†™ÔÙo§¬i¡·ªíöÕs§£'¼l÷IËS3Ö ѓɗ¼iqåçAOµëæÐàʺåabÂú*—[ÅÄ©>Äâ¡Iñy¨sØ‘R®R¥@Y—*é%ªDíÄmÖžê’G´ ¥eVÿâI¡%‚yŸ°Ýƒë­ZeZ6ÖkL 'p[Ÿ Žð¤9¥iÖ4˜òb7Û8(ˆ¤¯¤h†VÜ2¶2òcf™§ÀúǪiò{€!Ö@Ñ C5o€`·Í{”ÍË´8m{lMøaŸÕÙÀ2«m¤žâl" ø‘¥Ægð*ÈаFb[Aø•U û¹p€¤HÊi1*ëõ Š`³hog’Ð ’|è±nO†Tfàxj™y‚¥:AW` ŸÒ—KÙjƒ <0(gGLHJºPxmð8BŽ¡œKìó¶ÉŠÝSæùn`ã°žyÊ0l:Ài@A g¹µÃÒ·%.Í!¶ž R©ÙUtÈ`îÒ…€Û9$džfï³â‘ûÉ€ðdËÛœjEÞìÅ7\lÎÃä+¦¾ÏßLç/˜i«‡ìP~mŽIŠ´©Ýpôá}%<=;…ç8o²6I÷ºgAÚ¹‘ÆO¡“ïÀw‚idĘn š°N†´1'‰À {]åÛž˜8 l’>ºBX±9ÊI|º¥#=½ïyî!`"´I{Ô OœîÄ&ïÙÒ3ÔÈ ‡"B;?Ÿ¬^籆w/úCS˜mìîl8!q"P£ žE@·-h]j¬{=ƒFÅOP€º‘F'­~øù§ 05Pë¡.°VTªí(ùœLê¼;ÄN´œKÚþ1¨'톸ƒä9ÕC‹6ï hYZ‰2íi[ÚßóA¦Ü’ÎÈ9Ôƒu‡Ô$)rÇ':ŽePtI‘•Ÿ €B(Ϊì#†ª6¶NaÁÛ¬WêO¥8ÀCw­1~؇¥==ÑžwYûSþßlÕüôiHO0ÛéÞµm7jÚêù]’…Æt¤ù¨¢ï1-ÖE²öËÁE2µ[ÉÔjI$Ó÷D$k¯R8 ÍE 7ŠäD«¼l{·ÌË&_œ Ê.oã1‹ Ä`¾<Ííj£LhjF0j)Žýx‚˜Á°,’º2€7Ii†ãg£¸†+ ž‡<ä,‰´[—~B<¨e 5ŒK0ìö@·;¤Öûge¢oðÏÒ),ÊDjw–LD¸ÑÉD_û2 Ÿó½õ™2Ñ÷ñ¸ül™èQ‰U¹ aß NR£9_c Àµ–÷êÜšØÙY‡«·¦@®ÿl¨ðRÈ2ï- Djç D(½x¯y†Eµbº 4¨ŽLt–VDåFí—¥â6o¦4u@i¢Þù뎆ŽuÕViU¨}P¸:ÔJæ2É*#=TdüÏü=è-ÃÖ3^c"‹oáéÊ­7Z(³««Ã×®K”6Ý2iy|ø ‰køÿ_Ò®–WHj/Tóõ}µÀXc Ò.ÞÐ⥖f›'ÅûN¿äx#Ø&Çx˜>\$Z÷^FéhlÈ%4|F®ËKv]Y[ ¬y¹ÍûPêµÓóÛV‚^YÑT.‡¿»Ìe&¿í‚&´®èQP†™¯^´„d½¦¦]€lþ3ÆÈ?ß¾{ûf…ÞF~W8IëoWC1¦¥Èévé»›~üðv³6ž`Y?àƒAê­NßëÓku¼«×7·«£á!‡ñXs,×g„ûÒ­)èˆöÆH„1ÆÞK¸{!ÅëS;ø¿31 #øÖAÀš)Fó¼jë8õšcð(<¤]üžs?d¨ik L;üÉÀäs¼áÝf_aô()T»3è ÕwI™fÅúøù¬áX CY¥¡n³—#þzv½ ©‹,i¾¢3Ä*3Ò`â¶C÷‡(Ç"é¿áWN×Ô˜àî¡ÔiÒuRo)n mý7à à"áýä(sUà E<áã®Î2Z(ñšƒ)æ‡}Vö®bË5`)¾¥½ŸW€tèÉXÓvóúÓAŽŽ·7ýŒob Ÿ£»¬ÅûÛé‡8aá{7Ò³§Ž>»ßÊ,xz;òýSY`—y/Ž5?“7xJûÌ«SƒwDÕ1ÏÆ#±.:6ŒvlꉗxCnEÚ1Û û<~Œ£ÿ †ìo öíô@|_oˆû€!ëPXà~7GͦBg‚¿£áZ&„ÆÊÐ/Î(竈qwÅVŒ]uŸÝ9¡ÀožÅúOš%?e„H´ÌŠ»,†=ö>+ªcVÿ¹ïNù6–ùÏ‹ß.°Å~Ffœnl»éÎxÝt{{úlÖ€t¶¿ø·(aœÿûãIendstream endobj 1193 0 obj 3034 endobj 1208 0 obj <> stream xÚ­Z[oÛÈ~ׯl֜ٹ“D‹N“M]¤ö6«¦/ZÙ\H¤–¤’úß÷̔ΌHYE‹Å.dÍ™3çú‹–QÃ5Y~_0²\-Øñ¯ðïÓâÝrñÓÏœp8]/8að'‰ ‰áT²Ü.®î«•%ݳ%ùn·)WyWÖyÎ[²omeKVùfCºšüPØ._=ÿàÉ‹¼Ëɪ®:[uפìFl~lIcÛ]]µåc¹)»ǤÝ?¾}³üÍ ü=Ie£H­ý}\7/dÝX{|­íê&²¤Ýå 3ˆXY[Ø‚:v?ýÌ&Ô •R{¦ŠÊ%•žz¤áœQґ϶Û7 ÈTBu@õ%8Ö’ê$8Ï7{Û:š·Œ2™9]§Áô¨õÒ™z½¯VÞ—¢%9ÙÕ%¹q¶;±DÞØœ¬ëÆŸ´;»*{[ˆá¥«ÆXÿÕøø•ój“Wà—¦#õãovÕÑ@[%åBcÙnHÏD‘”J¬‚’’¦Ì`Ú»~ú>y ;%" &ß‚— £™L03$Ùæ/äÑ‚M&#Çdr¤v6ýʵ7H¯œ檆xiëU™wpŽc—€õJGŸàÚËÎÎé*eFyŠŸ»»ÿü÷¯÷ïþöá/˯ïo–73jó”¦ß;F¬ˆâÁ˜Œ¡Ž«Âxe)Üdä®n¶÷^Õ¶ûÕV…m®ÞÌf…Q¬¬ñ|*+0ùõ¥ªwmécšÑ4I•ƒ˜þÃÓâÃráƒÛ$'[ÿYjÊ3²Yh!©HÌÄ=õfñ¼X‡€ubyÇO€æš{aþPV«Í¾°äO¨~³+éóŸ±ü^`!{rgŸ»º°Í«bcü649¡l‰/Å© ¹?\…DŸæxú¾šfi@>mOûðæ³^Ô)È®/Š)/b:òÞ¶«¦Ü9„ÀÉÛtœ´QN¼IpjÊÈ’)U:ÅW¾Å)Ypnûz1“lZ‹ñ¥ïe÷ìù<•¡#À5&ˆ2´ \‘Á¹­»è»H€Hð"®£è:µ ÏMxp‰ìò&ßÚ.Šo)¨ŒC„ð¥sE8ïà ;‡’ÂÐ4•˜Å%Ž“™¡†×¢ÚÀ xç¾4@XÖt !­†˜<$.‹c¥Í{ ã!‘?ïìlSÖÅQõY—_ÖÐÍK\"¨JƒKN—@ Á2ê´8’8-Âb-„+JØË ¼$RÙ§×ñÚE^‚4öé…¤vŹömâP§»¼t;{¯÷ Ø®qíäC’ØÀ}`÷ørÒŒî[Ÿ·g°”Ñ suùì%9Vø0P‹‚÷ çºÞÐÖ5cÁC­çÉ$¡YÀÚÇë*¯œ‰|s]V^+×E'íTs£¹ïÿ[3 M1‹ËJ†¤_ú¿ -|°»1@%nFúöjé©L†)£Ò‘Ð$ät¦tT00»§R軔ƗfJ‡"‰ #¤‚QñÜDxÍS ]-¢ð9Æžƒ±zÈ,¸á{ò»û÷¾ÞÞ}¹ùtû~É[u¨WÙsy!.Ÿ©fŒ®aŒÜÊ£ j¸kŽ$¾‡›k;“Œ*©&48‡nJhfFíî5ÙWÛ~TÌD¥Y‚ûûK¢ÄeCwôpÕÚ3µLAMÑ#÷4Æ o>¼¹ÛÎB(tdjâ³} ô`ã%²kêÀwÚõ˜â[Yôy>+‰K#ÉbQ>|ƒ†fÎ{nQ…/¸5ÎEŽð©Ñ>×ûÍ¡PóC¡6"NVñþÀ¤•ÛgÅ Ÿ´Cƒ±W?쫮܀æíþqXn–ªsn1*[Џ9c|´Ýýwçm2" XlWÚ¶yaé¼í9e™‰ž{5} ˆf ïó ÕF&.pï´u~?`¤¹„b¤Ðñ±ÁbÓøªù@Ù3zC±3Æ ê³Ë´“Tc š#|}ìïç‚D$nq‡.œÌ¥d˜:]‡YnýšÛ…=éÜ6š5(ݱ6“[S·Íì‰^m§)¢?™S¡r¸)êHáÇÔÙ§ä®FšhùÈ8 s* "c0‚On‹³ËM‘¹ U#æ1{È ]´Û`ShƒýnS¤œJ‰V™§_ôÔî6]õ•ÙÅ»Mð* w›·E ¤0jÇ¡·`@ ™¯C¦áJ“gÄ“¼NšµDÈ y¤<·Ît›§4Ã~“~Cdñ6K%gKÁ!Ä…ËÌ̧5º-3•KtþÚ2pR2„Ž›€§’ð @©.)oÐÛŽˆ2t}0±uåªÜåPxSDA†eKع)í–ÒÙ¬ön”Iep>?sú±ZjTAä@¹åjÖiZ‚)·ÓƧ®®„ãfææV…i–gÄ_O#ê×Ä!ÔyxÅcN¤xûXvì˜e\Å÷ó›ýñ*Z©®^Õ¾;ØW%´ ÐAô¾_¿`W¶ÃÕq•¯â•C[;>7ŽPm AO£e¤+È­‚—.½Öý*é!åSuŒ1¼ÐƒØ„ÒXÆÛÝ: $B´ýM©É‚sßAܽn}*|cèo~¹…*ZؾxÄåC9®›zë¹>»ñpUowûΩUØu`µTAï€/æûMGnq“Ôêv~ Çu vr ì0ÙôŽCû}‰”a<8Ç¿Kóù-—ó`ùúú`Ìáu¨À]ˆrPácŸ9è×ÜÃîì^ÖH‰`ð[Õk°ûm'¸AÉmŸË«¼µç¶B™øorpè24,q óÄÀ¤‘Ÿ›183ÔAäñÆ…Ë3×3p|ïý4ïô F5¦õîû^Âôó8CÂ=À§%»»¿û03÷øÊ„où¬‚n¤`ä-8Lk²ê¤öŸÇ)þqúäO­Ã¿]»×ß“CŸ÷n‰äÔÈ„¸Q¼—Dg'¢`IPjîð°K¡×&¾ðÔáFõ>Ç29”W œ'øÿ_€.*ðWê~w ¨BBã,Xpn75Ì,?¶äã¾ìF æ?¿/Ü-ü7U£¸0n9qO¾`^Üžwr1{^ü‹TðΊ;ópendstream endobj 1209 0 obj 2644 endobj 1235 0 obj <> stream xÚ•ZkÛ6ýî_At?4Y4ªøÒûÒ&.N»©»ÝYkkK®$Ï4ÿ~)Ù¾W–<Ó8æå%yŸçŠåÓ"Ë?nðÿÃâ›åâëïB!•X®R„øOŠX‰Ø¦A¤ŒXî¯L*x½üßI@†2°Æ0)q[7»ÛzUÜÝÛ•V¡ ”ë\5EÛÞ½º{íýÂñt¤Ú’ÈÑLFLLüü¹ª÷mÙ:¹0Hâĸcöï— è"-vîs¬l S±]X¥G—_ ÒÛÅf±æF3" ôxÏ2 ”•~3)«|{Xâï óv_›Òý»­¤P¡{ñûºÞ :žâ\L‚Ù×Û™#‰à6áîHá35©ñû¬Zm æ²HŠk§?ÕiÊWã%ÇòüO¾Éš¿N|ŸáLßÖ뢹Ð'‘×µª¶|¨Š•(«Žj¿÷?Õ…ÒJí •¶›º!j÷ø—ø‡¸ýåÇ»×›àÈD=Áj*‚©˜xW´yS®¼h #í’öëïäÄ.Zý¼å¦lÅúPån¢hŠ®)™?¥…?“ˆÌxäÃQ 5.ZÑm ‘š¦¨:QÝ‹m–L¨›ßD[š¼ðžDtŠUÑyó­ëFì³ü7ªA#^MWìZlËÔ‡íj2‡Ãc½ÞÙÊûš&³±ž²Dr°ð)‡ÆlÑ$ȳèÌõ$[¤R”-Þp(`"&ÜuW™¢§ É`=ͩ؋˜¢Ÿ‰í™¢±¢šÃË/zé2Ec4€Ü‹™¢+ÜÉ@¬Võá~[ðâ¢ÜELŠØ÷_ŒË€†‰Žxb "™Lêšà‰¨³šÉvx™l(¥>›äFTl̦·óäH'…½Œ™®3tʈ¡•‡l|àGÙꢣ0Á¦+[Ì¢íÊ]ÖùòüÐÔ‡½Àjõ{Ù •ÕÆÍGV‚@|ÑòéI†ptꂞoÓ2Ñ£Ì× ¼ƒž¡k?ðn9~:‰±ñ¢š¥H°!Ê'~®"ÊaħðB( .Àâ*!@$Ji€+,{Ú~~Óv|3÷k{Ô¹É8¦CÕA ˜3ÖhÕšÀ*0ÃÞ)ÏË}æ—ÈÐ'جA!ÒYíÆ8€Ã±Oe·6Îú°9F¾ŽÇÞ‡&9õT¶WÜ­CR4þñåÉ+86%Uá°<–ÜÕ þÊóCãB×[‘Kcy± œR³Í,—יޑ!$tÊ@unš®{?,5Ox,xAjÙü^Ô¡ªD­dÌQjß”µ';™§"îÓnÒqÆt®ß¡³ÆÏ>–æw§”È SG„$"M*ðv¿ß–¹§­ÇÃ'–Rד‘õ‰Iì;†bî©`”j ¢fLE5;_r\œ:Ž*ìÀö§›Ëå§_~z÷vùþÝ\£N(6Sðz; QQž£vH6î.¡­[G:®”®Hd‡ÙÐo‹?º÷P5ï/†–6—’äNWçõV(H᦬VÎaÅÜÒêT¼Ÿ6¨ù&«ŠöÈv·5bïXÂë†×ôöËQz¡aJu"»ÎÙèò´g:*MF=w’éP±+L‡ŠM1:N™Žæ™ŽŠ£Ùžm´—mÏßèÊ‚£Ï|8‚~±Ì©óRÅÎùg´»_¶íaxU-24¨c¸^Ä¡ŠPKÖã8Äë<ê^Á¾çÌFÓ<‹<ã»Ø(žÓ¯¥LD—/ú‹ ’“œàyؾÆßk‡GG²nE3{$ë–4ìHƒ;ÐpN¿üB\‘„GÉÁŠ­{[mÙ8kð,²@:Oy»Z•So†*LA=©äñÍpì % ¹ƒ¬B¥Ã¤8 ¯ž9j’ã‹ß*èê ÇUÚ¢ó·nM^x"å_¡Ï =æáWGhþGùP¼qw)VäDþóñcBMæâŸÖò»«Ò~Þù·iào–$ÖUŽ…5î)Øm. /öC·£O£Ù Ÿq2C“çò /Í¿ˆL¿­Óg·1º'ÐrcbŒÃQÑ©ˆ ë1?¹_{±LŠû1ÅŠ!/¶õÞ³—›CÙ·%óß‹ßnÆ?sÜ.8ŸÛîÅ¡ßn/O¿»˜@”m¿Š ëüG'°endstream endobj 1236 0 obj 2837 endobj 1249 0 obj <> stream xÚ•ZmoÜÆþ®_A¸jÃå.ßТ€;ŽÆFm% u·'Ñå‘’'Eýõ}fÉ#gx¤ìÀ/¸»Ý™}æ™!¯ߘĻ~¼¼ëÍÅûúÿî.¾¿¾øîGå) ï.”àò’ÐKbåG±w½¿xyûäu÷Ö{uý¢‘—úšËføÆBþ¸+mÕ‹Ï5«0õÃ@ˆ{‡¼É÷¶³×ÕÃ*f¾ŠJC_…Ÿ÷Ÿ·Ÿ>./¡!ì{¿êÊklwlªKœ§h½š=ÎI?Š>'/3v¶±ÕÆn½çí ãÌOuö­†ÐYæ'*[1v—o¿ÛËÂ(í•„ƒ’—7A ¤Þ—vÓÑ/ðpˆ]ÀÃÜ™&;-B'ØÔû}^m=lî®»÷=n%~k>åúÞV^îµÇÛÖþ~´Uçmò²|ÆYaàl)×ñ¡nöê­}g»úÕo^Þ¼Z1 ¦k9+VÞ­õöùÖzEwïá{~84õ¡)òΖOWmñ?»,)YŸR°¶ÐÉè~ð$öcøðqÇÇSƒ3‰é»>bSMa… Ãij”ËŠXS:ôM&tYZÝØBH&ÊOÖõ`Ï&{F¼œ¼»©«Î’î nYÆg\³€ ¼p.l]Ú¶Å®`èºñàøÜ¹œ¶ùáã§Ÿ½VÙ¢$æŠïöXd‚~¸Âè$èVÅnÏc<˜ÅøÝ±ÁwØmãîÜTšë=³U”òaKp°¯;‹£T[Û3ãkÃ¥}w?Pñünz òŽü˜w^±Ã…iòC›7X²úÔ»“¥q½·.D;ºí‡"·å0]Ò1ÿDîØÚRœ×Ä¡™”¯ÿ Ç_gbÜ6=œô¡vÕŸ(N£Ù‰âl„¤Y8¦Ú7Š‹S@{ÌGmÓzõ±»ªwWu3³°Š”oèL|D1 °ñ×e[_z÷ÎqÛÆk–VÞ¼,|ë_’ý×`:Ì|Šu›úH»‚EQ†C qZ±µÝ3ø§3ºbR×íò F%¾‘ºyµŒ&Â%“¢3—Ã?:’.pñs¦*RÚÏ’uU‘JýTºÇàô‚L2õöx(‹ ñ{(lK1Ogi‘ØN!í{ï]̧`’»YäOüXç{ÑHI©’-óP ä•Jc?LÅfž¼ÊÚ-Âbo7À±¢Ý;ìØ"Ånº¢ºÁ‰Ÿ% [ýâ_‡¥)ê<~øPÉî:–ßO ΉVl"_Ãi´"RŒàñÅ=ŒŸÅBÌûähŒ¼.Àn„دr<x‰qâ7m Sa‡E&‡zÊpÛîXmœ§z2Õ®R6Dk‹ùë·@%ˆ·T#>°ÈŸ»c¹hÃK(ÃgIR—h?ŽÅ8²ØÃË9R'/·òz8«¤ŒFf"§í ŒõnÍ$Æ ñë˜ÏØåe»† „àRÚ+ª­‹0—™GÂA¸š®-ØP ªÇC?J˜E\VM3rd'™:Cø†KÌ2+ØŽ Š2§\6äéÙu¦ÜšDbEºÎà×ÒuÆÄA$ © àÃÄÆ“¸y¹ý %ásž%èäJìrâçhaD(_'3È*hSgex™ˆ .LLF§é”±‘0ù™»Zµ(Ë&ÖóõR…PžÏz¶¤‹PbõBæ¾=êo:"•²¡ªÿ„‡•SÑ6!h8¨(‰ü84#‚F3ü„m@ì¹”w*G~l¬ýþ¸“‘¥"09aÆCâ’R¢ê™¢ÐÏÈG¾Zy.æ}~ªêC[ &XðÝéÃÝÅÛë Ò ÇkåíÝgddÉò"^„àâç?ôÒåÅýÅN6ΊôidQn3)ªMyDÎý{˽>þý?DñD[AæÒ½øC âËdzØÏ„ÄÜ ŠÂD;¤ÎþZOpÁ¢ÆŸKå,K€He€Ã“äÍ«¿­º EšƒªÉmá’Û¸˜÷ƶ›¦pI€g ¦µäjk@Ò—’kió8¿GÒƒkëc³€ß{—÷P…×t›ú’(_/g4¨yŒLÂVó½…ê·8û¡ªO¦;íÊr&òG¾?”ör…­¦VÅÅg‡Ë#¶¸è‰à©29KkD€áž,·},Ú{–BéÜZC¹0Û[Háꈿ嫄]i.O%ðoŸÞþüñúíoŸß~xóöÓoï?¼þáúý¯oW’9ê(ã*ƒ]ñur9Ðbçaw\åyÇ W ZeQL\Xóá‡YKC§|t^÷ÖÛË®€Ÿ‡ÇŠtNÓºb3Èëd×e–;ÚÀ¤¯O­(îêM]zÈE5Åy{ºPÙ©»â"Û  5¨B ‡ËT8FÒ5yÕꦓdCemD›=c”à!°ë9M­±qÞb·yK9o³AÅKãC…S{úT6"»M©÷œ!¢<;áÚç.oºOÄ C¢¡ó÷´ÝõV–á% Oz¨g'=ŒUt'x µ3Ó`4Œ„&i¥ÀªL3]B¤øCS´}Úßç_ê¦èžÆÒ°#B0Ç2ÇÔ-M {¦E$˜ˆãXŒ?×Þ1`´e&=ƒC"`Q$lƒ]Qpž:Œz^5+gÛ¾[9´wžÎïHD&D‚Ÿ©“% jüX‹q¯ó¶… Ø ÑAè;‰¹>vçuÅÞ¶C|Ì6C{õØö4 |,¿³ô)ß×Ç¡‹ç«0™²ÆÉ<»öJOŽWo*…½÷Ô;Ý‹à@ˆ¼˜B›ÄOc¾Äƒl m¶/¼üNÖq =&å29n_¾#bš­‰m ª®TÌž‘–!Mépž¦¨1½]ït7¥%&ùK¯’­dÔ, Ÿ‰<.$¹¡e;šÞ÷¦^d¿Ü­’ “•c"T?É*[7/5ewh¯o¿ØM7®tºê,"’¸¶M}8 \‘á†Ïd} ñ_dDÚ n S8+í ‘ÅøØërÝ@×.ÚùÚ·cyÑô —’¨Qè0h„w·ÏO0€úig ‰/Ä&Eq¶ÙÔ©Ž_hë‹qûbÖM3D+¸žuÑ>ÿôñ—¾éc|•Ô ‚6\ Å÷Gçèr³\\*x“”Ï]0ƒ2 ù… MñuЧ^½ž«ÇS°À­ÅgJiÅþæ8Û®ñmEXVâñõ쮇àc`klÂì %u®ù°mÎïÁ’hU ÐÊ!Wƒ+P#9Ï|3ëZ1‰Ä¼×Ô÷¬ònöX"rý¨µõ‰ï;ײõË'™{áBy‚Ë ®{«d(©– W­Ïû% {ˆÁÎAØÌéNˆÌm‰ÂUUá :§*:p„‰é’Ð(þ1~F»U—=4~‹D¹ÔÞÑáˆàg`“Ès ±™ {óÏ’¨R‘ ÊIØvÙ‡qŸtºÆºlOmCn°Yp§Xêq©P 2?θÔzã\fVœ/6ιØ3s.¶Ô8çãcã|b¨3¹XÒßÃBU½ØJViB­I6•ÖXoy…QæfjyÅ‹-/.å­]…ˆ:våФ}±[Åž©[¥2Ch]·* ÁØkNý0Hc·*D‰'ßÜ­RYw>×­âÒv )±T7kTQ²_T¶Ð¨B(j©ìUDTÂ=¶Ø¨âb ª([OœÔå5 AÍ+‡[ÿ¾‚?§s`Ó1×"Sî˜IØèØ Ÿ 2`!¬”Ý­€Ð+ºuù‰Ðͫζ­7…ƒ¯þ­’ˆû(©[(VÑœ¾ßÛ£òÊ» 4—·ÝPuɇmµÚ‹Ç¾Ôª“l%bg‰x€Fˆ³â–Ü Ìf˜·úBMÜ>f§Nßcÿ.ÐÚ‹?½D“±y¾O¦•\ÅŸë“Õ›Íeõ@¯–ªVêXôªç¹•6\àaÞ/Éø(LqžÂè ·$0Lìòì7o[²ÀvÌeF¬½RÅ·^–+Ï­Bê2IäcÉ8ˆ¸Ëø»-Ú Ùa õž¶{ê´Åë4K€›?Ï‹‡q¦Ù=³C`5Ö««²2%Ÿ¢R“ž¦ÌšsqJe>ë?ÑË6dܾެÝѶé@hX§nò(‡NkÀhÿ…N¬Ø¸=t®ÑA*·.mlGv' ½˜²™ÏÖŽ®ì5LzVÇôćíâÅ:U»mÈÕ¬Ço|­QÁI3&CåÅ„|ï—ʽ-&u¡^ɸ®?è]ÏöWsëf'ˆE‚&PþJ«FQ ˜LÓOñøÉ©y¦DÆÇy—Ï=¥Æ[r6J ‡©¾Nù¯½¯å–±©«¶Øº÷± Y3+jÊšiÒìƒÈ½ï0Žæ%¨KßÐrWÙªhÝ{’Ž€x&Þ¼ ¾¶q,vŸOSF¼Î¿BP|'VÖÏ›ø\ùý5Ë0­Nެ¼±óGC:RòŽeX1㶬#m½wG8u8æ¿.~¿ {üŸšÓvQpÑvÏ~Üv{yþÛÙ¦ìþâß^…uþëëDÊendstream endobj 1250 0 obj 3503 endobj 1266 0 obj <> stream xÚZmoã6þî_Aà>\Ȳ"E½áìv³½hÒK}í}°Pd&V+K®^âæßßCJ²9²ìMÅ.¼â ÉÎ<óVÁE¤Ør·ðØ2[ˆÃ¿~ÀŸ§ÅÇåâ»Ï‚ ¬>.óðŸ`‘dQ(x²åfqñaµÊÛ¼*Ó¢xy·ü}O%¤à‰p)/YZ ?â>ÎsH^ØMUon~×Yûï´\š=»,Ò÷¹¯ÈùiÑé†=V5Ûêr•—O¬²ìøVWÖ®ó†5XÑ5KkÍÒ¢©XNî¡Åã v7}¦ë ½˜š¯ÒV¯ØýEWºi ½g4ç*I%#}Õ®u½ËÍjݦy©W÷ï Ž¢]WÝÓšîï>+sßU´HWdŸ›Û»Ÿ¾ÜýïËíǯ¾_~ùðñönyõ©gŸ>“ïy<‰]nVVmÞËøâÞó<Ê‘¥æ=¶I_؃fyÓtÔh×…=óžÝ›±‰ö{¶â¹Ï‰xŠ'!!cwºíê’2KR„ìWºsOukój1÷ò‚Q%Kc]™‘Ù:m #óFæÄDñ rYÍÙåäŒ0<”j/{4‘¦¤¡²¦S­ô5‘û‹ûw'51OÍF\ÌiÖ%c¿¼”Õ¶É{Såq+ãäý§ÅÕraöС`û[aׄ‹@ú\Fá̇žºX¬2ŽLÙîçq{™¿åeVt+ÍþYBèÛœ¯ÿåÞßKÏÙ“?WùŠ˜Dò„PPÝU„!TLˆï/A„7˜Ý¬G ‚?0EŸnƒ)ïßýãä‹IÌ£À}19÷b.û¤›¬Î·Æ4 é{ª"2³VD¡ñwÃy]ÂU5kÒ†—¥Á¾Æ~:…4à Î žÚãôl ‹„0ï]ê²ཇ!JT®Ø~ä#測»þ¢év[ä=±¶`“5-P²4ÕûA#ž '°„jÜ+Ë-HïòvÍRö”Óè#y’òçitŠY×å ¿àHÙÈ]â’бÖD\¦,“Xç…ÑÑY7ˆÃ¨=úFê¤ÒGhKÔDˆÝZ÷Ò™°X¼07‘…m몭²ª`º|Bb›üiÝ2ã¢&º# jmøzI¢dªù@'´?¼Y¹k×Lb¯ˆ}-X'°ó &ëCì=gÎFlXu¸Ž}z.b*.aãìúñÈ»F7Ô®/YÞ²M×à¯ô÷þ€¢¼ÀÝ{ ¶ ¯›jPy{Û­êZ7ÛªµÀøÁ)ÿÐ+ð±Ði£Ï¸¯ò¹ÞÞB¾ž)”y³ýË(ÉØ<øÑÌè¹)I¥9ÂP¹gÑTKBºn ?e½©êQþ`YUŽÞ˜¸»³8û6ƒut‰½†=ú •ŸÒé}ÉæMìS%{¬në´l6¨€lî’µ“ "ABë’?çí‹EÃ|HÀ´åä}À”a4{íaîö„à¸ÙVu›–­¹4äÕÖÒ]ú 4¤·Uƒb÷4 ø°ÉP¸g½ÑkLý›ÐÞô¦t´zCÑL5Ðm’ ¡àŠTàRw€Öƒ„,ïCÖ1rÀ/cáÒ¾ à#Ôz¾Ëuyú²ª+Væ-šü6Bü‰$Ý¥éýg¸CV¥‘ =ˆ¤xÃ’dw%qG–cÉcIw^å„¡- Ⱥƹc=!ü¾ž˜ƒ ¥Â7© µåš„C”é!Jh‡À&´}ca¨VjÄùvôUÊœk~ɪÒF:¨ŒXˆ½ÄÝð™.ãÕ=¢Ÿ—%šûzuÂ3PKÊ‚PgE6˜>‘‡€ðRÄä2‰ȧ›#h1±À'§D3±À'Îú „šº˜¿‡Ð ,Ñ.‹„©ês´˜¸»sù¨Œ\Ò×X”¤v¹lªÈIJ-‘ø„J¶Qµw$¤¤äâ>J9¤ÚÇÄN$7ðæ»5R~œö›îИ±ÙÅmMŽ <ÓÌ!ÇäU7ô[¢àœ§Iù-žvàšzªQé»¶YŦm$]¢åØwÔ—cÌtÄïK[â«Në> j $ùm™¸{VG„²Vyär=$ NßÊ ƒ½ö„ÏhOx¯uXÓ”Ž]›woӺͳ| 9‘.ô/ßè·æµå@¥v¦\ÞTeÞB›+ªx?5$î%lòA¯'¥RÂã0té`NµÉP™›uÛ>ÑFžÝC¹£?Ùƒþš4]PY ;Ë»Y[Ïú­Ï‹ÿÔÕƒ7̆EØÑ&-‘mÁsšª«3€ÝØ~¨Mo!³… yZØ@ï}”*ùñ銴&ÒHîGî:+»Íâb (͘œ¥#"ÄÔº°} òFpeß÷Ý]?ü|Ý?2E‰äôåÇO÷ï8ûL»\@O¹dUO='N„KòWŠ¢H—w€¹AUêèÝ£=AýÆXj<ÈngkÖluö£žêͼM¿P€Âq‚¼Î‹ÜSµÞ6CÛçÞŠÊ\FŒ¡Œ?ØB× £…þ¼¹1ŠîbH ìÖ—L·™)œKÇühÿ,@ñé²ã Ç¡í¢!Á —ò¯Öœ´bCÀ|ìZ˜9s´Ùλ,Ð%r÷1K(‰¹Óé鉯¼IÇxvzâ’™ž¸dsÓwýüôÄ1®7LOÖóÓ™¶¯9ÊÏNO\*v²ß5£Z ôÕÆóã—ìUãÓŽEoÇ'&M …3-9þÐS¿r|"Ÿ‡Ñ«Ç'fRçÆ'.ÅDyÇã—x:> yÏî67? !˜KûÊñ‰’‹È}±Ùñ‰K6Ÿ@ûÑéé‰@TVãðĶ£´iG‰ÐÉ–”ä*ŠîSC¼ã®+n¸œÓ™É4)‘8ÔËlS¸îŸ¬Ÿš¼ÞõêÔ C!—‘rúÚCE÷kª!7G~2 ç"ŠG…ÍÒaÚàÌAÃàŒÖ+“XÝ–™îÕe•‘›©õj&f6kSŸÏ…3%eE…´Ê#›’fú›”zÜ3‘H8'½ªB<:˜.ÙÐ5Îm«¨iMqRÈ„œHdƧŒPjâS³Æ%;`\²¹ã®Ÿ0•ú¦ørà܇óHä±÷Bqày6Ì·ÍïñgLÝÓ‚üÛ vÏ7â÷Ç¥“!ÛCJ(.¥½M(®âÞ$B 'lø-M 8m惥¦BÕßhÿ{z'h_©ë‘ûÿ’#éÌ6*:“H|›ë9뺨¶¶«úC—¯ô æ. ÇÇj¼.¢µ¹îÑÏ^·§w¿18›­¿±çüïù ´endstream endobj 1267 0 obj 2753 endobj 1286 0 obj <> stream xÚ•XÛŽÛ6}÷WèC7EÃðN - 4Íh³í®Û¾ì‹lÓ¶ Yr-i“ýûE{5”dÇE…Mž!‡3sÎfdþyÆÈ| ÞÃÿÍìõ|öê#\QEæë' þqb±ÚRm9™ïf7Š&ôÅüŸçéTS¥d!Ÿnï~#oÜã¸UTjÛM„H9MX!6y¹!ïÚrÙäUY{ôKFej½ó¯Þ º*Ig;ßæ5©]gJV®^ò…ƒ‘jçH¶Zå~<+Èú¸:YfEQ“f›5$;û&yB•±xùÇh^H*x4ŸåE¶(i*p¢¢pÈ$¥’lÐnºÓVm³oRí»#“¬\‘eU6‡ªðöÌŸŸWˆ“}ÕlÝdõŽ\“j Gq!ùn_¸+›Ì¯Ù¥¯Ë´Ϥ •J=ç™G™æŒS ³E>U‡Ý½kFɶpºxÁvó«ÃÁ4M"Ä£+n^<»7Ì­±š(¡Þ½¡ƒŠ¦&‚‘û§²Ú×yW:Œ&6Q¾ÚÇÍìí|æ×…0IvÝg#iÊI1Ó>£ÖL t1ÛÎÖ1w³ }Ö†¦Çbþ&/—E»räÇ¢öó>§ÛŸ°ÿ+–2àU¾"Õ`©ÑßÂE#t™ÿpÓ–u¾)ÝŠäeC oòðâ‡óç@n‹.&Ž`@{O´®xCÌ•UgÙªSImOÖžŠ¡à뮄ãS_`ÏÞÒU7O¾â»j0MØ„2•Þ""%ò'NÌg¨!‘"›¬h]Gª"*bÅ!º ^(wF®±ushÝô.žÌb, êv¹tuMÉÇ7ÿ&È¿žp·º®*–YYV/© ˆ VÙàö’ "‰œòqòEt¶4À@bƒuVÔî\e/VøÈ@ S·:¯ìR¤p½é•]N*;FuÊþKQÕn(íðTõ¯7 þº´Kf¨Be*§¥î’va`5¤]¤Ê“¬Wòñ@@_)íR™ð«¥]@#IÒKÒŽ8¼cm¨í—T\(ù‘ŸTq »JÅ…PP4à¯ßœßt2Þ~RŸ0ì‚>aØ”>áùËúÄ6åþ8^ 뉣&‰ƒQ_»al»ù=ß»‹ÄáÒ¿Á5r`’8vqRáyo¸€‹–E4 ð•´áð~òjÚ¤Âr‰5݇|è&Hƒàÿã>´‡ÅÐ}btZ–‘—ðˆÐš,Ã$ÝçÓÇÿ82úªuüÝß2ƒÝé7”.ˆÃên#áÚÏý òFŽœÂ>Yÿëá1™Œ¹BûN tèxÀ¨àÛóç£wÏ>)mͼõAî’~éŒ_³P:BEÍQÀóS°hÞÐGßÖä}›¯Üñ˜Ìþy‹üMÔÉ]Ȭww4À:w ÐbÛÙߤ„}þër$endstream endobj 1287 0 obj 1604 endobj 1295 0 obj <> stream xÚ”MÓ0†ïþ–8°=0ëï(e,°Dpé¥ÛzÛ 4)Í–ÿžIÒ;MT5²==¯ßÌ„Ñì‘0šÍñqÿ%gäòŠQŽ‹÷„S†?N­ ÖpRÓlM.8P `”ý8"œ)ð&Áè$Ôóm¾yÈ«²A/¯øÀ¹Òƒ6-Ÿ'6”žÛ^z9˜>ÂèmxØmKš`ŠƒW ö-;`<‰ÏŠ]¨ÏÊ7^É}Ìr0BåëžxZ©„¢7Õvý¶¨ê0 w ìÑanx·üœoÂôb::k Á›ùÈ@ |ÈÀ£_—Õ¦ÎÛÛ3pÖ©¦HºÁ’¼ËHs.C«8]·ci{Z-$k:º +rŸ–œ¢d_³d 4oÅ<ËËy±[úªDcÞlrX½Žõ78gøÖ:ü®ªŠäÍ{>!b;ÿ;œÁW’l˜¶[>”õ윇÷³rQšï§ÓÑ˳ÖkçÀêØúÁÖ‰±ÿjmðNƒ•ÕK?Ø:1öDëÄØPëÄñ§[G Ñ“uˆ3ú‚+Àsæ]eµãÃÐÅu2E0™Kœvûä¾ðÆó/«eƒ­£N¤ÄJ,¶Ÿót?ÀU”m`¡¥Ó£:EÇq_Z¨”Ÿ=|[n>Ý~ÄšˆýX.R'Ô¯$î1#K⡨6aû¼¦×»|ö×üB~’fÇŸNäâg­‘{²ÀZ¹¯lˆ[‘ï´Ä<O!ažendstream endobj 1296 0 obj 547 endobj 4 0 obj <> endobj 9 0 obj <> stream xÚÝ x[Õ•¨åûÞ;÷¶ ÓÞ;Ó¡´Ó¦Nl·‰ÓÈÏX–€Ä¹` ‘ 3þ‡6Ö±c%XGÇVÚp"9H–-4!‚Iü h:Ρ ¤¡PZ ¥ôB胦¬»öóìsô° HGt3_‰lm¯¯µ×Z{í}ö‰ÇsÝ>øéC}=Š¢ôôlìÝ´åží?rìø#Äÿ’Ûԙㄙ4ŸÌ›âóÝóö¹¿H蟻§¯W…FÍúqºxç/ þÝ-þ€ß¯bûƒ¡P( -Ô´€_Ùxè/þýÍJO¯·€¿`Cð¬uä`÷u¿øÙgŸ:¤(½‚í‡úCÚ¦Wy(€›_ÙôÎgûƒÍ€M©ƒáþþþÈtä}Úüþ{Þý¬b¿Ý£ôôQìÂFäáiÈjóoÿ,¹sÛÁkS2lÔBúLMÞûÐg ýx·Ïß·%ˆÀ¡p¤_l:îþˆ?¤!Wúþ,¡ŸñAÄB³Øû#ZlnìáþHÚÐÐP”´AÒúûtÈï6}fЧõøüÄIÃ:lD΀y‹jÚàXE©¼ã–‡?Ñ탻¨ºPùqmÓ'¢ÁŒô‡ž¤v}[å?ú¡nÅ¿…`h‘|p(iÖ©œ›À“¤v˦‡ò\Ý}TÝA>·#é©“«\m,Ÿß2•ÏêV˜ºõž†:=ø8|‚¾ñ\þª[ö°ºtó::<œ<…­÷ó\Ð{”yšÊ=,ê«/Ø×§óäàÁÓcOcë$úAdóuÿ8¹{3Ç)ˆ{thú–<Â3œ‘ÌÔÖµ“|·~¶;!Ÿ1Žû™9¶bæb¨?EðÁ~jìŠÏ°õùûrU8âÕ Ø#Z”O |Z{ŸO1 ¼[¸5úÆA{ìêâ™Âæîóm6†û'²_äÕ>öIÀ‡´à$uõÉÆ88_â'Ž ë›“³ˆ. }ªà ô^ŸÏwˆz6Î=¨ÁÑgm4“I¥;1}`ë>2¸)Ÿ0Á1÷ JÑE¥ŸHߨ ¤vë¼*à=F¤l~-7kU>ñZ&ĪþGGG’«E8¤òc¹.%ËÓqkÀ§Ss2p }4a’#๎iw¡µI;¶ ÄK#TœÃ'¹œÛbû;ŠßO+É‘aÎŽy3šÚiÀ±Ï”®j<ÐãóuçÖdÉÂLßd5¦Ö1 Í'g3¹õP8€ÈsÒ¦ …ú£\Ý:p@ÕˆþÉÀGU/en=ĸ֧ âàºâ)]Y‡Ö¯©C)ÞÜ©üERMÆX¸™«à¬ˆš-ð¡MÊww®¸Ïq…‡@ãºr¹€š-ðÁÁ°¦—+•߃“tô‡#¸Ö$–5¨ÙçKlì9Z¥“ žPB×&äYG \˜Tc”îܨ|‡B’|~M´ô‘œ‚CÒ¦Åß¶œ€Ë¸°J =*xôDz J§à9©B½+#×Ɔ>ÀB]EæœUåœT$6Ëäœ=å¤Ê6œ†rÙ— ׿SÂÑÙ=!Y<–ðH“÷Ê9ØL{@F® )<2˜!¸žð5ÔèdJŸ “xö“˜nÃáò")7¥géÏ_›~A®‡ Áy@–嬃{ñ&aˆs§ÖøÄ'l‚#r9ûîí]¯ƒ‡±¡GÓšzÖÁv\ôå¿¿`S0à›²íÓ NÔ-‚£ÊCð4¶>~øñÇ÷\¿ìÚÇö>»+|ìÙë®þ¿»b‰àÿät:‡ý߃=rÖýº—€CÊMÀGG“”E¶{W.w6^~Í3ãzèý+V¬X;´¯?¨?v£ øöûG…Š3·Ù9 Ûÿ=­—õ<Ý:,Ä£ÈÖîÊ éó{n¸òš­:ðñU®&Ò¹ÜnoØ-bïonnvâä˜Üvþ˜ þd‹ËÕÒÔ?½@(·p;&okks·-ß(ËÙMÞŽ+~ ùþH_«.Ï`öÁÇŸlr¹\NFþÇ>ÜÔ‚>Fcâjs»%©]r»Ûœ„õ°ËEZ›$IWª[ ˜{»ÓÑ`—ÚI»EñÏ*ø6NõMÍØ v¨à×\ÑâjáäŒÛÕ‚„oi2hn×3dÎ/…ñh‚>àn§5ÉÝrŒYú'¦ÆŸ?§’#k[þÿ’â»3ˤķ…Â×4µ`5ºÚ;¹D÷ÎÙB ¯dàãÍ.DÞ&©dðÙv4nI€¦Íó3 ~é§›}ÑÃÿ ÚªÚì¤}áFEÉî$÷õP§¾å:±Tžanê³?Ç}!öãv¹n–$löò @î–Ú“´õë(ø£ sø/HÃ"x3uþ³k³ Îk¡/ý•¤î@µc5¿t6—e?ÑB樎ì(¿Üf“’r··w¾EÀ¯µ7¨æ|X¿VkEÿàÙ¬F| ô¥Y(rßì93ÑÕ»ø56.ç:¹›“r·{&&~>q•Ý&þ`ýj·ú~8zþÙí*øC0£š\üÛôèÆ‹Yuꨟƒþ†£ËÙñ:·7p¥!ðýM*·GÀ~†Àv>IƒF©a¶02|D9õ3§› ¼´/«y[ܨ¼»¬ÑѦê‡?jçæ»~¢Yà~å6õ¿ð+j/#`oàê•^ÆàÀíTG‹ƒ?ŠƒWxǽÜ›Eð»¡ú¬?äLª;¨­Ç®ºÂÎ>ý%ÜØÂåó¼:ñŒÍ¦Bp·j\µ—öŸà8à.õ;lF=ÔäjiQÞÞ± weû¸.ìnƒ(ªNPÏaº“p¥ã Æòp߈¸ñ¯y@¥Çìêìh{p¨àĽ&4ÿ྆Wµ’öýüãèbð,æn>ަ¸³Q°AêwÆb D&ωd$^IŸ^;a·»ðq‡úË¿AàÏAÚíÖÌñeN§[ÿWFoÖz{ûJüdš÷ÇYf ‰fË…ìûؘê‹<±‰•ÍML/'&Æíê`½Š89øü ðÆÆF§H\ÉpölêÇÒÖ€ȽÙÛW˜’Rw mvjTAs˜Ønü—±`èÍOHtà/Oì<öOÐÏÅtßíhÔØ•„Á¯o¡†ÎðÆ‚Òõ@ÖÀÏðµÙE ¤—%œHÇžq,¥‚z^ŠÝØÄõÒq=/ºèŸL\'üóU´RC«6/!ðgÅÐAÝúƒMÌÐy.›uðwPþàáЕÎF—&#ùŒ;áŽØsÍêDľ Ù¶SÈÝ Fÿ7ìŸÃZÆ¥NŸNœ²^KUÑ®Ð:e¸…:ÿɪ0©®gïQ•÷ªñ¾F.£G˜~±«—²Iº.ÖÔäâ™x'ߣ_êpÜÌ9>×s³ïµµÐ\Prñyr?W¼weoûÈ«øE\›·Ø˜Öñ¸¼Quên'÷ÿžŽWXu BG a»‚­Ú$ÂÜíu„xö2··ÉþÑ–eÎFâ·¤è?0ðÎÃ#»yf-[ÑÈ3;’¶M „E][wžœºZ‡éxK-ªïU»k¸\Gy\6®+#jêÙ‹ãïxe øA#3cOô^›“#Fã3 ã±Fç ®ð7È>Ê21š½ñ¸>F£ßìxIØM€)ÎþŒ•j$’üKÙÜ,ñ)NÁ³˜²zññ•`Æ4¡ŠÚhåAêˆ]ídj~ýjf¥¨"q”€ ¶Ý.½ªÑ?›ÞãâþQ#Ÿâ·ÚXð0·§I5éžP„ô;”½’Þ­šàƒCCç3e¬F–Níï…Fañ¶î >.¬½ ÀArÒ”Pc<*€Á0R 9bk ÿEº¿u™£Ñ¡FñH€D³ìÝÎ!ð¾/s‹O>ô5VOºýˆäÆBé·“ì>îl»Ŷ›‹«øóÎFºðœ8ŸÙ&—îotˆ¾¦êYÔxÀ•¾«¸boðí¬®êYÍçdÇ.G£Ž7ýop:¹mKGŸõϽ›$€_Ï7 ‡9ž6ºxöÄž³r³W¨ÙH'þ[¸/çN»] ãϯà±ãW±›ºQѱ3ºT¨pm …ƒÙÀ—¢íM" ¾úã|îx¨¾û†f†QV6Š‹Qÿë&η¹´Ëß³œÔ‘ØÈWm¬ðì¹=úPmï çõý½>o67Îx#_nÞŠŸ5úÛדXô‰m—#ãtŠ«þî­‰ç„axcâR›Cg먯࿱;6²s› ÏD· ¾­ƒå핽Y½+Ä×Ó­:ì›ðÁÆáûæ°ÜLÐgìzpdémªï¾^X´¾4ñ¨­Aâê'à0Å—Ñßb##ÌfŸht»]Wf=Ù ãÈ»)ßw,e&ø ò8Êð»¦0æ j>â>]RW©Ë„ŽOìæ‘¡}=þ:pÌ©øÈ½dây>žoWCá6êÛdoVïî}QVì|yp+}îê‚9n1¯z=Ûe··iÀO8UR˜ÇÈe‹Óú|¾«&½€À¿ŽOñN >rNVwáÍñÏ« ÜëÍêc¦çdå œÉCŸÛ>ÛåÑ”BGwëÁWªTéÈÄıª‹GÆýO6^“è Ý—/çõ}ÐøÁŽÎÃôT@ôoiЏ =£Ñ׋ŠËY~É«ô~ž3í¥í¾¢±õ]#c£šÍ"âMBÕ[—k b«jëÒÓø<ßrÕûŽŒ¢ÆÏ¿ öu4F[ÑÕÝ!´qÖ+wÊ.øŠâçÚñ ðmŸskv“FG„=´kŠ6øVÌxÁ©£ llŽš’J—Ë?S’ì"äöÞ0Ú7ëñúÞÏ.øÛÞÿÆ[n¡+ч¨#ì'­FOÌÿ A›Ø¶‹%!Eitr¬v4±¯ÍQ-D²íŠ= ËŽ%=Ç¥·÷á›,»º³ü$9,ÐÀ•Ü·õÑG÷n÷³ûY¢§‚¿ŽÀGç¨;LGV6¡sO’š¡ŒCH仼ø€Óƒ³í©¨†× Ùø±‘ä’³ëš ø]ñ,·n¹W¸)€>`^y‹ ŽfãWÕÓJ.'2tz`WÔžq8ÔÍuRuøÊl¡#µ]%üÆ C©O.£Û¹·ìËúõvÈŠðÈü;´½åvæ–ñ#Å;ÏoS±‹&{$V¨¾H|ççĽ8éF»ºÊy:ùõ ýôvn|i«·+ëO`¡º'*d—bÜD6“:ž'ÏRïà¶ënãÇÙ:Hz²[Àê ‡¿v ¶\Hç'û‚”¶u|Ee?½/wH>4Ä•>íýN1íå!¯Å2šâø3t 5´œÝˆ²goØÖÙ¤CZp®ôéo¶¢¿Äè3œâ‘p¿…qw劒EÑ\ZÈÉ5×&dv¥—8+’ÌøDpüJ• y€º'§ Çwt)üšiõNqý=´`ï3àfô¨ê€´Ã7ØŽè/òC.L·ËˆÂ½¹ãŽOù|J’‹¦£ ×ïÎ|L!·ØŸpý4}¿+‡àñºTc/KH¸nyFw×%Þ_§¹Õk0¤çVä\4ôXú`Ho銷«Ë€—åÇ*gÆé˜î=cŸLázKúÛ7 ùÿß|8á~ùoéèõ¦]]]†¼R` âÆžá«®´ïHÏ=œÂÒ~üê;à6èe1çc5ïtIчØg ð!ñ-1HÝàгøÊ4팗;~³Û´oðKÐûHzß–ÂÒƒ~gܰö޽B›¾qRO>œ\á*ûhz‹–Î\ÚEØHᾸíÇr ò”ÉŒ&±ÍÔÒ‡Aá‘p(ˆ/ÙÆÜ]ƾ1d&&“ŠTj…ó÷= ôZK×\¾;ˆ Éœ(<'•ô´í{IÉ#¼ÉP¬Íúd 3ú*WZxÀwïbnÃß3åCä~övYí‹+U'7<í+Îð+FPÓX:Y‚‡Ù«2ü~bèòûqÃÛ¹®Drñ¥†¾Ú-Nõ’3z ]U¸ìÍ‹·½I Hxsg& ×½ðS|U·FáŠÜ•'/u|ß›ÄÚ§ êéÁE…‡U…cÏÖµ-ž'í &§Ü½_º(œðæè'Røšß§ Gú÷âyÓÞçäÁÀçmî=‰oÞŽÌLá‹鷯_ßÞæØHnÔŠ,ÍæŠ,û}ÿ_;\Òú žDõ…£K῾㎠íR›—š`aâçUû Ûëõúü/ c m$¡ˆ¤xO©þM¥ýªÂ;︓»¾ÀÜwæÝ+[·É€þœ˜ûŽ wÜI2]C¡h& W]›ç ¾¡Ýíü˜¹÷x<ÿÚqŸ÷‹6Ê„½/< Ÿ®LíÑiÎÁ;Xgˆü‹]¾ü|!õßg›D$Q×÷âk©ûC -ÉPá¹Û׫äŽûâyÚw;2s,hûÕþ@h w(DJ³)=¿1ßár·“qÄΑ§ï^¿?M}ƒmB"CiÛ@7|çeJCÛ 4nPÉ]Ëó’ûÈ÷ˆûëø^š@(œ’›À‡ÑåQܨK‡oéQ¥»Ï:y ËÕyÈýk»Sbq»zñQ,=z$¨g¹.«g(jûßv'»@þû¼ãþ}Qöªü~=Òs÷i¹ê×zù¯ùzÞ­Ûñç<ãþ3 d÷÷{Í©èá…ë¸{DnYþ[G wpÐq¾9¸©97–ï‹]^Eƒ®$à ܽÂ7Ð.p×G›fDóËÁÙÔN,òÉnH/»tè}¡Ð̸½]ÝïN5hlÉíº1¯™KÃí¼ Ö-1º¦mêÝÒ—v‚k¸»º¶¡ÊÚŸ´ÞÃíümþ2»‹9t"Ú2²p¹S‹Þ‹OnȾ^ô:¡4Ž­ì”í=D§óa×. ëŸò„›&ã|Ív·—£÷à£Y¬‘7Žõ†Ž¦†Œ¾ÓåÊj+ì.­ƒû(/¸ÿØ wè‚ã=·mjÊÀ-'4ů™~¿#£ö=í“ :·4¸Ïjèã¬~ñòŸàé¼²OÑbûÐ:VlŒºëný"lJtž(wm΋@&È„ú“* ðŒÞçKŠííÞž¬tüg½ƒû/ÃÁE+œÆçbxD3Y¸»·½2;ù­ÞÁýÑ`î+q Tqû4òÁ™·mÞ¸yÛæMwݵ±»»ïx»7Ÿ¦Æ°JëàÜ;¸Uö·&­ÈI®€]‰‘¹ëoõ,‹îvJçÚtp ,«Z8«Ë]ëŒâþHd²žXü^ïà ZœkƒkÊ@ö©Ö:Z´ΘÅyƒ~e’ýÅÄ·0ÔÆ8¸«@Cÿu޳ƒç¿Ö;ôæ¹íâüÖ\sÿ¿2} iÏíüJÈsÈôkàõ†-ÎsÈtU­ƒËŸþèo~ûÛû~xàÍ7L¥d¹öiçg™ÐÞüXVxêÛ ,øö³Ùl1›KJJæ-zó¬6‹ƒžã‰¦[œ‹ÕÇ“‰BÏÌÎ.ž‡¾\ZZº°¢¢ÜBš¹dîñ^™0;›[ó'½ƒ#‹ó— ¡-Xè2UèeÜñ”˜KÌ¥ÖŠ2Ô*JY'0Œû¦ dúµÑzÝâüGóvr¡˜‘Í/.Bº.·VTN*¬ÖJøïò²2èÂlž¿XW 1¢¶Jïà§úGÓ¢Ÿž[b1WÐf­ªªª®©©­®ÄÍj­€,*ù–{ƒÑ›Ö—kÜÍ…Hh«5¹ÐåÈàçíK/æ‹Ì–…VÔ*¬•Õ5uµÕ¨ÕV±N*½¤¨èfú'×U격ä¾B—R¡¹¶&‰ÐÅEE§Sw÷¸4‚m­ê4n¨Õðѳb­—ü«!LÌ lÌÁy`j~³Bº&…Ð'Suv²Ð¼ wQU][[ƒ[é¤Rè¤üFá·Œdúœ9¸u—k…&ÚbBW¡ËK-…O¤ˆÜ…æ…¸‡Êj7 ^ ­Z-îÔJÉ¡“ÿ¾ÞÐ"H<~,Î7løV¡ù›åXè*.tmM*¡ç'›—¿+4—–Àظں%¼ÕáV‹ÌõQj..0"é ¼Àm!BצñS¡ÏKìæ¤ ke µñ%Kêë“õQ[[Y£g.ùoï䀃Cn­Œøa.ôòÿªÐKˆÐV,ôe ~­Øl©@^±õQ[§~[ìƒWWBˆ€”ð|8á£ÿÅ„®Ö Ýšf|E)}@ÛLJ ïRŒ<ã’ÄV§Q9¸9è¤øwÆ‚Ÿ&BWV«B§ÇBƒºŠßÓô1¿º¨¨Dܵɸëõณ‚³†‚#¡¿Y¹µB·¦Ðº¤à#Í·X€ÀkÐ ƒ‡f:j´¡0œ¢¹FrŸ*¶ @VY-ÍDO!4²ö‹…>ÀG npèujõk&×B»´5kÖ@W¤ ëóÜÅú¶B$´„®ÍXèJ,´Î÷¡>®ªeàõõkèwY¤áŸÖád–¥ÅÆù·Å ÝŠLŸ m)âBŸ->ðБ> ƒ5ü[Ú>Ȱ֢t›‹ Sùi¼p¡«™Ðõé…®«eBî£},(!Î2ž:¾Åo%GÍŠú0¦rÐuCè÷pʆs€Zì3ë£ÊZ^qÑ •ŸÒ]—©Ð”ó`ÎBd¸4N×qVLÆ€_B^ÃsÔLÁ¡ Ì¥(ÍìÚÚ€WÁw`ô ž0Ä¥¡+‘Ð3'BŸ‚>ž(6—Yqµ|òàääÚƒb›$}ÔkÁ+,æÂY†¸t"t^Aè´J+dàKHP`N=E8#B)A57½–¨B/™ÐL[³NÅOà §’ÕJ 3ëz¡}hRÀœe«DèªÌ…nÅB×0¡ÇŸ*Á}TVͼ%ýsqAîÁÁ/YʘÐKfŽ*¸T| ¸ Ké û à5UUU• -#ÀÍ\èÖ:&´u!ÖÖ¼âRÜGõ ÀÕ>ÊË-FäësAèòdBOj„^›BèR¤­¹(È´µú>ðBåÜû6G¾­f¦BW¡üñÕ¤z¡ƒöQRø¦AN½º²V/ôdÆBŸ„>,V¶¸#¿2™›ûd~ ¡«p3ǃG Si|ò6Ú¬e„>rÈ?¡ŸÀù‹•ä@uõ­kXk“ôqð6qðªkhûŒ(¾”ÍLèÿP…®@B(0›Ñ¥šfêh¶LNÞªZ xõ’‚œ›úG¨rB×e"ô ¾„ ]Y…>iƒÇÁQ7è·N&ë£^^N¦KÎM}æB àeeeæ’‚S&¼°µÖÔ°Eé’dk”ƒ ù í£Â<¯Àp&tm¦B·ŠB—øï..Æ¥ ¼?Hë”lI»6ðò’yÀ¤zm‚Ðk+¥B—‚ÐS‹ÐQ€ ¼c¦)Cð09™ØG½¶ä‹H=<•ЧúÂøStYжÜêêZ™ÑÐ"é tÛmÉú(6|_!© s¡5•—µ‚ÐS}aül!ÍYqu­lE[âÿ¬©omÕg¬–’¢Eœ‡(œ7½Ð“鄆ܣ€¨+ia¾þ?ÄQ£é+íƒl£ñ™²ÒRC|šd½$©Ð§âñËŠè–„ºô5kÖ ßMÚ:e`±€›0±s8¿È\:¡éŽ)ÚRRb‚åIO²†íº’ÙÒ*Lñ…° 7h'å@z¡Aæ5)¦øBKQÁ…<Â'+Õó/¼ 2’­kÐN³Ð>C…ÎDRUÇ•õ¡—d,´‰æš(àÔÒdHÓÇñ¸Ýu´VT ó?³ ⎟‚0ŒW*)„®e^B¹©ÐüÐ×|pìd§íD މëÈAÉ2”é›a²|hxüjì]Ë….¡g™xuôCÓ\3鄜ÄSn gh*!û)/…>LÿhÜQÓ t©Fh‚>Ð%&á¬Û¢‚y”÷ô`¤î¨Ù{ª%Da^aYÀ¼£Aí2.teFB—1¡ÅZŽi{9\ÇŽ±²£câØUÓ±++5—šž2byj¡µ ¯Ò­©†Ÿ-€¸h&‡¾Ùœ©¥2Áhª­ çièx†ÎDèÊ *ôe‰3f!íÄŠOIJÃϤh_§±ôRH Œ ájû½À\–™ÐeDè„0t98ô|zÀ ©O}WÁÿ 'ÐãèH(˜ŒñÜñø›i…®…¶¤zŽ™=Žb­a]T‹gôñágÄm.*0åÃýb‹g$t e=§ÌBÚ‰•<â y6ÁZ†ºÀcg2çC[< È- \YLhø0:~† ášš¤cWbºøtµVVQiM2v`æOÅó¦ÎXèiöf曊P'¥¥´“…rÖD}®Ö%ç™NÇó¨M]„¶j„¶j„ž5+½Ð‹Lü›‹Qg:ô9E3~Nµ¸¸¸¨`®i~¾Ý {zžNhìÎÀÀ±ÐçMŸsœ¼ØTXŒš¹´¬\䆞¡˜Lˆç];y¡*ô¡ÁÊMïeÐËÙE¦Y¤H…- Ki`EÞˆçeûPºT'ô¬L…>»ØTPT4·Z!þ<ÜEÑ,“é?Œçm}}BŸ=yôpÞ¬óÀLL&øú….Z<Ïïöá›z¡/þXBtê©ËíÛ÷ÄâÅóŸz/ß¡¹ÆNí[´˜} ­Ðÿ6mÕŽendstream endobj 1299 0 obj 9586 endobj 1300 0 obj <> stream xÚÿü*† 0‘&4‘+5˜+7’-8š,8œ-E™(H*]ž&k€l j—t‰sˆ)}“”~”)Yo>ZpP/EdUj\tsk€.f~CiNhcgn=Ž6rŠ9rŠJq‰Vr‹eo‡r;•2D“;F•=z’;|“9Q—Jz“c–J}–[}–q;Ÿ0@Ÿ6LœC[ TA§6I²=N¹BP¼DQ¼DUºBw·7U¬LT¹IT½Ia¨Y_±Vs°lYÈL`ÑS`ÔTd×VfÙZjß\pæctífzöl†œ‰Ÿ"–­$ ·*Œ¡9™±5—­B´5µ?¡¸3¡¸=„N’ªN—°NŸµM…žfˆ¢o”®_Нp“­k›²]™´j¢¸n«Â1«Ä>¨¿M¨À^©Áo•ÌA¯Í?²Ê<²Ê<³Ë;³Ò>²ÌY´Îe³Înÿr€ôs‚øt®Étƒõu³Îs‚ÿt»Ó;ÄÞDËäHÒìI¿Ù]¸Ðp½ØjÆáWÑëTâúUìÿ[%~,‡0 5Œ"9š.B’,Bž)A¤4H—9L”7O„Jc€@Q˜8MšEV2H¢?S¢M^£+D©1J¯8O¬BWªMaª5P¹>W¼> endobj 1302 0 obj <> endobj 1303 0 obj <> endobj 1304 0 obj <> stream xÚ]ÔÍŠÚ`Æñ}®âí¢0]X£ïùp@„Á2tm‡±½€˜¼±š„Þ}óä‘)t¡ù‡$úã@Îǯ‡ÅSÕÓ"~ÎÃ[ºtסL‹ý·¢Ï–û—//m3†åëЕ‡4†ºi«á~O8¦SÓf«u¨šr¼ŸÍßåùþðávÓù¥­»l» Ë·éâenáaþÇOÙòÇP¥¡iOáá×þ0®}ÿ'S;†<ÛíB•êé‡&Ë÷âœÂò©úÚ•‹éÖ~ÞúÖóùІ²«Ò¥/Ê4í)eÛ<ß…íóó.KmõßµÍý‘c]þ.†l»Æ­y>¦^±Wè5{ŽìˆV¶¢7ì ú‘ýˆ.ØúÈ>¢Kv‰®Ø:±ºf×SGÚ"l‘¶[¤-Âi‹°Ea šÎg4¶¡iŽ0GÚ"l‘¶[¤-Âi‹° ƒÐ 0 ƒÐ 0 ƒÐ 0ˆ³MÀ#œ¡`†Â f(t œB§À)t œB§ÌNÎP0Cå 3Tú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWšf¥Ma3z £Çà1z £Çà1z £Çà1z £Çà1z £Çà1ÎÓ0O£Í`3ÎÓ0Oã< ó4š fç<ótú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§y:àe¿¿Õxí±Þ×Hy†iÃÌ[kÞ!ØM›Þ[ßõxjþürT6‹endstream endobj 1305 0 obj 565 endobj 334 0 obj <> endobj 1306 0 obj <> endobj 1307 0 obj <> endobj 1308 0 obj <> stream xÚ]“ÁŠÛ0E÷þ uQ˜.R;Žõ^L`HšEÛa<ý[–SCcÅYäï««¦ÐE¢#$ù.ÒÇ/Íæ©Ÿ;¿Ù}.Ì«¿Ì×àüæð½]²üpüzœÆÕä/av_Í0N}¸ï1?S¶-M?ºõ>Kÿî|?ÜÜ.«?§aÎêÚä¯qñ²†›yH‰Ÿ²ügè}§“yøuhâ¼¹.ËöÓjŠl¿7½⇢ËöìMþÔ›Ý&ný·ðv[¼)Ó|K7÷þ²´Î‡v:ù¬.н©ŸŸ÷™ŸúÿÖlÉ#Ýà~·!«Ë/qkQÄ!ò#ùÜ“ûÈ»6q²ºÚ&ŽCä’\‚wä¸"W`K¶`! XÉ ¦C‡Š*æV)ב˜nÜ*Oöà> endobj 1310 0 obj <> endobj 1311 0 obj <> endobj 1312 0 obj <> stream xÚ]“ÁŠÛ@DïúŠÉ!°98–5=Ý»` ‹Ã’,«ääÑÈÄ’åƒÿ>*•Ù@¶ŸÔõ¦püðZ®žëþ˜VþsîÞÒ¥¿Ž1­öߪ![ï_];¹õëØÇ2M®i»z¼?ãŽéÔvÙ¦pu§ûÕòÏ÷—ËÛeJçC×ôÙvëÖoóÍË4ÞÜÃ’ø)[ÿë4¶ÝÉ=üÚ—óuy†?霺ÉåÙnçêỖf—ïÕ9¹õsýµ«ùÑ7~Þ†äŠåzC‡Ø×é2T1UwJÙ6Ïwnûò²ËRWÿwO ¾rlâïj̶Íóùgf#ø‘ü~"?9r3³ç9~CÞ€ röd²€9€•¬`úxøxúxøxúxø³YÂ,A–0K%Ìd ³YÂ,A–0K%Ìd ³dÉŠä®É5˜:v"è$°“€NÝÜÝÜÝÜÝÜÝÜÝÜ”çUœW9S1S9S1S9S1S9S1S9S1S9S—™<¯â¼Êó*Ϋ¹ÉG0{Pô ìAу²EÊ={0ô`ô7øý þFƒ¿Ñßàoô7øý þFƒ¿Ñßàoô7øýç,Âý•À²¾¯X¼Žã¼}ËF/û…Íj»ô¾ôC?à­åóh"^endstream endobj 1313 0 obj 506 endobj 505 0 obj <> endobj 1314 0 obj <> endobj 1315 0 obj <> endobj 1316 0 obj <> stream xÚ]‘ÍjÃ0 Çï~ ï0èY¾Ú˜‚ ”޲¶•f{€ÄVºÀb'=ôí'[¡ƒbýdI9ÒãéIvÚv”Ï?Ãd¯^A²kK÷Ç—£fžž¼U ̼ŒöKïà2–\j^¼xªq)nnÓ ãÑô–IÉÓ3§Ùßø*v|bé‡×às᫯}ƒ~suîF03ÏX]s = á[ÞÛxºÓ¯V%˜úø¼9àEôszƒ²&×*𭹓YVsy8Ô ŒþË·TÒõê»õL!5ËÐ0Y¶‘Ñ0¹Ö‘Ñ 1 oŠÈhKâ¹Ê#£A¦û*Þ¯‰×7Ä›À[âm`E¬S¯*ôªzâYP_ú ÒA_¾ú‚ôEÐq‡°ümGXÔ}¼êê=N>n3Î6Lu0p_¸³.TÅï€ Ÿ%endstream endobj 1317 0 obj 324 endobj 506 0 obj <> endobj 1318 0 obj <> endobj 1319 0 obj <> endobj 1320 0 obj <> stream xÚ]ÁjÃ0DïúŠí¡)) ÆB}hâödií bI¬åƒÿ¾²*RèaÃÌHoõøpi‹£vÏ[WœÜL ‹úMzÆëæÔX€_È©ôÆjÊèp0–íö  Y¥S¹Ü.SÀ±±½ce üÍ)Лôâ㤑Œ`óU·Q·³÷7Ѭª@c/Š,ïrDàGýêT£ÆçâöIï~”Ó8y©¤•BTPžÏC«ÿy¹Ñõê[RN q8ÄyIùì¬Íu§;‰š‰"dZ> endobj 1322 0 obj <> endobj 1323 0 obj <> endobj 1324 0 obj <> stream xÚ]“ÁŠÛ0†ï~ õPØR;‰4³ &°¤,Í¡í²nÀ‘äÔÐØFqyûê÷¶ÐC¬OH3ó˜|üðÚ¬žÃxŒ«íçʼÅËxM>®ößÚ©(÷‡/‡¡ŸMùšFßÄÙtýÒýŽ9ÆS?ë ½Ÿï»åëÏ÷àæv™ãù0tcQצ|ˇ—9ÝÌÃRñSQþH!¦~8™‡_û&ï›ë4ý‰ç8̦*v;b—e—ïí9šò9|ý*_ýwðó6E³Yök:ø1ÄËÔú˜Úዺªv¦~yÙqÿÙ-CŽÿݦ¢ÞàjUå%ó#ùüD~rGr̼Ý,œ—Ì[òÜ’ÛÌv½p^2ó¾Å}kÉÌZµ,kYÔ²¬eQËvä.³£³ƒ³cN‡œŽŽùò;%kf¡ÀG+ˆÆ b…±‚Xqd²€™S–œ|7Á» {ô"|Á;ˆ'{0{ô(ìQУ°GAÊ=*=žJO…§ÒSá©ôTx*=žJO…§ÒSá©ôÌ †ä>  òûøùkJy2—i_fS×ñý1¢–ß_«Øœendstream endobj 1325 0 obj 432 endobj 543 0 obj <> endobj 1326 0 obj <> endobj 1327 0 obj <> endobj 1328 0 obj <> stream xÚ]ÁjÃ0DïúŠí¡)) ÆB}hâödií bI¬åƒÿ¾²*RèaÃÌHoõøpi‹£vÏ[WœÜL ‹úMzÆëæÔX€_È©ôÆjÊèp0–íö  Y¥S¹Ü.SÀ±±½ce üÍ)Лôâ㤑Œ`óU·Q·³÷7Ѭª@c/Š,ïrDàGýêT£ÆçâöIï~”Ó8y©¤•BTPžÏC«ÿy¹Ñõê[RN q8ÄyIùì¬Íu§;‰š‰"dZ> endobj 1330 0 obj <> endobj 1331 0 obj <> endobj 1332 0 obj <> stream xÚ]ÔÍŠÚ`Æñ}®âí¢0]XcÎÇ뀃eè,Úc{1yc5 QÞ}óä‘)t¡ù‡$úã@ÎǯûÅSÝÒB>çá-ûëX¥Åî[9dËÝË——®½„åëØWût MÛÕãýžpHǶËVE¨Ûêr?›¿«Óýáýí|I§—®é³Í&,ߦ‹çËx ó?~Ê–?Æ:mw ¿vûé|†?锺Kȳí6Ô©™~h²|/O),Ÿê¯}µ˜nýwáçmH¡˜ÏW4T}ÎCY¥±ìŽ)Ûäù6lžŸ·Yêêÿ®­ >rhªßå˜m ÜšçÓaê{….ØÚ؆Žìˆ^³×èGö#ºd—èû€®Øºf×èÄNè†ÝL-´ lB›À&´ l"lA+[Ñ4 ÌâlGÓ/ð ý¿Ð/ð ý¿Ð/ð ý¿Ð/ð ý¿Ð/ð+Í ³Ò¬0+Í ³Ò¬0+Í ³Ò¬0+Í ³Ò¬0+Í ³Ò¬0+Í ³Ò¬0+Í ³Ò¬0+Í ³q憙ý¿Ñoðý¿Ñoðý¿Ñoðý¿Ñoðý¿Ñoð=Óà08 ƒÓà08 ƒÓà08 ƒÓà08 ƒÓà08 ƒs†Ž:g蘡s†Ž:g蘡Óì0GÎ0b†‘þ¤?ÂéðGú#ü‘þ¤?ÂéðGú#ü‘þ¤:àÅ¿¿áXXNï+¥ºŽã´mæ 6ïl’¶KïKnè<5þ»e8€endstream endobj 1333 0 obj 567 endobj 12 0 obj <> endobj 1334 0 obj <> endobj 1335 0 obj <> endobj 1336 0 obj <> stream xÚ]ÁjÄ †ï>ÅôPزš AXR–æÐvÙ´`t’ Š1‡¼}+»ÐÃ?óÿ3Ÿóøp²=Ï{œíâ%Í»p„6íkktzöVv`ÐFùìGmHYÒ2d•^9åp·Î§Ö –Ô5ÐKlÎÁ¯°KŸýô ½6#ì¾›.ênqî'4áqPdù=ª7+‹h½7¾V‡P%]^¤U8;!Ñ 3"©ãPŸNœ QÿzÕ5ÑòGøìdìpˆõ£.ïZ¦|vn“¶?ÞÈäâ}„N‡HX6x»•³nK¥ú± wendstream endobj 1337 0 obj 243 endobj 1298 0 obj <> endobj 1293 0 obj <> endobj 1292 0 obj <> endobj 1291 0 obj <> endobj 1290 0 obj <> endobj 1289 0 obj <> endobj 1284 0 obj <> endobj 1283 0 obj <> endobj 1282 0 obj <> endobj 1281 0 obj <> endobj 1280 0 obj <> endobj 1279 0 obj <> endobj 1278 0 obj <> endobj 1277 0 obj <> endobj 1276 0 obj <> endobj 1275 0 obj <> endobj 1274 0 obj <> endobj 1273 0 obj <> endobj 1272 0 obj <> endobj 1271 0 obj <> endobj 1270 0 obj <> endobj 1269 0 obj <> endobj 1264 0 obj <> endobj 1263 0 obj <> endobj 1262 0 obj <> endobj 1261 0 obj <> endobj 1260 0 obj <> endobj 1259 0 obj <> endobj 1258 0 obj <> endobj 1257 0 obj <> endobj 1256 0 obj <> endobj 1255 0 obj <> endobj 1254 0 obj <> endobj 1253 0 obj <> endobj 1252 0 obj <> endobj 1247 0 obj <> endobj 1246 0 obj <> endobj 1245 0 obj <> endobj 1244 0 obj <> endobj 1243 0 obj <> endobj 1242 0 obj <> endobj 1241 0 obj <> endobj 1240 0 obj <> endobj 1239 0 obj <> endobj 1238 0 obj <> endobj 1233 0 obj <> endobj 1232 0 obj <> endobj 1231 0 obj <> endobj 1230 0 obj <> endobj 1229 0 obj <> endobj 1228 0 obj <> endobj 1227 0 obj <> endobj 1226 0 obj <> endobj 1225 0 obj <> endobj 1224 0 obj <> endobj 1223 0 obj <> endobj 1222 0 obj <> endobj 1221 0 obj <> endobj 1220 0 obj <> endobj 1219 0 obj <> endobj 1218 0 obj <> endobj 1217 0 obj <> endobj 1216 0 obj <> endobj 1215 0 obj <> endobj 1214 0 obj <> endobj 1213 0 obj <> endobj 1212 0 obj <> endobj 1211 0 obj <> endobj 1206 0 obj <> endobj 1205 0 obj <> endobj 1204 0 obj <> endobj 1203 0 obj <> endobj 1202 0 obj <> endobj 1201 0 obj <> endobj 1200 0 obj <> endobj 1199 0 obj <> endobj 1198 0 obj <> endobj 1197 0 obj <> endobj 1196 0 obj <> endobj 1195 0 obj <> endobj 1190 0 obj <> endobj 1189 0 obj <> endobj 1188 0 obj <> endobj 1187 0 obj <> endobj 1186 0 obj <> endobj 1185 0 obj <> endobj 1184 0 obj <> endobj 1183 0 obj <> endobj 1182 0 obj <> endobj 1181 0 obj <> endobj 1180 0 obj <> endobj 1179 0 obj <> endobj 1178 0 obj <> endobj 1177 0 obj <> endobj 1172 0 obj <> endobj 1171 0 obj <> endobj 1170 0 obj <> endobj 1169 0 obj <> endobj 1168 0 obj <> endobj 1167 0 obj <> endobj 1166 0 obj <> endobj 1165 0 obj <> endobj 1164 0 obj <> endobj 1159 0 obj <> endobj 1158 0 obj <> endobj 1157 0 obj <> endobj 1156 0 obj <> endobj 1155 0 obj <> endobj 1154 0 obj <> endobj 1153 0 obj <> endobj 1152 0 obj <> endobj 1151 0 obj <> endobj 1150 0 obj <> endobj 1145 0 obj <> endobj 1144 0 obj <> endobj 1143 0 obj <> endobj 1142 0 obj <> endobj 1141 0 obj <> endobj 1140 0 obj <> endobj 1139 0 obj <> endobj 1138 0 obj <> endobj 1137 0 obj <> endobj 1132 0 obj <> endobj 1131 0 obj <> endobj 1130 0 obj <> endobj 1129 0 obj <> endobj 1128 0 obj <> endobj 1127 0 obj <> endobj 1126 0 obj <> endobj 1125 0 obj <> endobj 1124 0 obj <> endobj 1123 0 obj <> endobj 1122 0 obj <> endobj 1121 0 obj <> endobj 1120 0 obj <> endobj 1119 0 obj <> endobj 1118 0 obj <> endobj 1117 0 obj <> endobj 1116 0 obj <> endobj 1115 0 obj <> endobj 1114 0 obj <> endobj 1113 0 obj <> endobj 1108 0 obj <> endobj 1107 0 obj <> endobj 1106 0 obj <> endobj 1105 0 obj <> endobj 1104 0 obj <> endobj 1103 0 obj <> endobj 1102 0 obj <> endobj 1101 0 obj <> endobj 1100 0 obj <> endobj 1099 0 obj <> endobj 1094 0 obj <> endobj 1093 0 obj <> endobj 1092 0 obj <> endobj 1091 0 obj <> endobj 1090 0 obj <> endobj 1089 0 obj <> endobj 1088 0 obj <> endobj 1087 0 obj <> endobj 1086 0 obj <> endobj 1081 0 obj <> endobj 1080 0 obj <> endobj 1079 0 obj <> endobj 1078 0 obj <> endobj 1077 0 obj <> endobj 1076 0 obj <> endobj 1075 0 obj <> endobj 1074 0 obj <> endobj 1073 0 obj <> endobj 1072 0 obj <> endobj 1071 0 obj <> endobj 1070 0 obj <> endobj 1069 0 obj <> endobj 1068 0 obj <> endobj 1067 0 obj <> endobj 1066 0 obj <> endobj 1061 0 obj <> endobj 1060 0 obj <> endobj 1059 0 obj <> endobj 1058 0 obj <> endobj 1057 0 obj <> endobj 1056 0 obj <> endobj 1055 0 obj <> endobj 1054 0 obj <> endobj 1053 0 obj <> endobj 1052 0 obj <> endobj 1051 0 obj <> endobj 1046 0 obj <> endobj 1045 0 obj <> endobj 1044 0 obj <> endobj 1043 0 obj <> endobj 1042 0 obj <> endobj 1041 0 obj <> endobj 1040 0 obj <> endobj 1039 0 obj <> endobj 1038 0 obj <> endobj 1033 0 obj <> endobj 1032 0 obj <> endobj 1031 0 obj <> endobj 1030 0 obj <> endobj 1029 0 obj <> endobj 1028 0 obj <> endobj 1027 0 obj <> endobj 1026 0 obj <> endobj 1025 0 obj <> endobj 1024 0 obj <> endobj 1023 0 obj <> endobj 1018 0 obj <> endobj 1017 0 obj <> endobj 1016 0 obj <> endobj 1015 0 obj <> endobj 1014 0 obj <> endobj 1013 0 obj <> endobj 1012 0 obj <> endobj 1007 0 obj <> endobj 1006 0 obj <> endobj 1005 0 obj <> endobj 1004 0 obj <> endobj 1003 0 obj <> endobj 1002 0 obj <> endobj 1001 0 obj <> endobj 1000 0 obj <> endobj 999 0 obj <> endobj 994 0 obj <> endobj 993 0 obj <> endobj 992 0 obj <> endobj 991 0 obj <> endobj 990 0 obj <> endobj 989 0 obj <> endobj 988 0 obj <> endobj 987 0 obj <> endobj 982 0 obj <> endobj 981 0 obj <> endobj 980 0 obj <> endobj 979 0 obj <> endobj 978 0 obj <> endobj 977 0 obj <> endobj 976 0 obj <> endobj 975 0 obj <> endobj 974 0 obj <> endobj 973 0 obj <> endobj 972 0 obj <> endobj 971 0 obj <> endobj 970 0 obj <> endobj 969 0 obj <> endobj 968 0 obj <> endobj 967 0 obj <> endobj 962 0 obj <> endobj 961 0 obj <> endobj 960 0 obj <> endobj 959 0 obj <> endobj 958 0 obj <> endobj 957 0 obj <> endobj 956 0 obj <> endobj 955 0 obj <> endobj 954 0 obj <> endobj 953 0 obj <> endobj 952 0 obj <> endobj 951 0 obj <> endobj 950 0 obj <> endobj 949 0 obj <> endobj 944 0 obj <> endobj 943 0 obj <> endobj 942 0 obj <> endobj 941 0 obj <> endobj 940 0 obj <> endobj 939 0 obj <> endobj 938 0 obj <> endobj 937 0 obj <> endobj 936 0 obj <> endobj 935 0 obj <> endobj 934 0 obj <> endobj 933 0 obj <> endobj 932 0 obj <> endobj 931 0 obj <> endobj 926 0 obj <> endobj 925 0 obj <> endobj 924 0 obj <> endobj 923 0 obj <> endobj 922 0 obj <> endobj 921 0 obj <> endobj 920 0 obj <> endobj 919 0 obj <> endobj 918 0 obj <> endobj 917 0 obj <> endobj 916 0 obj <> endobj 911 0 obj <> endobj 910 0 obj <> endobj 909 0 obj <> endobj 908 0 obj <> endobj 907 0 obj <> endobj 906 0 obj <> endobj 905 0 obj <> endobj 904 0 obj <> endobj 903 0 obj <> endobj 902 0 obj <> endobj 901 0 obj <> endobj 896 0 obj <> endobj 895 0 obj <> endobj 894 0 obj <> endobj 893 0 obj <> endobj 892 0 obj <> endobj 891 0 obj <> endobj 890 0 obj <> endobj 889 0 obj <> endobj 888 0 obj <> endobj 887 0 obj <> endobj 886 0 obj <> endobj 885 0 obj <> endobj 884 0 obj <> endobj 883 0 obj <> endobj 878 0 obj <> endobj 877 0 obj <> endobj 876 0 obj <> endobj 875 0 obj <> endobj 874 0 obj <> endobj 873 0 obj <> endobj 872 0 obj <> endobj 871 0 obj <> endobj 870 0 obj <> endobj 869 0 obj <> endobj 868 0 obj <> endobj 867 0 obj <> endobj 866 0 obj <> endobj 865 0 obj <> endobj 864 0 obj <> endobj 859 0 obj <> endobj 858 0 obj <> endobj 857 0 obj <> endobj 856 0 obj <> endobj 855 0 obj <> endobj 854 0 obj <> endobj 853 0 obj <> endobj 848 0 obj <> endobj 847 0 obj <> endobj 846 0 obj <> endobj 845 0 obj <> endobj 844 0 obj <> endobj 843 0 obj <> endobj 842 0 obj <> endobj 841 0 obj <> endobj 840 0 obj <> endobj 839 0 obj <> endobj 838 0 obj <> endobj 837 0 obj <> endobj 836 0 obj <> endobj 835 0 obj <> endobj 834 0 obj <> endobj 833 0 obj <> endobj 832 0 obj <> endobj 831 0 obj <> endobj 830 0 obj <> endobj 825 0 obj <> endobj 824 0 obj <> endobj 823 0 obj <> endobj 822 0 obj <> endobj 821 0 obj <> endobj 820 0 obj <> endobj 819 0 obj <> endobj 818 0 obj <> endobj 817 0 obj <> endobj 816 0 obj <> endobj 815 0 obj <> endobj 814 0 obj <> endobj 813 0 obj <> endobj 812 0 obj <> endobj 811 0 obj <> endobj 806 0 obj <> endobj 805 0 obj <> endobj 804 0 obj <> endobj 803 0 obj <> endobj 798 0 obj <> endobj 797 0 obj <> endobj 796 0 obj <> endobj 795 0 obj <> endobj 794 0 obj <> endobj 789 0 obj <> endobj 788 0 obj <> endobj 787 0 obj <> endobj 786 0 obj <> endobj 785 0 obj <> endobj 784 0 obj <> endobj 783 0 obj <> endobj 782 0 obj <> endobj 781 0 obj <> endobj 776 0 obj <> endobj 775 0 obj <> endobj 774 0 obj <> endobj 773 0 obj <> endobj 772 0 obj <> endobj 771 0 obj <> endobj 770 0 obj <> endobj 769 0 obj <> endobj 768 0 obj <> endobj 767 0 obj <> endobj 762 0 obj <> endobj 761 0 obj <> endobj 760 0 obj <> endobj 759 0 obj <> endobj 758 0 obj <> endobj 757 0 obj <> endobj 756 0 obj <> endobj 755 0 obj <> endobj 750 0 obj <> endobj 749 0 obj <> endobj 748 0 obj <> endobj 747 0 obj <> endobj 746 0 obj <> endobj 745 0 obj <> endobj 744 0 obj <> endobj 743 0 obj <> endobj 742 0 obj <> endobj 741 0 obj <> endobj 740 0 obj <> endobj 735 0 obj <> endobj 734 0 obj <> endobj 733 0 obj <> endobj 732 0 obj <> endobj 731 0 obj <> endobj 730 0 obj <> endobj 729 0 obj <> endobj 728 0 obj <> endobj 727 0 obj <> endobj 726 0 obj <> endobj 725 0 obj <> endobj 724 0 obj <> endobj 723 0 obj <> endobj 722 0 obj <> endobj 717 0 obj <> endobj 716 0 obj <> endobj 715 0 obj <> endobj 714 0 obj <> endobj 713 0 obj <> endobj 712 0 obj <> endobj 711 0 obj <> endobj 710 0 obj <> endobj 709 0 obj <> endobj 708 0 obj <> endobj 707 0 obj <> endobj 706 0 obj <> endobj 701 0 obj <> endobj 700 0 obj <> endobj 699 0 obj <> endobj 698 0 obj <> endobj 697 0 obj <> endobj 696 0 obj <> endobj 691 0 obj <> endobj 690 0 obj <> endobj 689 0 obj <> endobj 688 0 obj <> endobj 687 0 obj <> endobj 686 0 obj <> endobj 685 0 obj <> endobj 680 0 obj <> endobj 679 0 obj <> endobj 678 0 obj <> endobj 677 0 obj <> endobj 676 0 obj <> endobj 675 0 obj <> endobj 670 0 obj <> endobj 669 0 obj <> endobj 668 0 obj <> endobj 667 0 obj <> endobj 666 0 obj <> endobj 665 0 obj <> endobj 664 0 obj <> endobj 663 0 obj <> endobj 662 0 obj <> endobj 661 0 obj <> endobj 660 0 obj <> endobj 659 0 obj <> endobj 658 0 obj <> endobj 657 0 obj <> endobj 656 0 obj <> endobj 651 0 obj <> endobj 650 0 obj <> endobj 649 0 obj <> endobj 648 0 obj <> endobj 647 0 obj <> endobj 646 0 obj <> endobj 645 0 obj <> endobj 644 0 obj <> endobj 643 0 obj <> endobj 642 0 obj <> endobj 641 0 obj <> endobj 640 0 obj <> endobj 639 0 obj <> endobj 634 0 obj <> endobj 633 0 obj <> endobj 632 0 obj <> endobj 631 0 obj <> endobj 630 0 obj <> endobj 629 0 obj <> endobj 628 0 obj <> endobj 627 0 obj <> endobj 626 0 obj <> endobj 625 0 obj <> endobj 620 0 obj <> endobj 619 0 obj <> endobj 618 0 obj <> endobj 617 0 obj <> endobj 616 0 obj <> endobj 615 0 obj <> endobj 614 0 obj <> endobj 613 0 obj <> endobj 612 0 obj <> endobj 611 0 obj <> endobj 610 0 obj <> endobj 605 0 obj <> endobj 604 0 obj <> endobj 603 0 obj <> endobj 602 0 obj <> endobj 601 0 obj <> endobj 600 0 obj <> endobj 599 0 obj <> endobj 598 0 obj <> endobj 597 0 obj <> endobj 596 0 obj <> endobj 595 0 obj <> endobj 594 0 obj <> endobj 593 0 obj <> endobj 588 0 obj <> endobj 587 0 obj <> endobj 586 0 obj <> endobj 585 0 obj <> endobj 584 0 obj <> endobj 583 0 obj <> endobj 582 0 obj <> endobj 581 0 obj <> endobj 580 0 obj <> endobj 579 0 obj <> endobj 578 0 obj <> endobj 577 0 obj <> endobj 576 0 obj <> endobj 575 0 obj <> endobj 574 0 obj <> endobj 573 0 obj <> endobj 572 0 obj <> endobj 571 0 obj <> endobj 570 0 obj <> endobj 569 0 obj <> endobj 564 0 obj <> endobj 563 0 obj <> endobj 562 0 obj <> endobj 561 0 obj <> endobj 560 0 obj <> endobj 559 0 obj <> endobj 558 0 obj <> endobj 557 0 obj <> endobj 556 0 obj <> endobj 555 0 obj <> endobj 554 0 obj <> endobj 553 0 obj <> endobj 552 0 obj <> endobj 551 0 obj <> endobj 550 0 obj <> endobj 549 0 obj <> endobj 548 0 obj <> endobj 547 0 obj <> endobj 546 0 obj <> endobj 545 0 obj <> endobj 544 0 obj <> endobj 538 0 obj <> endobj 537 0 obj <> endobj 536 0 obj <> endobj 535 0 obj <> endobj 534 0 obj <> endobj 533 0 obj <> endobj 532 0 obj <> endobj 531 0 obj <> endobj 530 0 obj <> endobj 529 0 obj <> endobj 528 0 obj <> endobj 527 0 obj <> endobj 526 0 obj <> endobj 525 0 obj <> endobj 520 0 obj <> endobj 519 0 obj <> endobj 518 0 obj <> endobj 517 0 obj <> endobj 516 0 obj <> endobj 515 0 obj <> endobj 514 0 obj <> endobj 513 0 obj <> endobj 512 0 obj <> endobj 511 0 obj <> endobj 510 0 obj <> endobj 509 0 obj <> endobj 508 0 obj <> endobj 507 0 obj <> endobj 500 0 obj <> endobj 499 0 obj <> endobj 498 0 obj <> endobj 497 0 obj <> endobj 496 0 obj <> endobj 495 0 obj <> endobj 494 0 obj <> endobj 493 0 obj <> endobj 492 0 obj <> endobj 491 0 obj <> endobj 490 0 obj <> endobj 489 0 obj <> endobj 488 0 obj <> endobj 487 0 obj <> endobj 482 0 obj <> endobj 481 0 obj <> endobj 480 0 obj <> endobj 479 0 obj <> endobj 478 0 obj <> endobj 477 0 obj <> endobj 476 0 obj <> endobj 475 0 obj <> endobj 474 0 obj <> endobj 473 0 obj <> endobj 472 0 obj <> endobj 471 0 obj <> endobj 470 0 obj <> endobj 465 0 obj <> endobj 464 0 obj <> endobj 463 0 obj <> endobj 462 0 obj <> endobj 461 0 obj <> endobj 460 0 obj <> endobj 459 0 obj <> endobj 458 0 obj <> endobj 457 0 obj <> endobj 456 0 obj <> endobj 455 0 obj <> endobj 454 0 obj <> endobj 453 0 obj <> endobj 452 0 obj <> endobj 451 0 obj <> endobj 450 0 obj <> endobj 449 0 obj <> endobj 448 0 obj <> endobj 447 0 obj <> endobj 442 0 obj <> endobj 441 0 obj <> endobj 440 0 obj <> endobj 439 0 obj <> endobj 438 0 obj <> endobj 437 0 obj <> endobj 436 0 obj <> endobj 435 0 obj <> endobj 434 0 obj <> endobj 433 0 obj <> endobj 432 0 obj <> endobj 431 0 obj <> endobj 430 0 obj <> endobj 429 0 obj <> endobj 428 0 obj <> endobj 427 0 obj <> endobj 426 0 obj <> endobj 425 0 obj <> endobj 424 0 obj <> endobj 423 0 obj <> endobj 422 0 obj <> endobj 421 0 obj <> endobj 420 0 obj <> endobj 419 0 obj <> endobj 418 0 obj <> endobj 417 0 obj <> endobj 416 0 obj <> endobj 415 0 obj <> endobj 414 0 obj <> endobj 413 0 obj <> endobj 408 0 obj <> endobj 407 0 obj <> endobj 406 0 obj <> endobj 405 0 obj <> endobj 404 0 obj <> endobj 403 0 obj <> endobj 402 0 obj <> endobj 401 0 obj <> endobj 400 0 obj <> endobj 399 0 obj <> endobj 398 0 obj <> endobj 397 0 obj <> endobj 396 0 obj <> endobj 395 0 obj <> endobj 394 0 obj <> endobj 393 0 obj <> endobj 392 0 obj <> endobj 391 0 obj <> endobj 390 0 obj <> endobj 389 0 obj <> endobj 388 0 obj <> endobj 387 0 obj <> endobj 386 0 obj <> endobj 385 0 obj <> endobj 384 0 obj <> endobj 379 0 obj <> endobj 374 0 obj <> endobj 373 0 obj <> endobj 372 0 obj <> endobj 371 0 obj <> endobj 370 0 obj <> endobj 369 0 obj <> endobj 368 0 obj <> endobj 367 0 obj <> endobj 366 0 obj <> endobj 365 0 obj <> endobj 364 0 obj <> endobj 363 0 obj <> endobj 362 0 obj <> endobj 361 0 obj <> endobj 360 0 obj <> endobj 359 0 obj <> endobj 358 0 obj <> endobj 353 0 obj <> endobj 352 0 obj <> endobj 351 0 obj <> endobj 350 0 obj <> endobj 349 0 obj <> endobj 348 0 obj <> endobj 347 0 obj <> endobj 346 0 obj <> endobj 345 0 obj <> endobj 344 0 obj <> endobj 343 0 obj <> endobj 342 0 obj <> endobj 341 0 obj <> endobj 340 0 obj <> endobj 339 0 obj <> endobj 338 0 obj <> endobj 337 0 obj <> endobj 336 0 obj <> endobj 335 0 obj <> endobj 329 0 obj <> endobj 328 0 obj <> endobj 327 0 obj <> endobj 321 0 obj <> >> endobj 320 0 obj <> >> endobj 319 0 obj <> >> endobj 313 0 obj <> >> endobj 312 0 obj <> >> endobj 311 0 obj <> >> endobj 310 0 obj <> >> endobj 309 0 obj <> endobj 308 0 obj <> endobj 307 0 obj <> endobj 306 0 obj <> endobj 305 0 obj <> endobj 304 0 obj <> endobj 303 0 obj <> endobj 302 0 obj <> endobj 301 0 obj <> endobj 300 0 obj <> endobj 299 0 obj <> endobj 298 0 obj <> endobj 297 0 obj <> endobj 296 0 obj <> endobj 295 0 obj <> endobj 294 0 obj <> endobj 293 0 obj <> endobj 292 0 obj <> endobj 291 0 obj <> endobj 290 0 obj <> endobj 289 0 obj <> endobj 288 0 obj <> endobj 287 0 obj <> endobj 286 0 obj <> endobj 285 0 obj <> endobj 284 0 obj <> endobj 283 0 obj <> endobj 282 0 obj <> endobj 281 0 obj <> endobj 280 0 obj <> endobj 279 0 obj <> endobj 278 0 obj <> endobj 277 0 obj <> endobj 276 0 obj <> endobj 275 0 obj <> endobj 274 0 obj <> endobj 273 0 obj <> endobj 272 0 obj <> endobj 271 0 obj <> endobj 270 0 obj <> endobj 269 0 obj <> endobj 268 0 obj <> endobj 267 0 obj <> endobj 266 0 obj <> endobj 265 0 obj <> endobj 264 0 obj <> endobj 263 0 obj <> endobj 262 0 obj <> endobj 261 0 obj <> endobj 260 0 obj <> endobj 259 0 obj <> endobj 258 0 obj <> endobj 257 0 obj <> endobj 256 0 obj <> endobj 255 0 obj <> endobj 254 0 obj <> endobj 253 0 obj <> endobj 252 0 obj <> endobj 251 0 obj <> endobj 250 0 obj <> endobj 249 0 obj <> endobj 248 0 obj <> endobj 247 0 obj <> endobj 246 0 obj <> endobj 245 0 obj <> endobj 244 0 obj <> endobj 243 0 obj <> endobj 242 0 obj <> endobj 241 0 obj <> endobj 240 0 obj <> endobj 239 0 obj <> endobj 238 0 obj <> endobj 237 0 obj <> endobj 236 0 obj <> endobj 235 0 obj <> endobj 234 0 obj <> endobj 233 0 obj <> endobj 232 0 obj <> endobj 231 0 obj <> endobj 230 0 obj <> endobj 229 0 obj <> endobj 228 0 obj <> endobj 227 0 obj <> endobj 226 0 obj <> endobj 225 0 obj <> endobj 224 0 obj <> endobj 223 0 obj <> endobj 222 0 obj <> endobj 221 0 obj <> endobj 220 0 obj <> endobj 219 0 obj <> endobj 218 0 obj <> endobj 217 0 obj <> endobj 216 0 obj <> endobj 215 0 obj <> endobj 214 0 obj <> endobj 213 0 obj <> endobj 212 0 obj <> endobj 211 0 obj <> endobj 210 0 obj <> endobj 209 0 obj <> endobj 208 0 obj <> endobj 203 0 obj <> endobj 202 0 obj <> endobj 201 0 obj <> endobj 200 0 obj <> endobj 199 0 obj <> endobj 198 0 obj <> endobj 197 0 obj <> endobj 196 0 obj <> endobj 195 0 obj <> endobj 194 0 obj <> endobj 193 0 obj <> endobj 192 0 obj <> endobj 191 0 obj <> endobj 190 0 obj <> endobj 189 0 obj <> endobj 188 0 obj <> endobj 187 0 obj <> endobj 186 0 obj <> endobj 185 0 obj <> endobj 184 0 obj <> endobj 183 0 obj <> endobj 182 0 obj <> endobj 181 0 obj <> endobj 180 0 obj <> endobj 179 0 obj <> endobj 178 0 obj <> endobj 177 0 obj <> endobj 176 0 obj <> endobj 175 0 obj <> endobj 174 0 obj <> endobj 173 0 obj <> endobj 172 0 obj <> endobj 171 0 obj <> endobj 170 0 obj <> endobj 169 0 obj <> endobj 168 0 obj <> endobj 167 0 obj <> endobj 166 0 obj <> endobj 165 0 obj <> endobj 164 0 obj <> endobj 163 0 obj <> endobj 162 0 obj <> endobj 161 0 obj <> endobj 160 0 obj <> endobj 159 0 obj <> endobj 158 0 obj <> endobj 157 0 obj <> endobj 156 0 obj <> endobj 155 0 obj <> endobj 154 0 obj <> endobj 153 0 obj <> endobj 152 0 obj <> endobj 151 0 obj <> endobj 150 0 obj <> endobj 149 0 obj <> endobj 148 0 obj <> endobj 147 0 obj <> endobj 146 0 obj <> endobj 145 0 obj <> endobj 144 0 obj <> endobj 143 0 obj <> endobj 142 0 obj <> endobj 141 0 obj <> endobj 140 0 obj <> endobj 139 0 obj <> endobj 138 0 obj <> endobj 137 0 obj <> endobj 136 0 obj <> endobj 135 0 obj <> endobj 134 0 obj <> endobj 133 0 obj <> endobj 132 0 obj <> endobj 131 0 obj <> endobj 130 0 obj <> endobj 129 0 obj <> endobj 128 0 obj <> endobj 127 0 obj <> endobj 126 0 obj <> endobj 125 0 obj <> endobj 124 0 obj <> endobj 123 0 obj <> endobj 122 0 obj <> endobj 121 0 obj <> endobj 120 0 obj <> endobj 119 0 obj <> endobj 118 0 obj <> endobj 117 0 obj <> endobj 116 0 obj <> endobj 115 0 obj <> endobj 114 0 obj <> endobj 113 0 obj <> endobj 112 0 obj <> endobj 111 0 obj <> endobj 110 0 obj <> endobj 109 0 obj <> endobj 108 0 obj <> endobj 107 0 obj <> endobj 106 0 obj <> endobj 105 0 obj <> endobj 104 0 obj <> endobj 103 0 obj <> endobj 102 0 obj <> endobj 101 0 obj <> endobj 100 0 obj <> endobj 99 0 obj <> endobj 98 0 obj <> endobj 97 0 obj <> endobj 96 0 obj <> endobj 95 0 obj <> endobj 94 0 obj <> endobj 93 0 obj <> endobj 92 0 obj <> endobj 91 0 obj <> endobj 90 0 obj <> endobj 89 0 obj <> endobj 88 0 obj <> endobj 83 0 obj <> endobj 82 0 obj <> endobj 81 0 obj <> endobj 80 0 obj <> endobj 79 0 obj <> endobj 78 0 obj <> endobj 77 0 obj <> endobj 76 0 obj <> endobj 75 0 obj <> endobj 74 0 obj <> endobj 73 0 obj <> endobj 72 0 obj <> endobj 71 0 obj <> endobj 70 0 obj <> endobj 69 0 obj <> endobj 68 0 obj <> endobj 67 0 obj <> endobj 66 0 obj <> endobj 65 0 obj <> endobj 64 0 obj <> endobj 63 0 obj <> endobj 62 0 obj <> endobj 61 0 obj <> endobj 60 0 obj <> endobj 59 0 obj <> endobj 58 0 obj <> endobj 57 0 obj <> endobj 56 0 obj <> endobj 55 0 obj <> endobj 54 0 obj <> endobj 53 0 obj <> endobj 52 0 obj <> endobj 51 0 obj <> endobj 50 0 obj <> endobj 49 0 obj <> endobj 48 0 obj <> endobj 47 0 obj <> endobj 46 0 obj <> endobj 45 0 obj <> endobj 44 0 obj <> endobj 43 0 obj <> endobj 42 0 obj <> endobj 41 0 obj <> endobj 40 0 obj <> endobj 39 0 obj <> endobj 38 0 obj <> endobj 37 0 obj <> endobj 36 0 obj <> endobj 35 0 obj <> endobj 34 0 obj <> endobj 33 0 obj <> endobj 32 0 obj <> endobj 31 0 obj <> endobj 30 0 obj <> endobj 29 0 obj <> endobj 28 0 obj <> endobj 27 0 obj <> endobj 26 0 obj <> endobj 25 0 obj <> endobj 24 0 obj <> endobj 23 0 obj <> endobj 22 0 obj <> endobj 21 0 obj <> endobj 20 0 obj <> endobj 19 0 obj <> >> endobj 18 0 obj <> >> endobj 17 0 obj <> >> endobj 16 0 obj <> >> endobj 15 0 obj <> >> endobj 14 0 obj <> >> endobj 13 0 obj <> >> endobj 1 0 obj <> ] >> /Names 1338 0 R /PageMode /UseNone /OpenAction [5 0 R /XYZ 0 841.9 0] /Metadata 3 0 R >> endobj 2 0 obj <> endobj 1340 0 obj <> endobj 1341 0 obj <> endobj 1342 0 obj <> endobj 1343 0 obj <> endobj 1344 0 obj <> endobj 1345 0 obj <> endobj 1346 0 obj <> endobj 5 0 obj <> endobj 8 0 obj <> /XObject <> >> endobj 1347 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1348 0 obj 44 endobj 84 0 obj <> endobj 87 0 obj <> >> endobj 1349 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1350 0 obj 44 endobj 204 0 obj <> endobj 207 0 obj <> >> endobj 1351 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1352 0 obj 44 endobj 314 0 obj <> endobj 317 0 obj <> >> endobj 1353 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1354 0 obj 44 endobj 322 0 obj <> endobj 325 0 obj <> >> endobj 1355 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1356 0 obj 44 endobj 330 0 obj <> endobj 333 0 obj <> >> endobj 1357 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1358 0 obj 44 endobj 354 0 obj <> endobj 357 0 obj <> >> endobj 1359 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1360 0 obj 44 endobj 375 0 obj <> endobj 378 0 obj <> >> endobj 1361 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1362 0 obj 44 endobj 380 0 obj <> endobj 383 0 obj <> >> endobj 1363 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1364 0 obj 44 endobj 409 0 obj <> endobj 412 0 obj <> >> endobj 1365 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1366 0 obj 44 endobj 443 0 obj <> endobj 446 0 obj <> >> endobj 1367 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1368 0 obj 44 endobj 466 0 obj <> endobj 469 0 obj <> >> endobj 1369 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1370 0 obj 44 endobj 483 0 obj <> endobj 486 0 obj <> >> endobj 1371 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1372 0 obj 44 endobj 501 0 obj <> endobj 504 0 obj <> >> endobj 1373 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1374 0 obj 44 endobj 521 0 obj <> endobj 524 0 obj <> >> endobj 1375 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1376 0 obj 44 endobj 539 0 obj <> endobj 542 0 obj <> >> endobj 1377 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1378 0 obj 44 endobj 565 0 obj <> endobj 568 0 obj <> >> endobj 1379 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1380 0 obj 44 endobj 589 0 obj <> endobj 592 0 obj <> >> endobj 1381 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1382 0 obj 44 endobj 606 0 obj <> endobj 609 0 obj <> >> endobj 1383 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1384 0 obj 44 endobj 621 0 obj <> endobj 624 0 obj <> >> endobj 1385 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1386 0 obj 44 endobj 635 0 obj <> endobj 638 0 obj <> >> endobj 1387 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1388 0 obj 44 endobj 652 0 obj <> endobj 655 0 obj <> >> endobj 1389 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1390 0 obj 44 endobj 671 0 obj <> endobj 674 0 obj <> >> endobj 1391 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1392 0 obj 44 endobj 681 0 obj <> endobj 684 0 obj <> >> endobj 1393 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1394 0 obj 44 endobj 692 0 obj <> endobj 695 0 obj <> >> endobj 1395 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1396 0 obj 44 endobj 702 0 obj <> endobj 705 0 obj <> >> endobj 1397 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1398 0 obj 44 endobj 718 0 obj <> endobj 721 0 obj <> >> endobj 1399 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1400 0 obj 44 endobj 736 0 obj <> endobj 739 0 obj <> >> endobj 1401 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1402 0 obj 44 endobj 751 0 obj <> endobj 754 0 obj <> >> endobj 1403 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1404 0 obj 44 endobj 763 0 obj <> endobj 766 0 obj <> >> endobj 1405 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1406 0 obj 44 endobj 777 0 obj <> endobj 780 0 obj <> >> endobj 1407 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1408 0 obj 44 endobj 790 0 obj <> endobj 793 0 obj <> >> endobj 1409 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1410 0 obj 44 endobj 799 0 obj <> endobj 802 0 obj <> >> endobj 1411 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1412 0 obj 44 endobj 807 0 obj <> endobj 810 0 obj <> >> endobj 1413 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1414 0 obj 44 endobj 826 0 obj <> endobj 829 0 obj <> >> endobj 1415 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1416 0 obj 44 endobj 849 0 obj <> endobj 852 0 obj <> >> endobj 1417 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1418 0 obj 44 endobj 860 0 obj <> endobj 863 0 obj <> >> endobj 1419 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1420 0 obj 44 endobj 879 0 obj <> endobj 882 0 obj <> >> endobj 1421 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1422 0 obj 44 endobj 897 0 obj <> endobj 900 0 obj <> >> endobj 1423 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1424 0 obj 44 endobj 912 0 obj <> endobj 915 0 obj <> >> endobj 1425 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1426 0 obj 44 endobj 927 0 obj <> endobj 930 0 obj <> >> endobj 1427 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1428 0 obj 44 endobj 945 0 obj <> endobj 948 0 obj <> >> endobj 1429 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1430 0 obj 44 endobj 963 0 obj <> endobj 966 0 obj <> >> endobj 1431 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1432 0 obj 44 endobj 983 0 obj <> endobj 986 0 obj <> >> endobj 1433 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1434 0 obj 44 endobj 995 0 obj <> endobj 998 0 obj <> >> endobj 1435 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1436 0 obj 44 endobj 1008 0 obj <> endobj 1011 0 obj <> >> endobj 1437 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1438 0 obj 44 endobj 1019 0 obj <> endobj 1022 0 obj <> >> endobj 1439 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1440 0 obj 44 endobj 1034 0 obj <> endobj 1037 0 obj <> >> endobj 1441 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1442 0 obj 44 endobj 1047 0 obj <> endobj 1050 0 obj <> >> endobj 1443 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1444 0 obj 44 endobj 1062 0 obj <> endobj 1065 0 obj <> >> endobj 1445 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1446 0 obj 44 endobj 1082 0 obj <> endobj 1085 0 obj <> >> endobj 1447 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1448 0 obj 44 endobj 1095 0 obj <> endobj 1098 0 obj <> >> endobj 1449 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1450 0 obj 44 endobj 1109 0 obj <> endobj 1112 0 obj <> >> endobj 1451 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1452 0 obj 44 endobj 1133 0 obj <> endobj 1136 0 obj <> >> endobj 1453 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1454 0 obj 44 endobj 1146 0 obj <> endobj 1149 0 obj <> >> endobj 1455 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1456 0 obj 44 endobj 1160 0 obj <> endobj 1163 0 obj <> >> endobj 1457 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1458 0 obj 44 endobj 1173 0 obj <> endobj 1176 0 obj <> >> endobj 1459 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1460 0 obj 44 endobj 1191 0 obj <> endobj 1194 0 obj <> >> endobj 1461 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1462 0 obj 44 endobj 1207 0 obj <> endobj 1210 0 obj <> >> endobj 1463 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1464 0 obj 44 endobj 1234 0 obj <> endobj 1237 0 obj <> >> endobj 1465 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1466 0 obj 44 endobj 1248 0 obj <> endobj 1251 0 obj <> >> endobj 1467 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1468 0 obj 44 endobj 1265 0 obj <> endobj 1268 0 obj <> >> endobj 1469 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1470 0 obj 44 endobj 1285 0 obj <> endobj 1288 0 obj <> >> endobj 1471 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1472 0 obj 44 endobj 1294 0 obj <> endobj 1297 0 obj <> >> endobj 1473 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 1474 0 obj 44 endobj 3 0 obj <> stream Untitled Unknown XEP 4.12 build 20080425 Unknown 20141105T101135Z 20141105T101135Z endstream endobj 1338 0 obj <> endobj 1339 0 obj <> endobj 1615 0 obj <> endobj 1616 0 obj <> endobj 1617 0 obj <> endobj 1618 0 obj <> endobj 1619 0 obj <> endobj 1620 0 obj <> endobj 1621 0 obj <> endobj 1622 0 obj <> endobj 1623 0 obj <> endobj 1612 0 obj <> endobj 1521 0 obj <> endobj 1544 0 obj <> endobj 1507 0 obj <> endobj 1508 0 obj <> endobj 1575 0 obj <> endobj 1565 0 obj <> endobj 1513 0 obj <> endobj 1515 0 obj <> endobj 1601 0 obj <> endobj 1511 0 obj <> endobj 1580 0 obj <> endobj 1532 0 obj <> endobj 1594 0 obj <> endobj 1602 0 obj <> endobj 1577 0 obj <> endobj 1516 0 obj <> endobj 1583 0 obj <> endobj 1556 0 obj <> endobj 1588 0 obj <> endobj 1540 0 obj <> endobj 1550 0 obj <> endobj 1487 0 obj <> endobj 1494 0 obj <> endobj 1599 0 obj <> endobj 1566 0 obj <> endobj 1475 0 obj <> endobj 1609 0 obj <> endobj 1605 0 obj <> endobj 1518 0 obj <> endobj 1529 0 obj <> endobj 1528 0 obj <> endobj 1584 0 obj <> endobj 1500 0 obj <> endobj 1530 0 obj <> endobj 1499 0 obj <> endobj 1495 0 obj <> endobj 1498 0 obj <> endobj 1598 0 obj <> endobj 1569 0 obj <> endobj 1557 0 obj <> endobj 1514 0 obj <> endobj 1581 0 obj <> endobj 1614 0 obj <> endobj 1571 0 obj <> endobj 1519 0 obj <> endobj 1582 0 obj <> endobj 1564 0 obj <> endobj 1533 0 obj <> endobj 1496 0 obj <> endobj 1545 0 obj <> endobj 1591 0 obj <> endobj 1501 0 obj <> endobj 1527 0 obj <> endobj 1538 0 obj <> endobj 1592 0 obj <> endobj 1549 0 obj <> endobj 1608 0 obj <> endobj 1586 0 obj <> endobj 1542 0 obj <> endobj 1595 0 obj <> endobj 1479 0 obj <> endobj 1492 0 obj <> endobj 1536 0 obj <> endobj 1589 0 obj <> endobj 1534 0 obj <> endobj 1490 0 obj <> endobj 1491 0 obj <> endobj 1576 0 obj <> endobj 1525 0 obj <> endobj 1506 0 obj <> endobj 1547 0 obj <> endobj 1578 0 obj <> endobj 1517 0 obj <> endobj 1596 0 obj <> endobj 1537 0 obj <> endobj 1574 0 obj <> endobj 1563 0 obj <> endobj 1510 0 obj <> endobj 1522 0 obj <> endobj 1553 0 obj <> endobj 1543 0 obj <> endobj 1546 0 obj <> endobj 1520 0 obj <> endobj 1593 0 obj <> endobj 1573 0 obj <> endobj 1503 0 obj <> endobj 1590 0 obj <> endobj 1613 0 obj <> endobj 1512 0 obj <> endobj 1488 0 obj <> endobj 1572 0 obj <> endobj 1535 0 obj <> endobj 1579 0 obj <> endobj 1555 0 obj <> endobj 1502 0 obj <> endobj 1611 0 obj <> endobj 1523 0 obj <> endobj 1509 0 obj <> endobj 1560 0 obj <> endobj 1539 0 obj <> endobj 1604 0 obj <> endobj 1476 0 obj <> endobj 1483 0 obj <> endobj 1497 0 obj <> endobj 1562 0 obj <> endobj 1610 0 obj <> endobj 1493 0 obj <> endobj 1552 0 obj <> endobj 1489 0 obj <> endobj 1568 0 obj <> endobj 1603 0 obj <> endobj 1554 0 obj <> endobj 1551 0 obj <> endobj 1597 0 obj <> endobj 1570 0 obj <> endobj 1548 0 obj <> endobj 1600 0 obj <> endobj 1558 0 obj <> endobj 1567 0 obj <> endobj 1606 0 obj <> endobj 1478 0 obj <> endobj 1607 0 obj <> endobj 1587 0 obj <> endobj 1477 0 obj <> endobj 1559 0 obj <> endobj 1504 0 obj <> endobj 1524 0 obj <> endobj 1484 0 obj <> endobj 1541 0 obj <> endobj 1531 0 obj <> endobj 1505 0 obj <> endobj 1485 0 obj <> endobj 1481 0 obj <> endobj 1482 0 obj <> endobj 1480 0 obj <> endobj 1486 0 obj <> endobj 1526 0 obj <> endobj 1561 0 obj <> endobj 1585 0 obj <> endobj xref 0 1624 0000000000 65535 f 0000373999 00000 n 0000374173 00000 n 0000415177 00000 n 0000243008 00000 n 0000375290 00000 n 0000000015 00000 n 0000010329 00000 n 0000376013 00000 n 0000243196 00000 n 0000257238 00000 n 0000263002 00000 n 0000264849 00000 n 0000373867 00000 n 0000373738 00000 n 0000373613 00000 n 0000373489 00000 n 0000373369 00000 n 0000373253 00000 n 0000373110 00000 n 0000373019 00000 n 0000372925 00000 n 0000372834 00000 n 0000372740 00000 n 0000372651 00000 n 0000372557 00000 n 0000372465 00000 n 0000372370 00000 n 0000372278 00000 n 0000372183 00000 n 0000372092 00000 n 0000371997 00000 n 0000371904 00000 n 0000371809 00000 n 0000371719 00000 n 0000371624 00000 n 0000371532 00000 n 0000371437 00000 n 0000371345 00000 n 0000371250 00000 n 0000371158 00000 n 0000371063 00000 n 0000370971 00000 n 0000370876 00000 n 0000370784 00000 n 0000370689 00000 n 0000370584 00000 n 0000370477 00000 n 0000370373 00000 n 0000370267 00000 n 0000370167 00000 n 0000370065 00000 n 0000369966 00000 n 0000369863 00000 n 0000369766 00000 n 0000369667 00000 n 0000369564 00000 n 0000369459 00000 n 0000369358 00000 n 0000369255 00000 n 0000369160 00000 n 0000369063 00000 n 0000368955 00000 n 0000368845 00000 n 0000368745 00000 n 0000368643 00000 n 0000368547 00000 n 0000368449 00000 n 0000368348 00000 n 0000368245 00000 n 0000368145 00000 n 0000368043 00000 n 0000367941 00000 n 0000367837 00000 n 0000367736 00000 n 0000367633 00000 n 0000367531 00000 n 0000367427 00000 n 0000367324 00000 n 0000367217 00000 n 0000367116 00000 n 0000367013 00000 n 0000366922 00000 n 0000366828 00000 n 0000376274 00000 n 0000010350 00000 n 0000024662 00000 n 0000377419 00000 n 0000366723 00000 n 0000366616 00000 n 0000366510 00000 n 0000366402 00000 n 0000366299 00000 n 0000366194 00000 n 0000366088 00000 n 0000365980 00000 n 0000365872 00000 n 0000365762 00000 n 0000365661 00000 n 0000365556 00000 n 0000365451 00000 n 0000365344 00000 n 0000365250 00000 n 0000365153 00000 n 0000365048 00000 n 0000364941 00000 n 0000364835 00000 n 0000364727 00000 n 0000364624 00000 n 0000364519 00000 n 0000364416 00000 n 0000364311 00000 n 0000364205 00000 n 0000364097 00000 n 0000363996 00000 n 0000363893 00000 n 0000363792 00000 n 0000363689 00000 n 0000363583 00000 n 0000363475 00000 n 0000363362 00000 n 0000363247 00000 n 0000363134 00000 n 0000363019 00000 n 0000362921 00000 n 0000362821 00000 n 0000362723 00000 n 0000362623 00000 n 0000362520 00000 n 0000362415 00000 n 0000362307 00000 n 0000362197 00000 n 0000362103 00000 n 0000362006 00000 n 0000361903 00000 n 0000361798 00000 n 0000361696 00000 n 0000361592 00000 n 0000361491 00000 n 0000361388 00000 n 0000361287 00000 n 0000361184 00000 n 0000361075 00000 n 0000360964 00000 n 0000360858 00000 n 0000360750 00000 n 0000360638 00000 n 0000360524 00000 n 0000360417 00000 n 0000360308 00000 n 0000360202 00000 n 0000360092 00000 n 0000359987 00000 n 0000359880 00000 n 0000359773 00000 n 0000359664 00000 n 0000359559 00000 n 0000359450 00000 n 0000359348 00000 n 0000359244 00000 n 0000359134 00000 n 0000359022 00000 n 0000358908 00000 n 0000358792 00000 n 0000358684 00000 n 0000358574 00000 n 0000358470 00000 n 0000358364 00000 n 0000358257 00000 n 0000358146 00000 n 0000358043 00000 n 0000357938 00000 n 0000357835 00000 n 0000357730 00000 n 0000357625 00000 n 0000357518 00000 n 0000357416 00000 n 0000357312 00000 n 0000357209 00000 n 0000357104 00000 n 0000357001 00000 n 0000356896 00000 n 0000356793 00000 n 0000356688 00000 n 0000356580 00000 n 0000356468 00000 n 0000356357 00000 n 0000356244 00000 n 0000356136 00000 n 0000356026 00000 n 0000355921 00000 n 0000355814 00000 n 0000355710 00000 n 0000355604 00000 n 0000355497 00000 n 0000355388 00000 n 0000355285 00000 n 0000355178 00000 n 0000355071 00000 n 0000354962 00000 n 0000354857 00000 n 0000354748 00000 n 0000354645 00000 n 0000354538 00000 n 0000377627 00000 n 0000024684 00000 n 0000037953 00000 n 0000378707 00000 n 0000354435 00000 n 0000354330 00000 n 0000354225 00000 n 0000354118 00000 n 0000354024 00000 n 0000353927 00000 n 0000353822 00000 n 0000353715 00000 n 0000353611 00000 n 0000353505 00000 n 0000353398 00000 n 0000353289 00000 n 0000353180 00000 n 0000353069 00000 n 0000352960 00000 n 0000352849 00000 n 0000352738 00000 n 0000352623 00000 n 0000352513 00000 n 0000352401 00000 n 0000352289 00000 n 0000352175 00000 n 0000352062 00000 n 0000351947 00000 n 0000351837 00000 n 0000351725 00000 n 0000351613 00000 n 0000351499 00000 n 0000351383 00000 n 0000351265 00000 n 0000351152 00000 n 0000351037 00000 n 0000350921 00000 n 0000350803 00000 n 0000350690 00000 n 0000350575 00000 n 0000350475 00000 n 0000350371 00000 n 0000350261 00000 n 0000350149 00000 n 0000350038 00000 n 0000349925 00000 n 0000349831 00000 n 0000349734 00000 n 0000349629 00000 n 0000349522 00000 n 0000349417 00000 n 0000349310 00000 n 0000349199 00000 n 0000349086 00000 n 0000348981 00000 n 0000348874 00000 n 0000348771 00000 n 0000348664 00000 n 0000348551 00000 n 0000348436 00000 n 0000348332 00000 n 0000348226 00000 n 0000348122 00000 n 0000348016 00000 n 0000347911 00000 n 0000347804 00000 n 0000347701 00000 n 0000347596 00000 n 0000347494 00000 n 0000347390 00000 n 0000347284 00000 n 0000347176 00000 n 0000347070 00000 n 0000346962 00000 n 0000346855 00000 n 0000346746 00000 n 0000346652 00000 n 0000346555 00000 n 0000346454 00000 n 0000346351 00000 n 0000346247 00000 n 0000346139 00000 n 0000346036 00000 n 0000345931 00000 n 0000345825 00000 n 0000345717 00000 n 0000345610 00000 n 0000345501 00000 n 0000345399 00000 n 0000345295 00000 n 0000345193 00000 n 0000345089 00000 n 0000344986 00000 n 0000344881 00000 n 0000344787 00000 n 0000344690 00000 n 0000344585 00000 n 0000344478 00000 n 0000344374 00000 n 0000344268 00000 n 0000344163 00000 n 0000344056 00000 n 0000343953 00000 n 0000343846 00000 n 0000343740 00000 n 0000343632 00000 n 0000343499 00000 n 0000343370 00000 n 0000343245 00000 n 0000343124 00000 n 0000378927 00000 n 0000037976 00000 n 0000041927 00000 n 0000379183 00000 n 0000260790 00000 n 0000343003 00000 n 0000342886 00000 n 0000342742 00000 n 0000379426 00000 n 0000041949 00000 n 0000046199 00000 n 0000379682 00000 n 0000253896 00000 n 0000342636 00000 n 0000342528 00000 n 0000342425 00000 n 0000379937 00000 n 0000046221 00000 n 0000051213 00000 n 0000380321 00000 n 0000255752 00000 n 0000342320 00000 n 0000342205 00000 n 0000342098 00000 n 0000341994 00000 n 0000341887 00000 n 0000341782 00000 n 0000341677 00000 n 0000341575 00000 n 0000341470 00000 n 0000341365 00000 n 0000341264 00000 n 0000341161 00000 n 0000341058 00000 n 0000340954 00000 n 0000340844 00000 n 0000340740 00000 n 0000340630 00000 n 0000340523 00000 n 0000340417 00000 n 0000380565 00000 n 0000051235 00000 n 0000056019 00000 n 0000380933 00000 n 0000340311 00000 n 0000340204 00000 n 0000340104 00000 n 0000340004 00000 n 0000339897 00000 n 0000339790 00000 n 0000339690 00000 n 0000339585 00000 n 0000339485 00000 n 0000339384 00000 n 0000339278 00000 n 0000339179 00000 n 0000339080 00000 n 0000338973 00000 n 0000338872 00000 n 0000338771 00000 n 0000338672 00000 n 0000381200 00000 n 0000056041 00000 n 0000059867 00000 n 0000381440 00000 n 0000338574 00000 n 0000381695 00000 n 0000059889 00000 n 0000063448 00000 n 0000382127 00000 n 0000338471 00000 n 0000338367 00000 n 0000338261 00000 n 0000338157 00000 n 0000338050 00000 n 0000337942 00000 n 0000337837 00000 n 0000337735 00000 n 0000337630 00000 n 0000337527 00000 n 0000337424 00000 n 0000337323 00000 n 0000337220 00000 n 0000337118 00000 n 0000337021 00000 n 0000336918 00000 n 0000336814 00000 n 0000336713 00000 n 0000336612 00000 n 0000336510 00000 n 0000336408 00000 n 0000336308 00000 n 0000336208 00000 n 0000336106 00000 n 0000336003 00000 n 0000382382 00000 n 0000063470 00000 n 0000067151 00000 n 0000382854 00000 n 0000335897 00000 n 0000335790 00000 n 0000335686 00000 n 0000335593 00000 n 0000335492 00000 n 0000335400 00000 n 0000335306 00000 n 0000335212 00000 n 0000335102 00000 n 0000334995 00000 n 0000334893 00000 n 0000334790 00000 n 0000334684 00000 n 0000334586 00000 n 0000334480 00000 n 0000334377 00000 n 0000334272 00000 n 0000334176 00000 n 0000334075 00000 n 0000333975 00000 n 0000333871 00000 n 0000333767 00000 n 0000333661 00000 n 0000333555 00000 n 0000333452 00000 n 0000333344 00000 n 0000333237 00000 n 0000333134 00000 n 0000333037 00000 n 0000332936 00000 n 0000383121 00000 n 0000067173 00000 n 0000068791 00000 n 0000383505 00000 n 0000332834 00000 n 0000332729 00000 n 0000332617 00000 n 0000332508 00000 n 0000332404 00000 n 0000332302 00000 n 0000332190 00000 n 0000332087 00000 n 0000331984 00000 n 0000331870 00000 n 0000331766 00000 n 0000331662 00000 n 0000331547 00000 n 0000331438 00000 n 0000331326 00000 n 0000331219 00000 n 0000331114 00000 n 0000330996 00000 n 0000330884 00000 n 0000383737 00000 n 0000068813 00000 n 0000071553 00000 n 0000384073 00000 n 0000330783 00000 n 0000330678 00000 n 0000330571 00000 n 0000330466 00000 n 0000330358 00000 n 0000330250 00000 n 0000330144 00000 n 0000330038 00000 n 0000329932 00000 n 0000329826 00000 n 0000329721 00000 n 0000329615 00000 n 0000329508 00000 n 0000384340 00000 n 0000071575 00000 n 0000074035 00000 n 0000384684 00000 n 0000329405 00000 n 0000329299 00000 n 0000329195 00000 n 0000329092 00000 n 0000328983 00000 n 0000328877 00000 n 0000328771 00000 n 0000328668 00000 n 0000328559 00000 n 0000328453 00000 n 0000328347 00000 n 0000328241 00000 n 0000328131 00000 n 0000328023 00000 n 0000384951 00000 n 0000074057 00000 n 0000077997 00000 n 0000385295 00000 n 0000258861 00000 n 0000260022 00000 n 0000327920 00000 n 0000327814 00000 n 0000327715 00000 n 0000327619 00000 n 0000327512 00000 n 0000327406 00000 n 0000327303 00000 n 0000327199 00000 n 0000327100 00000 n 0000327003 00000 n 0000326897 00000 n 0000326792 00000 n 0000326689 00000 n 0000326584 00000 n 0000385586 00000 n 0000078019 00000 n 0000083056 00000 n 0000385930 00000 n 0000326480 00000 n 0000326373 00000 n 0000326263 00000 n 0000326157 00000 n 0000326051 00000 n 0000325946 00000 n 0000325843 00000 n 0000325729 00000 n 0000325626 00000 n 0000325522 00000 n 0000325418 00000 n 0000325306 00000 n 0000325192 00000 n 0000325088 00000 n 0000386198 00000 n 0000083078 00000 n 0000087447 00000 n 0000386598 00000 n 0000262231 00000 n 0000324982 00000 n 0000324876 00000 n 0000324770 00000 n 0000324664 00000 n 0000324556 00000 n 0000324457 00000 n 0000324353 00000 n 0000324250 00000 n 0000324151 00000 n 0000324052 00000 n 0000323955 00000 n 0000323854 00000 n 0000323747 00000 n 0000323641 00000 n 0000323539 00000 n 0000323433 00000 n 0000323329 00000 n 0000323223 00000 n 0000323119 00000 n 0000323018 00000 n 0000322916 00000 n 0000386901 00000 n 0000087469 00000 n 0000091392 00000 n 0000387293 00000 n 0000322812 00000 n 0000322711 00000 n 0000322608 00000 n 0000322499 00000 n 0000322392 00000 n 0000322288 00000 n 0000322181 00000 n 0000322077 00000 n 0000321970 00000 n 0000321862 00000 n 0000321762 00000 n 0000321657 00000 n 0000321550 00000 n 0000321442 00000 n 0000321334 00000 n 0000321228 00000 n 0000321128 00000 n 0000321030 00000 n 0000320925 00000 n 0000320819 00000 n 0000387560 00000 n 0000091414 00000 n 0000093305 00000 n 0000387896 00000 n 0000320714 00000 n 0000320609 00000 n 0000320503 00000 n 0000320397 00000 n 0000320290 00000 n 0000320186 00000 n 0000320084 00000 n 0000319979 00000 n 0000319874 00000 n 0000319769 00000 n 0000319662 00000 n 0000319559 00000 n 0000319457 00000 n 0000388163 00000 n 0000093327 00000 n 0000096353 00000 n 0000388483 00000 n 0000319362 00000 n 0000319256 00000 n 0000319151 00000 n 0000319051 00000 n 0000318944 00000 n 0000318844 00000 n 0000318739 00000 n 0000318632 00000 n 0000318517 00000 n 0000318412 00000 n 0000318305 00000 n 0000388750 00000 n 0000096375 00000 n 0000099733 00000 n 0000389062 00000 n 0000318204 00000 n 0000318099 00000 n 0000317984 00000 n 0000317872 00000 n 0000317767 00000 n 0000317664 00000 n 0000317556 00000 n 0000317441 00000 n 0000317334 00000 n 0000317227 00000 n 0000389329 00000 n 0000099755 00000 n 0000103107 00000 n 0000389665 00000 n 0000317120 00000 n 0000317015 00000 n 0000316908 00000 n 0000316793 00000 n 0000316681 00000 n 0000316578 00000 n 0000316473 00000 n 0000316366 00000 n 0000316251 00000 n 0000316139 00000 n 0000316035 00000 n 0000315920 00000 n 0000315808 00000 n 0000389932 00000 n 0000103129 00000 n 0000105946 00000 n 0000390284 00000 n 0000315703 00000 n 0000315596 00000 n 0000315484 00000 n 0000315379 00000 n 0000315276 00000 n 0000315171 00000 n 0000315056 00000 n 0000314953 00000 n 0000314848 00000 n 0000314751 00000 n 0000314646 00000 n 0000314541 00000 n 0000314434 00000 n 0000314335 00000 n 0000314228 00000 n 0000390551 00000 n 0000105968 00000 n 0000109102 00000 n 0000390831 00000 n 0000314123 00000 n 0000314016 00000 n 0000313914 00000 n 0000313809 00000 n 0000313702 00000 n 0000313597 00000 n 0000391098 00000 n 0000109124 00000 n 0000113332 00000 n 0000391386 00000 n 0000313493 00000 n 0000313386 00000 n 0000313283 00000 n 0000313186 00000 n 0000313079 00000 n 0000312972 00000 n 0000312865 00000 n 0000391653 00000 n 0000113354 00000 n 0000117363 00000 n 0000391933 00000 n 0000312761 00000 n 0000312656 00000 n 0000312549 00000 n 0000312446 00000 n 0000312339 00000 n 0000312240 00000 n 0000392212 00000 n 0000117385 00000 n 0000120232 00000 n 0000392540 00000 n 0000312140 00000 n 0000312035 00000 n 0000311921 00000 n 0000311820 00000 n 0000311715 00000 n 0000311601 00000 n 0000311499 00000 n 0000311389 00000 n 0000311282 00000 n 0000311171 00000 n 0000311063 00000 n 0000310952 00000 n 0000392807 00000 n 0000120254 00000 n 0000123793 00000 n 0000393151 00000 n 0000310845 00000 n 0000310740 00000 n 0000310635 00000 n 0000310530 00000 n 0000310425 00000 n 0000310321 00000 n 0000310211 00000 n 0000310102 00000 n 0000309996 00000 n 0000309890 00000 n 0000309786 00000 n 0000309673 00000 n 0000309560 00000 n 0000309453 00000 n 0000393406 00000 n 0000123815 00000 n 0000127389 00000 n 0000393726 00000 n 0000309348 00000 n 0000309246 00000 n 0000309140 00000 n 0000309043 00000 n 0000308940 00000 n 0000308840 00000 n 0000308737 00000 n 0000308631 00000 n 0000308526 00000 n 0000308420 00000 n 0000308309 00000 n 0000393993 00000 n 0000127411 00000 n 0000131084 00000 n 0000394289 00000 n 0000308202 00000 n 0000308097 00000 n 0000307999 00000 n 0000307894 00000 n 0000307787 00000 n 0000307683 00000 n 0000307577 00000 n 0000307470 00000 n 0000394544 00000 n 0000131106 00000 n 0000134443 00000 n 0000394856 00000 n 0000307367 00000 n 0000307262 00000 n 0000307155 00000 n 0000307050 00000 n 0000306944 00000 n 0000306838 00000 n 0000306733 00000 n 0000306628 00000 n 0000306517 00000 n 0000306414 00000 n 0000395111 00000 n 0000134465 00000 n 0000137687 00000 n 0000395415 00000 n 0000306313 00000 n 0000306208 00000 n 0000306102 00000 n 0000305993 00000 n 0000305888 00000 n 0000305783 00000 n 0000305669 00000 n 0000305557 00000 n 0000305448 00000 n 0000395670 00000 n 0000137709 00000 n 0000140992 00000 n 0000395942 00000 n 0000305342 00000 n 0000305229 00000 n 0000305126 00000 n 0000305017 00000 n 0000304910 00000 n 0000396197 00000 n 0000141014 00000 n 0000144736 00000 n 0000396461 00000 n 0000304807 00000 n 0000304702 00000 n 0000304594 00000 n 0000304489 00000 n 0000396716 00000 n 0000144758 00000 n 0000148200 00000 n 0000397068 00000 n 0000304388 00000 n 0000304285 00000 n 0000304182 00000 n 0000304077 00000 n 0000303975 00000 n 0000303870 00000 n 0000303760 00000 n 0000303653 00000 n 0000303541 00000 n 0000303438 00000 n 0000303333 00000 n 0000303229 00000 n 0000303123 00000 n 0000303020 00000 n 0000302913 00000 n 0000397335 00000 n 0000148222 00000 n 0000151466 00000 n 0000397719 00000 n 0000302812 00000 n 0000302709 00000 n 0000302606 00000 n 0000302505 00000 n 0000302404 00000 n 0000302302 00000 n 0000302201 00000 n 0000302103 00000 n 0000301997 00000 n 0000301894 00000 n 0000301786 00000 n 0000301683 00000 n 0000301582 00000 n 0000301482 00000 n 0000301380 00000 n 0000301281 00000 n 0000301178 00000 n 0000301071 00000 n 0000300965 00000 n 0000397986 00000 n 0000151488 00000 n 0000155610 00000 n 0000398274 00000 n 0000300858 00000 n 0000300752 00000 n 0000300644 00000 n 0000300543 00000 n 0000300441 00000 n 0000300338 00000 n 0000300235 00000 n 0000398529 00000 n 0000155632 00000 n 0000159082 00000 n 0000398881 00000 n 0000300128 00000 n 0000300022 00000 n 0000299917 00000 n 0000299813 00000 n 0000299707 00000 n 0000299604 00000 n 0000299497 00000 n 0000299395 00000 n 0000299291 00000 n 0000299185 00000 n 0000299081 00000 n 0000298975 00000 n 0000298870 00000 n 0000298767 00000 n 0000298663 00000 n 0000399148 00000 n 0000159104 00000 n 0000163228 00000 n 0000399492 00000 n 0000298550 00000 n 0000298445 00000 n 0000298339 00000 n 0000298233 00000 n 0000298135 00000 n 0000298039 00000 n 0000297933 00000 n 0000297828 00000 n 0000297726 00000 n 0000297622 00000 n 0000297519 00000 n 0000297407 00000 n 0000297302 00000 n 0000297200 00000 n 0000399747 00000 n 0000163250 00000 n 0000166691 00000 n 0000400067 00000 n 0000297094 00000 n 0000296985 00000 n 0000296881 00000 n 0000296778 00000 n 0000296673 00000 n 0000296571 00000 n 0000296466 00000 n 0000296361 00000 n 0000296251 00000 n 0000296147 00000 n 0000296043 00000 n 0000400334 00000 n 0000166713 00000 n 0000169470 00000 n 0000400654 00000 n 0000295938 00000 n 0000295831 00000 n 0000295727 00000 n 0000295622 00000 n 0000295517 00000 n 0000295404 00000 n 0000295299 00000 n 0000295195 00000 n 0000295091 00000 n 0000294988 00000 n 0000294883 00000 n 0000400909 00000 n 0000169492 00000 n 0000173849 00000 n 0000401253 00000 n 0000294777 00000 n 0000294672 00000 n 0000294567 00000 n 0000294463 00000 n 0000294358 00000 n 0000294248 00000 n 0000294148 00000 n 0000294050 00000 n 0000293941 00000 n 0000293835 00000 n 0000293735 00000 n 0000293638 00000 n 0000293532 00000 n 0000293429 00000 n 0000401520 00000 n 0000173871 00000 n 0000176948 00000 n 0000401864 00000 n 0000293323 00000 n 0000293218 00000 n 0000293112 00000 n 0000293009 00000 n 0000292900 00000 n 0000292791 00000 n 0000292687 00000 n 0000292582 00000 n 0000292484 00000 n 0000292386 00000 n 0000292280 00000 n 0000292171 00000 n 0000292064 00000 n 0000291965 00000 n 0000402119 00000 n 0000176970 00000 n 0000179923 00000 n 0000402479 00000 n 0000291865 00000 n 0000291757 00000 n 0000291654 00000 n 0000291554 00000 n 0000291448 00000 n 0000291348 00000 n 0000291237 00000 n 0000291137 00000 n 0000291032 00000 n 0000290932 00000 n 0000290834 00000 n 0000290731 00000 n 0000290622 00000 n 0000290515 00000 n 0000290417 00000 n 0000290312 00000 n 0000402734 00000 n 0000179945 00000 n 0000184404 00000 n 0000403030 00000 n 0000290212 00000 n 0000290105 00000 n 0000289999 00000 n 0000289895 00000 n 0000289788 00000 n 0000289683 00000 n 0000289572 00000 n 0000289465 00000 n 0000403297 00000 n 0000184426 00000 n 0000187578 00000 n 0000403609 00000 n 0000289362 00000 n 0000289257 00000 n 0000289151 00000 n 0000289046 00000 n 0000288938 00000 n 0000288831 00000 n 0000288723 00000 n 0000288630 00000 n 0000288522 00000 n 0000403876 00000 n 0000187600 00000 n 0000191408 00000 n 0000404174 00000 n 0000288418 00000 n 0000288312 00000 n 0000288209 00000 n 0000288102 00000 n 0000287995 00000 n 0000287889 00000 n 0000287785 00000 n 0000404442 00000 n 0000191431 00000 n 0000195305 00000 n 0000404776 00000 n 0000287677 00000 n 0000287568 00000 n 0000287462 00000 n 0000287355 00000 n 0000287251 00000 n 0000287142 00000 n 0000287036 00000 n 0000286930 00000 n 0000286827 00000 n 0000286719 00000 n 0000286614 00000 n 0000405032 00000 n 0000195328 00000 n 0000198561 00000 n 0000405348 00000 n 0000286501 00000 n 0000286397 00000 n 0000286290 00000 n 0000286186 00000 n 0000286073 00000 n 0000285963 00000 n 0000285853 00000 n 0000285750 00000 n 0000285634 00000 n 0000405616 00000 n 0000198584 00000 n 0000202342 00000 n 0000405950 00000 n 0000285522 00000 n 0000285416 00000 n 0000285311 00000 n 0000285203 00000 n 0000285096 00000 n 0000284985 00000 n 0000284875 00000 n 0000284767 00000 n 0000284652 00000 n 0000284546 00000 n 0000284440 00000 n 0000406230 00000 n 0000202365 00000 n 0000205534 00000 n 0000406609 00000 n 0000284327 00000 n 0000284212 00000 n 0000284100 00000 n 0000283985 00000 n 0000283874 00000 n 0000283764 00000 n 0000283654 00000 n 0000283551 00000 n 0000283445 00000 n 0000283329 00000 n 0000283216 00000 n 0000283104 00000 n 0000282999 00000 n 0000282893 00000 n 0000282778 00000 n 0000282667 00000 n 0000406865 00000 n 0000205557 00000 n 0000208145 00000 n 0000407181 00000 n 0000282551 00000 n 0000282447 00000 n 0000282340 00000 n 0000282227 00000 n 0000282124 00000 n 0000282017 00000 n 0000281898 00000 n 0000281780 00000 n 0000281674 00000 n 0000407437 00000 n 0000208168 00000 n 0000211385 00000 n 0000407762 00000 n 0000281565 00000 n 0000281450 00000 n 0000281337 00000 n 0000281234 00000 n 0000281115 00000 n 0000280996 00000 n 0000280894 00000 n 0000280789 00000 n 0000280682 00000 n 0000280579 00000 n 0000408018 00000 n 0000211408 00000 n 0000214706 00000 n 0000408433 00000 n 0000280466 00000 n 0000280356 00000 n 0000280246 00000 n 0000280136 00000 n 0000280031 00000 n 0000279926 00000 n 0000279823 00000 n 0000279709 00000 n 0000279606 00000 n 0000279494 00000 n 0000279389 00000 n 0000279282 00000 n 0000279175 00000 n 0000279077 00000 n 0000278972 00000 n 0000278865 00000 n 0000278758 00000 n 0000278652 00000 n 0000278551 00000 n 0000278448 00000 n 0000408689 00000 n 0000214729 00000 n 0000216934 00000 n 0000409005 00000 n 0000278341 00000 n 0000278234 00000 n 0000278134 00000 n 0000278028 00000 n 0000277925 00000 n 0000277820 00000 n 0000277715 00000 n 0000277601 00000 n 0000277494 00000 n 0000409261 00000 n 0000216957 00000 n 0000219839 00000 n 0000409586 00000 n 0000277388 00000 n 0000277285 00000 n 0000277178 00000 n 0000277082 00000 n 0000276974 00000 n 0000276867 00000 n 0000276770 00000 n 0000276674 00000 n 0000276558 00000 n 0000276453 00000 n 0000409842 00000 n 0000219862 00000 n 0000222756 00000 n 0000410158 00000 n 0000276349 00000 n 0000276244 00000 n 0000276139 00000 n 0000276034 00000 n 0000275930 00000 n 0000275825 00000 n 0000275720 00000 n 0000275613 00000 n 0000275509 00000 n 0000410414 00000 n 0000222779 00000 n 0000225357 00000 n 0000410775 00000 n 0000275402 00000 n 0000275294 00000 n 0000275186 00000 n 0000275081 00000 n 0000274976 00000 n 0000274866 00000 n 0000274761 00000 n 0000274656 00000 n 0000274549 00000 n 0000274441 00000 n 0000274334 00000 n 0000274231 00000 n 0000274126 00000 n 0000274019 00000 n 0000411031 00000 n 0000225380 00000 n 0000228492 00000 n 0000411374 00000 n 0000273915 00000 n 0000273808 00000 n 0000273699 00000 n 0000273592 00000 n 0000273486 00000 n 0000273378 00000 n 0000273269 00000 n 0000273162 00000 n 0000273053 00000 n 0000272946 00000 n 0000272838 00000 n 0000272733 00000 n 0000411630 00000 n 0000228515 00000 n 0000231237 00000 n 0000412072 00000 n 0000272633 00000 n 0000272525 00000 n 0000272422 00000 n 0000272317 00000 n 0000272212 00000 n 0000272107 00000 n 0000272002 00000 n 0000271897 00000 n 0000271792 00000 n 0000271687 00000 n 0000271582 00000 n 0000271482 00000 n 0000271375 00000 n 0000271270 00000 n 0000271161 00000 n 0000271054 00000 n 0000270950 00000 n 0000270852 00000 n 0000270748 00000 n 0000270643 00000 n 0000270542 00000 n 0000270441 00000 n 0000270340 00000 n 0000412340 00000 n 0000231260 00000 n 0000234175 00000 n 0000412665 00000 n 0000270234 00000 n 0000270131 00000 n 0000270027 00000 n 0000269923 00000 n 0000269818 00000 n 0000269710 00000 n 0000269606 00000 n 0000269499 00000 n 0000269393 00000 n 0000269290 00000 n 0000412921 00000 n 0000234198 00000 n 0000237779 00000 n 0000413273 00000 n 0000269181 00000 n 0000269074 00000 n 0000268971 00000 n 0000268865 00000 n 0000268755 00000 n 0000268648 00000 n 0000268541 00000 n 0000268431 00000 n 0000268329 00000 n 0000268227 00000 n 0000268124 00000 n 0000268017 00000 n 0000267915 00000 n 0000413541 00000 n 0000237802 00000 n 0000240633 00000 n 0000413920 00000 n 0000267813 00000 n 0000267710 00000 n 0000267603 00000 n 0000267498 00000 n 0000267392 00000 n 0000267288 00000 n 0000267183 00000 n 0000267081 00000 n 0000266980 00000 n 0000266877 00000 n 0000266775 00000 n 0000266677 00000 n 0000266574 00000 n 0000266471 00000 n 0000266366 00000 n 0000266263 00000 n 0000414176 00000 n 0000240656 00000 n 0000242338 00000 n 0000414456 00000 n 0000266156 00000 n 0000266051 00000 n 0000265945 00000 n 0000265838 00000 n 0000265734 00000 n 0000414700 00000 n 0000242361 00000 n 0000242986 00000 n 0000414944 00000 n 0000265628 00000 n 0000252994 00000 n 0000253017 00000 n 0000253874 00000 n 0000254415 00000 n 0000254896 00000 n 0000255087 00000 n 0000255730 00000 n 0000256199 00000 n 0000256471 00000 n 0000256672 00000 n 0000257216 00000 n 0000257719 00000 n 0000258049 00000 n 0000258255 00000 n 0000258839 00000 n 0000259245 00000 n 0000259397 00000 n 0000259598 00000 n 0000260000 00000 n 0000260194 00000 n 0000260253 00000 n 0000260454 00000 n 0000260768 00000 n 0000261230 00000 n 0000261497 00000 n 0000261699 00000 n 0000262209 00000 n 0000262405 00000 n 0000262464 00000 n 0000262666 00000 n 0000262980 00000 n 0000263520 00000 n 0000263985 00000 n 0000264182 00000 n 0000264827 00000 n 0000265025 00000 n 0000265088 00000 n 0000265285 00000 n 0000265606 00000 n 0000416090 00000 n 0000416129 00000 n 0000374287 00000 n 0000374432 00000 n 0000374580 00000 n 0000374728 00000 n 0000374876 00000 n 0000375029 00000 n 0000375187 00000 n 0000376131 00000 n 0000376253 00000 n 0000377484 00000 n 0000377606 00000 n 0000378784 00000 n 0000378906 00000 n 0000379283 00000 n 0000379405 00000 n 0000379794 00000 n 0000379916 00000 n 0000380422 00000 n 0000380544 00000 n 0000381057 00000 n 0000381179 00000 n 0000381552 00000 n 0000381674 00000 n 0000382239 00000 n 0000382361 00000 n 0000382978 00000 n 0000383100 00000 n 0000383594 00000 n 0000383716 00000 n 0000384197 00000 n 0000384319 00000 n 0000384808 00000 n 0000384930 00000 n 0000385443 00000 n 0000385565 00000 n 0000386055 00000 n 0000386177 00000 n 0000386758 00000 n 0000386880 00000 n 0000387417 00000 n 0000387539 00000 n 0000388020 00000 n 0000388142 00000 n 0000388607 00000 n 0000388729 00000 n 0000389186 00000 n 0000389308 00000 n 0000389789 00000 n 0000389911 00000 n 0000390408 00000 n 0000390530 00000 n 0000390955 00000 n 0000391077 00000 n 0000391510 00000 n 0000391632 00000 n 0000392069 00000 n 0000392191 00000 n 0000392664 00000 n 0000392786 00000 n 0000393263 00000 n 0000393385 00000 n 0000393850 00000 n 0000393972 00000 n 0000394401 00000 n 0000394523 00000 n 0000394968 00000 n 0000395090 00000 n 0000395527 00000 n 0000395649 00000 n 0000396054 00000 n 0000396176 00000 n 0000396573 00000 n 0000396695 00000 n 0000397192 00000 n 0000397314 00000 n 0000397843 00000 n 0000397965 00000 n 0000398386 00000 n 0000398508 00000 n 0000399005 00000 n 0000399127 00000 n 0000399604 00000 n 0000399726 00000 n 0000400191 00000 n 0000400313 00000 n 0000400766 00000 n 0000400888 00000 n 0000401377 00000 n 0000401499 00000 n 0000401976 00000 n 0000402098 00000 n 0000402591 00000 n 0000402713 00000 n 0000403154 00000 n 0000403276 00000 n 0000403733 00000 n 0000403855 00000 n 0000404299 00000 n 0000404421 00000 n 0000404889 00000 n 0000405011 00000 n 0000405473 00000 n 0000405595 00000 n 0000406087 00000 n 0000406209 00000 n 0000406722 00000 n 0000406844 00000 n 0000407294 00000 n 0000407416 00000 n 0000407875 00000 n 0000407997 00000 n 0000408546 00000 n 0000408668 00000 n 0000409118 00000 n 0000409240 00000 n 0000409699 00000 n 0000409821 00000 n 0000410271 00000 n 0000410393 00000 n 0000410888 00000 n 0000411010 00000 n 0000411487 00000 n 0000411609 00000 n 0000412197 00000 n 0000412319 00000 n 0000412778 00000 n 0000412900 00000 n 0000413398 00000 n 0000413520 00000 n 0000414033 00000 n 0000414155 00000 n 0000414557 00000 n 0000414679 00000 n 0000415034 00000 n 0000415156 00000 n 0000422266 00000 n 0000426310 00000 n 0000427478 00000 n 0000427321 00000 n 0000424138 00000 n 0000428061 00000 n 0000427955 00000 n 0000428008 00000 n 0000426363 00000 n 0000427690 00000 n 0000427902 00000 n 0000428112 00000 n 0000422054 00000 n 0000425673 00000 n 0000426682 00000 n 0000424401 00000 n 0000424454 00000 n 0000424191 00000 n 0000426576 00000 n 0000422107 00000 n 0000422800 00000 n 0000423498 00000 n 0000426416 00000 n 0000422853 00000 n 0000422746 00000 n 0000422640 00000 n 0000423659 00000 n 0000425939 00000 n 0000425459 00000 n 0000427584 00000 n 0000427849 00000 n 0000424609 00000 n 0000421045 00000 n 0000421098 00000 n 0000426098 00000 n 0000425035 00000 n 0000421420 00000 n 0000425619 00000 n 0000421259 00000 n 0000423066 00000 n 0000421312 00000 n 0000421736 00000 n 0000424765 00000 n 0000422425 00000 n 0000423282 00000 n 0000425300 00000 n 0000420939 00000 n 0000425088 00000 n 0000426045 00000 n 0000427637 00000 n 0000424558 00000 n 0000428164 00000 n 0000423711 00000 n 0000422532 00000 n 0000422478 00000 n 0000422692 00000 n 0000427796 00000 n 0000421526 00000 n 0000423444 00000 n 0000424348 00000 n 0000425780 00000 n 0000424242 00000 n 0000424873 00000 n 0000423765 00000 n 0000426204 00000 n 0000421950 00000 n 0000427743 00000 n 0000424031 00000 n 0000425194 00000 n 0000420992 00000 n 0000423552 00000 n 0000425247 00000 n 0000424660 00000 n 0000427056 00000 n 0000423873 00000 n 0000422003 00000 n 0000426895 00000 n 0000426629 00000 n 0000425141 00000 n 0000426842 00000 n 0000425886 00000 n 0000421843 00000 n 0000423012 00000 n 0000427162 00000 n 0000427531 00000 n 0000426151 00000 n 0000428216 00000 n 0000426469 00000 n 0000424981 00000 n 0000423390 00000 n 0000421206 00000 n 0000422213 00000 n 0000427215 00000 n 0000426735 00000 n 0000422958 00000 n 0000427002 00000 n 0000423228 00000 n 0000425727 00000 n 0000425406 00000 n 0000424927 00000 n 0000421152 00000 n 0000424505 00000 n 0000421683 00000 n 0000424711 00000 n 0000425833 00000 n 0000421473 00000 n 0000423120 00000 n 0000423336 00000 n 0000421789 00000 n 0000422586 00000 n 0000428270 00000 n 0000423979 00000 n 0000427427 00000 n 0000421897 00000 n 0000424295 00000 n 0000425512 00000 n 0000423606 00000 n 0000423819 00000 n 0000425353 00000 n 0000421579 00000 n 0000424085 00000 n 0000424819 00000 n 0000426948 00000 n 0000422906 00000 n 0000422160 00000 n 0000427109 00000 n 0000421366 00000 n 0000421632 00000 n 0000426789 00000 n 0000426257 00000 n 0000422372 00000 n 0000427268 00000 n 0000427374 00000 n 0000423926 00000 n 0000422319 00000 n 0000426522 00000 n 0000425992 00000 n 0000420886 00000 n 0000425566 00000 n 0000423174 00000 n 0000416242 00000 n 0000416776 00000 n 0000417313 00000 n 0000417888 00000 n 0000418447 00000 n 0000419059 00000 n 0000419612 00000 n 0000420151 00000 n 0000420607 00000 n trailer <] >> startxref 428323 %%EOF norm-1.5.8+dfsg2/doc/NormDeveloperGuide.xml0000644000000000000000000124350513056576023015436 0ustar
<inlinemediaobject> <imageobject> <imagedata align="center" fileref="NormLogo.gif" scale="50"/> </imageobject> </inlinemediaobject> NORM Developer's Guide (version 1.5b5) NORM Developer's Guide This document describes an application programming interface (API) for the Nack-Oriented Reliable Multicast (NORM) protocol implementation developed by the Protocol Engineering and Advance Networking (PROTEAN) Research Group of the United States Naval Research Laboratory (NRL). The NORM protocol provides general purpose reliable data transport for applications wishing to use Internet Protocol (IP) Multicast services for group data delivery. NORM can also support unicast (point-to-point) data communication and may be used for such when deemed appropriate. The current NORM protocol specification is given in the Internet Engineering Task Force (IETF) RFC 3940. This document is currently a reference guide to the NORM API of the NRL reference implementation. More tutorial material may be include in a future version of this document or a separate developer's tutorial may be created at a later date. Background This document describes an application programming interface (API) for the Nack-Oriented Reliable Multicast (NORM) protocol implementation developed by the Protocol Engineering and Advance Networking (PROTEAN) Research Group of the United States Naval Research Laboratory (NRL). The NORM protocol provides general purpose reliable data transport for applications wishing to use Internet Protocol (IP) Multicast services for group data delivery. NORM can also support unicast (point-to-point) data communication and may be used for such when deemed appropriate. The current NORM protocol specification is given in the Internet Engineering Task Force (IETF) RFC 5740. The NORM protocol is designed to provide end-to-end reliable transport of bulk data objects or streams over generic IP multicast routing and forwarding services. NORM uses a selective, negative acknowledgement (NACK) mechanism for transport reliability and offers additional protocol mechanisms to conduct reliable multicast sessions with limited "a priori" coordination among senders and receivers. A congestion control scheme is specified to allow the NORM protocol to fairly share available network bandwidth with other transport protocols such as Transmission Control Protocol (TCP). It is capable of operating with both reciprocal multicast routing among senders and receivers and with asymmetric connectivity (possibly a unicast return path) from the senders to receivers. The protocol offers a number of features to allow different types of applications or possibly other higher-level transport protocols to utilize its service in different ways. The protocol leverages the use of FEC-based repair and other proven reliable multicast transport techniques in its design. The NRL NORM library attempts to provide a general useful capability for development of reliable multicast applications for bulk file or other data delivery as well as support of stream-based transport with possible real-time delivery requirements. The API allows access to many NORM protocol parameters and control functions to tailor performance for specific applications. While default parameters, where provided, can be useful to a potential wide range of requirements, the many different possible group communication paradigms dictate different needs for different applications. Even with NORM, the developer should have a thorough understanding of the specific application's group communication needs. Overview The NORM API has been designed to provide simple, straightforward access to and control of NORM protocol state and functions. Functions are provided to create and initialize instances of the NORM API and associated transport sessions (NormSessions). Subsequently, NORM data transmission (NormSender) operation can be activated and the application can queue various types of data (NormObjects) for reliable transport. Additionally or alternatively, NORM reception (NormReceiver) operation can also be enabled on a per-session basis and the protocol implementation alerts the application of receive events. By default, the NORM API will create an operating system thread in which the NORM protocol engine runs. This allows user application code and the underlying NORM code to execute somewhat independently of one another. The NORM protocol thread notifies the application of various protocol events through a thread-safe event dispatching mechanism and API calls are provided to allow the application to control NORM operation. (Note: API mechanisms for lower-level, non-threaded control and execution of the NORM protocol engine code may also be provided in the future.) The NORM API operation can be roughly summarized with the following categories of functions: API Initialization Session Creation and Control Data Transport API Event Notification Note the order of these categories roughly reflects the order of function calls required to use NORM in an application. The first step is to create and initialize, as needed, at least one instance of the NORM API. Then one or more NORM transport sessions (where a "session" corresponds to data exchanges on a given multicast group (or unicast address) and host port number) may be created and controlled. Applications may participate as senders and/or receivers within a NORM session. NORM senders transmit data to the session destination address (usually an IP multicast group) while receivers are notified of incoming data. The NORM API provides and event notification scheme to notify the application of significant sender and receiver events. There are also a number support functions provided for the application to control and monitor its participation within a NORM transport session. API Initialization The NORM API requires that an application explicitly create at least one instance of the NORM protocol engine that is subsequently used as a conduit for further NORM API calls. By default, the NORM protocol engine runs in its own operating system thread and interacts with the application in a thread-safe manner through the API calls and event dispatching mechanism. In general, only a single thread should access the NormGetNextEvent() API call for a given NormInstance. This function serves as the conduit for delivering NORM protocol engine events to the application. A NORM application can be designed to be single-threaded, even with multiple active NormSessions, but also multiple API instances can be created (see NormCreateInstance()) as needed for applications with specific requirements for accessing and controlling participation in multiple NormSessions from separate operating system multiple threads. Or, alternatively, a single NormInstance could be used, with a "master thread" serving as an intermediary between the NormGetNextEvent() function, demultiplexing and dispatching events as appropriate to other "child threads" that are created to handle "per-NormSession" input/output. The advantage of this alternative approach is that the end result would be one NORM protocol engine thread plus one "master thread" plus one "child thread" per NormSession instead of two threads (protocol engine plus application thread) per NormSession if such multi-threaded operation is needed by the application. Session Creation and Control Once an API instance has been successfully created, the application may then create NORM transport session instances as needed. The application can participate in each session as a sender and/or receiver of data. If an application is participating as a sender, it may enqueue data transport objects for transmission. The control of transmission is largely left to the senders and API calls are provided to control transmission rate, FEC parameters, etc. Applications participating as receivers will be notified via the NORM API's event dispatching mechanism of pending and completed reliable reception of data along with other significant events. Additionally, API controls for some optional NORM protocol mechanisms, such as positive acknowledgment collection, are also provided. Note when multiple senders are involved, receivers allocate system resources (buffer space) for each active sender. With a very large number of concurrently active senders, this may translate to significant memory allocation on receiver nodes. Currently, the API allows the application to control how much buffer space is allocated for each active sender (NOTE: In the future, API functions may be provided limit the number of active senders monitored and/or provide the application with finer control over receive buffer allocation, perhaps on a per sender basis). Data Transport The NORM protocol supports transport of three basic types of data content. These include the types NORM_OBJECT_FILE and NORM_OBJECT_DATA which represent predetermined, fixed-size application data content. The only differentiation with respect to these two types is the implicit "hint" to the receiver to use non-volatile (i.e. file system) storage or memory. This "hint" lets the receiver allocate appropriate storage space with no other information on the incoming data. The NORM implementation reads/writes data for the NORM_OBJECT_FILE type directly from/to file storage, while application memory space is accessed for the NORM_OBJECT_DATA type. The third data content type, NORM_OBJECT_STREAM, represents unbounded, possibly persistent, streams of data content. Using this transport paradigm, traditional, byte-oriented streaming transport service (e.g. similar to that provided by a TCP socket) can be provided. Additionally, NORM has provisions for application-defined message-oriented transport where receivers can recover message boundaries without any "handshake" with the sender. Stream content is buffered by the NORM implementation for transmission/retransmission and as it is received. Data Transmission The behavior of data transport operation is largely placed in the control of the NORM sender(s). NORM senders controls their data transmission rate, forward error correction (FEC) encoding settings, and parameters controlling feedback from the receiver group. Multiple senders may operate in a session, each with independent transmission parameters. NORM receivers learn needed parameter values from fields in NORM message headers. NORM transport "objects" (file, data, or stream) are queued for transmission by NORM senders. NORM senders may also cancel transmission of objects at any time. The NORM sender controls the transmission rate either manually (fixed transmission rate) or automatically when NORM congestion control operation is enabled. The NORM congestion control mechanism is designed to be "friendly" to other data flows on the network, fairly sharing available bandwidth.NormSetAutoParity()) to achieve reliable transfer) receive object transmission before any extensive repair process that may be required to satisfy other receivers with poor network connectivity. The repair boundary can also be set for individual remote senders using the NormNodeSetRepairBoundary() function.NORM_OBJECT_FILE objects. This function must be called before any file objects may be received and thus should be called before any calls to NormStartReceiver() are made. However, note that the cache directory may be changed even during active NORM reception. In this case, the new specified directory path will be used for subsequently-received files. Any files received before a directory path change will remain in the previous cache location. Note that the NormFileRename() function may be used to rename, and thus potentially move, received files after reception has begun. By default, the NORM sender transmits application-enqueued data content, providing repair transmissions (usually in the form of FEC messages) only when requested by NACKs from the receivers. However, the application may also configure NORM to proactively send some amount of FEC content along with the original data content to create a "robust" transmission that, in some cases, may be reliably received without any NACKing activity. This can allow for some degree of reliable protocol operation even without receiver feedback available. NORM senders may also requeue (within the limits of "transmit cache" settings) objects for repeat transmission, and receivers may combine together multiple transmissions to reliably receive content. Additionally, hybrid proactive/reactive FEC repair operation is possible with the receiver NACK process as a "backup" for when network packet loss exceeds the repair capability of the proactive FEC settings. The NRL NORM implementation also supports optional collection of positive acknowledgment from a subset of the receiver group at application-determined positions during data transmission. The NORM API allows the application to specify the receiver subset ("acking node list") and set "watermark" points for which positive acknowledgement is collected. This process can provide the application with explicit flow control for an application-determined critical set of receivers in the group. For a NORM application to perform data transmission, it must first create a session using NormCreateSession() and make a call to NormStartSender() before sending actual user data. The functions NormFileEnqueue(), NormDataEnqueue(), and NormStreamWrite() are available for the application to pass data to the NORM protocol engine for transmission. Note that to use NormStreamWrite(), a "sender stream" must first be created using NormStreamOpen(). In the case of NormFileEnqueue() and NormDataEnqueue(), the NORM protocol engine directly accesses the application file or memory space to refer to the transmitted content and does not make its own copy of this data. The calls to enqueue transport objects or write to a stream may be called at any time, but the NORM_TX_QUEUE_EMPTY and NORM_TX_QUEUE_VACANCY notification events (see NormGetNextEvent()) provide useful cues for when these functions may be successfully called. Typically, an application might catch both NORM_TX_QUEUE_EMPTY and NORM_TX_QUEUE_VACANCY event types as cues for enqueuing additional transport objects or writing to a stream. However, an application may choose to cue off of NORM_TX_QUEUE_EMPTY only if it wishes to provide the "freshest" data to NORM for transmission. The advantage of additionally using NORM_TX_QUEUE_VACANCY is that if the application uses this cue to fill up NORM transport object or stream buffers, it can keep the NORM stream busy sending data and realize the highest possible transmission rate when attempting very high speed communication (Otherwise, the NORM protocol engine may experience some "dead air time" waiting for the application thread to respond to a NORM_TX_QUEUE_EMPTY event). Note the sender application can control buffer depths as needed with the NormSetTxCacheBounds() and NormStreamOpen() calls. Additionally, it is possible for applications to configure the transmit object "cache" (see NormSetTxCacheBounds()) and use the NormRequeueObject() call (for objects that have not yet received a NORM_TX_OBJECT_PURGED notification) to effect a sort of "data carousel" operation with repeated transmission of the cached objects. The NORM_TX_OBJECT_SENT notification can be used a cue to properly control the "requeue" cycle(s). The NORM implementation provides a form of timer-based flow control that limits how quickly sender applications may enqueue new objects or stream data for transmission. The NormSetFlowControl() call is provided to control this behavior, including the option to disable it. This timer-based mechanism is a type of "soft" flow control by allowing receivers "sufficient" time to request repair of pending data the sender has enqueued. A more explicit form of flow control using the optional "watermark flushing" mechanism is described below. Another cue that can be leveraged by the sender application to determine when it is appropriate to enqueue (or write) additional data for transmission is the NORM_TX_WATERMARK_COMPLETED event. This event is posted when the flushing or explicit positive acknowledgment collection process has completed for a "watermark" point in transmission that was set by the sender (see NormSetWatermark() and NormAddAckingNode()). A list of NormNodeId values can be supplied from which explicit acknowledgement is expected and/or the NormNodeId NORM_NODE_NONE can be set (using NormAddAckingNode()) for completion of a NACK-based version of the watermark flushing procedure. This flushing process can be used as a flow control mechanism for NORM applications. Note this is distinct from NORM's congestion control mechanism that, while it provides network-friendly transmission rate control, does guarantee flow control to receiving nodes.NORM_NODE_NONE can be set (using NormAddAckingNode()) for completion of a NACK-based version of the watermark flushing procedure. This flushing process can be used as a flow control mechanism for NORM applications. Note this is distinct from NORM's congestion control mechanism that, while it provides network-friendly transmission rate control, does guarantee flow control to receiving nodes. Data Reception NORM receiver applications learn of active senders and their corresponding pending and completed data transfers, etc via the API event dispatching mechanism. By default, NORM receivers use NACK messages to request repair of transmitted content from the originating sender as needed to achieve reliable transfer. Some API functions are available to provide some additional control over the NACKing behavior, such as initially NACKing for NORM_INFO content only or even to the extent of disabling receiver feedback (silent receiver or emission-controlled (EMCON) operation) entirely. Otherwise, the parameters and operation of reliable data transmission are left to sender applications and receivers learn of sender parameters in NORM protocol message headers and are instructed by NORM_CMD messages from the sender(s). With respect to the NORM API, the receiver application is informed of new senders and receive data objects via the the NORM_REMOTE_SENDER_NEW and NORM_RX_OBJECT_NEW notifications, respectfully. Additionally, object reception progress is indicated with the NORM_RX_OBJECT_UPDATED notification and this also serves as an indicator for the NORM_OBJECT_STREAM type that the receive application should make calls to NormStreamRead() to read newly received stream content. NORM sender status is also conveyed via the NORM_REMOTE_SENDER_ACTIVE and NORM_REMOTE_SENDER_INACTIVE notifications. For example, the receiver application may use the NORM_REMOTE_SENDER_INACTIVE as a cue to make calls to NormNodeFreeBuffers() and/or NormNodeDelete() to free memory resources allocated for buffering received content for the given sender. The amount of memory allocated per sender is set in the NormStartReceiver() call. API Event Notification An asynchronous event dispatching mechanism is provided to notify the application of significant NORM protocol events. The centerpiece of this is the NormGetNextEvent() function that can be used to retrieve the next NORM protocol engine event in the form of a NormEvent structure. This function will typically block until a NormEvent occurs. However, non-blocking operation may be achieved by using the NormGetDescriptor() call to get a NormDescriptor (file descriptor) value (Unix int or Win32 HANDLE) suitable for use in a asynchronous I/O monitoring functions such as the Unix select() or Win32 MsgWaitForMultipleObjects() system calls. The a NormDescriptor will be signaled when a NormEvent is available. For Win32 platforms, dispatching of a user-defined Windows message for NORM event notification is also planned for a future update to the NORM API. Build Notes To build applications that use the NORM library, a path to the "normApi.h" header file must be provided and the linker step needs to reference the NORM library file ("libnorm.a" for Unix platforms and "Norm.lib" for Win32 platforms). NORM also depends upon the NRL Protean Protocol Prototyping toolkit "Protokit" library (a.k.a "Protolib") (static library files "libProtokit.a" for Unix and "Protokit.lib" for Win32). Shared or dynamically-linked versions of these libraries may also be built from the NORM source code or provided. Depending upon the platform, some additional library dependencies may be required to support the needs of NORM and/or Protokit. These are described below. The "makefiles" directory contains Unix Makefiles for various platforms the "win32" and "wince" sub-directories there contain Microsoft Visual C++ (VC++) and Embedded VC++ project files for building the NORM implementation. Additionally, a "waf" (Python-based build tool) build option is supported that can be used to build and install the NORM library code on the supported platforms. Finally, Python and Java bindings to the NORM API are included and "src/python" and "src/java" directories contain the code for these and the "makefiles/java" directory contains Makefiles to build the NORM Java JNI bindings. Note the "waf" tool can also be used to build the Java and Python bindings. Unix Platforms NORM has been built and tested on Linux (various architectures), MacOS (BSD), Solaris, and IRIX (SGI) platforms. The code should be readily portable to other Unix platforms. To support IPv6 operation, the NORM and the Protokit library must be compiled with the "HAVE_IPV6" macro defined. This is default in the NORM and Protokit Makefiles for platforms that support IPv6. It is important that NORM and Protokit be built with this macro defined the same. With NORM, it is recommended that "large file support" options be enabled when possible. The NORM API uses threading so that the NORM protocol engine may run independent of the application. Thus the "POSIX Threads" library must be included ("-pthread") in the linking step. MacOS/BSD also requires the addition of the "-lresolv" (resolver) library and Solaris requires the dynamic loader, network/socket, and resolver libraries ("-lnsl -lsocket -lresolv") to achieve successful compilation. The Makefiles in the NORM source code distribution are a reference for these requirements. Note that MacOS 9 and earlier are not supported. Additionally, it is critical that the _FILE_OFFSET_BITS macro be consistently defined for the NORM library build and the application build using the library. The distributed NORM Makefiles have -D_FILE_OFFSET_BITS=64 set in the compilation to enable "large file support". Applications built using NORM should have the same compilation option set to operate correctly (The definition of the NormSize type in "normApi.h" depends upon this compilation flag). Win32/WiNCE Platforms NORM has been built using Microsoft's Visual C++ (6.0 and .NET) and Embedded VC++ 4.2 environments. In addition to proper macro definitions (e.g., HAVE_IPV6, etc) that are included in the respective "Protokit" and "NORM" project files, it is important that common code generation settings be used when building the NORM application. The NORM and Protokit projects are built with the "Multi-threading DLL" library usage set. The NORM API requires multi-threading support. This is a critical setting and numerous compiler and linker errors will result if this is not properly set for your application project. NORM and Protokit also depend on the Winsock 2.0 ("ws2_32.lib" (or "ws2.lib" (WinCE)) and the IP Helper API ("iphlpapi.lib") libraries and these must be included in the project "Link" attributes. An additional note is that a bug in VC++ 6.0 and earlier compilers (includes embedded VC++ 4.x compilers) prevent compilation of Protokit-based code with debugging capabilities enabled. However, this has been resolved in VC++ .NET and is hoped to be resolved in the future for the WinCE build tools. Operation on Windows NT4 (and perhaps other older Windows operating systems) requires that the compile time macro WINVER=0x0400 defined. This is because the version of the IP Helper API library (iphlpapi.lib) used by Protolib (and hence NORM) for this system doesn't support some of the functions defined for this library. This may be related to IPv6 support issues so it may be possible that the Protolib build could be tweaked to provide a single binary executable suitable for IPv4 operation only across a large range of Windows platforms. API Reference This section provides a reference to the NORM API variable types, constants and functions. API Variable Types and Constants The NORM API defines and enumerates a number of supporting variable types and values which are used in different function calls. The variable types are described here. NormInstanceHandle The NormInstanceHandle type is returned when a NORM API instance is created (see NormCreateInstance()). This handle can be subsequently used for API calls which require reference to a specific NORM API instance. By default, each NORM API instance instantiated creates an operating system thread for protocol operation. Note that multiple NORM transport sessions may be created for a single API instance. In general, it is expected that applications will create a single NORM API instance, but some multi-threaded application designs may prefer multiple corresponding NORM API instances. The value NORM_INSTANCE_INVALID corresponds to an invalid API instance. NormSessionHandle The NormSessionHandle type is used to reference NORM transport sessions which have been created using the NormCreateSession() API call. Multiple NormSessionHandle values may be associated with a given NormInstanceHandle. The special value NORM_SESSION_INVALID is used to refer to invalid session references. NormSessionId The NormSessionId type is used by applications to uniquely identify their instance of participation as a sender within a NormSession. This type is a parameter to the NormStartSender() function. Robust applications can use different NormSessionId values when initiating sender operation so that receivers can discriminate when a sender has terminated and restarted (whether intentional or due to system failure). For example, an application could cache its prior NormSessionId value in non-volatile storage which could then be recovered and incremented (for example) upon system restart to produce a new value. The NormSessionId value is used for the value of the instance_id field in NORM protocol sender messages (see the NORM protocol specification) and receivers use this field to detect sender restart within a NormSession. NormNodeHandle The NormNodeHandle type is used to reference state kept by the NORM implementation with respect to other participants within a NormSession. Most typically, the NormNodeHandle is used by receiver applications to dereference information about remote senders of data as needed. The special value NORM_NODE_INVALID corresponds to an invalid reference. NormNodeId The NormNodeId type corresponds to a 32-bit numeric value which should uniquely identify a participant (node) in a given NormSession. The NormNodeGetId() function can be used to retrieve this value given a valid NormNodeHandle. The special value NORM_NODE_NONE corresponds to an invalid (or null) node while the value NORM_NODE_ANY serves as a wild card value for some functions. NormObjectHandle The NormObjectHandle type is used to reference state kept for data transport objects being actively transmitted or received. The state kept for NORM transport objects is temporary, but the NORM API provides a function to persistently retain state associated with a sender or receiver NormObjectHandle (see NormObjectRetain()) if needed. For sender objects, unless explicitly retained, the NormObjectHandle can be considered valid until the referenced object is explicitly canceled (see NormObjectCancel()) or purged from the sender transmission queue (see the event NORM_TX_OBJECT_PURGED). For receiver objects, these handles should be treated as valid only until a subsequent call to NormGetNextEvent() unless, again, specifically retained. The special value NORM_OBJECT_INVALID corresponds to an invalid transport object reference. NormObjectType The NormObjectType type is an enumeration of possible NORM data transport object types. As previously mentioned, valid types include: NORM_OBJECT_FILE NORM_OBJECT_DATA, and NORM_OBJECT_STREAM Given a NormObjectHandle, the application may determine an object's type using the NormObjectGetType() function call. A special NormObjectType value, NORM_OBJECT_NONE, indicates an invalid object type. NormSize The NormSize is the type used for NormObject size information. For example, the NormObjectGetSize() function returns a value of type NormSize. The range of NormSize values depends upon the operating system and NORM library compilation settings. With "large file support" enabled, as is the case with distributed NORM library "Makefiles", the NormSize type is a 64-bit integer. However, some platforms may support only 32-bit object sizes. NormObjectTransportId The NormObjectTransportId type is a 16-bit numerical value assigned to NormObjects by senders during active transport. These values are temporarily unique with respect to a given sender within a NormSession and may be "recycled" for use for future transport objects. NORM sender nodes assign these values in a monotonically increasing fashion during the course of a session as part of protocol operation. Typically, the application should not need access to these values, but an API call such as NormObjectGetTransportId() (TBD) may be provided to retrieve these values if needed. (Note this type may be deprecated; i.e., it may not be needed at since the NormRequeueObject() function is implemented using handles only, but _some_ applications requiring persistence even after a system reboot may need the ability to recall previous transport ids?) NormEventType The NormEventType is an enumeration of NORM API events. "Events" are used by the NORM API to signal the application of significant NORM protocol operation events (e.g., receipt of a new receive object, etc). A description of possible NormEventType values and their interpretation is given below. The function call NormGetNextEvent() is used to retrieve events from the NORM protocol engine. NormEvent The NormEvent type is a structure used to describe significant NORM protocol events. This structure is defined as follows: typedef struct { NormEventType type; NormSessionHandle session; NormNodeHandle node; NormObjectHandle object; } NormEvent; The type field indicates the NormEventType and determines how the other fields should be interpreted. Note that not all NormEventType fields are relevant to all events. The session, node, and object fields indicate the applicable NormSessionHandle, NormNodeHandle, and NormObjectHandle, respectively, to which the event applies. NORM protocol events are made available to the application via the NormGetNextEvent() function call. NormDescriptor The NormDescriptor type can provide a reference to a corresponding file descriptor (Unix int or Win32 HANDLE) for the NormInstance. For a given NormInstanceHandle, the NormGetDescriptor() function can be used to retrieve a NormDescriptor value that may, in turn, used in appropriate system calls (e.g. select() or MsgWaitForMultipleObjects()) to asynchronously monitor the NORM protocol engine for notification events (see NormEvent description). NormFlushMode The NormFlushMode type consists of the following enumeration: enum NormFlushMode { NORM_FLUSH_NONE, NORM_FLUSH_PASSIVE, NORM_FLUSH_ACTIVE }; The use and interpretation of these values is given in the descriptions of NormStreamFlush() and NormStreamSetAutoFlush() functions. NormProbingMode The NormProbingMode type consists of the following enumeration: enum NormProbingMode { NORM_PROBE_NONE, NORM_PROBE_PASSIVE, NORM_PROBE_ACTIVE }; The use and interpretation of these values is given in the description of NormSetGrttProbingMode() function. NormSyncPolicy The NormSyncPolicy type consists of the following enumeration: enum NormSyncPolicy { NORM_SYNC_CURRENT, NORM_SYNC_ALL }; The use and interpretation of these values is given in the descriptions of the NormSetDefaultSyncPolicy() function. NormNackingMode The NormNackingMode type consists of the following enumeration: enum NormNackingMode { NORM_NACK_NONE, NORM_NACK_INFO_ONLY, NORM_NACK_NORMAL }; The use and interpretation of these values is given in the descriptions of the NormSetDefaultNackingMode(), NormNodeSetNackingMode() and NormObjectSetNackingMode() functions. NormRepairBoundary The NormRepairBoundary types consists of the following enumeration: enum NormRepairBoundary { NORM_BOUNDARY_BLOCK, NORM_BOUNDARY_OBJECT }; The interpretation of these values is given in the descriptions of the NormSetDefaultRepairBoundary() and NormNodeSetRepairBoundary() functions. NormAckingStatus The NormAckingStatus consist of the following enumeration: enum NormAckingStatus { NORM_ACK_INVALID, NORM_ACK_FAILURE, NORM_ACK_PENDING, NORM_ACK_SUCCESS }; The interpretation of these values is given in the descriptions of the NormGetAckingStatus() function. API Initialization and Operation The first step in using the NORM API is to create an "instance" of the NORM protocol engine. Note that multiple instances may be created by the application if necessary, but generally only a single instance is required since multiple NormSessions may be managed under a single NORM API instance. NormCreateInstance() Synopsis #include <normApi.h> NormInstanceHandle NormCreateInstance(bool priorityBoost = false); Description This function creates an instance of a NORM protocol engine and is the necessary first step before any other API functions may be used. With the instantiation of the NORM protocol engine, an operating system thread is created for protocol execution. The returned NormInstanceHandle value may be used in subsequent API calls as needed, such NormCreateSession(), etc. The optional priorityBoost parameter, when set to a value of true, specifies that the NORM protocol engine thread be run with higher priority scheduling. On Win32 platforms, this corresponds to THREAD_PRIORITY_TIME_CRITICAL and on Unix systems with the sched_setscheduler() API, an attempt to get the maximum allowed SCHED_FIFO priority is made. The use of this option should be carefully evaluated since, depending upon the application's scheduling priority and NORM API usage, this may have adverse effects instead of a guaranteed performance increase! Return Values A value of NORM_INSTANCE_INVALID is returned upon failure. The function will only fail if system resources are unavailable to allocate the instance and/or create the corresponding thread. NormDestroyInstance() Synopsis #include <normApi.h> void NormDestroyInstance(NormInstanceHandle instanceHandle); Description The NormDestroyInstance() function immediately shuts down and destroys the NORM protocol engine instance referred to by the instanceHandle parameter. The application should make no subsequent references to the indicated NormInstanceHandle or any other API handles or objects associated with it. However, the application is still responsible for releasing any object handles it has retained (see NormObjectRetain() and NormObjectRelease()). Return Values The function has no return value. NormStopInstance() Synopsis #include <normApi.h> void NormStopInstance(NormInstanceHandle instanceHandle); Description This function immediately stops the NORM protocol engine thread corresponding to the given instanceHandle parameter. It also posts a "dummy" notification event so that if another thread is blocked on a call to NormGetNextEvent(), that thread will be released. Hence, for some multi-threaded uses of the NORM API, this function may be useful as a preliminary step to safely coordinate thread shutdown before a call is made to NormDestroyInstance(). After NormStopInstance() is called and any pending events posted prior to its call have been retrieved, NormGetNextEvent() will return a value of false. When this function is invoked, state for any NormSessions associated with the given instance is "frozen". The complementary function, NormRestartInstance() can be subsequently used to "unfreeze" and resume NORM protocol operation (a new thread is created and started). Return Values The function has no return value. NormRestartInstance() Synopsis #include <normApi.h> bool NormRestartInstance(NormInstanceHandle instanceHandle); Description This function creates and starts an operating system thread to resume NORM protocol engine operation for the given instanceHandle that was previously stopped by a call to NormStopInstance(). It is not expected that this function will be used often, but there may be special application cases where "freezing" and later resuming NORM protocol operation may be useful. Return Values The function returns true when the NORM protocol engine thread is successfully restarted, and false otherwise. NormSetCacheDirectory() Synopsis #include <normApi.h> bool NormSetCacheDirectory(NormInstanceHandle instanceHandle, const char* cachePath); Description This function sets the directory path used by receivers to cache newly-received NORM_OBJECT_FILE content. The instanceHandle parameter specifies the NORM protocol engine instance (all NormSessions associated with that instanceHandle share the same cache path) and the cachePath is a string specifying a valid (and writable) directory path. Return Values The function returns true on success and false on failure. The failure conditions are that the indicated directory does not exist or the process does not have permissions to write. NormGetNextEvent() Synopsis #include <normApi.h> bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent); Description This function retrieves the next available NORM protocol event from the protocol engine. The instanceHandle parameter specifies the applicable NORM protocol engine, and the theEvent parameter must be a valid pointer to a NormEvent structure capable of receiving the NORM event information. For expected reliable protocol operation, the application should make every attempt to retrieve and process NORM notification events in a timely manner. Note that this is currently the only blocking call in the NORM API. But non-blocking operation may be achieved by using the NormGetDescriptor() function to obtain a descriptor (int for Unix or HANDLE for WIN32) suitable for asynchronous input/output (I/O) notification using such system calls the Unix select() or Win32 WaitForMultipleObjects() calls. The descriptor is signaled when a notification event is pending and a call to NormGetNextEvent() will not block.NormGetNextEvent Return Values The function returns true when a NormEvent is successfully retrieved, and false otherwise. Note that a return value of false does not indicate an error or signify end of NORM operation. NORM Notification Event Types The following table enumerates the possible NormEvent values and describes how these notifications should be interpreted as they are retrieved by the application via the NormGetNextEvent() function call. Sender Notifications: NORM_TX_QUEUE_VACANCY This event indicates that there is room for additional transmit objects to be enqueued, or, if the handle of NORM_OBJECT_STREAM is given in the corresponding event "object" field, the application may successfully write to the indicated stream object. Note this event is not dispatched until a call to NormFileEnqueue(), NormDataEnqueue(), or NormStreamWrite() fails because of a filled transmit cache or stream buffer. NORM_TX_QUEUE_EMPTY This event indicates the NORM protocol engine has no new data pending transmission and the application may enqueue additional objects for transmission. If the handle of a sender NORM_OBJECT_STREAM is given in the corresponding event "object" field, this indicates the stream transmit buffer has been emptied and the sender application may write to the stream (Use of NORM_TX_QUEUE_VACANCY may be preferred for this purpose since it allows the application to keep the NORM protocol engine busier sending data, resulting in higher throughput when attempting very high transfer rates). NORM_TX_FLUSH_COMPLETED This event indicates that the flushing process the NORM sender observes when it no longer has data ready for transmission has completed. The completion of the flushing process is a reasonable indicator (with a sufficient NORM "robust factor" value) that the receiver set no longer has any pending repair requests. Note the use of NORM's optional positive acknowledgement feature is more deterministic in this regards, but this notification is useful when there are non-acking (NACK-only) receivers. The default NORM robust factor of 20 (20 flush messages are sent at end-of-transmission) provides a high assurance of reliable transmission, even with packet loss rates of 50%. NORM_TX_WATERMARK_COMPLETED This event indicates that the flushing process initiated by a prior application call to NormSetWatermark() has completed The posting of this event indicates the appropriate time for the application to make a call NormGetAckingStatus() to determine the results of the watermark flushing process. NORM_TX_OBJECT_SENT This event indicates that the transport object referenced by the event's "object" field has completed at least one pass of total transmission. Note that this does not guarantee that reliable transmission has yet completed; only that the entire object content has been transmitted. Depending upon network behavior, several rounds of NACKing and repair transmissions may be required to complete reliable transfer. NORM_TX_OBJECT_PURGED This event indicates that the NORM protocol engine will no longer refer to the transport object identified by the event's "object' field. Typically, this will occur when the application has enqueued more objects than space available within the set sender transmit cache bounds (see NormSetTxCacheBounds()). Posting of this notification means the application is free to free any resources (memory, files, etc) associated with the indicated "object". After this event, the given "object" handle (NormObjectHandle) is no longer valid unless it is specifically retained by the application.NormObjectHandle NORM_TX_CMD_SENT This event indicates that an application-defined command previously enqueued with a call to NormSendCommand() has been transmitted, including any repetition. NORM_TX_RATE_CHANGED This event indicates that NORM Congestion Control operation has adjusted the transmission rate. The NormGetTxRate() call may be used to retrieve the new corresponding transmission rate. Note that if NormSetCongestionControl() was called with its adjustRate parameter set to false, then no actual rate change has occurred and the rate value returned by NormGetTxRate() reflects a "suggested" rate and not the actual transmission rate. NORM_LOCAL_SENDER_CLOSED This event is posted when the NORM protocol engine completes the "graceful shutdown" of its participation as a sender in the indicated "session" (see NormStopSender()). NORM_CC_ACTIVE This event indicates that congestion control feedback from receivers has begun to be received (This also implies that receivers in the group are actually present and can be used as a cue to begin data transmission.). Note that congestion control must be enabled (see NormSetCongestionControl()) for this event to be posted. Congestion control feedback can be assumed to be received until a NORM_CC_INACTIVE event is posted. NORM_CC_INACTIVE This event indicates there has been no recent congestion control feedback received from the receiver set and that the local NORM sender has reached its minimum transmit rate. Applications may wish to refrain from new data transmission until a NORM_CC_ACTIVE event is posted. This notification is only posted when congestion control operation is enabled (see NormSetCongestionControl()) and a previous NORM_CC_ACTIVE event has occurred. Receiver Notifications: NORM_REMOTE_SENDER_NEW This event is posted when a receiver first receives messages from a specific remote NORM sender. This marks the beginning of the interval during which the application may reference the provided "node" handle (NormNodeHandle). NORM_REMOTE_SENDER_ACTIVE This event is posted when a previously inactive (or new) remote sender is detected operating as an active sender within the session. NORM_REMOTE_SENDER_INACTIVE This event is posted after a significant period of inactivity (no sender messages received) of a specific NORM sender within the session. The NORM protocol engine frees buffering resources allocated for this sender when it becomes inactive. NORM_REMOTE_SENDER_PURGED This event is posted when the NORM protocol engine frees resources for, and thus invalidates the indicated "node" handle. NORM_RX_OBJECT_NEW This event is posted when reception of a new transport object begins and marks the beginning of the interval during which the specified "object" (NormObjectHandle) is valid. NORM_RX_OBJECT_INFO This notification is posted when the NORM_INFO content for the indicated "object" is received. NORM_RX_OBJECT_UPDATED This event indicates that the identified receive "object" has newly received data content. NORM_RX_OBJECT_COMPLETED This event is posted when a receive object is completely received, including available NORM_INFO content. Unless the application specifically retains the "object" handle, the indicated NormObjectHandle becomes invalid and must no longer be referenced. NORM_RX_OBJECT_ABORTED This notification is posted when a pending receive object's transmission is aborted by the remote sender. Unless the application specifically retains the "object" handle, the indicated NormObjectHandle becomes invalid and must no longer be referenced. NORM_RX_CMD_NEW This event indicates that an application-defined command has been received from a remote sender. The NormEvent node element indicates the NormNodeHandle value associated with the given sender. The NormNodeGetCommand() call can be used to retrieve the received command content. Miscellaneous Notifications: NORM_GRTT_UPDATED This notification indicates that either the local sender estimate of GRTT has changed, or that a remote sender's estimate of GRTT has changed. The "sender" member of the NormEvent is set to NORM_NODE_INVALID if the local sender's GRTT estimate has changed or to the NormNodeHandle of the remote sender that has updated its estimate of GRTT. NORM_EVENT_INVALID This NormEventType indicates an invalid or "null" notification which should be ignored. Return Values This function generally blocks the thread of application execution until a NormEvent is available and returns true when a NormEvent is available. However, there are some exceptional cases when the function may immediately return even when no event is pending. In these cases, the return value is false indicating the NormEvent should be ignored. Win32 Note: A future version of this API will provide an option to have a user-defined Window message posted when a NORM API event is pending. (Also some event filtering calls may be provided (e.g. avoid the potentially numerous NORM_RX_OBJECT_UPDATED events if not needed by the application)). NormGetDescriptor() Synopsis #include <normApi.h> NormDescriptor NormGetDescriptor(NormInstanceHandle instance); Description This function is used to retrieve a NormDescriptor (Unix int file descriptor or Win32 HANDLE) suitable for asynchronous I/O notification to avoid blocking calls to NormGetNextEvent(). A NormDescriptor is available for each protocol engine instance created using NormCreateInstance(). The descriptor returned is suitable for use as an input (or "read") descriptor which is signaled when a NORM protocol event is ready for retrieval via NormGetNextEvent(). Hence, a call to NormGetNextEvent() will not block when the descriptor has been signaled. The Unix select() or Win32 WaitForMultipleObjects() system calls can be used to detect when the NormDescriptor is signaled. Note that for Unix select() call usage, the NORM descriptor should be treated as a "read" descriptor. Return Values A NormDescriptor value is returned which is valid until a call to NormDestroyInstance() is made. Upon error, a value of NORM_DESCRIPTOR_INVALID is returned. Session Creation and Control Functions Whether participating in a NORM protocol session as a sender, receiver, or both, there are some common API calls used to instantiate a NormSession and set some common session parameters. Functions are provided to control network socket and multicast parameters. Additionally, a "user data" value may be associated with a NormSessionHandle for programming convenience when dealing with multiple sessions. NormCreateSession() Synopsis #include <normApi.h NormSessionHandle NormCreateSession(NormInstanceHandle instance, const char* address, unsigned short port, NormNodeId localId); Description This function creates a NORM protocol session (NormSession) using the address (multicast or unicast) and port parameters provided. While session state is allocated and initialized, active session participation does not begin until a call is made to NormStartSender() and/or NormStartReceiver() to join the specified multicast group (if applicable) and start protocol operation. The following parameters are required in this function call: instance This must be a valid NormInstanceHandle previously obtained with a call to NormCreateInstance(). address This points to a string containing an IP address (e.g. dotted decimal IPv4 address (or IPv6 address) or name resolvable to a valid IP address. The specified address (along with the port number) determines the destination of NORM messages sent. For multicast sessions, NORM senders and receivers must use a common multicast address and port number. For unicast sessions, the sender and receiver must use a common port number, but specify the other node's IP address as the session address (Although note that receiver-only unicast nodes who are providing unicast feedback to senders will not generate any messages to the session IP address and the address parameter value is thus inconsequential for this special case). port This must be a valid, unused port number corresponding to the desired NORM session address. See the address parameter description for more details. localId The localId parameter specifies the NormNodeId that should be used to identify the application's presence in the NormSession. All participant's in a NormSession should use unique localId values. The application may specify a value of NORM_NODE_ANY or NORM_NODE_ANY for the localId parameter. In this case, the NORM implementation will attempt to pick an identifier based on the host computer's "default" IP address (based on the computer's default host name). Note there is a chance that this approach may not provide unique node identifiers in some situations and the NORM protocol does not currently provide a mechanism to detect or resolve NormNodeId collisions. Thus, the application should explicitly specify the localId unless there is a high degree of confidence that the default IP address will provide a unique identifier. Return Values The returned NormSessionHandle value is valid until a call to NormDestroySession() is made. A value of NORM_SESSION_INVALID is returned upon error. NormDestroySession() Synopsis #include <normApi.h> void NormDestroySession(NormSessionHandle sessionHandle); Description This function immediately terminates the application's participation in the NormSession identified by the sessionHandle parameter and frees any resources used by that session. An exception to this is that the application is responsible for releasing any explicitly retained NormObjectHandle values (See NormObjectRetain() and NormObjectRelease()). Return Values This function has no returned values. NormSetUserData() Synopsis #include <normApi.h> void NormSetUserData(NormSessionHandle sessionHandle, const void* userData); Description This function allows the application to attach a value to the previously-created NormSession instance specified by the sessionHandle parameter. This value is not used or interpreted by NORM, but is available to the application for use at the programmer's discretion. The set userData value can be later retrieved using the NormGetUserData() function call. Return Values This function has no returned values. NormGetUserData() Synopsis #include <normApi.h> const void* NormGetUserData(NormSessionHandle sessionHandle); Description This function retrieves the "user data" value set for the specified sessionHandle with a prior call to NormSetUserData(). Return Values This function returns the user data value set for the specified session. If no user data value has been previously set, a NULL (i.e., (const void*)0) value is returned. NormGetLocalNodeId() Synopsis #include <normApi.h> NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle); Description This function retrieves the NormNodeId value used for the application's participation in the NormSession identified by the sessionHandle parameter. The value may have been explicitly set during the NormCreateSession() call or may have been automatically derived using the host computer's "default" IP network address. Return Valuess The returned value indicates the NormNode identifier used by the NORM protocol engine for the local application's participation in the specified NormSession. NormSetTxPort() Synopsis #include <normApi.h> bool NormSetTxPort(NormSessionHandle sessionHandle, unsigned short txPort, bool enableReuse = false, const char* txBindAddress = (const char*)0); Description This function is used to force NORM to use a specific port number for UDP packets sent for the specified sessionHandle. Additionally, it can optionally enable reuse of the specified port number and/or specify a specific source address binding that is used for packet transmission. By default, NORM uses separate port numbers for packet transmission and session packet reception (the receive port is specified as part of the NormCreateSession() call), allowing the operating system to pick a freely available port for transmission. This call allows the application to pick a specific port number for transmission, and furthermore allows the application to even specify the same port number for transmission as is used for reception. However, the use of separate transmit/receive ports allows NORM to discriminate when unicast feedback is occurring and thus it is not generally recommended that the transmit port be set to the same value as the session receive port. The enableReuse parameter, when set to true, allows that the specified port may be reused for multiple sessions, but care must be taken when enabling this option. The txBindAddress parameter allows specification of a specific source address binding for packet transmission. The specified address MUST be a valid unicast IP address assigned and configured for the host system. Additionally, the address specified must be compatible with multicast routing and/or the interfaces specified in any calls to NormSetMulticastInterface() for the given session when IP multicast is used. When the txPort is set equal to the session port number and a txBindAddress is not specified or set equal to the session address, a single socket is used for both transmission and reception. If the same port number is desired for both packet transmission and reception, and a specific source address binding is set, then the enableReuse parameter MUST be (and is automatically) set to true for successful operation. In this case, the receive socket is bound to session address if it is multicast and the transmit socket is bound to the specified txAddress although both are bound to the same port number. Note this call MUST be made before any calls to NormStartSender() or NormStartReceiver() for the given session to work as described. Return Values This function returns true upon success and false upon failure. Failure will occur if a txBindAddress is provided that does not correspond to a valid, configured IP address for the local host system. NormSetTxOnly() Synopsis #include <normApi.h> void NormSetTxOnly(NormSessionHandle sessionHandle, bool txOnly, bool connectToSessionAddress = false); Description This function limits the NormSession to perform NORM sender functions only. It also limits the underlying NORM UDP socket usage to open only a single transmit socket (tx_socket) and does not open or bind a receive socket for the given session address or port number. Thus, if this property is set, any NORM receivers MUST enable unicast feedback via a call to the NormSetDefaultUnicastNack() or appropriate NormNodeSetUnicastNack() function in order for their feedback messages (NACKs and ACKs) to be received by this sender. The purpose of this function is to allow NORM sender sessions to be created as separate process from a corresponding NORM receiver session for the same session address and port number. By default (when this call is not made), a NormSession, even when acting as only a sender (see NormStartSender()) opens two separate UDP sockets including a "receive" socket bound to the session port number and a "transmit" socket used for message transmission and reception of unicast feedback messages when receivers are so configured. The optional connectToSessionAddress parameter, when set to true, causes the underlying NORM code to "connect()" the UDP socket to the session (remote receiver) address and port number. If the corresponding NORM remote receiver instance uses NormSetTxPort() to set its transmit port to the same as the session port number, the result is a unique binding between this "tx only" sender instance and the remote NORM receiver instance. With proper use of NormSetRxPortReuse(), this allows multiple senders to be properly associated (i.e., binded with respect to UDP socket packet demultiplexing) with multiple receivers on a single host (all using the same session port number). Note the NORM receiver MUST also use the NormSetDefaultUnicastNack() call so that its feedback messages are directed to the "tx only" sender address/port. The motivation for this API call is to allow systems have NORM sender and receiver instances in separate processes supporting a set (e.g. a mesh) of unicast connections to other hosts. The only constraint is that the senders uses a "tx port" number that is different from the "rx port" number. This enables firewall configurations that only open a pair of UDP ports and allow for connection among an arbitrary number of hosts. This option is really only relevant for unicast NORM sessions. Return Values This function has no return values. NormSetRxPortReuse() Synopsis #include <normApi.h> void NormSetRxPortReuse(NormSessionHandle session, bool enableReuse, const char* rxBindAddress = (const char*)0, const char* senderAddress = (const char*)0, UINT16 senderPort = 0); Description This function allows the user to control the port reuse and binding behavior for the receive socket used for the given NORM sessionHandle. When the enablReuse parameter is set to true, reuse of the NormSession port number by multiple NORM instances or sessions is enabled. If the optional rxBindAddress is supplied (an IP address or host name in string form), the socket will bind() to the given address when it is opened in a call to NormStartReceiver() or NormStartSender(). The rxBindAddress MUST be the session multicast address (if it is a multicast session) or a valid local unicast address in the case of NORM unicast operation. This binding limits the socket to receive only packets destined for the specified rxBindAddress. This allows multiple NORM sessions to reuse the same port number, but use different multicast addresses (or allow for multiple NORM sessions for multiple local unicast addresses). The optional senderAddress and senderPort parameters can be used to connect() the underlying NORM receive socket to specific address/port. This limits the socket to receiving only packets from the specified senderAddress/senderPort. This, with receive port reuse enabled, allows for multiple NORM receiver instances to be listening to different NORM senders and have proper UDP socket demultiplexing occur. Note that it is also possible to have single NORM receiver receive transmissions from multiple senders, but in some cases it may be desirable for separate NORM processes or threads to be used to handle reception from separate senders. Thus, this socket binding option is provided. When this call is not made in any form, the default socket binding to IP address INADDR_ANY (equivalent to when this call is made and rxBindAddress is set to NULL) allows the NormSession receive socket to receive any multicast or unicast transmissions to the session port number provided in the call to NormCreateSession(). This allows a NORM receiver to receive from senders sending to a multicast session address or the receiver's unicast address. As mentioned, enabling port reuse and binding the session destination address allows multiple NORM sessions on the same port number, but participating in different multicast groups. Note this call MUST be made before any calls to NormStartSender() or NormStartReceiver() for the given sessionHandle to succeed. This call could also be used in conjunction with NormSetMulticastInterface() so that multiple NormSessions, using the same port and multicast address, could separately cover multiple network interfaces (and some sort of application-layer bridging of reliable multicast could be realized if desired). Return Values This function has no return values. NormSetMulticastInterface() Synopsis #include <normApi.h> bool NormSetMulticastInterface(NormSessionHandle session, const char* interfaceName); Description This function specifies which host network interface is used for IP Multicast transmissions and group membership. This should be called before any call to NormStartSender() or NormStartReceiver() is made so that the IP multicast group is joined on the proper host interface. However, if a call to NormSetMulticastInterface() is made after either of these function calls, the call will not affect the group membership interface, but only dictate that a possibly different network interface is used for transmitted NORM messages. Thus, the code: NormSetMulticastInterface(session, "interface1"); NormStartReceiver(session, ...); NormSetMulticastInterface(session, "interface2"); will result in NORM group membership (i.e. multicast reception) being managed on "interface1" while NORM multicast transmissions are made via "interface2". Return Values A return value of true indicates success while a return value of false indicates that the specified interface was invalid. This function will always return true if made before calls to NormStartSender() or NormStartReceiver(). However, those calls may fail if an invalid interface was specified with the call described here. NormSetSSM() Synopsis #include <normApi.h> bool NormSetSSM(NormSessionHandle session, const char* sourceAddress); Description This function sets the source address for Source-Specific Multicast (SSM) operation. This should be called before any call to NormStartSender() or NormStartReceiver() is made so that the proper group join is done. The receiver application MUST also use the NormSetDefaultUnicastNack() call so that feedback traffic is directed back to appropriate sender. Return Values A return value of true indicates success while a return value of false indicates that the specified source address was invalid. Note that if a valid IP address is specified but is improper for SSM (e.g., an IP multicast address) the later calls to NormStartSender() or NormStartReceiver() may fail. NormSetTTL() Synopsis #include <normApi.h> bool NormSetTTL(NormSessionHandle session, unsigned char ttl); Description This function specifies the time-to-live (ttl) for IP Multicast datagrams generated by NORM for the specified sessionHandle. The IP TTL field limits the number of router "hops" that a generated multicast packet may traverse before being dropped. For example, if TTL is equal to one, the transmissions will be limited to the local area network (LAN) of the host computers network interface. Larger TTL values should be specified to span large networks. Also note that some multicast router configurations use artificial "TTL threshold" values to constrain some multicast traffic to an administrative boundary. In these cases, the NORM TTL setting must also exceed the router "TTL threshold" in order for the NORM traffic to be allowed to exit the administrative area. Return Values A return value of true indicates success while a return value of false indicates that the specified ttl could not be set. This function will always return true if made before calls to NormStartSender() or NormStartReceiver(). However, those calls may fail if the desired ttl value cannot be set. NormSetTOS() Synopsis #include <normApi.h> bool NormSetTOS(NormSessionHandle sessionHandle, unsigned char tos); Description This function specifies the type-of-service (tos) field value used in IP Multicast datagrams generated by NORM for the specified sessionHandle. The IP TOS field value can be used as an indicator that a "flow" of packets may merit special Quality-of-Service (QoS) treatment by network devices. Users should refer to applicable QoS information for their network to determine the expected interpretation and treatment (if any) of packets with explicit TOS marking. Return Values A return value of true indicates success while a return value of false indicates that the specified tos could not be set. This function will always return true if made before calls to NormStartSender() or NormStartReceiver(). However, those calls may fail if the desired tos value cannot be set. NormSetLoopback() Synopsis #include <normApi.h> void NormSetLoopback(NormSessionHandle sessionHandle, bool loopbackEnable); Description This function enables or disables loopback operation for the indicated NORM sessionHandle. If loopbackEnable is set to true, loopback operation is enabled which allows the application to receive its own message traffic. Thus, an application which is both actively receiving and sending may receive its own transmissions. Note it is expected that this option would be principally be used for test purposes and that applications would generally not need to transfer data to themselves. If loopbackEnable is false, the application is prevented from receiving its own NORM message transmissions. By default, loopback operation is disabled when a NormSession is created. Return Values This function has no return values. NormSetFragmentation() Synopsis #include <normApi.h> bool NormSetFragmentation(NormSessionHandle sessionHandle, bool fragmentation); Description This function sets an underlying socket option that enables or disables IP datagram fragmentation by network intermediate systems according to whether the fragmentation parameter is set to a value of true or false, respectively. If set to true to enable fragmentation, the DF (don't fragment) bit of the headers of NORM UDP/IP packets sent will be cleared. Otherwise the DF bit is set and packets will not be fragmented by network devices if they exceed a link Maximum Transmission Unit (MTU) and will instead be dropped. For IP Multicast destinations, some operating systems may always set the DF bit of transmitted packets, regardless of the setting here and the underlying socket option status. Typically, the DF bit is set (i.e., fragmentation disabled) by default on most operating systems. This call is not currently functional on the Mac OSX system that does not support the needed IP_MTU_DISCOVER or IP_DONTFRAG socket options. Return Values This function returns true upon success and false upon failure. <anchor id="_NORM_Sender_Functions"/>NORM Sender Functions The functions described in this section apply only to NORM sender operation. Applications may participate strictly as senders or as receivers, or may act as both in the context of a NORM protocol session. The NORM sender is responsible for most parameters pertaining to its transmission of data. This includes transmission rate, data segmentation sizes, FEC coding parameters, stream buffer sizes, etc. NormStartSender() Synopsis #include <normApi.h> bool NormStartSender(NormSessionHandle sessionHandle, NormSessionId instanceId, unsigned long bufferSpace, unsigned short segmentSize, unsigned char blockSize, unsigned char numParity); Description The application's participation as a sender within a specified NormSession begins when this function is called. This includes protocol activity such as congestion control and/or group round-trip timing (GRTT) feedback collection and application API activity such as posting of sender-related NormEvent notifications. The parameters required for this function call include: sessionHandle This must be a valid NormSessionHandle previously obtained with a call to NormCreateSession(). instanceId Application-defined value used as the instance_id field of NORM sender messages for the application's participation within a session. Receivers can detect when a sender has terminated and restarted if the application uses different instanceId values when initiating sender operation. For example, a robust application could cache previous instanceId values in non-volatile storage and gracefully recover (without confusing receivers) from a total system shutdown and reboot by using a new instanceId value upon restart. bufferSpace This specifies the maximum memory space (in bytes) the NORM protocol engine is allowed to use to buffer any sender calculated FEC segments and repair state for the session. The optimum bufferSpace value is function of the network topology bandwidth*delay product and packet loss characteristics. If the bufferSpace limit is too small, the protocol may operate less efficiently as the sender is required to possibly recalculate FEC parity segments and/or provide less efficient repair transmission strategies (resort to explicit repair) when state is dropped due to constrained buffering resources. However, note the protocol will still provide reliable transfer. A large bufferSpace allocation is safer at the expense of possibly committing more memory resources. segmentSize This parameter sets the maximum payload size (in bytes) of NORM sender messages (not including any NORM message header fields). A sender's segmentSize value is also used by receivers to limit the payload content of some feedback messages (e.g. NORM_NACK message content, etc.) generated in response to that sender. Note different senders within a NormSession may use different segmentSize values. Generally, the appropriate segment size to use is dependent upon the types of networks forming the multicast topology, but applications may choose different values for other purposes. Note that application designers MUST account for the size of NORM message headers when selecting a segmentSize. For example, the NORM_DATA message header for a NORM_OBJECT_STREAM with full header extensions is 48 bytes in length. In this case, the UDP payload size of these messages generated by NORM would be up to (48 + segmentSize) bytes. blockSize This parameter sets the number of source symbol segments (packets) per coding block, for the systematic Reed-Solomon FEC code used in the current NORM implementation. For traditional systematic block code "(n,k)" nomenclature, the blockSize value corresponds to "k". NORM logically segments transport object data content into coding blocks and the blockSize parameter determines the number of source symbol segments (packets) comprising a single coding block where each source symbol segment is up to segmentSize bytes in length.. A given block's parity symbol segments are calculated using the corresponding set of source symbol segments. The maximum blockSize allowed by the 8-bit Reed-Solomon codes in NORM is 255, with the further limitation that (blockSize + numParity) <= 255. numParity This parameter sets the maximum number of parity symbol segments (packets) the sender is willing to calculate per FEC coding block. The parity symbol segments for a block are calculated from the corresponding blockSize source symbol segments. In the "(n,k)" nomenclature mention above, the numParity value corresponds to "n - k". A property of the Reed-Solomon FEC codes used in the current NORM implementation is that one parity segment can fill any one erasure (missing segment (packet)) for a coding block. For a given blockSize, the maximum numParity value is (255 - blockSize). However, note that computational complexity increases significantly with increasing numParity values and applications may wish to be conservative with respect to numParity selection, given anticipated network packet loss conditions and group size scalability concerns. Additional FEC code options may be provided for this NORM implementation in the future with different parameters, capabilities, trade-offs, and computational requirements. These parameters are currently immutable with respect to a sender's participation within a NormSession. Sender operation must be stopped (see NormStopSender()) and restarted with another call to NormStartSender() if these parameters require alteration. The API may be extended in the future to support additional flexibility here, if required. For example, the NORM protocol "intance_id" field may possibly be leveraged to permit a node to establish multiple virtual presences as a sender within a NormSession in the future. This would allow the sender to provide multiple concurrent streams of transport, with possibly different FEC and other parameters if appropriate within the context of a single NormSession. Again, this extended functionality is not yet supported in this implementation. Return Values A value of true is returned upon success and false upon failure. The reasons failure may occur include limited system resources or that the network sockets required for communication failed to open or properly configure. (TBD - Provide a NormGetError(NormSessionHandle sessionHandle) function to retrieve a more specific error indication for this and other functions.) NormStopSender() Synopsis #include <normApi.h> void NormStopSender(NormSessionHandle sessionHandle, bool graceful = false); Description This function terminates the application's participation in a NormSession as a sender. By default, the sender will immediately exit the session identified by the sessionHandle parameter without notifying the receiver set of its intention. However a "graceful shutdown" option, enabled by setting the graceful parameter to true, is provided to terminate sender operation gracefully, notifying the receiver set its pending exit with appropriate protocol messaging. A NormEvent, NORM_LOCAL_SENDER_CLOSED, is dispatched when the graceful shutdown process has completed. Return Values This function has no return values. NormSetTxRate() Synopsis #include <normApi.h> void NormSetTxRate(NormSessionHandle sessionHandle, double rate); Description This function sets the transmission rate (in bits per second (bps)) limit used for NormSender transmissions for the given sessionHandle. For fixed-rate transmission of NORM_OBJECT_FILE or NORM_OBJECT_DATA, this limit determines the data rate at which NORM protocol messages and data content are sent. For NORM_OBJECT_STREAM transmissions, this is the maximum rate allowed for transmission (i.e. if the application writes to the stream at a lower rate, a lower average NORM transmission rate will occur). Note that the application will need to consider the overhead of NORM protocol headers when determining an appropriate transmission rate for its purposes. When NORM congestion control is enabled (see NormSetCongestionControl()), the rate set here will be set, but congestion control operation, if enabled, may quickly readjust the transmission rate. Return Values This function has no return values. NormGetTxRate() Synopsis #include <normApi.h> double NormGetTxRate(NormSessionHandle sessionHandle); Description This function retrieves the current sender transmission rate in units of bits per second (bps) for the given sessionHandle. When NORM congestion control is enabled (see NormSetCongestionControl()), this reflects the current rate set (or suggested) by NORM congestion control operation. Otherwise, this returns the rate that was set with the NormSetTxRate() call. Return Values This function returns the sender transmission rate in units of bits per second (bps). NormSetTxSocketBuffer() Synopsis #include <normApi.h> bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle, unsigned int bufferSize); Description This function can be used to set a non-default socket buffer size for the UDP socket used by the specified NORM sessionHandle for data transmission. The bufferSize parameter specifies the desired socket buffer size in bytes. Large transmit socket buffer sizes may be necessary to achieve high transmission rates when NORM, as a user-space process, is unable to precisely time its packet transmissions. Similarly, NORM receivers may need to set large receive socket buffer sizes to achieve successful, sustained high data rate reception (see NormSetRxSocketBuffer()). Typically, it is more important to set the receive socket buffer size (see NormSetRxSocketBuffer()) as this maintains reliability (i.e. by avoiding receive socket buffer overflow) at high data rates while setting a larger transmit socket buffer size allows higher average transmission rates to be achieved. Return Values This function returns true upon success and false upon failure. Possible failure modes include an invalid sessionHandle parameter, a call to NormStartReceiver() or NormStartSender() has not yet been made for the session, or an invalid bufferSize was given. Note some operating systems may require additional system configuration to use non-standard socket buffer sizes. NormSetFlowControl() Synopsis #include <normApi.h> void NormSetFlowControl(NormSessionHandle sessionHandle, double flowControlFactor); Description This function controls a scaling factor that is used for sender timer-based flow control for the the specified NORM sessionHandle. Timer-based flow control works by preventing the NORM sender application from enqueueing new transmit objects or stream data that would purge "old" objects or stream data when there has been recent NACK activity for those old objects or data. If the flowControlFactor is set to ZERO, then the flow control mechanism is effectively disabled. Larger flowControlFactor values enforce more robust flow control by forcing the sender to maintain state longer, but then larger transmit buffer, stream buffer, transmit cache bounds and receive cache limits (see NormStartSender(), NormStreamOpen(), NormSetTxCacheBounds(), and NormSetRxCacheLimit(), respectively) may be needed to maintain throughput in larger <delay*bandwidth, loss> conditions. Effectively, a larger flowControlFactor can favor reliability over throughput when buffer-constrained. The flowControlFactor is used to compute a delay time for when a sender buffered object (or block of stream data) may be released (i.e. purged) after transmission or applicable NACKs reception. The delay time function is: flowControlDelay = flowControlFactor * GRTT * (backoffFactor + 1) where the "GRTT" is the sender's advertised GRTT estimate and the backoffFactor is the sender's configured timer-based feedback scaling factor. The default value (when this function is not called) of the flowControlFactor is 2.0. Note that a NORM application can also implement more explicit, deterministic flow control through use of the NormSetWatermark() API call, potentially even requiring positive acknowledgement of older data before enqueueing new data. Note that using the NormSetWatermark() API call with a NORM_NODE_NONE member in acking node list to force a "full" watermark flush is somewhat equivalent to timer-based flow control with a flowControlFactor equal to 2.0 * txRobustFactor. If such explicit flow control is implemented by the application, then a reduced flowControlFactor (or even ZERO) may be used. If "push mode" is enabled for a NORM_OBJECT_STREAM (see NormStreamSetPushEnable()), then flow control has no effect for the stream. Return Values This function has no return values. NormSetCongestionControl() Synopsis #include <normApi.h> void NormSetCongestionControl(NormSessionHandle sessionHandle, bool enable, bool adjustRate = true); Description This function enables (or disables) the NORM sender congestion control operation for the session designated by the sessionHandle parameter. For best operation, this function should be called before the call to NormStartSender() is made, but congestion control operation can be dynamically enabled/disabled during the course of sender operation. If the value of the enable parameter is true, congestion control operation is enabled while it is disabled for enable equal to false. When congestion control operation is enabled, the NORM sender automatically adjusts its transmission rate based on feedback from receivers. If bounds on transmission rate have been set (see NormSetTxRateBounds()) the rate adjustment will remain within the set bounds. The application will be notified of any changes to the sender transmission rate via a NormEvent of type NORM_TX_RATE_CHANGED. The rate set by NormSetTxRate() has no effect when congestion control operation is enabled, unless the adjustRate parameter here is set to false. When the adjustRate parameter is set to false, the NORM Congestion Control operates as usual, with feedback collected from the receiver set and the "current limiting receiver" identified, except that no actual adjustment is made to the sender's transmission rate. I.e., the transmission rate that was set by NormSetTxRate() is observed by the sender regardless of the feedback received. The NORM_TX_RATE_CHANGED notification will still occur as if the rate were being adjusted and the value returned by NormGetTxRate() reflects the rate that would have been used had the adjustRate parameter been enabled even though no actual rate change has occurred. The purpose of this variation of NORM Congestion Control operation is to allow applications to get a "suggested" rate from the NORM-CC mechanism. But, it is important to note that this "suggested" rate may or may not be appropriate since the operation of the NORM-CC algorithm is somewhat dependent on the associated NORM sender load on the network. For example, the "suggested" rate may be artificially high if the sender application has not been correspondingly setting the rate and actively transmitting data at that rate. This optional mode of operation is provided for EXPERIMENTAL purposes and is NOT RECOMMENDED for typical use of NORM. NORM's congestion algorithm provides rate adjustment to fairly compete for available network bandwidth with other TCP, NORM, or similarly governed traffic flows. (TBD - Describe the NormSetEcnSupport() function as this experimental option matures.) Return Values This function has no return values. NormSetTxRateBounds() Synopsis #include <normApi.h> bool NormSetTxRateBounds(NormSessionHandle sessionHandle, double rateMin, double rateMax); Description This function sets the range of sender transmission rates within which the NORM congestion control algorithm is allowed to operate for the given sessionHandle. By default, the NORM congestion control algorithm operates with no lower or upper bound on its rate adjustment. This function allows this to be limited where rateMin corresponds to the minimum transmission rate (bps) and rateMax corresponds to the maximum transmission rate. One or both of these parameters may be set to values less than zero to remove one or both bounds. For example, the call "NormSetTxRateBounds(session, -1.0, 64000.0)" will set an upper limit of 64 kbps for the sender transmission rate with no lower bound. These rate bounds apply only when congestion control operation is enabled (see NormSetCongestionControl()). If the current congestion control rate falls outside of the specified bounds, the sender transmission rate will be adjusted to stay within the set bounds. Return Values This function returns true upon success. If both rateMin and rateMax are greater than or equal to zero, but (rateMax < rateMin), the rate bounds will remain unset or unchanged and the function will return false. NormSetTxCacheBounds() Synopsis #include <normApi.h> void NormSetTxCacheBounds(NormSessionHandle sessionHandle, NormSize sizeMax, unsigned int countMin, unsigned int countMax); Description This function sets limits that define the number and total size of pending transmit objects a NORM sender will allow to be enqueued by the application. Setting these bounds to large values means the NORM protocol engine will keep history and state for previously transmitted objects for a larger interval of time (depending upon the transmission rate) when the application is actively enqueueing additional objects in response to NORM_TX_QUEUE_EMPTY notifications. This can allow more time for receivers suffering degraded network conditions to make repair requests before the sender "purges" older objects from its "transmit cache" when new objects are enqueued. A NORM_TX_OBJECT_PURGED notification is issued when the enqueuing of a new transmit object causes the NORM transmit cache to overflow, indicating the NORM sender no longer needs to reference the designated old transmit object and the application is free to release related resources as needed. The sizeMax parameter sets the maximum total size, in bytes, of enqueued objects allowed, providing the constraints of the countMin and countMax parameters are met. The countMin parameter sets the minimum number of objects the application may enqueue, regardless of the objects' sizes and the sizeMax value. For example, the default sizeMax value is 20 Mbyte and the default countMin is 8, thus allowing the application to always have at least 8 pending objects enqueued for transmission if it desires, even if their total size is greater than 20 Mbyte. Similarly, the countMax parameter sets a ceiling on how many objects may be enqueued, regardless of their total sizes with respect to the sizeMax setting. For example, the default countMax value is 256, which means the application is never allowed to have more than 256 objects pending transmission enqueued, even if they are 256 very small objects. Note that countMax must be greater than or equal to countMin and countMin is recommended to be at least two. Note that in the case of NORM_OBJECT_FILE objects, some operating systems impose limits (e.g. 256) on how many open files a process may have at one time and it may be appropriate to limit the countMax value accordingly. In other cases, a large countMin or countMax may be desired to allow the NORM sender to act as virtual cache of files or other data available for reliable transmission. Future iterations of the NRL NORM implementation may support alternative NORM receiver "group join" policies that would allow the receivers to request transmission of cached content. The utility of the NormRequeueObject() API call also depends on the parameters set by this function. The NormRequeueObject() call will only succeed when the given objectHandle corresponds to an object maintained in the NORM senders "transmit cache". Return Values This function has no return value. NormSetAutoParity() Synopsis #include <normApi.h> void NormSetAutoParity(NormSessionHandle sessionHandle, unsigned char autoParity); Description This function sets the quantity of proactive "auto parity" NORM_DATA messages sent at the end of each FEC coding block. By default (i.e., autoParity = 0), FEC content is sent only in response to repair requests (NACKs) from receivers. But, by setting a non-zero value for autoParity, the sender can automatically accompany each coding block of transport object source data segments ((NORM_DATA messages) with the set number of FEC segments. The number of source symbol messages (segments) per FEC coding block is determined by the blockSize parameter used when NormStartSender() was called for the given sessionHandle. The use of proactively-sent "auto parity" may eliminate the need for any receiver NACKing to achieve reliable transfer in networks with low packet loss. However, note that the quantity of "auto parity" set adds overhead to transport object transmission. In networks with a predictable level of packet loss and potentially large round-trip times, the use of "auto parity" may allow lower latency in the reliable delivery process. Also, its use may contribute to a smaller amount of receiver feedback as only receivers with exceptional packet loss may need to NACK for additional repair content. The value of autoParity set must be less than or equal to the numParity parameter set when NormStartSender() was called for the given sessionHandle. Return Values This function has no return values. NormGetGrttEstimate() Synopsis #include <normApi.h> double NormGetGrttEstimate(NormSessionHandle sessionHandle); Description This function returns the sender's current estimate(in seconds) of group round-trip timing (GRTT) for the given NORM session. This function may be useful for applications to leverage for other purposes the assessment of round-trip timing made by the NORM protocol engine. For example, an application may scale its own timeouts based on connectivity delays among participants in a NORM session. Note that the NORM_GRTT_UPDATED event is posted (see NormGetNextEvent()) by the NORM protocol engine to indicate when changes in the local sender or remote senders' GRTT estimate occurs. Return Values This function returns the current sender group round-trip timing (GRTT) estimate (in units of seconds). A value of -1.0 is returned if an invalid session value is provided. NormSetGrttEstimate() Synopsis #include <normApi.h> void NormSetGrttEstimate(NormSessionHandle sessionHandle, double grtt); Description This function sets the sender's estimate of group round-trip time (GRTT) (in units of seconds) for the given NORM sessionHandle. This function is expected to most typically used to initialize the sender's GRTT estimate prior to the call to NormStartSender() when the application has a priori confidence that the default initial GRTT value of 0.5 second is inappropriate. The sender GRTT estimate will be updated during normal sender protocol operation after sender startup or if this call is made while sender operation is active. For experimental purposes (or very special application needs), this API provides a mechanism to control or disable the sender GRTT update process (see NormSetGrttProbingMode()). The grtt value (in seconds) will be limited to the maximum GRTT as set (see NormSetGrttMax()) or the default maximum of 10 seconds. The sender GRTT is advertised to the receiver group and is used to scale various NORM protocol timers. The default NORM GRTT estimation process dynamically measures round-trip timing to determine an appropriate operating value. An overly-large GRTT estimate can introduce additional latency into the reliability process (resulting in a larger virtual delay*bandwidth product for the protocol and potentially requiring more buffer space to maintain reliability). An overly-small GRTT estimate may introduce the potential for feedback implosion, limiting the scalability of group size. Also note that the advertised GRTT estimate can also be limited by transmission rate. When the sender transmission rate is low, the GRTT is also governed to a lower bound of the nominal packet transmission interval (i.e., 1/txRate). This maintains the "event driven" nature of the NORM protocol with respect to receiver reception of NORM sender data and commands. Return Values This function has no return values. NormSetGrttMax() Synopsis #include <normApi.h> void NormSetGrttMax(NormSessionHandle sessionHandle, double grttMax); Description This function sets the sender's maximum advertised GRTT value for the given NORM sessionHandle. The grttMax parameter, in units of seconds, limits the GRTT used by the group for scaling protocol timers, regardless of larger measured round trip times. The default maximum for the NRL NORM library is 10 seconds. See the NormSetGrttEstimate() function description for the purpose of the NORM GRTT measurement process. Return Values This function has no return values. NormSetGrttProbingMode() Synopsis #include <normApi.h> void NormSetGrttProbingMode(NormSessionHandle sessionHandle, NormProbingMode probingMode); Description This function sets the sender's mode of probing for round trip timing measurement responses from the receiver set for the given NORM sessionHandle. Possible values for the probingMode parameter include NORM_PROBE_NONE, NORM_PROBE_PASSIVE, and NORM_PROBE_ACTIVE. The default probing mode is NORM_PROBE_ACTIVE. In this mode, the receiver set explicitly acknowledges NORM sender GRTT probes ((NORM_CMD(CC) messages) with NORM_ACK responses that are group-wise suppressed. Note that NORM receivers also will include their response to GRTT probing piggy-backed on any NORM_NACK messages sent in this mode as well to minimize feedback. Note that the NORM_PROBE_ACTIVE probing mode is required and automatically set when NORM congestion control operation is enabled (see NormSetCongestionControl()). Thus, when congestion control is enabled, the NormSetGrttProbingMode() function has no effect. If congestion control operation is not enabled, the NORM application may elect to reduce the volume of feedback traffic by setting the probingMode to NORM_PROBE_PASSIVE. Here, the NORM sender still transmits NORM_CMD(CC) probe messages multiplexed with its data transmission, but the receiver set does not explicitly acknowledge these probes. Instead the receiver set is limited to opportunistically piggy-backing responses when NORM_NACK messages are generated. Note that this may, in some cases, introduce some opportunity for bursts of large volume receiver feedback when the sender's estimate of GRTT is incorrect due to the reduced probing feedback. But, in some controlled network environments, this option for passive probing may provide some benefits in reducing protocol overhead. Finally, the probingMode can be set to NORM_PROBE_NONE to eliminate the overhead (and benefits) of NORM GRTT measurement entirely. In this case, the sender application must explicitly set its estimate of GRTT using the NormSetGrttEstimate() function. See this function for a description of the purpose of the NORM GRTT measurement. Return Values This function has no return values. NormSetGrttProbingInterval() Synopsis #include <normApi.h> void NormSetGrttProbingInterval(NormSessionHandle sessionHandle, double intervalMin, double intervalMax); Description This function controls the sender GRTT measurement and estimation process for the given NORM sessionHandle. The NORM sender multiplexes periodic transmission of NORM_CMD(CC) messages with its ongoing data transmission or when data transmission is idle. When NORM congestion control operation is enabled, these probes are sent once per RTT of the current limiting receiver (with respect to congestion control rate). In this case the intervalMin and intervalMax parameters (in units of seconds) control the rate at which the sender's estimate of GRTT is updated. At session start, the estimate is updated at intervalMin and the update interval time is doubled until intervalMax is reached. This dynamic allows for a rapid initial estimation of GRTT and a slower, steady-state update of GRTT. When congestion control is disabled and NORM GRTT probing is enabled ((NORM_PROBE_ACTIVE or NORM_PROBE_PASSIVE) the intervalMin and intervalMax values also determine the rate at which NORM_CMD(CC) probes are transmitted by the sender. Thus by setting larger values for intervalMin and intervalMax, the NORM sender application can reduce the overhead of the GRTT measurement process. However, this also reduces the ability of NORM to adapt to changes in GRTT. The default NORM GRTT intervalMin and intervalMax values, i.e., when this call is not made, are 1.0 second and 30.0 seconds, respectively. Return Values This function has no return values. NormSetBackoffFactor() Synopsis #include <normApi.h> void NormSetBackoffFactor(NormSessionHandle sessionHandle, double backoffFactor); Description This function sets the sender's "backoff factor" for the given sessionHandle. The backoffFactor (in units of seconds) is used to scale various timeouts related to the NACK repair process. The sender advertises its backoffFactor setting to the receiver group in NORM protocol message headers. The default backoffFactor for NORM sessions is 4.0 seconds. The backoffFactor is used to determine the maximum time that receivers may delay NACK transmissions (and other feedback messages) as part of NORM's probabilistic feedback suppression technique. For example, the maximum NACK delay time is backoffFactor*GRTT. Thus a large backoffFactor value introduces latency into the NORM repair process. However, a small backoffFactor value causes feedback suppression to be less effective and increases the risk of feedback implosion for large receiver group sizes. The default setting of 4.0 provides reasonable feedback suppression for moderate to large group sizes when multicast feedback is possible. The NORM specification recommends a backoffFactor value of 6.0 when unicast feedback is used. However, for demanding applications (with respect to repair latency) when group sizes are modest, a small (even 0.0) backoffFactor value can be specified to reduce the latency of reliable data delivery. Return Values This function has no return values. NormSetGroupSize() Synopsis #include <normApi.h> void NormSetGroupSize(NormSessionHandle sessionHandle, unsigned int groupSize); Description This function sets the sender's estimate of receiver group size for the given sessionHandle. The sender advertises its groupSize setting to the receiver group in NORM protocol message headers that, in turn, use this information to shape the distribution curve of their random timeouts for the timer-based, probabilistic feedback suppression technique used in the NORM protocol. Note that the groupSize estimate does not have to be very accurate and values within an order of magnitude of the actual group size tend to produce acceptable performance. The default groupSize setting in NORM is 1,000 and thus can work well for a wide range of actual receiver group sizes. The penalty of an overly large estimate is statistically a little more latency in reliable data delivery with respect to the round trip time and some potential for excess feedback. A substantial underestimation of groupSize increases the risk of feedback implosion. Currently, the NORM implementation does not attempt to automatically measure groupSize from receiver feedback. Applications could add their own mechanism for this (perhaps keeping explicit track of group membership), or it is possible that future versions of the NRL NORM implementation may have some provision for automatic groupSize estimation by the sender based on receiver feedback messages. Return Values This function has no return values. NormSetTxRobustFactor() Synopsis #include <normApi.h> void NormSetTxRobustFactor(NormSessionHandle sessionHandle, int txRobustFactor); Description This routine sets the "robustness factor" used for various NORM sender functions. These functions include the number of repetitions of "robustly-transmitted" NORM sender commands such as NORM_CMD(FLUSH) or similar application-defined commands, and the number of attempts that are made to collect positive acknowledgement from receivers. These commands are distinct from the NORM reliable data transmission process, but play a role in overall NORM protocol operation. The default txRobustFactor value is 20. This relatively large value makes the NORM sender end-of-transmission flushing and positive acknowledgement collection functions somewhat immune from packet loss. However, for some applications, the default value may make the NORM protocol more "chatty" than desired (particularly if flushing is invoked often). In other situations where the network connectivity may be intermittent or extremely lossy, it may be useful to actually increase this value. The default value (20) is expected to provide reasonable operation across a wide range of network conditions and application types. Since this value is not communicated among NORM participants as part of the protocol operation, it is important that applications consistently set this value among all applications participating in a NORM session. Setting txRobustFactor to a value of -1 makes the redundant transmission of these commands continue indefinitely until completion. For example, with positive acknowledgement collection, the request process will continue indefinitely until all recipients requested acknowledge or the request is canceled by the application. Similarly, flushing commands would be transmitted repeatedly until data transmission is resumed. Typically, setting txRobustFactor to -1 is not recommended. Return Values This function has no return values. NormFileEnqueue() Synopsis #include <normApi.h> NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle, const char* filename, const char* infoPtr = NULL, unsigned int infoLen = 0); Description This function enqueues a file for transmission within the specified NORM sessionHandle. Note that NormStartSender() must have been previously called before files or any transport objects may be enqueued and transmitted. The fileName parameter specifies the path to the file to be transmitted. The NORM protocol engine read and writes directly from/to file system storage for file transport, potentially providing for a very large virtual "repair window" as needed for some applications. While relative paths with respect to the "current working directory" may be used, it is recommended that full paths be used when possible. The optional infoPtr and infoLen parameters are used to associate NORM_INFO content with the sent transport object. The maximum allowed infoLen corresponds to the segmentSize used in the prior call to NormStartSender(). The use and interpretation of the NORM_INFO content is left to the application's discretion. Example usage of NORM_INFO content for NORM_OBJECT_FILE might include file name, creation date, MIME-type or other information which will enable NORM receivers to properly handle the file when reception is complete. The application is allowed to enqueue multiple transmit objects within in the "transmit cache" bounds (see NormSetTxCacheBounds()) and enqueued objects are transmitted (and repaired as needed) within the limits determined by automated congestion control (see NormSetCongestionControl()) or fixed rate (see NormSetTxRate()) parameters. Return Values A NormObjectHandle is returned which the application may use in other NORM API calls as needed. This handle can be considered valid until the application explicitly cancels the object's transmission (see NormObjectCancel()) or a NORM_TX_OBJECT_PURGED event is received for the given object. Note the application may use the NormObjectRetain() method if it wishes to refer to the object after the NORM_TX_OBJECT_PURGED notification. In this case, the application, when finished with the object, must use NormObjectRelease() to free any resources used or else a memory leak condition will result. A value of NORM_OBJECT_INVALID is return upon error. Possible failure conditions include the specified session is not operating as a NormSender, insufficient memory resources were available, or the "transmit cache" limits have been reached and all previously enqueued NORM transmit objects are pending transmission. Also the call will fail if the infoLen parameter exceeds the local NormSender segmentSize limit. NormDataEnqueue() Synopsis #include <normApi.h> NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle, const char* dataPtr, unsigned int dataLen, const char* infoPtr = NULL, unsigned int infoLen = 0); Description This function enqueues a segment of application memory space for transmission within the specified NORM sessionHandle. Note that NormStartSender() MUST have been previously called before files or any transport objects may be enqueued and transmitted. The dataPtr parameter must be a valid pointer to the area of application memory to be transmitted and the dataLen parameter indicates the quantity of data to transmit. The NORM protocol engine read and writes directly from/to application memory space so it is important that the application does not modify (or deallocate) the memory space during the time the NORM protocol engine may access this area. After calling NormDataEnqueue() for a specific application "dataPtr" memory space, the application MUST NOT deallocate (or change the contents of) that memory space until a NORM_TX_OBJECT_PURGED notification is received for the given object or the application itself explicitly cancels the object's transmission (see NormObjectCancel()). The optional infoPtr and infoLen parameters are used to associate NORM_INFO content with the sent transport object. The maximum allowed infoLen corresponds to the segmentSize used in the prior call to NormStartSender(). The use and interpretation of the NORM_INFO content is left to the application's discretion. Example usage of NORM_INFO content for NORM_OBJECT_DATA might include application-defined data typing or other information which will enable NORM receiver applications to properly interpret the received data when reception is complete. Of course, it is possible that the application may embed such typing information in the object data content itself. This is left to the application's discretion. The application is allowed to enqueue multiple transmit objects within in the "transmit cache" bounds (see NormSetTxCacheBounds()) and enqueued objects are transmitted (and repaired as needed) within the limits determined by automated congestion control (see NormSetCongestionControl()) or fixed rate (see NormSetTxRate()) parameters. Return Values A NormObjectHandle is returned which the application may use in other NORM API calls as needed. This handle can be considered valid until the application explicitly cancels the object's transmission (see NormObjectCancel()) or a NORM_TX_OBJECT_PURGED event is received for the given object. Note the application may use the NormObjectRetain() method if it wishes to refer to the object after the NORM_TX_OBJECT_PURGED notification. In this case, the application, when finished with the object, must use NormObjectRelease() to free any resources used or else a memory leak condition will result. A value of NORM_OBJECT_INVALID is return upon error. Possible failure conditions include the specified session is not operating as a NormSender, insufficient memory resources were available, or the "transmit cache" limits have been reached and all previously enqueued NORM transmit objects are pending transmission. Also the call will fail if the infoLen parameter exceeds the local NormSender segmentSize limit. NormRequeueObject() Synopsis #include <normApi.h> bool NormRequeueObject(NormSessionHandle sessionHandle, NormObjectHandle objectHandle); Description This function allows the application to resend (or reset transmission of) a NORM_OBJECT_FILE or NORM_OBJECT_DATA transmit object that was previously enqueued for the indicated sessionHandle. This function is useful for applications sending to silent (non-NACKing) receivers as it enables the receivers to take advantage of multiple retransmissions of objects (including any auto-parity set, see NormSetAutoParity()) to more robustly receive content. The objectHandle parameter must be a valid transmit NormObjectHandle that has not yet been "purged" from the sender's transmit queue. Upon success, the specified object will be fully retransmitted using the same NORM object transport identifier as was used on its initial transmission. This call may be made at any time to restart transmission of a previously-enqueued object, but the NORM_TX_OBJECT_SENT or NORM_TX_FLUSH_COMPLETED notifications can serve as good cues for an appropriate time to resend an object. If multiple objects are re-queued, they will be resent in order of their initial enqueueing. The transmit cache bounds set by NormSetTxCacheBounds() determine the number of previously-sent objects retained in the sender's transmit queue and that are thus eligible to be requeued for retransmission. An object may be requeued via this call multiple times, but each distinct requeue should be done after an indication such as NORM_TX_OBJECT_SENT or NORM_TX_FLUSH_COMPLETED for the given object. Otherwise, the object will simply be reset from its current transmission point to transmit from the beginning (i.e. restart). Note that the object type NORM_OBJECT_STREAM cannot currently be requeued. (TBD - should a "numRepeats" parameter be added to this function?) Return Values A value of true is returned upon success and a value of false is returned upon failure. Possible reasons for failure include an invalid objectHandle was provided (i.e. a non-transmit object or transmit object that has been "purged" from the transmit queue (see NORM_TX_OBJECT_PURGED)) or the provided object was of type NORM_OBJECT_STREAM. NormStreamOpen() Synopsis #include <normApi.h> NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle, unsigned int bufferSize, const char* infoPtr = NULL, unsigned int infoLen = 0); Description This function opens a NORM_OBJECT_STREAM sender object and enqueues it for transmission within the indicated sessionHandle. NORM streams provide reliable, in-order delivery of data content written to the stream by the sender application. Note that no data is sent until subsequent calls to NormStreamWrite() are made unless NORM_INFO content is specified for the stream with the infoPtr and infoLen parameters. Example usage of NORM_INFO content for NORM_OBJECT_STREAM might include application-defined data typing or other information which will enable NORM receiver applications to properly interpret the received stream as it is being received. The NORM protocol engine buffers data written to the stream for original transmission and repair transmissions as needed to achieve reliable transfer. The bufferSize parameter controls the size of the stream's "repair window" which limits how far back the sender will "rewind" to satisfy receiver repair requests. NORM, as a NACK-oriented protocol, currently lacks a mechanism for receivers to explicitly feedback flow control status to the sender unless the sender application specifically leverages NORM's optional positive-acknowledgement (ACK) features. Thus, the bufferSize selection plays an important role in reliable delivery of NORM stream content. Generally, a larger bufferSize value is safer with respect to reliability, but some applications may wish to limit how far the sender rewinds to repair receivers with poor connectivity with respect to the group at large. Such applications may set a smaller bufferSize to avoid the potential for large latency in data delivery (i.e. favor peak delivery latency over full reliability). This may result in breaks in the reliable delivery of stream data to some receivers, but this form of quasi-reliability while limiting latency may be useful for some types of applications (e.g. reliable real-time messaging, video or sensor or media data transport). Note that NORM receivers can quickly, automatically "resync" to the sender after such breaks if the application leverages the application message boundary recovery features of NORM (see NormStreamMarkEom()). Note that the current implementation of NORM is designed to support only one active stream per session, and that any NORM_OBJECT_DATA or NORM_OBJECT_FILE objects enqueued for transmission will not begin transmission until an active stream is closed. Applications requiring multiple streams or concurrent file/data transfer SHOULD generally instantiate multiple NormSessions as needed. Note there is no corresponding "open" call for receiver streams. Receiver NORM_OBJECT_STREAMs are automatically opened by the NORM protocol engine and the receiver applications is notified of new streams via the NORM_RX_OBJECT_NEW notification (see NormGetNextEvent()). Return Values A NormObjectHandle is returned which the application may use in other NORM API calls as needed. This handle can be considered valid until the application explicitly cancels the object's transmission (see NormObjectCancel()) or a NORM_TX_OBJECT_PURGED event is received for the given object. Note the application may use the NormObjectRetain() method if it wishes to refer to the object after the NORM_TX_OBJECT_PURGED notification. In this case, the application, when finished with the object, must use NormObjectRelease() to free any resources used or else a memory leak condition will result. A value of NORM_OBJECT_INVALID is return upon error. Possible failure conditions include the specified session is not operating as a NormSender, insufficient memory resources were available, or the "transmit cache" bounds have been reached and all previously enqueued NORM transmit objects are pending transmission. Also the call will fail if the infoLen parameter exceeds the local NormSender segmentSize limit. NormStreamClose() Synopsis #include <normApi.h> void NormStreamClose(NormObjectHandle streamHandle, bool graceful = false); Description This function halts transfer of the stream specified by the streamHandle parameter and releases any resources used unless the associated object has been explicitly retained by a call to NormObjectRetain(). No further calls to NormStreamWrite() will be successful for the given streamHandle. The optional graceful parameter, when set to a value of true, may be used by NORM senders to initiate "graceful" shutdown of a transmit stream. In this case, the sender application will be notified that stream has (most likely) completed reliable transfer via the NORM_TX_OBJECT_PURGED notification upon completion of the graceful shutdown process. When the graceful option is set to true, receivers are notified of the stream end via an "stream end" stream control code in NORM_DATA message and will receive a NORM_RX_OBJECT_COMPLETED notification after all received stream content has been read. Otherwise, the stream is immediately terminated, regardless of receiver state. In this case, this function is equivalent to the NormObjectCancel() routine and may be used for sender or receiver streams. So, it is expected this function (NormStreamClose()) will typically be used for transmit streams by NORM senders. Return Values This function has no return values. NormStreamWrite() Synopsis #include <normApi.h> unsigned int NormStreamWrite(NormObjectHandle streamHandle const char* buffer, unsigned int numBytes); Description This function enqueues data for transmission within the NORM stream specified by the streamHandle parameter. The buffer parameter must be a pointer to the data to be enqueued and the numBytes parameter indicates the length of the data content. Note this call does not block and will return immediately. The return value indicates the number of bytes copied from the provided buffer to the internal stream transmission buffers. Calls to this function will be successful unless the stream's transmit buffer space is fully occupied with data pending original or repair transmission if the stream's "push mode" is set to false (default, see NormStreamSetPushEnable() for details). If the stream's "push mode" is set to true, a call to NormStreamWrite() will always result in copying of application data to the stream at the cost of previously enqueued data pending transmission (original or repair) being dropped by the NORM protocol engine. While NORM NACK-based reliability does not provide explicit flow control, there is some degree of implicit flow control in limiting writing new data to the stream against pending repairs. Other flow control strategies are possible using the NormSetWatermark() function.NormSetWatermark() function. The NormEvent values NORM_TX_QUEUE_EMPTY and NORM_TX_QUEUE_VACANCY are posted with the NormEvent::object field set to a valid sender stream NormObjectHandle to indicate when the stream is ready for writing via this function. Note that the NORM_TX_QUEUE_VACANCY event type is posted only after the stream's transmit buffer has been completely filled. Thus, the application must make a call to NormStreamWrite() that copies less than the requested numBytes value (return value less than numBytes) before additional NORM_TX_QUEUE_VACANCY events are posted for the given streamHandle (i.e., the event type is not re-posted until the application has again filled the available stream transmit buffer space). By cueing off of NORM_TX_QUEUE_EMPTY, the application can write its "freshest" available data to the stream, but by cueing off of NORM_TX_QUEUE_VACANCY, an application can keep the NORM protocol engine busiest, to achieve the maximum possible throughput at high data rates. Return Values This function returns the number of bytes of data successfully enqueued for NORM stream transmission. If the underlying send stream buffer is full, this function may return zero or a value less than the requested numBytes. NormStreamFlush() Synopsis #include <normApi.h> void NormStreamFlush(NormObjectHandle streamHandle, bool eom = false, NormFlushMode flushMode = NORM_FLUSH_PASSIVE); Description This function causes an immediate "flush" of the transmit stream specified by the streamHandle parameter. Normally, unless NormStreamSetAutoFlush() has been invoked, the NORM protocol engine buffers data written to a stream until it has accumulated a sufficient quantity to generate a NORM_DATA message with a full payload (as designated by the segmentSize parameter of the NormStartSender() call). This results in most efficient operation with respect to protocol overhead. However, for some NORM streams, the application may not wish wait for such accumulation when critical data has been written to a stream. The default stream "flush" operation invoked via NormStreamFlush() for flushMode equal to NORM_FLUSH_PASSIVE causes NORM to immediately transmit all enqueued data for the stream (subject to session transmit rate limits), even if this results in NORM_DATA messages with "small" payloads. If the optional flushMode parameter is set to NORM_FLUSH_ACTIVE, the application can achieve reliable delivery of stream content up to the current write position in an even more proactive fashion. In this case, the sender additionally, actively transmits NORM_CMD(FLUSH) messages after any enqueued stream content has been sent. This immediately prompt receivers for repair requests which reduces latency of reliable delivery, but at a cost of some additional messaging. Note any such "active" flush activity will be terminated upon the next subsequent write to the stream. If flushMode is set to NORM_FLUSH_NONE, this call has no effect other than the optional end-of-message marking described here. The optional eom parameter, when set to true, allows the sender application to mark an end-of-message indication (see NormStreamMarkEom()) for the stream and initiate flushing in a single function call. The end-of-message indication causes NORM to embed the appropriate message start byte offset in the NORM_DATA message generated following a subsequent write to the stream with the NORM_FLAGS_MSG_START flag. This mechanism provide a means for automatic application message boundary recovery when receivers join or re-sync to a sender mid-stream. Note that frequent flushing, particularly for NORM_FLUSH_ACTIVE operation, may result in more NORM protocol activity than usual, so care must be taken in application design and deployment when scalability to large group sizes is expected. Return Values This function has no return values. NormStreamSetAutoFlush() Synopsis #include <normApi.h> void NormStreamSetAutoFlush(NormObjectHandle streamHandle NormFlushMode flushMode); Description This function sets "automated flushing" for the NORM transmit stream indicated by the streamHandle parameter. By default, a NORM transmit stream is "flushed" only when explicitly requested by the application (see NormStreamFlush()). However, to simplify programming, the NORM API allows that automated flushing be enabled such that the "flush" operation occurs every time the full requested buffer provided to a NormStreamWrite() call is successfully enqueued. This may be appropriate for messaging applications where the provided buffers corresponds to an application messages requiring immediate, full transmission. This may make the NORM protocol perhaps more "chatty" than its typical "bulk transfer" form of operation, but can provide a useful capability for some applications. Possible values for the flushMode parameter include NORM_FLUSH_NONE, NORM_FLUSH_PASSIVE, and NORM_FLUSH_ACTIVE. The default setting for a NORM stream is NORM_FLUSH_NONE where no flushing occurs unless explicitly requested via NormStreamFlush(). By setting the automated flushMode to NORM_FLUSH_PASSIVE, the only action taken is to immediately transmit any data that has been written to the stream, even if "runt" NORM_DATA messages (with payloads less than the NormSender segmentSize parameter) are generated as a result. If NORM_FLUSH_ACTIVE is specified, the automated flushing operation is further augmented with the additional transmission of NORM_CMD(FLUSH) messages to proactively excite the receiver group for repair requests. Return Values This function has no return values. NormStreamSetPushEnable() Synopsis #include <normApi.h> void NormStreamSetPushEnable(NormObjectHandle streamHandle, bool pushEnable); Description This function controls how the NORM API behaves when the application attempts to enqueue new stream data for transmission when the associated stream's transmit buffer is fully occupied with data pending original or repair transmission. By default (pushEnable = false), a call to NormStreamWrite() will return a zero value under this condition, indicating it was unable to enqueue the new data. However, if pushEnable is set to true for a given streamHandle, the NORM protocol engine will discard the oldest buffered stream data (even if it is pending repair transmission or has never been transmitted) as needed to enqueue the new data. Thus a call to NormStreamWrite() will never fail to copy data. This behavior may be desirable for applications where it is more important to quickly delivery new data than to reliably deliver older data written to a stream. The default behavior for a newly opened stream corresponds to pushEnable equals false. This limits the rate to which an application can write new data to the stream to the current transmission rate and status of the reliable repair process. Return Values This function has no return values. NormStreamHasVacancy() Synopsis #include <normApi.h> bool NormStreamHasVacancy(NormObjectHandle streamHandle); Description This function can be used to query whether the transmit stream, specified by the streamHandle parameter, has buffer space available so that the application may successfully make a call to NormStreamWrite(). Normally, a call to NormStreamWrite() itself can be used to make this determination, but this function can be useful when "push mode" has been enabled (see the description of the NormStreamSetPushEnable() function) and the application wants to avoid overwriting data previously written to the stream that has not yet been transmitted. Note that when "push mode" is enabled, a call to NormStreamWrite() will always succeed, overwriting previously-enqueued data if necessary. Normally, this function will return true after a NORM_TX_QUEUE_VACANCY notification has been received for a given NORM stream object. Return Values This function returns a value of true when there is transmit buffer space to which the application may write and false otherwise. NormStreamMarkEom() Synopsis #include <normApi.h> void NormStreamMarkEom(NormObjectHandle streamHandle); Description This function allows the application to indicate to the NORM protocol engine that the last data successfully written to the stream indicated by streamHandle corresponded to the end of an application-defined message boundary. The end-of-message indication given here will cause the NORM protocol engine to embed the appropriate message start byte offset in the NORM_DATA message generated that contains the data for the subsequent application call to NormStreamWrite(). Use of this end-of-message marking enables NORM receivers to automatically re-sync to application-defined message boundaries when joining (or re-joining) a NORM session already in progress. Return Values This function has no return values. NormSetWatermark() Synopsis #include <normApi.h> bool NormSetWatermark(NormSessionHandle sessionHandle, NormObjectHandle objectHandle, bool overrideFlush = true); Description This function specifies a "watermark" transmission point at which NORM sender protocol operation should perform a flushing process and/or positive acknowledgment collection for a given sessionHandle. For NORM_OBJECT_FILE and NORM_OBJECT_DATA transmissions, the positive acknowledgement collection will begin when the specified object has been completely transmitted. The objectHandle parameter must be a valid handle to a previously-created sender object (see NormFileEnqueue(), NormDataEnqueue(), or NormStreamOpen()). For NORM_OBJECT_STREAM transmission, the positive acknowledgment collection begins immediately, using the current position (offset of most recent data written) of the sender stream as a reference. The functions NormAddAckingNode() and NormRemoveAckingNode() are used to manage the list of NormNodeId values corresponding to NORM receivers that are expected to explicitly acknowledge the watermark flushing messages transmitted by the sender. Note that the NormNodeId NORM_NODE_NONE may be included in the list. Inclusion of NORM_NODE_NONE forces the watermark flushing process to proceed through a full NORM_ROBUST_FACTOR number of rounds before completing, prompting any receivers that have not completed reliable reception to the given watermark point to NACK for any repair needs. If NACKs occur, the flushing process is reset and repeated until completing with no NACKs for data through the given watermark transmission point are received. Thus, even without explicit positive acknowledgment, the sender can use this process (by adding NORM_NODE_NONE to the session's list of "acking nodes") for a high level of assurance that the receiver set is "happy" (completed reliable data reception) through the given object (or stream transmission point). The event NORM_TX_WATERMARK_COMPLETED is posted for the given session when the flushing process or positive acknowledgment collection has completed. The process completes as soon as all listed receivers have responded unless NORM_NODE_NONE is included in the "acking node" list. The sender application may use the function NormGetAckingStatus() to determine the degree of success of the flushing process in general or for individual NormNodeId values. The flushing is conducted concurrently with ongoing data transmission and does not impede the progress of reliable data transfer. Thus the sender may still enqueue NormObjects for transmission (or write to the existing stream) and the positive acknowledgement collection and flushing procedure will be multiplexed with the ongoing data transmission. However, the sender application may wish to defer from or limit itself in sending more data until a NORM_TX_WATERMARK_COMPLETED event is received for the given session. This provides a form of sender->receiver(s) flow control which does not exist in NORM's default protocol operation. If a subsequent call is made to NormSetWatermark() before the current acknowledgement request has completed, the pending acknowledgment request is canceled and the new one begins. The optional overrideFlush parameter, when set to true, causes the watermark acknowledgment process that is established with this function call to potentially fully supersede the usual NORM end-of-transmission flushing process that occurs. If overrideFlush is set and the "watermark" transmission point corresponds to the last transmission that will result from data enqueued by the sending application, then the watermark flush completion will terminate the usual flushing process. I.e., if positive acknowledgement of watermark is received from the full "acking node list", then no further flushing is conducted. Thus, the overrideFlush parameter should only be set when the "acking node list" contains a complete list of intended recipients. This is useful for small receiver groups (or unicast operation) to reduce the "chattiness" of NORM's default end-of-transmission flush process. Note that once the watermark flush is completed and further data enqueued and transmitted, the normal default end-of-transmission behavior will be resumed unless another "watermark" is set with overrideFlush enabled. Thus, as long as new watermarks are established by successive use of this API call, this effectively "morphs" NORM into a protocol driven by positive acknowledgement behavior. Return Values The function returns true upon successful establishment of the watermark point. The function may return false upon failure. NormCancelWatermark() Synopsis #include <normApi.h> bool NormCancelWatermark(NormSessionHandle sessionHandle); Description This function cancels any "watermark" acknowledgement request that was previously set via the NormSetWatermark() function for the given sessionHandle. The status of any NORM receivers that may have acknowledged prior to cancellation can be queried using the NormGetAckingStatus() function even after NormCancelWatermark() is called. Typically, applications should wait until a event has been posted, but in some special cases it may be useful to terminate the acknowledgement collection process early. Return Values The function has no return values. NormAddAckingNode() Synopsis #include <normApi.h> bool NormAddAckingNode(NormSessionHandle sessionHandle, NormNodeId nodeId); Description When this function is called, the specified nodeId is added to the list of NormNodeId values (i.e., the "acking node" list) used when NORM sender operation performs positive acknowledgement (ACK) collection for the specified sessionHandle. The optional NORM positive acknowledgement collection occurs when a specified transmission point (see NormSetWatermark()) is reached or for specialized protocol actions such as positively-acknowledged application-defined commands. Additionally the special value of nodeId equal to NORM_NODE_NONE may be set to force the watermark flushing process through a full NORM_ROBUST_FACTOR number of rounds regardless of actual acking nodes. Otherwise the flushing process is terminated when all of the nodes in the acking node list have responded. Setting a "watermark" and forcing a full flush process with the special NORM_NODE_NONE value of nodeId enables the resultant NORM_TX_WATERMARK_COMPLETED notification to be a indicator with high (but not absolute) assurance that the receiver set has completed reliable reception of content up through the "watermark" transmission point. This provides a form of scalable reliable multicast "flow control" for NACK-based operation without requiring explicit positive acknowledgement from all group members. Note that the use of the NORM_NODE_NONE value may be mixed with other nodeId for a mix of positive acknowledgement collection from some nodes and a measure of assurance for the group at large. Return Values The function returns true upon success and false upon failure. The only failure condition is that insufficient memory resources were available. If a specific nodeId is added more than once, this has no effect. NormRemoveAckingNode() Synopsis #include <normApi.h> void NormRemoveAckingNode(NormSessionHandle sessionHandle, NormNodeId nodeId); Description This function deletes the specified nodeId from the list of NormNodeId values used when NORM sender operation performs positive acknowledgement (ACK) collection for the specified sessionHandle. Note that if the special nodeId value "NORM_NODE_NONE" has been added to the list, it too must be explicitly removed to change the watermark flushing behavior if desired. Return Values The function has no return values. NormGetNextAckingNode() Synopsis #include <normApi.h> NormNodeId NormGetNextAckingNode(NormSessionHandle session, bool reset = false); Description This function iteratively retrieves the NormNodeId values in the "acking node" list maintained by a NORM sender (see NormAddAckingNode()) for the given sessionHandle. If the optional reset parameter is set to a value of true, the first NormNodeId value in the list is returned and subsequent calls to NormGetNextAckingNode()with the reset parameter set to its default false value will iteratively return the remaining NormNodeId values contained in the list. A value of NORM_NODE_NONE is returned when the end of the list is reached. The "acking node" list is populated with application calls to NormAddAckingNode() or auto-populated if that optional behavior is set for a NormSession. Note that this API does not enable the programmer to check if the NORM_NODE_NONE value itself is contained in the list. The programmer should keep track of that by other means. The following code example illustrates how to use this call to iterate through the set of stored NormNodeId values and get the current "acking status" for each: NormNodeId nextNodeId = NormGetNextAckingNode(session, true); while(NORM_NODE_NONE != nextNodeId) { NormAckingStatus ackingStatus = NormGetAckingStatus(session, nextNodeId); printf("ACKing node id = %lu acking status = %d\n", nextNodeId, (int)ackingStatus); }As noted below, a good time to check the acking status of the receiver set is after a NORM_TX_WATERMARK_COMPLETED notification has occurred. Return Values The function iteratively returns NormNodeId values from the given session's local sender "acking node" list. A value of NORM_NODE_NONE is returned when the end of the list is reached. NormGetAckingStatus() Synopsis #include <normApi.h> NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle, NormNodeId nodeId = NORM_NODE_ANY); Description This function queries the status of the watermark flushing process and/or positive acknowledgment collection initiated by a prior call to NormSetWatermark() for the given sessionHandle. In general, it is expected that applications will invoke this function after the corresponding NORM_TX_WATERMARK_COMPLETED event has been posted. Setting the default parameter value nodeId = NORM_NODE_ANY returns a "status" indication for the overall process. Also, individual nodeId values may be queried using the NormNodeId values of receivers that were included in previous calls to NormAddAckingNode() to populate the sender session's acking node list. If the flushing/acknowledgment process is being used for application flow control, the sender application may wish to reset the watermark and flushing process (using NormSetWatermark()) if the response indicates that some nodes have failed to respond. However, note that the flushing/acknowledgment process itself does elicit NACKs from receivers as needed and is interrupted and reset by any repair response that occurs. Thus, even by the time the flushing process has completed (and NORM_TX_WATERMARK_COMPLETED is posted) once, this is an indication that the NORM protocol has made a valiant attempt to deliver the content. Resetting the watermark process can increase robustness, but it may be in vain to repeat this process multiple times when likely network connectivity has been lost or expected receivers have failed (dropped out, shut down, etc). Return Values Possible return values include: NORM_ACK_INVALID The given sessionHandle is invalid or the given nodeId is not in the sender's acking list. NORM_ACK_FAILURE The positive acknowledgement collection process did not receive acknowledgment from every listed receiver (nodeId = NORM_NODE_ANY) or the identified nodeId did not respond. NORM_ACK_PENDING The flushing process at large has not yet completed (nodeId = NORM_NODE_ANY) or the given individual nodeId is still being queried for response. NORM_ACK_SUCCESS All receivers (nodeId = NORM_NODE_ANY) responded with positive acknowledgement or the given specific nodeId did acknowledge. NormSendCommand() Synopsis #include <normApi.h> bool NormSendCommand(NormSessionHandle session, const char* cmdBuffer, unsigned int cmdLength, bool robust = false); Description This function enqueues a NORM application-defined command for transmission. The cmdBuffer parameter points to a buffer containing the application-defined command content that will be contained in the NORM_CMD(APPLICATION) message payload. The cmdLength indicates the length of this content (in bytes) and MUST be less than or equal to the segmentLength value for the given session (see NormStartSender()). The NORM command transmission will be multiplexed with any NORM data transmission. The command is NOT delivered reliably, but can be optionally transmitted with repetition (once per GRTT) according to the NORM transmit robust factor value (see NormSetTxRobustFactor()) for the given session if the robust parameter is set to true. The command transmission is subject to any congestion control or set rate limits for the NORM session. Once the command has been transmitted (with repetition if robust is set to true), a NORM_TX_CMD_SENT notification is issued. An application can only enqueue a single command at a time (i.e. the NORM_TX_CMD_SENT notification must occur before another command can be sent). The NormCancelCommand() call is available to terminate command transmission if needed. Note that if a rapid succession of commands are sent it is possible that the commands may be delivered to the receivers out-of-order. Also, when repetition is requested (i.e., if robust is set to true) the receiver may receive duplicate copies of the same command. It is up to the application to provide any needed mechanism for detecting and/or filtering duplicate command reception. The application-defined command feature allows NORM applications to provide some out-of-band (with respect to reliable data delivery) signaling to support session management or other functions. The reception of these "atomic" commands is relatively stateless (as compared to reliable data delivery) and thus it is possible for many senders within a group to send commands without extreme resource burden on receivers (i.e. other participants). Again, this "light-weight" signaling mechanism may be used to provide ancillary communication for the group. In the future, an additional API mechanism will be provided to support application-defined positive acknowledgement requests that could conceivably be used to help guarantee command delivery if desired. Return Values The function returns true upon success. The function may fail, returning false, if the session is not set for sender operation (see NormStartSender()), the cmdLength exceeds the configured session segmentLength, or a previously-enqueued command has not yet been sent. NormCancelCommand() Synopsis #include <normApi.h> void NormCancelCommand(NormSessionHandle session); Description This function terminates any pending NORM_CMD(APPLICATION) transmission that was previously initiated with the NormSendCommand() call. Due to the asynchrony of the NORM protocol engine thread and the application, it is possible that the command may have been already sent but the NormCancelCommand() call will ensure a NORM_TX_CMD_SENT notification is not issued for that prior command. The application-defined command feature allows NORM applications to provide some out-of-band (with respect to reliable data delivery) signaling to support session management or other functions. The reception of these "atomic" commands is relatively stateless (as compared to reliable data delivery) and thus it is possible for many senders within a group to send commands without extreme resource burden on receivers (i.e. other participants). Again, this "light-weight" signaling mechanism may be used to provide ancillary communication for the group. In the future, an additional API mechanism will be provided to support application-defined positive acknowledgement requests that could conceivably be used to help guarantee command delivery if desired. Return Values The function has not return value. NORM Receiver Functions NormStartReceiver() Synopsis #include <normApi.h> bool NormStartReceiver(NormSessionHandle sessionHandle, unsigned long bufferSpace); Description This function initiates the application's participation as a receiver within the NormSession identified by the sessionHandle parameter. The NORM protocol engine will begin providing the application with receiver-related NormEvent notifications, and, unless NormSetSilentReceiver(true) is invoked, respond to senders with appropriate protocol messages. The bufferSpace parameter is used to set a limit on the amount of bufferSpace allocated by the receiver per active NormSender within the session. The appropriate bufferSpace to use is a function of expected network delay*bandwidth product and packet loss characteristics. A discussion of trade-offs associated with NORM transmit and receiver buffer space selection is provided later in this document. An insufficient bufferSpace allocation will result in potentially inefficient protocol operation, even though reliable operation may be maintained. In some cases of a large delay*bandwidth product and/or severe packet loss, a small bufferSpace allocation (coupled with the lack of explicit flow control in NORM) may result in the receiver "re-syncing" to the sender, resulting in "outages" in the reliable transmissions from a sender (this is analogous to a TCP connection timeout failure). Return Values A value of true is returned upon success and false upon failure. The reasons failure may occur include limited system resources or that the network sockets required for session communication failed to open or properly configure. NormStopReceiver() Synopsis #include <normApi.h> void NormStopReceiver(NormSessionHandle sessionHandle, unsigned int gracePeriod = 0); Description This function ends the application's participation as a receiver in the NormSession specified by the session parameter. By default, all receiver-related protocol activity is immediately halted and all receiver-related resources are freed (except for those which have been specifically retained (see NormNodeRetain() and NormObjectRetain()). However, and optional gracePeriod parameter is provided to allow the receiver an opportunity to inform the group of its intention. This is applicable when the local receiving NormNode has been designated as an active congestion control representative (i.e. current limiting receiver (CLR) or potential limiting receiver (PLR)). In this case, a non-zero gracePeriod value provides an opportunity for the receiver to respond to the applicable sender(s) so the sender will not expect further congestion control feedback from this receiver. The gracePeriod integer value is used as a multiplier with the largest sender GRTT to determine the actual time period for which the receiver will linger in the group to provide such feedback (i.e. "graceTime" = (gracePeriod * GRTT)). During this time, the receiver will not generate any requests for repair or other protocol actions aside from response to applicable congestion control probes. When the receiver is removed from the current list of receivers in the sender congestion control probe messages (or the gracePeriod expires, whichever comes first), the NORM protocol engine will post a NORM_LOCAL_RECEIVER_CLOSED event for the applicable session, and related resources are then freed. Return Values This function has no return values. NormSetRxCacheLimit() Synopsis #include <normApi.h> void NormSetRxCacheLimit(NormSessionHandle sessionHandle, unsigned short countMax); Description This function sets a limit on the number of outstanding (pending) NormObjects for which a receiver will keep state on a per-sender basis. Note that the value countMax sets a limit on the maximum consecutive range of objects that can be pending. The default value (when this function is not called) of countMax is 256. This should be sufficient for most bulk transfer usage, but if small object sizes (e.g. small NORM_OBJECT_DATA messages) are being transferred, it may be useful to raise this limit in cases of high transmission speeds or large <delay*bandwidth, loss> network conditions. If the receiver cache limit is set too small (i.e. for high speed or large <delay*bandwidth> operation), the receiver may not maintain reliable reception or impact session throughput when flow control is enabled (see NormSetFlowControl()). The maximum allowed value of countMax is 16,384. If this value is changed after NormStartReceiver() has been called, it will only affect newly-detected remote senders, so this should typically be called before NORM receiver operation is initiated. Return Values This function has no return value. NormSetRxSocketBuffer() Synopsis #include <normApi.h> bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle, unsigned int bufferSize); Description This function allows the application to set an alternative, non-default buffer size for the UDP socket used by the specified NORM sessionHandle for packet reception. This may be necessary for high speed NORM sessions where the UDP receive socket buffer becomes a bottleneck when the NORM protocol engine (which is running as a user-space process) doesn't get to service the receive socket quickly enough resulting in packet loss when the socket buffer overflows. The bufferSize parameter specifies the socket buffer size in bytes. Different operating systems and sometimes system configurations allow different ranges of socket buffer sizes to be set. Note that a call to NormStartReceiver() (or NormStartSender()) must have been previously made for this call to succeed (i.e., the socket must be already open). Return Values This function returns true upon success and false upon failure. Possible reasons for failure include, 1) the specified session is not valid, 2) that NORM "receiver" (or "sender") operation has not yet been started for the given session, or 3) an invalid bufferSize specification was given. NormSetSilentReceiver() Synopsis #include <normApi.h> void NormSetSilentReceiver(NormSessionHandle sessionHandle, bool silent, INT32 maxDelay = -1); Description This function provides the option to configure a NORM receiver application as a "silent receiver". This mode of receiver operation dictates that the host does not generate any protocol messages while operating as a receiver within the specified sessionHandle. Setting the silent parameter to true enables silent receiver operation while setting it to false results in normal protocol operation where feedback is provided as needed for reliability and protocol operation. Silent receivers are dependent upon proactive FEC transmission (see NormSetAutoParity()) or using repair information requested by other non-silent receivers within the group to achieve reliable transfers. The optional maxDelay parameter is most applicable for reception of the NORM_OBJECT_STREAM type. The default value of maxDelay = -1 corresponds to normal operation where source data segments for incompletely-received FEC coding blocks (or transport objects) are passed to the application only when imposed buffer constraints (either the NORM_OBJECT_STREAM buffer size (see NormStreamOpen()) or the FEC receive buffer limit (see NormStartReceiver()) require. Thus, the default behavior (maxDelay = -1), causes the receiver to buffer received FEC code blocks for as long as possible (within buffer constraints as newer data arrives) before allowing the application to read the data. Hence, the receive latency (delay) can be quite long depending upon buffer size settings, transmission rate, etc. When the maxDelay parameter is set to a non-negative value, the value determines the maximum number of FEC coding blocks (according to a NORM sender's current transmit position) the receiver will cache an incompletely-received FEC block before giving the application the (incomplete) set of received source segments. For example, a value of maxDelay = 0 will provide the receive application with any data from the previous FEC block as soon as a subsequent FEC block is begun reception. However, this provide no protection against the possibility of out-of-order delivery of packets by the network. Therefore, if lower latency operation is desired when using silent receivers, a minimum maxDelay value of 1 is recommended. For NORM_OBJECT_FILE and NORM_OBJECT_DATA, the only impact of a non-negative maxDelay value is that previous transport objects will be immediately aborted when subsequent object begin reception. Thus, it is not usually recommended to apply a non-negative maxDelay value when NORM_OBJECT_STREAM is not being used. Return Values This function has no return values. NormSetDefaultUnicastNack() Synopsis #include <normApi.h> void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle, bool enable); Description This function controls the default behavior determining the destination of receiver feedback messages generated while participating in the session. If the enable parameter is true, "unicast NACKing" is enabled for new remote senders while it is disabled for state equal to false. The NACKing behavior for current remote senders is not affected. When "unicast NACKing" is disabled (default), NACK messages are sent to the session address (usually a multicast address) and port, but when "unicast NACKing" is enabled, receiver feedback messages are sent to the unicast address (and port) based on the source address of sender messages received. For unicast NORM sessions, it is recommended that "unicast NACKing" be enabled. Note that receiver feedback messages subject to potential "unicast NACKing" include NACK-messages as well as some ACK messages such as congestion control feedback. Explicitly solicited ACK messages, such as those used to satisfy sender watermark acknowledgement requests (see NormSetWatermark()) are always unicast to the applicable sender. (TBD - provide API option so that all messages are multicast.) The default session-wide behavior for unicast NACKing can be overridden via the NormNodeSetUnicastNack() function for individual remote senders. Return Values This function has no return values. NormNodeSetUnicastNack() Synopsis #include <normApi.h> void NormNodeSetUnicastNack(NormNodeHandle senderNode, bool enable); Description This function controls the destination address of receiver feedback messages generated in response to a specific remote NORM sender corresponding to the senderNode parameter. If enable is true, "unicast NACKing" is enabled while it is disabled for enable equal to false. See the description of NormSetDefaultUnicastNack() for details on "unicast NACKing" behavior. Return Values This function has no return values. NormSetDefaultSyncPolicy() Synopsis #include <normApi.h> void NormSetDefaultSyncPolicy(NormSessionHandle sessionHandle, NormSyncPolicy syncPolicy); Description This function sets the default "synchronization policy" used when beginning (or restarting) reception of objects from a remote sender (i.e., "syncing" to the sender) for the given sessionHandle. The "synchronization policy" is the behavior observed by the receiver with regards to what objects it attempts to reliably receive (via transmissions of Negative Acknowledgements to the sender(s) or group as needed). There are currently two synchronization policy types defined: NORM_SYNC_CURRENT Attempt reception of "current" and new objects only. (default) NORM_SYNC_ALL Attempt recovery and reliable reception of all objects held in sender transmit object cache and newer objects. The behavior of a receiver using the default NORM_SYNC_CURRENT policy is to attempt reliable reception only for the first received "current" and newer (with respect to the ordinal NORM object transport identifiers used by the protocol) objects from a given NORM sender. Additionally, reliable reception is only attempted when receiving a non-repair NORM_DATA message (or optionally a NORM positive acknowledgement request) from the first forward error correction (FEC) encoding block of the given object. This somewhat conservative synchronization behavior helps prevent late-joining (or otherwise "flaky" with respect to group membership) receivers from penalizing other receivers in the group by causing the sender to "rewind" and transmit older object content to satisfy the late joiner instead of moving forward with transmission of new content. For large scale, loosely-organized multicast applications, the NORM_SYNC_CURRENT policy is typically recommended. The NORM_SYNC_ALL policy allows newly joining receivers much more aggressive behavior as they will immediately NACK for all objects from the "current" object backwards through the entire range of objects set by the NormSetRxCacheLimit() function. This behavior depends upon the sender to issue an appropriate NORM_CMD(SQUELCH) response (if applicable) to align (i.e. "synchronize") the new receiver with its current transmit object cache (similar to a "repair window"). This synchronization behavior may be useful for unicast uses of NORM or other applications where the group membership is more carefully managed and it is important that all content (including older content) is received. Note that the sender transmit cache bounds (see NormSetTxCacheBounds()) and the receiver receive cache limit (see NormSetRxCacheLimit()) settings will limit how far back onto the sender transmission history that transmitted objects can be reliably recovered from the "current" transmission point when the receiver begins reception. When this function is not invoked, the NORM_SYNC_CURRENT behavior is observed as the default receiver synchronization policy. This call SHOULD be made before NormStartReceiver() is called. Return Values This function has no return values. NormSetDefaultNackingMode() Synopsis #include <normApi.h> void NormSetDefaultNackingMode(NormSessionHandle sessionHandle, NormNackingMode nackingMode); Description This function sets the default "nacking mode" used when receiving objects for the given sessionHandle. This allows the receiver application some control of its degree of participation in the repair process. By limiting receivers to only request repair of objects in which they are really interested in receiving, some overall savings in unnecessary network loading might be realized for some applications and users. Available nacking modes include: NORM_NACK_NONE Do not transmit any repair requests for the newly received object. NORM_NACK_INFO_ONLY Transmit repair requests for NORM_INFO content only as needed. NORM_NACK_NORMAL Transmit repair requests for entire object as needed. This function specifies the default behavior with respect to any new sender or object. This default behavior may be overridden for specific sender nodes or specific object using NormNodeSetNackingMode() or NormObjectSetNackingMode(), respectively. The receiver application's use of NORM_NACK_NONE essentially disables a guarantee of reliable reception, although the receiver may still take advantage of sender repair transmissions in response to other receivers' requests. When the sender provides, NORM_INFO content for transmitted objects, the NORM_NACK_INFO_ONLY mode may allows the receiver to reliably receive object context information from which it may choose to "upgrade" its nackingMode for the specific object via the NormObjectSetNackingMode() call. Similarly, the receiver may changes its default nackingMode with respect to specific senders via the NormNodeSetNackingMode() call. The default "default nackingMode" when this call is not made is NORM_NACK_NORMAL. Return Values This function has no return values. NormNodeSetNackingMode() Synopsis #include <normApi.h> void NormNodeSetNackingMode(NormNodeHandle nodeHandle, NormNackingMode nackingMode); Description This function sets the default "nacking mode" used for receiving new objects from a specific sender as identified by the nodeHandle parameter. This overrides the default nackingMode set for the receive session. See NormSetDefaultNackingMode() for a description of possible nackingMode parameter values and other related information. Return Values This function has no return values. NormObjectSetNackingMode() Synopsis #include <normApi.h> void NormObjectSetNackingMode(NormObjectHandle objectHandle, NormNackingMode nackingMode); Description This function sets the "nacking mode" used for receiving a specific transport object as identified by the objectHandle parameter. This overrides the default nacking mode set for the applicable sender node. See NormSetDefaultNackingMode() for a description of possible nackingMode parameter values and other related information. Return Values This function has no return values. NormSetDefaultRepairBoundary() Synopsis #include <normApi.h> void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle, NormRepairBoundary repairBoundary); Description This function allows the receiver application to customize, for a given sessionHandle, at what points the receiver initiates the NORM NACK repair process during protocol operation. Normally, the NORM receiver initiates NACKing for repairs at the FEC code block and transport object boundaries. For smaller block sizes, the NACK repair process is often/quickly initiated and the repair of an object will occur, as needed, during the transmission of the object. This default operation corresponds to repairBoundary equal to NORM_BOUNDARY_BLOCK. Using this function, the application may alternatively, setting repairBoundary equal to NORM_BOUNDARY_OBJECT, cause the protocol to defer NACK process initiation until the current transport object has been completely transmitted. Return Values This function has no return values. NormNodeSetRepairBoundary() Synopsis #include <normApi.h> void NormNodeSetRepairBoundary(NormNodeHandle nodeHandle, NormRepairBoundary repairBoundary); Description This function allows the receiver application to customize, for the specific remote sender referenced by the nodeHandle parameter, at what points the receiver initiates the NORM NACK repair process during protocol operation. See the description of NormSetDefaultRepairBoundary() for further details on the impact of setting the NORM receiver repair boundary and possible values for the repairBoundary parameter. Return Values This function has no return values. NormSetDefaultRxRobustFactor() Synopsis #include <normApi.h> void NormSetDefaultRxRobustFactor(NormSessionHandle sessionHandle, int rxRobustFactor); Description This routine controls how persistently NORM receivers will maintain state for sender(s) and continue to request repairs from the sender(s) even when packet reception has ceased. The rxRobustFactor value determines how many times a NORM receiver will self-initiate NACKing (repair requests) upon cessation of packet reception from a sender. The default value is 20. Setting rxRobustFactor to -1 will make the NORM receiver infinitely persistent (i.e., it will continue to NACK indefinitely as long as it is missing data content). It is important to note that the NormSetTxRobustFactor() also affects receiver operation in setting the time interval that is used to gauge that sender packet transmission has ceased (i.e., the sender inactivity timeout). This "timeout" interval is a equal of (2 * GRTT * txRobustFactor). Thus the overall timeout before a NORM receiver quits NACKing is (rxRobustFactor * 2 * GRTT * txRobustFactor). The NormNodeSetRxRobustFactor() function can be used to control this behavior on a per-sender basis. When a new remote sender is detected, the default rxRobustFactor set here is used. Again, the default value is 20. Return Values This function has no return values. NormNodeSetRxRobustFactor() Synopsis #include <normApi.h> void NormNodeSetRxRobustFactor(NormNodeHandle nodeHandle, int rxRobustFactor); Description This routine sets the rxRobustFactor as described in NormSetDefaultRxRobustFactor() for an individual remote sender identified by the nodeHandle parameter. See the description of NormSetDefaultRxRobustFactor() for details Return Values This function has no return values. NormStreamRead() Synopsis #include <normApi.h> bool NormStreamRead(NormObjectHandle streamHandle, char* buffer unsigned int* numBytes); Description This function can be used by the receiver application to read any available data from an incoming NORM stream. NORM receiver applications "learn" of available NORM streams via NORM_RX_OBJECT_NEW notification events. The streamHandle parameter here must correspond to a valid NormObjectHandle value provided during such a prior NORM_RX_OBJECT_NEW notification. The buffer parameter must be a pointer to an array where the received data can be stored of a length as referenced by the numBytes pointer. On successful completion, the numBytes storage will be modified to indicate the actual number of bytes copied into the provided buffer. If the numBytes storage is modified to a zero value, this indicates that no stream data was currently available for reading. Note that NormStreamRead() is never a blocking call and only returns failure (false) when a break in the integrity of the received stream occurs. The NORM_RX_OBJECT_UPDATE provides an indication to when there is stream data available for reading. When such notification occurs, the application should repeatedly read from the stream until the numBytes storage is set to zero, even if a false value is returned. Additional NORM_RX_OBJECT_UPDATE notifications might not be posted until the application has read all available data. Return Values This function normally returns a value of true. However, if a break in the integrity of the reliable received stream occurs (or the stream has been ended by the sender), a value of false is returned to indicate the break. Unless the stream has been ended (and the receiver application will receive NORM_RX_OBJECT_COMPLETED notification for the stream in that case), the application may continue to read from the stream as the NORM protocol will automatically "resync" to streams, even if network conditions are sufficiently poor that breaks in reliability occur. If such a "break" and "resync" occurs, the application may be able to leverage other NORM API calls such as NormStreamSeekMsgStart() or NormStreamGetReadOffset() if needed to recover its alignment with received stream content. This depends upon the nature of the application and its stream content. NormStreamSeekMsgStart() Synopsis #include <normApi.h> bool NormStreamSeekMsgStart(NormObjectHandle streamHandle); Description This function advances the read offset of the receive stream referenced by the streamHandle parameter to align with the next available message boundary. Message boundaries are defined by the sender application using the NormStreamMarkEom() call. Note that any received data prior to the next message boundary is discarded by the NORM protocol engine and is not available to the application (i.e., there is currently no "rewind" function for a NORM stream). Also note this call cannot be used to skip messages. Once a valid message boundary is found, the application must read from the stream using NormStreamRead() to further advance the read offset. The current offset (in bytes) for the stream can be retrieved via NormStreamGetReadOffset(). Return Values This function returns a value of true when start-of-message is found. The next call to NormStreamRead() will retrieve data aligned with the message start. If no new message boundary is found in the buffered receive data for the stream, the function returns a value of false. In this case, the application should defer repeating a call to this function until a subsequent NORM_RX_OBJECT_UPDATE notification is posted. NormStreamGetReadOffset() Synopsis #include <normApi.h> unsigned long NormStreamGetReadOffset(NormObjectHandle streamHandle); Description This function retrieves the current read offset value for the receive stream indicated by the streamHandle parameter. Note that for very long-lived streams, this value may wrap. Thus, in general, applications should not be highly dependent upon the stream offset, but this feature may be valuable for certain applications which associate some application context with stream position. Return Values This function returns the current read offset in bytes. The return value is undefined for sender streams. There is no error result. NORM Object Functions The functions described in this section may be used for sender or receiver purposes to manage transmission and reception of NORM transport objects. In most cases, the receiver will be the typical user of these functions to retrieve additional information on newly-received objects. All of these functions require a valid NormObjectHandle argument which specifies the applicable object. Note that NormObjectHandle values obtained from a NormEvent notification may be considered valid only until a subsequent call to NormGetNextEvent(), unless explicitly retained by the application (see NormObjectRetain()). NormObjectHandle values obtained as a result of NormFileEnqueue(), NormDataEnqueue(), or NormStreamOpen() calls can be considered valid only until a corresponding NORM_TX_OBJECT_PURGED notification is posted or the object is dequeued using NormObjectCancel(), unless, again, otherwise explicitly retained (see NormObjectRetain()). NormObjectGetType() Synopsis #include <normApi.h> NormObjectType NormObjectGetType(NormObjectHandle objectHandle); Description This function can be used to determine the object type ((NORM_OBJECT_DAT, NORM_OBJECT_FILE, or NORM_OBJECT_STREAM) for the NORM transport object identified by the objectHandle parameter. The objectHandle must refer to a current, valid transport object. Return Values This function returns the NORM object type. Valid NORM object types include NORM_OBJECT_DATA, NORM_OBJECT_FILE, or NORM_OBJECT_STREAM. A type value of NORM_OBJECT_NONE will be returned for an objectHandle value of NORM_OBJECT_INVALID. NormObjectHasInfo() Synopsis #include <normApi.h> bool NormObjectHasInfo(NormObjectHandle objectHandle); Description This function can be used to determine if the sender has associated any NORM_INFO content with the transport object specified by the objectHandle parameter. This can even be used before the NORM_INFO content is delivered to the receiver and a NORM_RX_OBJECT_INFO notification is posted. Return Values A value of true is returned if NORM_INFO is (or will be) available for the specified transport object. A value of false is returned otherwise. NormObjectGetInfoLength() Synopsis #include <normApi.h> unsigned short NormObjectGetInfoLength(NormObjectHandle objectHandle); Description This function can be used to determine the length of currently available NORM_INFO content (if any) associated with the transport object referenced by the objectHandle parameter. Return Values The length of the NORM_INFO content, in bytes, of currently available for the specified transport object is returned. A value of 0 is returned if no NORM_INFO content is currently available or associated with the object. NormObjectGetInfo() Synopsis #include <normApi.h> unsigned short NormObjectGetInfo(NormObjectHandle objectHandle, char* buffer, unsigned short bufferLen); Description This function copies any NORM_INFO content associated (by the sender application) with the transport object specified by objectHandle into the provided memory space referenced by the buffer parameter. The bufferLen parameter indicates the length of the buffer space in bytes. If the provided bufferLen is less than the actual NORM_INFO length, a partial copy will occur. The actual length of NORM_INFO content available for the specified object is returned. However, note that until a NORM_RX_OBJECT_INFO notification is posted to the receive application, no NORM_INFO content is available and a zero result will be returned, even if NORM_INFO content may be subsequently available. The NormObjectHasInfo() call can be used to determine if any NORM_INFO content will ever be available for a specified transport object (i.e., determine if the sender has associated any NORM_INFO with the object in question). Return Values The actual length of currently available NORM_INFO content for the specified transport object is returned. This function can be used to determine the length of NORM_INFO content for the object even if a NULL buffer value and zero bufferLen is provided. A zero value is returned if NORM_INFO content has not yet been received (or is non-existent) for the specified object. NormObjectGetSize() Synopsis #include <normApi.h> NormSize NormObjectGetSize(NormObjectHandle objectHandle); Description This function can be used to determine the size (in bytes) of the transport object specified by the objectHandle parameter. NORM can support large object sizes for the NORM_OBJECT_FILE type, so typically the NORM library is built with any necessary, related macros defined such that operating system large file support is enabled (e.g., "#define _FILE_OFFSET_BITS 64" or equivalent). The NormSize type is defined accordingly, so the application should be built with the same large file support configuration. For objects of type NORM_OBJECT_STREAM, the size returned here corresponds to the stream buffer size set by the sender application when opening the referenced stream object. Return Values A size of the data content of the specified object, in bytes, is returned. Note that it may be possible that some objects have zero data content, but do have NORM_INFO content available. NormObjectGetBytesPending() Synopsis #include <normApi.h> NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle); Description This function can be used to determine the progress of reception of the NORM transport object identified by the objectHandle parameter. This function indicates the number of bytes that are pending reception (I.e., when the object is completely received, "bytes pending" will equal ZERO). This function is not necessarily applicable to objects of type NORM_OBJECT_STREAM which do not have a finite size. Note it is possible that this function might also be useful to query the "transmit pending" status of sender objects, but it does not account for pending FEC repair transmissions and thus may not produce useful results for this purpose. Return Values A number of object source data bytes pending reception (or transmission) is returned. NormObjectCancel() Synopsis #include <normApi.h> void NormObjectCancel(NormObjectHandle objectHandle); Description This function immediately cancels the transmission of a local sender transport object or the reception of a specified object from a remote sender as specified by the objectHandle parameter. The objectHandle must refer to a currently valid NORM transport object. Any resources used by the transport object in question are immediately freed unless the object has been otherwise retained by the application via the NormObjectRetain() call. Unless the application has retained the object in such fashion, the object in question should be considered invalid and the application must not again reference the objectHandle after this call is made. If the canceled object is a sender object not completely received by participating receivers, the receivers will be informed of the object's cancellation via the NORM protocol NORM_CMD(SQUELCH) message in response to any NACKs requesting repair or retransmission of the applicable object. In the case of receive objects, the NORM receiver will not make further requests for repair of the indicated object, but furthermore, will acknowledge the object as completed with respect to any associated positive acknowledgement requests (see NormSetWatermark()). Return Values This function has no return value. NormObjectRetain() Synopsis #include <normApi.h> void NormObjectRetain(NormObjectHandle objectHandle); Description This function "retains" the objectHandle and any state associated with it for further use by the application even when the NORM protocol engine may no longer require access to the associated transport object. Normally, the application is guaranteed that a given NormObjectHandle is valid only while it is being actively transported by NORM (i.e., for sender objects, from the time an object is created by the application until it is canceled by the application or purged (see the NORM_TX_OBJECT_PURGED notification) by the protocol engine, or, for receiver objects, from the time of the object's NORM_RX_OBJECT_NEW notification until its reception is canceled by the application or a NORM_RX_OBJECT_COMPLETED or NORM_RX_OBJECT_ABORTED notification is posted). Note that an application may refer to a given object after any related notification until the application makes a subsequent call to NormGetNextEvent(). When the application makes a call to NormObjectRetain() for a given objectHandle, the application may use that objectHandle value in any NORM API calls until the application makes a call to NormObjectRelease() for the given object. Note that the application MUST make a corresponding call to NormObjectRelease() for each call it has made to NormObjectRetain() in order to free any system resources (i.e., memory) used by that object. Also note that retaining a receive object also automatically retains any state associated with the NormNodeHandle corresponding to the remote sender of that receive object so that the application may use NORM node API calls for the value returned by NormObjectGetSender() as needed. Return Values This function has no return value. NormObjectRelease() Synopsis #include <normApi.h> void NormObjectRelease(NormObjectHandle objectHandle); Description This function complements the NormObjectRetain() call by immediately freeing any resources associated with the given objectHandle, assuming the underlying NORM protocol engine no longer requires access to the corresponding transport object. Note the NORM protocol engine retains/releases state for associated objects for its own needs and thus it is very unsafe for an application to call NormObjectRelease() for an objectHandle for which it has not previously explicitly retained via NormObjectRetain(). Return Values This function has no return value. NormFileGetName() Synopsis #include <normApi.h> bool NormFileGetName(NormObjectHandle objectHandle, char* nameBuffer, unsigned int bufferLen); Description This function copies the name, as a NULL-terminated string, of the file object specified by the objectHandle parameter into the nameBuffer of length bufferLen bytes provided by the application. The objectHandle parameter must refer to a valid NormObjectHandle for an object of type NORM_OBJECT_FILE. If the actual name is longer than the provided bufferLen, a partial copy will occur. Note that the file name consists of the entire path name of the specified file object and the application should give consideration to operating system file path lengths when providing the nameBuffer. Return Values This function returns true upon success and false upon failure. Possible failure conditions include the objectHandle does not refer to an object of type NORM_OBJECT_FILE. NormFileRename() Synopsis #include <normApi.h> bool NormFileRename(NormObjectHandle objectHandle, const char* fileName); Description This function renames the file used to store content for the NORM_OBJECT_FILE transport object specified by the objectHandle parameter. This allows receiver applications to rename (or move) received files as needed. NORM uses temporary file names for received files until the application explicitly renames the file. For example, sender applications may choose to use the NORM_INFO content associated with a file object to provide name and/or typing information to receivers. The fileName parameter must be a NULL-terminated string which should specify the full desired path name to be used. NORM will attempt to create sub-directories as needed to satisfy the request. Note that existing files of the same name may be overwritten. Return Values This function returns true upon success and false upon failure. Possible failure conditions include the case where the objectHandle does not refer to an object of type NORM_OBJECT_FILE and where NORM was unable to successfully create any needed directories and/or the file itself. NormDataAccessData() Synopsis #include <normApi.h> const char* NormDataAccessData(NormObjectHandle objectHandle); Description This function allows the application to access the data storage area associated with a transport object of type NORM_OBJECT_DATA. For example, the application may use this function to copy the received data content for its own use. Alternatively, the application may establish "ownership" for the allocated memory space using the NormDataDetachData() function if it is desired to avoid the copy. If the object specified by the objectHandle parameter has no data content (or is not of type NORM_OBJECT_DATA), a NULL value may be returned. The application MUST NOT attempt to modify the memory space used by NORM_OBJECT_DATA objects during the time an associated objectHandle is valid. The length of data storage area can be determined with a call to NormObjectGetSize() for the same objectHandle value. Return Values This function returns a pointer to the data storage area for the specified transport object. A NULL value may be returned if the object has no associated data content or is not of type NORM_OBJECT_DATA. NormDataDetachData() Synopsis #include <normApi.h> char* NormDataDetachData(NormObjectHandle objectHandle); Description This function allows the application to disassociate data storage allocated by the NORM protocol engine for a receive object from the NORM_OBJECT_DATA transport object specified by the objectHandle parameter. It is important that this function is called after the NORM protocol engine has indicated it is finished with the data object (i.e., after a NORM_TX_OBJECT_PURGED, NORM_RX_OBJECT_COMPLETED, or NORM_RX_OBJECT_ABORTED notification event). But the application must call NormDataDetachData() before a call is made to NormObjectCancel() or NormObjectRelease() for the object if it plans to access the data content afterwards. Otherwise, the NORM protocol engine will free the applicable memory space when the associated NORM_OBJECT_DATA transport object is deleted and the application will be unable to access the received data unless it has previously copied the content. Once the application has used this call to "detach" the data content, it is the application's responsibility to subsequently free the data storage space as needed. Return Values This function returns a pointer to the data storage area for the specified transport object. A NULL value may be returned if the object has no associated data content or is not of type NORM_OBJECT_DATA. NormObjectGetSender() Synopsis #include <normApi.h> NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle); Description This function retrieves the NormNodeHandle corresponding to the remote sender of the transport object associated with the given objectHandle parameter. Note that the returned NormNodeHandle value is only valid for the same period that the objectHandle is valid. The returned NormNodeHandle may optionally be retained for further use by the application using the NormNodeRetain() function call. The returned value can be used in the NORM Node Functions described later in this document. Return Values This function returns the NormNodeHandle corresponding to the remote sender of the transport object associated with the given objectHandle parameter. A value of NORM_NODE_INVALID is returned if the specified objectHandle references a locally originated, sender object. NORM Node Functions The functions described in this section may be used for NORM sender or receiver (most typically receiver) purposes to retrieve additional information about a remote NormNode, given a valid NormNodeHandle. Note that, unless specifically retained (see NormNodeRetain()), a NormNodeHandle provided in a NormEvent notification should be considered valid only until a subsequent call to NormGetNextEvent() is made. NormNodeHandle values retrieved using NormObjectGetSender() can be considered valid for the same period of time as the corresponding NormObjectHandle is valid. NormNodeGetId() Synopsis #include <normApi.h> NormNodeId NormNodeGetId(NormNodeHandle nodeHandle); Description This function retrieves the NormNodeId identifier for the remote participant referenced by the given nodeHandle value. The NormNodeId is a 32-bit value used within the NORM protocol to uniquely identify participants within a NORM session. The participants identifiers are assigned by the application or derived (by the NORM API code) from the host computers default IP address. Return Values This function returns the NormNodeId value associated with the specified nodeHandle. In the case nodeHandle is equal to NORM_NODE_INVALID, the return value will be NORM_NODE_NONE. NormNodeGetAddress() Synopsis #include <normApi.h> bool NormNodeGetAddress(NormNodeHandle nodeHandle, char* addrBuffer, unsigned int* bufferLen, unsigned short* port = NULL); Description This function retrieves the current network source address detected for packets received from remote NORM sender referenced by the nodeHandle parameter. The addrBuffer must be a pointer to storage of bufferLen bytes in length in which the referenced sender node's address will be returned. Optionally, the remote sender source port number (see NormSetTxPort()) is also returned if the optional port pointer to storage parameter is provided in the call. Note that in the case of Network Address Translation (NAT) or other firewall activities, the source address detected by the NORM receiver may not be the original address of the original NORM sender. Return Values A value of true is returned upon success and false upon failure. An invalid nodeHandle parameter value would lead to such failure. NormNodeGetGrtt() Synopsis #include <normApi.h> double NormNodeGetGrtt(NormNodeHandle nodeHandle); Description This function retrieves the advertised estimate of group round-trip timing (GRTT) for the remote sender referenced by the given nodeHandle value. Newly-starting senders that have been participating as a receiver within a group may wish to use this function to provide a more accurate startup estimate of GRTT (see NormSetGrttEstimate()) prior to a call to NormStartSender(). Applications may use this information for other purpose as well. Note that the NORM_GRTT_UPDATED event is posted (see NormGetNextEvent()) by the NORM protocol engine to indicate when changes in the local sender or remote senders' GRTT estimate occurs. Return Values This function returns the remote sender's advertised GRTT estimate in units of seconds. A value of -1.0 is returned upon failure. An invalid nodeHandle parameter value will lead to such failure. NormNodeGetCommand() Synopsis #include <normApi.h> bool NormNodeGetCommand(NormNodeHandle nodeHandle, char* buffer, unsigned int* buflen); Description This function retrieves the content of an application-defined command that was received from a remote sender associated with the given nodeHandle. This call should be made in response to the NORM_RX_CMD_NEW notification. This notification is issued for each command received. However the application may use this call to poll for received commands if desired. Additionally, the received command length can be "queried" by setting the value referenced by the buflen parameter to ZERO. Upon return, this value referenced by the buflen parameter is adjusted to reflect the command length. Then a subsequent call to NormNodeGetCommand() can be made with an appropriately-sized buffer to retrieve the received command content. The command size will be less than or equal to the NORM segment size configured for the given remote sender. Note that if a rapid succession of commands are sent it is possible that the commands may be delivered to the receivers out-of-order. Also, when repetition is requested (i.e., if robust is set to true) the receiver may receive duplicate copies of the same command. It is up to the application to provide any needed mechanism for detecting and/or filtering duplicate command reception. Return Values This function returns true upon successful retrieval of command content. A return value of false indicates that either no command was available or the provided buffer size (buflen parameter) was inadequate. The value referenced by the buflen parameter is adjusted to indicate the actual command length (in bytes) upon return. NormNodeFreeBuffers() Synopsis #include <normApi.h> void NormNodeFreeBuffers(NormNodeHandle nodeHandle); Description This function releases memory resources that were allocated for a remote sender. For example, the receiver application may wish to free memory resources when receiving a NORM_REMOTE_SENDER_INACTIVE notification for a given remote sender when multiple senders may be providing content. The NORM protocol engine allocates memory for reliable transport buffering on a per sender basis according to the limit set in the NormStartReceiver() call. These buffering resources comprise the majority of the state allocated for a given remote sender. For NORM applications with possibly multiple senders active at different times, this function can be used to manage to amount of memory allocated for reliable reception. If a sender becomes "active" again after a call to NormNodeFreeBuffers(), new memory resources will be allocated. Note that state for any pending (uncompleted) objects will be dropped when this function is called and the receiver may request retransmission and repair of content if the sender once again becomes "active". The application SHOULD call NormObjectCancel() for any pending objects before calling NormNodeFreeBuffers() if it wishes to never receive those pending objects. Alternatively, a call to NormNodeDelete() will completely eliminate all state for a given remote sender and, if that sender becomes "active" again, it will be treated as a completely new sender. Return Values This function has no return value. NormNodeDelete() Synopsis #include <normApi.h> void NormNodeDelete(NormNodeHandle nodeHandle); Description This function can be used by a NORM receiver application to completely remove the state associated with a remote sender for the given nodeHandle. For example, when a NORM_REMOTE_SENDER_INACTIVE notification occurs for a given sender, the application may wish to completely free all associated resources. Note this is distinct from the NormNodeFreeBuffers() call where only the buffering resources are freed and other state pertaining to the sender is kept. If the deleted sender again becomes "active", it will be treated as a brand new sender. Unless explicitly retained with a call to NormNodeRetain(), the nodeHandle should be considered invalid after this call is made. Additionally, any NormObjectHandle values for pending objects from this sender are also invalidated (unless otherwise retained), although NORM_RX_OBJECT_ABORTED notifications may be issued for those pending objects. Return Values This function has no return value. NormNodeRetain() Synopsis #include <normApi.h> void NormNodeRetain(NormNodeHandle nodeHandle); Description In the same manner as the NormObjectRetain() function, this function allows the application to retain state associated with a given nodeHandle value even when the underlying NORM protocol engine might normally free the associated state and thus invalidate the NormNodeHandle. If the application uses this function, it must make a corresponding call to NormNodeRelease() when finished with the node information to avoid a memory leak condition. NormNodeHandle values (unless retained) are valid from the time of a NORM_REMOTE_SENDER_NEW notification until a complimentary NORM_REMOTE_SENDER_PURGED notification. During that interval, the application will receive NORM_REMOTE_SENDER_ACTIVE and NORM_REMOTE_SENDER_INACTIVE notifications according to the sender's message transmission activity within the session. It is important to note that, if the NORM protocol engine posts a NORM_REMOTE_SENDER_PURGED notification for a given NormNodeHandle, the NORM protocol engine could possibly, subsequently establish a new, different NormNodeHandle value for the same remote sender (i.e., one of equivalent NormNodeId) if it again becomes active in the session. A new NormNodeHandle may likely be established even if the application has retained the previous NormNodeHandle value. Therefore, to the application, it might appear that two different senders with the same NormNodeId are participating if these notifications are not carefully monitored. This behavior is contingent upon how the application has configured the NORM protocol engine to manage resources when there is potential for a large number of remote senders within a session (related APIs are TBD). For example, the application may wish to control which specific remote senders for which it keeps state (or limit the memory resources used for remote sender state, etc) and the NORM API may be extended in the future to control this behavior. Return Values This function has no return value. NormNodeRelease() Synopsis #include <normApi.h> void NormNodeRelease(NormNodeHandle nodeHandle); Description In complement to the NormNodeRetain() function, this API call releases the specified nodeHandle so that the NORM protocol engine may free associated resources as needed. Once this call is made, the application should no longer reference the specified NormNodeHandle, unless it is still valid. Return Values This function has no return value. NORM Debugging Functions This section describes some additional function calls that are available to set debugging output options and control other aspects of the NORM implementation. NormSetDebugLevel() Synopsis #include <normApi.h> void NormSetDebugLevel(unsigned int level); Description This function controls the verbosity of NORM debugging output. Higher values of level result in more detailed output. The highest level of debugging is 12. The debug output consists of text written to STDOUT by default but may be directed to a log file using the NormOpenDebugLog() function. Return Values This function has no return value. NormOpenDebugLog() Synopsis #include <normApi.h> bool NormOpenDebugLog(NormInstanceHandle instance, const char* fileName); Description This function allows NORM debug output to be directed to a file instead of the default STDERR. Return Values The function returns true on success. If the specified file cannot be opened a value of false is returned. NormCloseDebugLog() Synopsis #include <normApi.h> bool NormCloseDebugLog(NormInstanceHandle instance); Description TBD Return Values TBD NormOpenDebugPipe() Synopsis #include <normApi.h> bool NormOpenDebugPipe(NormInstanceHandle instance, const char* pipeName); Description TBD Return Values TBD NormCloseDebugPipe() Synopsis #include <normApi.h> bool NormCloseDebugPipe(NormInstanceHandle instance); Description TBD Return Values TBD
norm-1.5.8+dfsg2/doc/NormLogo.gif0000644000000000000000000003064511156550135013371 0ustar GIF89aùî÷1*† 0‘&4‘+5˜+7’-8š,8œ-E™(H*]ž&k€l j—t‰sˆ)}“”~”)Yo>ZpP/EdUj\tsk€.f~CiNhcgn=Ž6rŠ9rŠJq‰Vr‹eo‡r;•2D“;F•=z’;|“9Q—Jz“c–J}–[}–q;Ÿ0@Ÿ6LœC[ TA§6I²=N¹BP¼DQ¼DUºBw·7U¬LT¹IT½Ia¨Y_±Vs°lYÈL`ÑS`ÔTd×VfÙZjß\pæctífzöl†œ‰Ÿ"–­$ ·*Œ¡9™±5—­B´5µ?¡¸3¡¸=„N’ªN—°NŸµM…žfˆ¢o”®_Нp“­k›²]™´j¢¸n«Â1«Ä>¨¿M¨À^©Áo•ÌA¯Í?²Ê<²Ê<³Ë;³Ò>²ÌY´Îe³Înÿr€ôs‚øt®Étƒõu³Îs‚ÿt»Ó;ÄÞDËäHÒìI¿Ù]¸Ðp½ØjÆáWÑëTâúUìÿ[%~,‡0 5Œ"9š.B’,Bž)A¤4H—9L”7O„Jc€@Q˜8MšEV2H¢?S¢M^£+D©1J¯8O¬BWªMaª5P¹>W¼TåfF¢!…î'^ynbã&œäx㎚ôè£&ÅAø!$92¢‰HŠF! ®H[$–dcŒb‚ÉŽ9f©e–;vÙ¥&™ç¡z752‰*ž%©&Yù,¢âs•P8%•Åá¸åxz©§áirœ%Bb…“ƒÊ¤¹æ¡F)3}“À©¡~sV¨ ž”â¹Êž^Y埂â4‰#¨ *êKù’bƒµEb¥…‘^2i¥°Þÿ‰©—t‚ש§þŒª+J¥1ú\«1¾ë°ZÎÚe­—d×­bè®ÐT* V9 I˜È^bã*«ëmŽ—k£¦T'YVˆ bÈtѶK*€Ð‰$óJ"e¶6rÒí·üŠ{c¶­ùÓ Ì¸ë®M æU ¾›ÀÂïÃ:ú» ²º‰ €òH®ëÚˆŠy·jŒ6: 1ÄáŠK.äA²Ó $v¬æÇôÑ‹Œ­–|òΜHåj궪ծBpKĦrø2V0Ѭ¹áZt—!°âé­)ôiýè T»6Ξ9bf>å²<"ý °ñGUf)mIU~p}ÜÜ¸ÇØŸ:–n±šì²#ˆ?ü³‘Øl ÿù¨­Zªê\[Ú“:²[ŠÿFÀV üØìúä¦ðÅJmÄíözë[»WK=ʦ*Sˆ×–²\n\(Ô´ç2nº¼¥.CO{Ý,…õ\©%1Ë(r6C"I›^õÊ“½Ã²`Å,‘Ĭ »0õ`úh:¡: K~V\lý OÇʈ—ùDY(¦u¼~pn³´_¡Rxž>¥7D¾@ñ•îèèpð›,œæV¥$¶ë‰ÿûÛ‰©Ù‰+aúˆŽÂ…Æ™ø¬)Ubiî8¨=¾ðíÂÚŒ-µ¾§¢©œòú\Ç>ù)žè 1— úÍy•4EG¯‚_L\³ÿËsÔ*7æ<çwÒ¹®¼lod¿Hæ2¯ÅoÆÕè ¨õçõz œ°çÜ…~yÑŽ^oýôÌ Šê+.Û Lÿ°`¸çÐå…U“ÙùèRËux”¶ô¥ Á“!Ãø«¤¥›o{[8O×Ôž´_˜‰Rˆ€!Ø€#îÂGøó0±ÆÏmoŠÛ´ASÑóŒ´zeÑ \àÂZxÂn‘ d´¢¡«C¨ …VÌb×>JÖ %¸; ˆ!vr:Ùpqó¸ ª%¢BÚð´F.¸/@a V8†Ü~*‹^Tááw·œ „$X< '8Š0œaÝ^¨ø(¨I©á ÿ‡B»+®Ÿhº˜õu*› ëÈ^{"ÉnÍbã–a‹-4Á ¡È*CeÑ…3|ä^ˆ‚Å‘àŠ’ö PGúº%Þî‹'ሔ·‹2œá eøÂÑݽÊaׂWGùºçÀv:Ì! †ØÉ‹H §Î42>E¦ž 2bgwÅM ZyÊb_øúÇ‘®ô$  mƼò£¯û s êP;ÔAósðBÖÁì¸V(þôsà|šÐºJÿˆ!GB:o‡ÚÛ> ?¡F1Eawñb¢_Ãâc_ ãY ^/ƒà“@ø«ÂS`?}2¯zÎÓá Ç€'7dá„Ä}ñÔ§ƒÿô`ûò×þóeˆFO/|=õ´·}2Z¿ï½\ æ/ÿOQÌE%[.V0yŠwys ©Ð:£Ð^|ÔÇyMà|î$ Â}˜ùW¸`g²ðI xe°yã—"h{z° §¦í·y"¨­³#Àrs0‚a`€PL±ô–0  §§‚µ§«W €>X~Ï0 Ò&§‡œ7‚å×î´PHÀgP„N8‚{€§V HX~u„”³#¸n_h{W@ƒÅd_âU  î·ywP~w°p¥p†µ‡HèNÖàuŠ—zWh~ÐÐN µ'ׄƒx…y@ÒÿÕ8Wàxø7‚ÍP97r(ˆ"Ø 4ˆ`”éRh‘ Ÿð^H~ù·­DVp“˜Ziø~zè„zÐNÝ@ Spuµh{{°tp…wðˆ³0—Nø–¸ ¨|‰W‹z€®VCu:Q , HŒ"xßÀŠŽ7‚y PíÔ ÞWæ§Ÿw…&˜‹Æ˜1(‚æiSh‹Äøg‹Ë8‹UˆŠæW\€‡PI‡QG&\OÐnñØAT §‡q@ŽÖ0‹šH‚ÙÀG°ùg´‹LànY~×ðNއŒ"X×9çWh‰µpzgP‹wà 8ñ•Ä7ÿta ÜØ«˜BSÀIð“åî€“é¨ ´p 'w…I ©FY~&èNKç„Õð8­ qgp…Ai7¨xeàuâ7‚w08á•ôGÒ3¢Àn½¨•¸6³ÐJÀWY{ÏÐNaàq_§ˆ?8’´ Ž×—¶Gާ˜·èN®pŒŽ™ c =’æ× ”³¨×‹wp17ásç9á—Þ,`p,y…ʨ6¨S•z¨uJøuVXZ¨PÖ`qa9‚ % §‡éNÉðnŽùˆ ¹nŠi{­©6¸À½h\p+P0eEQ$瘙Ž) ù˜zàS\ÿ‰W‘µ—ÖàNˆ™«)‚N9œî¦‡áðN[И+øˆ*^ðœw`7«pŽUx…u ¨a0_5äö5s•ð —œ$(† ™î&‚à0 Ö ˜`ð…YøNëÙžù7’¶ðùW ï$x#¨…Ž™*¢'i7Z°”š¨˜u@`bä¦PFø c *춈u0Às ç¢v Ó0 aà}}y…èNËànFj{&ŠR:‚NYŽH·‚Ó ]È rJ°æ§6§ ñ§‡z`£k!8ZFM%KlVM`p»9ˆÞ]·ànuj{w0 É0‹gø˜Ây¥#Xˆø¨dpŸ¹}àÿ'‚ã(]Zàn>¹ˆBº K µ—œ]` AÖ9Mt›5s’ ŸÚ žùןÀC×—|(v´y†êN#ªSZ{…HqJ€Ž:•K¹Ÿà™ \u¨Jðœµw§¯2J{Ÿ§˜¡À©ŒñÖD1&sGæ w†sÈ©ªPp†¿à {÷Œ"è ðt„*‚&ºrŠéˆÛ@¨·«RJ¬v¯Ð ‰ç}ñG¾úÞ‘h5c‹‘VSp­æ—y8–±@šÖ` `€œþh{uOÆÈƒNx Öð›" ½“LÙ”\ +7²ç·‚¯À™_÷¨èvýZ~zGÄUoMÿD „6SP’æiÛ(‚šÉ8Ñà°¯h±±`1+³ñ„«{j~Ú +§‡"‹²¹~³¦ÿ¨¹@‘ÊZîw†]@³‹6ÙDÇD­‘0—ÈùG@µµ·f íf¤zp \°vk{H O'¦v@ ‘ªr#è~§¨†ÉUXp_èv"8K©ˆupV)‚£ ¶Yñ‹PF¦Ài|u>j†æ—®¨92 DÛ´vU0±I˧‡ÛN:¬NH ‡:¥^K¸Û©¯+]Ù ù·n"x}^§‰ŸŸ8ŒA[F¤À¹êÓ¢˜j{¹prMºŠ³ð!‡™Ön{žñ„ ÿË›+§«ùǯU¨w¬<¤ZÿH”'©xgr­kw°]k¡¼ÊAëpo…3 Øë“[›`GЗyP‰®@ªWYÑPú©˜ OVú°Žj êz’2éˆ[µk †H°ñ½zpíÖ½\`%•ÀZà©5Ä@-´ ¤ú…z° ž€r§ú °p K‡· ŸU ‡y0Ÿ†ØNµë„á¾Æ»ˆçy]Êc³¸úiÉxèx~’Ê„ùW¹–ÛZ9ÚDøà 6§î—ÞÐ3G0{ÿاT šWù o¼€#OJŽ´0¾#XÚPÁE»ˆz°pRLª¾k~jp?ûÿ©_ÁÿH qF­¥ e”düŒÀÀÿx 9Gp†k°À—÷…Ï@ªbŠêK޾énÉy‹òª_àÄåwÇP ªi¤Î€ÈFú…j€í¨ã•Dd;ç×, ðÃ$˜% ‘ù÷Îð ÿè »«Ò† !'»»*qä+Ëõ*iËГM«ÖàÉlü; +W¿÷û¯Jô”\Fd"ûµ†œ%¤àŠà¹ªù…wð•U,Ž‹¶S·ÇÐ¥¬ì„„i±’¦0˜Ž± HpÀ¬ `)‚ak¹ÊûJUC;a£ºvX» %WœŽÊ\{¿À çšãOÙY«zÀ –ÿùË"²§‡‚¼¾Hkó ˆì·w ÙØnŠy ø{¹€fÏwq5lÈÈ %@ÑÿxtM[®p -m~¿ð|<;‚i…ü·0ÑzHË= Ø[Ͷ—³Ð ''Ób° ‡ZÖ`( IÝZ6[FðR+Òv ©€8œ@ íws0©2; È §N¨Ö¹ ͘žÙé¾à) ˆ¼®<¶ ö‡ºã€B'÷Ç|ZظJÚG: Þ!ÉÐ×ÒŠF‚àkw•w`N|Î`ˆ×µ³;‚»ËQ ž´ a ‹´àɨ{¤%5ð˜yÃÞណr‘¼ÃüJ† ˆP¤}é ¤/P”€¼s¡ðÓz¸·m]¿v 7®pÒæ·Aµ ‰»€>M Sã &I‚Ëp#ÐáÉ©×+,Fd›•$ ñÒáÝKÞG¾З_ø Ó ç·ïd H¨íäâgLÜíäÉÛÿYGWc ]ŽÀ3>5Ÿz°Š;âJžjÎÂàMMs+Vš@ py›ó ®Ðç³ëN\ШÿH®‡iŠÉâ)pºÍ§Ž3ZQgHq$5§p <5]‚ ¼©‘kê€SLœÖ ¦¹`DéN¸Š± ºùêÅí}õ+¨ÎmâzëN@=àø  QPß¶× (Qþö=^r|Ú¬ÙšÀ~ϯd U±ë?˜d$ ¡Gj:¯ {µú·€yŽàÅï ï¶Gës#àÉY*ðßqíËÝ{„ÃBê`‚ ¢œzÊ÷ðMýK…`iÿmŒ Ft^¡vÈ: €¯u½ ”ƒ)ß蘭Pнv@ñ³pÞË}~G`nµ°r=kÑ è–W”‘’0~0ž^FÆœ³Ÿ µP ¹@ ÄU¥ú¬ @ðµç \à}^gÃïä›ú9õv•s Ø‹u€©`®F-‚Ñ€cböBYŸ\Ÿ¹þ4h4“LúaX6Ò4/‚ßHM€Þ"øqçXy›ÊO)©µ¸~‡:Û­"ø Ä¢j‚Ã5þ¤f7áQícðËf#iðÝJ©b:ø——–åÇÁîôØüë— Ðô^«¿0òwt •±Â5ÿéžØG0ŒI%úUd#b­|º ºT ¸]~n×Vh¿ñÔê´ª–ë7 àùj I¼Ø!X`N .L¨ÉáCˆ–"M¤XIÐÅ‹þüãØÑãG!EŽ$YÒäIüþjtRÅL—d^ÚäpÓMœ›RåòÖ«ÙªW¯`%ú*ƒI•¤ÕÔiÓ#—l:ËêÕ s¦g•Ã@¥zZ1$Ë âYM•(®ÅxÑ4”qåÎ¥KW @…Zkiæ¥Lšr¾Y4VÑ¢»òlUš§)·§N€]šÖUÌêLÕëjˆÍõèé«,Y´1­e‹~ueϦÿ-—ÝJ½‚ÖVŠ9saœ‚FL´Æñ`Žì4ÉR=yd]Æ|KØ;±ª#[çM3í°N/¬™ZÓjÖ•r_ 4¨ö{øñ9®$t±Ú‰~gb\hñ¢~Yƒ±:œ©Î*§ £%–4+èŽiœ:ð*hô ¨=ž™pÂWÆSÈ<‡.a-‹ÚzK>S”K@Ém·Þ.Áä’ßúà ¨¡ ê—;òÀ ÜðÀǦæ™k"³é¨[ò*??ÖÚ ÄTÔrËüi±>A ¡R¿eªÑÆ„„šEÇ \qæŽoœyÆ•'7|LA ëÔ³º(qĉi¤Å?ÜãòÐÿC L¾`’ñ/NÐ\è?÷´t–ǪÒÓÉ:Å‹²<ó…„_ËQTU¼§ÅÜ^¢ˆ¦¿dЏ²<ðR\©ËsCn,í0J5ɤ"!)µECSUV¾GÁè>Š,)3ÖY;Ò¢pÅ•(æ4½ŠÓ'û4 DL$Š’BÒ=ÖeÛO¥¶Ò‹Rk=ÄVÛm+EÐ[=Å= '‡ÎMw`RKMÖ]„e+ÅŒ ‘d­Gc¥)'qmÅ×W6³J(X<»*µ[SÜò¦µ¤KVùØv¹. ¤aÖ$ž 'qÓôøâ:3FÌ´k‹ëS¦JŠ6Úh•Ó5¶ÔE^vz.SÆ(½ÿic½)ç4_áùÉ}& kP§:å²Kýƒ”µ/I©]ª¹ê™4¹›¡¼õ^“o¡r~%ìÔ69Yð¢#)»¯Tüô‘qÖ¾‡!–“7™|¡Ê/îšo¿ÿN ô¢Ë>[æQÞ#i³õ¸!QòÙ™gÌ¿ÎùïM.áåÑU÷£åá»ÿ'?â•w¦yel~¡çµÞÓ>7×ýzµÊä?üpÇ{ï©1¾ä'z´ü›Ïyê‹Þ¯ü¬šÀ/i¢£Ÿ?ü]©-®‚ä¬&À„%}O* ÿûD=ëñŽpfÓË•ê—zÏ+ßnæöæa0! ëYôrö›÷]]@—[ê·ŽâûëßK^)»M.‰ ¡!‡ ˜;q"p×#¡ dfBS‚øÍÎÅC#Q&²“!7X@ö}!è¬(3AÔOZLámJ&0‚1bcÝn˜3Þw}Â!ˆ86K|îW¼Òé˜Bf y ã aG“2ާc˜ƒ¢yVBLdâdk#‡¥GQ’üb÷hIHEi‰`£Ø&”ÆñtHw¢Äº¶H™½&6© â!XIÉJÆÊ‚1̤pbË äŒs9yˆÀ’ÿ6*S¾…Ä bÌŽÅdBâu/$#Cf)MgÒjë\çiÎB4£Y—ÙËæ=¸IÇ!~³•yT¦˘NÂ|’S¼ÞjFg6B0â=éˆ?è3œäãã%bxN’4'…çõäyÐB\m~`†CSy•” œÈäè_Ê99nt ðC™èF÷»+úA&%&ÎFd@úá(`Ó›´”¦–¼€ˆ²ÍÌ„‡à)7QúS=BÂJ˜lQÔÏa‚–H­h¹àGŠ=ìÁsP‚!ö»:²ªÄ\U©á0tI@ g¨Ãø Ú ‘/- R“ÊQø•£}àƒê0‡ÿ$¬¬~Û›«Có1ü!/˜@Î@‡:ðA´| …ÿRÐÓœI£šàèç@—‡Å.¶±u8à Ðõ9žª²÷\ef-€/€v´ŒíÃ(LËFøÖ°Õ+ëõô[Ù6–^˜@ÿ@ÝV•à£Àd„+Zèòá–˜—Yij4±V+¦¬m.èî0ÜØŠÖÓ¥€‡™]žâ#ðÂBËè2–{hʦu^ÁI˰EåâWÇWºJø~wË_ÿÚÀ0A¨`6¹!¸áZš Þí)ޝcÙª[ ;t \ÝŒh÷ aµNWiEC±ˆy ( æ&ì)è,q®Òÿ¼ží¢c“na¯}µq|ûc/Ø6].A™ˆ‡äu9‘Ò‚]™cu²1OL‚pý ßOw Pæf9Be8Çg@B#ÖÓ°.Ã=`NÏ>éǶ$ú"ÈŠ—g/ÀƒÎ„p`ƺ8 †Pt[îãZDR‰Ðq“Ä¡ÃÙiŒÔh´üŠé ÛcÒA´‡wÿ kM#bͨÞK 7êô˜™»N´ª[„%”aŘÎô‹g?ð÷»Ìn,[ë>b£zl_vÜ„MÉ–ðm„òhüè?öÉÏîÞdÞÌâ8+aƒ˜,òÝiI„®ÛÞþ6ÃÍkrÂÿþ°ô­™<ß3„Ý›1_Ñ i1p䆨·¸ÛâˆFL¢`®D©û ‰£·¢Øæ?èai Ã;ÓÓMÇ·Ïâ×Ó}ÂGò¡ˆŠóº%ÇÂK#Z'jyüãÅÓB·§ sä­Vùʽ@—«méÁMùÌÏÀ‘äƒ 4ÞEQ0žó>N‚„s«|¶spBݶ[ç½±kUÂ>â‚cÐ{{xwá墨̦^õ™]|½q_“øÃݯcÏË·+Úý¥ÿ½„ç«yÈ&¦ýJÜFx™­^ùi}¡HÑv¹Ø嚟¯Α{eAþÝÔ®~Ëß3|Ñ>`ßò•?ÙAˆb}§K:˜Îýéû‡j”á é7¨ÈùÀÇ:”ñCxQxGX„E0„AHÀ+Z¨Byj€½øè¸Ó0øSº›?-‘@eƒ°™ó‚*¨»†ë=Ù"gÃ@q?ª£>:8ƒÊ«;‚‹<\£-Ü3Áø¸»àA½+ÁºÛ¼“¼êÃ|~˜=êã¼ Ì=xx¿”´ ” Ùã=Í›0ù›?;S6 œ9%µ&¤ Ès¸¦“./ð>¬¿ÏŠBÎc¿-‰)P1ÿ<¸é*‡-Ô>œ¼uKC“°³ôÁœÁ&ÂTÁ3P;, u`:=dÁA´Á¸sÃ0D‘¾?ôÁÇR44Á©£ƒWë@¨sDðÃí;8#äÄ€¹2”¼j³ÀIë‡xà^†`q†Jìˆ'üÄðš°ME9¤¾ÇjA“؇UlÅWŒÅX¬E„iÀf\ÆxFxƘFØqð¼h8%3ÅîE[$ÂCT8‘@‡elFxƈƘƨFq8B„Ù‡pt”¸ÇШèGŒÆ`€1*`Ã/¬¾8ðF8¹„?ëû}è¨G{œÿ|ÔøG\Çw˜È‰œðŒ¤”¤˜ìÇt|F^È<¼47¼=…üÄăŒ?ކ˜Èg$I“LI”\É–ŒFuHT逯¨“ÔÇ¡,JðÐÇ}DIu|ÆèéÓCÊ»IÀR„µSÜpJ¨ÄÊ©Tɪ¼J}¬­DÇxa@ÆÙ¨‡hhÄJ¿,I Ì !‚ øÄL̪Ô—,€¸mŒAËŽ˜1\l14¾Œ’ŒJ¶ L ÌÂ<ÌÄD̪äG€t˜L`hJȪŒÍ’üÁ$à Ü ‚!‚Ò4M«4Iÿh(4€5µš;Ê ÙƒÁðºלØ\LÍ‚ÜÄÍÝìÍxKà4€á¬‡ø˜zŒØŒNÀM! ÂÍë´Ní4OÆ Îƒ\ü½]LN¨µ†Œ-=hʰΌMôTÏõ¼ÎÁ$ÍÒ„Ï~l@‡÷@‡ˆÊØ Í!‚õ\O"0P!ÐÎíŒÎ{ìǸèêFü ‰B ®L׬NÝÄÐ ½ÍöÔÎ 0ϧdÉÐÚh‡ÍÇè¤M•ѽÐ! $µÍ ]Oóô{ÔQð«<Ñ‘ƒ$P6Ѻµ¨ŒÍ‚!ÍÐê4Ò$UR"mÒ'•ÿxxŒ‹wˆÐ ¨Ò%Ì#-<ÍS=-S$•QÜtÒ'„ãC* 2¬-MG9ÕGÚ$Òê,L"ÐSJ->5S Ô{T ‹xˆPhT«SœÔ"0#¨Ô=åS#5Ò« Ñu<€°<Ô‘XNçdT“´JÑÌPSMU<õUJ½Ô"hÕ!ØNXm‹yHK(IÀ´Îõ¼ÓSUÕJ½TL5ÌíäGiL¼¤Ò~`fuVÝUiVuUÅTIHZ[U©DLåÙŽ[³=[µE[¶u·ÅÔÞ”Û ^HGML 8Ò°ýU#pƒÀE[À½ÜÀå["àÍÄLÉÔn½Ép\€\ÉåÛS­\ÍÍ\ÍMÛ6pÙÎ-Í””öÛ‡‰”¨ÔÛÿ åSTeÛ×e×ÞJÅPÒ]£­Û¤­‡‘œM•M]$ýYË}Ýâ}ÝjÅÖPÞà…É‹ÕU •\ÊÞ´½^Í=ÞVõ”ô×Àݤ_¡|TI5U"0óÅÜüE[õ5Rö¥÷…_˜8•SÚŒÖsýÕýEßËíß pQid^ZõшS]E`KUàüeàÀuàbàp×8YŒ-L–å`óõ`µÍ^WýM€€’-¾œßhÝØS]àýeÞÎíŒá€ îRøÝ ¥TüíàváŽÍ~ßÅ¥Râ§|K#Æá$^á%¦Tˆub‘m‡ŽÐ…´”S+nU$fÿb(b Ûbhc7~c7&†ËUXL…àÅŒÆZí1®ÐVÅb4Vc6†cBVãÖVµãŽÆxŽ €t„ÎÄ$V#hê \9(dB&Û¿%Âm8€KMdÙtÉO*¾4`ĤdKþYLÖd8æd³%TeQ®ãRÎNåyµÊV¶ÔéÚËÍdYŽã¿•[¦Za¾Ð½ãh ÆOÍ´G`þ!æÕ…åX>æ6¦å²]f mæÝÜå0®fÄìPà%ænöfpVfªMU¡5ç­¥Ò¥ävÓ2¥ÚböæoNfq¾eaFR!Àçºõ…ÝegÄôç$èÿx>æy.èªZÒô—T*cF…ܰ•hµ5fy&hªEW¡õÜø4Úø>¶Gižéóh56if.S!ÍÈ~äèEK˜–騥i̵éŠ>i>ÝéÀôŸÔø0€{Œi½ ixi¤Æi ]jÐaݪ~ÊÄ ¬æfµMcNfz¦Z¯nê`IŽÞË‹=ë´FÕËekovk9¨ç¸†àöÔp8Ñ(ëkNÏ™Îê´åëcökÀ.Ó øj­T­a]ÕÙ6j6°éb€l¸–lÊÎÈq0l̦MlÞlÆF[Ç–eÐîjÑnj­,måKæÈeíÿŸ•cµõì7^ã¿í$lÚ&mÓFmk~hé­gßN[àŽc²ì$MÁFnMÇÜžäÅÚb\Ï&h6ìsíÜÑΘf±ÕínåîþÙïþm›oò^Xó>nôÖ…_æ?®dÂEÕø>êùþÛï¦n$¥ÎëFoïMNU2ne2õoøÖê7ÛÿÙaðØ2Eð“”Ï`â â=bÊÅßç&Þð&ðñÚ6àSëk=íäì!æ]5Ó„Õë'é¾&ðÿFÕa8èÌ«¬~dPt\­ÊÏf$¶p5Nq ¯çßpДKì>Q%U5ã'/Ûo–r0§Ú wqÿ"OÉu €v€îÌR%q=­Þš®ðp®g!¿ïíUÉpÕò6¯J;…ó<•soëN>é;çi”a}HK ÖÙ@GbB'ÞB×d®þÙD?s¨v }kH7àhuò„­ô³óÇNf¥6sÞlßO÷‡pÍ|”t;=ãÀ=q4~í6vkòWàiÔã öÚÓQ\_ë\ÇtV'îêæô˜Æø_øåv.U$eØJ·teie^cp_qÙ¶ò`v vüäPí][OR†m]LÆäo_cCþu<‡u˜ö}¨f’LLlÏv½ébxµýäWFÕÀþßà,€ R{ÿ¸ëk/ÓWŽw‹ïö´5øqGèóNæ €ç½féT#÷öË pÁ5WÅÚíÝT>wP*yky‡-ù“?ßëUùµEâk¥]˜WsŽ€=Ý«ž\<…¶-^žG[žwŸ'ÖèìÇhw Yü|¦|J£[Õ-¥w¦×ܧá!˜úm8t yè4zëLÝŽ%ÞçÖunW[…}ØõM4€áCýðˆû/û¯W`e>_‚Ç{³Gû°þ{[f}܃õYêUæë-^Âíá]~ü†?Ô~|ÓUYô4u$^ÌßëÀÝ|.nÕΟNo(ý&}ÜÄám&fÿ³…îÕgùkõR–Äã«Ø¨}ÅýzÆßÔwúÞ×Ó–ßûª þø{kûˆoÖª¤×•T†M~`­ÜÝ/xJmq©ç{ŸTÀ§UÁÇÙìÏØ;íþäOX³­t¨o}è×hŸ¾Ýiÿ²Žd/!A„B¤H# Aè¡Â6n&ºiø°ÈŒ…øèèCFŒÔûgò$Ê”*W²léò%̘2e 0CÆ ?bÐ!C…!‘HÑâC=~ €>•ñØÄ©ÓgOŸDEHäë×®•vÔ¡dŒÌlëö-ܸ3Ûhq“ÆÕ!Y‡l]ØÕ؃b•rôaÿ­Z,_Ô•!£†Çz{òMȵkàƒJ ùáÙ3Ð5BÆU.êÔªW«,À…c‘±Rî‹ôbæ±J;þ:4iü±Ô`ÄM²;þB„2A¢b3Ý<¤÷¢g€‚5øðâaÖ;c†rΡWö;”:ëØµÓ¨Á=-.w¼N¾¼ãz“õ$–WaØÕÚY8”6ÜxJ8 ýŦÞsFG`nj$v¿5øàKþ @ ŽáÅ”s$PffožÑGw-˜æË„=úˆZ?'¦(ʑŗՋïQg½Ý˜£iáÀ´OÜtS>H¶×Axÿ #|ò}„a> 7ÀÞý¸&›3éSå•9±H[A]~éP˜›ag–™2 ™ŸLå!—–Y! ^zIÕ%Ø›} 0mZz)Kï˜ç`‘‘!ª¨¢Œ‚%ãf ö†£¤#±5:æôŸY:섨‹b„©@1Pv†ép_Z“VŠ)±ÅŠãj °š5«^µòÚÛ³ºòZÖY¤éøÔ[¼ÀR¬Ýú@³agc–3˜k.i1ðqź{iÛ&Û-ŸàÖ*î¸Yšy.°¥a —.p‚”½Ëõ긽2…ã¹háÀ>ïJliXyÁôvt°­ùfɰ¹·„qÀÅ!eÿ,›¿ù€+A ëË/°#“PÒÄ9¯É Êé®l˜Ë0›:_¹üZ Q¡fOØEd-ÿÆ`v/Ì/HëÀ£Î]ÿXOÓO‡õÔTû`µG £§îSÁ°æÏ ®¹ROƒc9}6sÈ"@8{=ø„þ” 7Ý9•MÞV‘[ôÚª 8k;PWHØ5ƒÝg9ö¹Ã!déë¦ùB»„«.! —Û傿çuzÞé†Ôé¬ øw¢Cʹ“~^}´;f{ °çþñ¬þü„è4=€ð6ÍÀ¸ñ¡‡¤¼îÌÏãã>–×$¼èŽå°6ò𠬔л/¡>âW_þ çk‚Ÿy ë¯Õþšûôpy 0‚‘ŒdOsí ï(í}ŒPø(@Vé€ \ x©} £B#!€À<’-°ØAR÷ÀFHâðàßB8‘¬$@¡ ßÕvø;à/tу¼ÀóÈ! “8¡}´ƒ(¢‰Œ#‚' ;norm-1.5.8+dfsg2/doc/NormUserGuide.pdf0000644000000000000000000024450011156550135014366 0ustar %PDF-1.4 %âãÏÓ 6 0 obj <> stream xÚ­Ý[“ÛÆ™Æñ{} ”nâTYÁ÷ÐÝ{g;–˵ÛqÆ›ßP3”ÄÍ 9&9²ýí·$gÐàLÿs±•J" xø§§‚¿½ê»yþOßõê³y/'›Í=u×w¯æ3&žÿ?ÿÓo¯æÝÕïùÏWׯzM3=έ‹YþT2o¿ŸwÛ¾úGþO ¿Âóî»ü߯¾¾zõöݼ[è,Fé®><>ÿbfþôôWw¯¾Ølww½úßln†YËlŸŒèLúj†ÙøµôÚÓuÓ¦;LOíé¶€éÓc{º÷0üüøð àÀ/‚_¿~ üø¥¶ßb>‡éÓ¦·ýý¦Loû-=LW˜~~~~~ ~ ~ ~~~~~~~~üøð‹àÁ/‚_¿~ üRÛOæ ˜n0½í'}Ó¦·ýd1‡éÓ¦ƒŸ€Ÿ€Ÿ€Ÿ‚Ÿ‚Ÿ‚ŸŸŸŸŸƒŸƒŸƒ_¿~ü"øEð‹àÁ/_¿ÔöÓyÓ¦·ý´ŸÃtéÓÛ~ºXÀtƒéà'àýC¡(ô…þ¡Ð?ú‡BÿPè ýC¡(ô…þ¡Ð?ú‡BÿPè ýC¡(ô…þ¡Ð?ú‡Aÿ0èýàØ ýãq|à)gù`°8&s‡'ËøAÞ«žC‹Y÷õÃúöf½ùØG=t2àÐ÷§Á’Ñ\çá•ùóceXÀûú‰.Æ ×L"òÊ ¥@€@^?!@’$IF’Œ$I2‘d"É’e¤B§H–Ñ@² @@)@’B’B’B’B’J’J’J’F’F’F’N’N’N’N’$I’Œ$I2’d"ÉD’‰$H–±@² '@@)’eDB§I I I I*I*I*IIIII:I:I:I’ $H2’d$ÉH’‘$I&’L Y  É2Þ¡€S$˘Œ$)$)$)$©$IG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u£ŽcÔqŒ:ŽQDZ—:ÎÅ@ÃqHÂëцcÒÒbœL9” ž†$úY÷ËfýÇ3—3„YµJ_\¯¡€S A ¯µ0 DäµJ’ $H2d ÉH’‘$#I&’L$™@²ŒL@@(àÉ22£H–‘ (HRHRHRHRHRIRIRIÒHÒHÒHÒIÒIÒIÒI2d É@’‘$#IF’L$™H2‘dÉ22£H–‘ (@²ŒL@@(à I!I!I!I%I%I%I#I#I#I#I'I'I'É@’$IF’Œ$I2’d"ÉD’ $ËÈ” YF& p €d™€€Q€$…$…$©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽQÇ1ê8FǨãØKçb¼áqdb<èpº¬¢Ó‘‰rXò82±˜U_öè‡áÔX…þUÊ`¨ÕõF—CåJ&«Ÿîò«í@‚@¹˜©0 D”ë™Ú¥@€@¹¤© É@’$#IF’Œ$™H2‘dÉáËí€PÀ)’Ã,Ú£Hß±h”$)$)$)$)$©$©$©$i$i$i$é$é$é$é$H2d ÉH’‘$#I&’L$™H2äðõ‹vÀ(’Ã70Ú¥H_Âh„N’’’’T’T’T’4’4’4’4’t’t’t’ $H2d$ÉH’‘$#I&’L$™@rø~F; Éá+í€PÀ)’Ã×4Ú£I I I I*IRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JǨãu£ŽcÔq쥎s1Üp˜ÐzÌá˜ÌûÖé·8Ê9›SHfÝ7ÛÍõêþ°ï¶ºïW»åa½Ý\3äå"o+ª™/ºo;— "òr¥@hJ÷…€PÀ)’¥ûBÀ(’¥ûB@)@’B’B’B’B’J’J’J’F’F’F’N’N’N’N’$I’Œ$I2’d"ÉD’‰$H–î £H–î ¥H–î ¡€S€$…$…$…$•$•$•$$$$$$$$I’ $I2’d$ÉH’‰$I&,ÝJ,ÝB§H–î £I I I I*I*I*I*IIII:I:I:I’ $IG©ã(u¥Ž£Ôq”:ŽRÇQê8FǨãu£Žc/uœ‹FûxƒQòÜ}%MNÊ[òQ÷ígÝ»õíª>3Ÿæ«äÕôÖ‡±¯»åf·ÞïŸmÎå•På/[k; íÀÐZÛ¡€S A |¢í€Q$‡ÖÚ(HRHRHRHRHRIRIRIÒHÒHÒHÒIÒIÒIÒI2d É@’‘$#IF’L$™H2‘dÉ¡µ¶FZk; É¡µ¶B§I I I I*I*I*IIIII:I:I:I’ $H2’d$ÉH’‘$I&’L 9´Öv@)’Ckm„NZk;` I!I!I!I%I%I%I%I#I#I#I'I'I'É@’$I’Œ$I’:ŽRÇQê8JǨãu£ŽcÔq쥎sÑEÏ—’W…ôôuxõik:j­‹Y÷ÏÃnµ¼«{kÙeë¢ÊÖ½5ï‘ó:Ðê­ÃÑrç/oŒÖ8ÊMÚ£@„@¹1Z; ’’’’T’T’T’4’4’4’t’t’t’t’ $H2d$ÉH’‘$I&’L$™@r¸1Z;`ÉáÆhí€R$‡£µB§I I I I*I*I*IIIII:I:I:I’ $H2’d$ÉH’‘$I&’L 9Ü­P €äpc´v@(àÉáÆhí€Q€$…$…$…$•$•$•$•$$$$$$$I’ $H2’d$ÉH’‰$I&4ê8FǨãu{©ã\4ÁóU¾U<µËùřΰuF™uß­6«Ýò¶ûi·½_íëÕ¾ûñóEŸK¡šsµû¼^ÕeçT¢G¡ß/»c9 æõ‹¸< Ö$”“`í€Q B œk”å$X;@’N’N’$I’Œ$I2’d"ÉD’‰$H'ÁÚ£H'ÁÚ¥H'ÁÚ¡€S€$…$…$…$•$•$•$$$$$$$$I’ $I2’d$ÉH’‰$I&N‚µJN‚µB§H'ÁÚ£I I I I*I*I*I*IIII:I:I:I’ $H2d$ÉH’‘$I&’L 9œk„NN‚=¸¨)çK7ÇÉóÏXG›Ÿ κ®67«]«Ï”kE­šñ™>3ŸÍcz®ÏÌg‹T….Nà´§;LOíé¹ì´§Líé¹é´§+Líé~~~~üøð‹àÁ/‚_¿~ üRÛ¯›ötƒém¿ÒjÚÓ¦·ýJ¥iO˜î0üüüüüüü ü ü ü üüüüøð àÁ/‚_¿~ üø¥¶_é-íé ÓÛ~¥´´§ Lw˜Þö+…¥=Ý`:ø ø ø ø)ø)ø)ø)øøøø9ø9ø9øð àÀ/€_¿~üø%ðKm¿RKÚÓ¦;Loû•JòÜô‹žñØHFÉS#Yôý´‘èøF*6ë~^]¯ÖõwÅòë–¾J~®¯Úësý¨íN㳘d’¿è4>s©CÏuŸ™k•º(%í@n%0 Däb¥@€@þ¨!  I'É@’$IF’Œ$I2‘d"ÉD’ $KS€Q$KY€R$K_€PÀ)@’B’B’B’J’J’J’F’F’F’F’N’N’N’$I’Œ$I2’d$ÉD’‰$H–*¥H–6¡€S$K£€Q€$…$…$…$•$•$•$•$$$$$$$I’ $H2’d$ÉH’‰$I&,]B§H–¾ólà¢Æ<žQò\x:¹s¤ÉÓ—•ôøƒoßi×ç^ñá1WªjžsœÝlwwǰLÂ}¹‹¦Ôéîa¿ü¸zæ7<óGgõ‹¨ï‚Q6'í@€@Ùœ´B§@‚@Ùœ´F'I'I'É@’$I’Œ$I2’d"ÉD’ $ËYLœ Y¾†£H–¯áA@)@’B’B’B’B’J’J’J’F’F’F’N’N’N’N’$I’Œ$I2’d"ÉD’‰$HC&í€Q$‡!“v@)’ÃI; p ¤¤¤¤’¤’¤’¤‘¤‘¤‘¤‘¤“¤“¤“d É@’$#IF’Œ$I2‘d"É’ÃI; ÉaȤ 8@r2iŒ$IG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥Ž£Ôq”:ŽRÇ1ê8FǨãu{©ã\ „<Þºe”´cÒ£NÏ/t4dÒϺ_6ëëåþÐú© >O‹jÖ‹R ДR ¡€S A ƒCÀ(!°è)  I!I!I!I!I%I%I%I#I#I#I'I'I'I'É@’$IF’Œ$I2‘d"ÉD’ $K©„€Q$K©„€R$K©„€PÀ)@’B’B’B’J’J’J’F’F’F’F’N’N’N’$I’Œ$I2’d$ÉD’‰$H–R ¥H–R ¡€S$K©„€Q€$…$…$…$•$•$•$•$$$$$$$I’ $H2’d$ÉH’Ôq”:ŽRÇ1ê8FǨãu{©ã\TÅÇR9JžJ¥¤‹óðýÓ÷%­ü‚ãÝÝrsÓý¼ú°Ú­6×Ïœ;/¿ ë/NÇBÀ) P~´0 D”ßm”¡¾TÚœ Yš3Œ Yš3”$)$)$)$)$©$©$©$i$i$i$é$é$é$é$H2d ÉH’‘$#I&’L$™H2diÎ0 €diÎP €diÎ 8HRHRHRHRIRIRIÒHÒHÒHÒHÒIÒIÒI2d É@’‘$#IF’Œ$™H2‘dÉÒœ! ÉÒœ! p €diÎ0 ¤¤¤¤’¤’¤’¤’¤‘¤‘¤‘¤“¤“¤“$u¥Ž£Ôq”:ŽRÇQê8JG©ã(u¥ŽcÔqŒ:ŽQÇ1ê8öRǹèÃÍy\ŠIë/~Ic>5çþ鮨§½æll˜-ÊïAÎç/7Bœ åûÍí€Q B 7B(HRHRHRHRHRIRIRIÒHÒHÒHÒIÒIÒIÒI2d É@’‘$#IF’L$™H2‘dÉáîKí€Q$‡0µJîÁÔœ$)$)$)$©$©$©$i$i$i$i$é$é$é$H2d ÉH’‘$#IF’L$™H2äp{¦v@)’Úڡ€S$‡»4µF’’’’T’T’T’T’4’4’4’t’t’t’ $H2d ÉH’‘$#I&’L$IǨãu£ŽcÔq쥎sÑó'c\öŽÉ ÓFXxŸáâñ¶²B¨³¹ÄjÆË«o[áêÛv@(àH(g¦Û£@„@¹ú¶P ¤¤¤¤¤’¤’¤’¤‘¤‘¤‘¤“¤“¤“¤“d É@’$#IF’Œ$™H2‘d"É’ÃÕ·í€Q$‡«oÛ¥HWß¶B§I I I I*I*I*IIIII:I:I:I’ $H2’d$ÉH’‘$I&’L 9\}Û(@r¸ú¶ 8@r¸ú¶0 ¤¤¤¤’¤’¤’¤’¤‘¤‘¤‘¤“¤“¤“d É@’$IF’Œ$I2‘$u¥ŽcÔqŒ:ŽQÇ1ê8öRǹèçÆ8N†Óuº:ýJgùˆŸ£¼pÛ_w­’·ýµ¾´:ç"oŽ{YTùIßS äÍ1„N¼9†€Q B@HRHRHRIRIRIRIÒHÒHÒHÒIÒIÒI2d É@’$#IF’Œ$™H2‘dI™Ï) p €¤ô @R=”$)$)$)$)$©$©$©$i$i$i$é$é$é$é$H2d ÉH’‘$#I&’L$™H2¤Î0 €¤ö=” ©‹9„N’’’’T’T’T’4’4’4’4’t’t’t’ $H2d$ÉH’‘$#I&’L$™@Ò¨ãu{©ã\´8+#„ºÊõóÓÉÄ䓯[–q…sÊgÝOãç,U{îUd¹[Þ­CÛì×7§Ûüyie¡åMæY®>­÷ÝÍöúánµ9t7«ýõný~µïŸVÝC鶺ežp·ÝìÇkê»åýýíúúøççå!'O³ü0½£FÞ@UÏ÷ÕtO’ÛGøæ¿ßü¸[ç³*¿¬t»^¾¿]u¸= ¿ß{ü„Td2ªSv½çGøõ‹~üùï¿þµË/w³¿ßîÝýn{Ø^oo»Û]·;?ê0ýn½ß—÷‘ßfyð·ïìöůóùüøOgÃ/nWû/»÷²Ê®»[í Ì²ZÞu×Ûüš7‡Y×]l˜¼~Wj³¼h3ÚiP+CMÞS>¤9ϲ?f¹;^ª&ÿQ-_eݨç¾~8 ïøýz³ÜýÙåüõñédéèËåÍ«¹7ÛÝ]í0þñ)õ:ý:|èöŸ¶·7ÝûüN·å£“CYØ^¿¸,½>þ%/JËnÿð~¿:œ„ºëåý›ÓBϧWó”£Ïó“/߯oׇ?ϳ•åàñ³Ÿ|0}>H)+Éxö¯nnÖå…,ooÿœVh³:ûåñ…=ìveÅù<½Ë“…¾Š¯vç¥l@¯A7Ûü޳RY‹ž^öÅXè¢~«_E,^¬ ’cOOóÓnûq·¼»[o>vßçEu÷¡æ˜ƒ¨ãy—׫î×/¾úéû².•ϯl*N[ˆ›n½^ìëáÕþmUçúÌúê±>Os¥~®Õíö~µû˾ûîa}³z}±å]JYæGs\øŸ_˜­fºUsæù,zc ¹xÚ ½¼éÛov™èz{³ÊKÙêzu3,諌tñÛD ­t²¼”+åê@ñ6ÉãEyz« hÕ<ù“šºåL—X§º‡‡Ýª^fµüÒTïõk¨–ÙÓ¯\,l½ýT¿¯ooËÆà:o*7O{é›+7‹©zìüæºòk{Ã#-o÷Ûn¿Ú}žÞ—(i5Óª[–Éîü }Ýa;<ÙÅHy#s½‘é5UÓ«ç-7–ÒjòqaÞW{ýü å.xã¥÷ù¥¶ÜÇΪlc\ZŽWáz }¸/û¿£ò‡íííöâ§àê§ú½lÊçò_Ó×nOëÐäpF«‰?n²òúnØCîV÷§;ïiO;Ú·eE¹?œ¬¼¡?nåÿ£}oyÌ›u~€Ã6"ì§/QžÝÅìt¤Z](Z^ì(vU½‘4ËÀñäÑñÁôe§=ÿýú~Øæ…«8ÿóêoßÿp^o÷ÇÛšŽ?”u^E–›aÛúËfýG·ÿsXÝ]~Q±¼ÖÅÓ²¼ÝÜþùë_§ïy´ÔÉéøµiú0£Ôsoy4¹ñ–_Ÿx^ÿÿ¼ïçÞoù%Éó+9±tOï;œ‹'«mïé?X©Êµ:ÜZ«ÊÞ¡Nç­üp“ 7·ëMyeS´{ؼõ]ÞîVÃà.d®/ö®r:H?bÞ»æýêr²N–Ѹ²'/Ì+ÈLJӆwø´n—»éÝÌâääc×ÍÃÝûü1å97‹yc6ý&noOëÄã¡ôýù ·ûé‘U¹Ø0Æj®¯>Ö§êæ³dub¹Þ|9+÷ ¿ZçãÕeyçÇ/ó–Ã×¼p Iu`—÷g›ëãa[9ö+GWu_ígùØmü\Ÿ§…7ZÔ¯åvx¾õætˆ5S}Z1//u¹.Bn,uåç¥Nן/»õáéXñiW{^M aò4Nþ‘—°uy}ËÛááËþëf¹»™®GålU áòIÎ+ûîÓrz+Ñ^ûñ Ÿ§#iáãé¹¼¯V›¼«™Þå²4œñã¬÷Çå ì½s8/C[üöêqÖy÷¦×Üj»ë»WYÔ‡?Ÿÿ»ÛW¶8^Vsù׬þ.ù¯ÇùÊŸ>½úp\IæåCûújԃʽ*BW~fiq<¼xMã—òÁ@>”9ý¹€žö™Òõ?¸_ÚãŸË‹ûÇ«ß^•ç»Ëÿõ> stream xÚ•ZYs7~ׯ@éeåŠ €Á©Tªâ#Yׯ²×¡ã½ 9 9ñÜÁ´þý60Ñ’–Ëe›F_à]@y’Åá* ‹ÕÕóãð÷ËÕËÅÕýï‚0X^_1ÀFbNâˆQ‘EuuóºÍÖ&Y“¢#zÓìÊœ,©›Nå¤Ûdü£ÈCöbñÏÄ‚ NE”¸|öx=¦Œ¡õ¬$•VY»Ú?³eÓf]Ó>‘Ç›‡>¾ Eµ-U¥ê.늦&Íš<¼ÿø®?¿Ð¤UÛVé;sF`.èÞ%LÇ3`;ȼQ­"›LÃ-TMvÛ<³7i€‰Ùÿ»ró¬ÿÕ¨£µêïÛÓN÷ cÊ¥{Ô¾ÐÀtÛ6]³jJj£“¾p<w¼­I–ç…½ÓmàZ¹ªšZwmél»-‹•ý|K@-†=’" i˜H—é¾È¯WÖ( )‹e›rE·Åƒ*Ë»üÄåïò5\É=PtàoÞöwûwer¤êÍf-§wE—-KEÖMëÞäXÃŒÓ@"&Ø£XDÓ­«²Ù¡ ÍÏ…‘KùÛ ÷¬,Ÿ\RÁ %"½í½”¯›]»RdÕäŠä©Xº{Ca¢¹{wö^z·Ý6-„&ۥƅò¢Ì‹úK¯N ôÔˆ£:•gáÌ}ÕTÛ¦ ¢ªõ·qüþÃÛ©Uw@—5G.Û¦ýJtQíÊÞ ªF=š8ôû¢mj£q *ÿ¨ÖªíÙêËì ¸ðî¥Ø;ÔR"¿¸§±PP†.ñ¦ë¶?ß߯4-ºœÖmIkŒALÐ8A[öȺœOhU”÷Ù MbDj¹¯›¶BdIDƒ‘ýj=n¯ià¿öhmìc¢Îü¿ÛÞuÍ!²ŸyD»,U«ÁúÊEñ=€—ÁÃ:AÞ¬vžÒ>ÐAÏ€c‰— "É( bË›SWÄDÒ˜3D@^nKz–Áœ%‹¦Âmõ "™õtã+’™´u2CE<¢ íæxXZè&)ÆÂñxÒœ+càјim•Õ&ñ¡°epB”0´ БuÛTTX¿þ^ˆ(¢q*1'kB~G„i~5ަ\†9憽‹3°¾­j! ª‹owËÌd¯f«ŒóŒ$ÆRµ 'úIwªÒ·äú]öéI€"~FÂ)•¾&¤k/Ó±$ÐM;“êl_â Ohš"Bã d™cR4Át)A£Ëþ-3õˆë@vUî¬ë›ðt§~ üh¶ZùÖe«2H0Y‹ƒ¬±‘|FJ ‰ ŠZôà%¸’8E1céqzõ†L†Æ`)á ÿUo3p|s8(ûSA­šúûÆÿ² ëY~rÊMB¨KDŠÑ»ÉÍä]±jݬ»S˜*Ó`Úö·Ë7Nh„— ½ƒØyõÓO^ÙÂ8àƒD¤{!ÅËcÕâ¥[Nñ‡éöˆÞ¬NJÛL܃7CðJÀaHløŸ†GÃ,4¥ÓºH! g†–½040‰ ¦(<ÜŒC‘¢ª‰hÏ'¿Ÿ‘Üp'–N»°z vp_7žîÀ±ÜõC]6YnÝ|WƒÇ=bŒ ý]Ö.¡Î¤žaOœø`Ј$T t"ºUNŒNîw—lÆrÚ .1vèªìëh—x$uÂnÚ~³&€ój]”Šþ2e‹~%GƒtÍÐtKrtM\Y@Žƒn‘|6vþšÇxtÖ5Ýå“®é<Ï5ÝßsM—öù®á´kæšîâ)×t×Ì5=)DÂ'F|jd]¨i\"?õøBÑïR(h‚­Ÿàl/ C—ôoƒ©>Æ4aˆj‚BÛ×#`'× ¼¯È_¯ÿs YZwpIÕ«Êäçæ¢¾¸ØA5_tóÜè &6*ËU‹³v`F.ÑíXsàN‡ Çt³šÄ$f£)‡êZÁG±Hjµëíg¥SŸôA#'1zA"|8Tï·ª¶¦¸>: J3a®êl2DuYŸ ¦ʾï¸&½“ÐÕ=¾¸={œ9…r~\®§ã1щ<}ô{æ4¨#Î(¤ ˆçîWg)Ô)q<;ðMµTyî _B JM`9ÄF²Ç¸( !\bOÍcQ6¹ñÑ\kŠ#jô’™“°#æ„vQÒ(õ}Ä!ZÝc†²På&˜å”œ¦_‹Í¾oÓª„Ÿ†¸Ç=t ¦»ÛôpÞÜH@U‹sâÏ­ê†ÌåËOÕ7uÆø …H½;<'VÉ¡(KsÃu³3f£î$@GÄ<'6݇KiKŒƒI¾vêqÿô˜é3—à°Jctt»-h¾Á8ÇÃÐTÆ.åÅ) >sÈ›B¸äUS¯Ô¶ÓfPü¾/Lz˜Ôâiïñ'ªnê sôÅ©Ôàôu.ñ¥©4Ú ¦Fc…iˆ;x@¡—DhßÞŸˆ†Ø>/ÖXÑŒ†L"ºµjM²„d¦ýéh Ín4×DÕèŽtO[ºì“ º—…Í(Õ®ì`(@ÝÏëÖì|$ë-"„?Û4X=ž®U÷“Ä TdwRN‡‚2´kïgËT¢uÕš›ÿOÒ”ÆP»to Í(“áù“Ì:Bï(ê(bLi¤¶×±¯6‰³ÙZM£Á¦Y’óBІ0AV”ÖT Æm±UTöEFþZ¼~û £,pÆà4¾t€I)‘w€"˧dnOuҜˉðºRZg_Ô5Xe•î§ÓêmÒ¨Ëã|¸ñ@Ð0AÄdð 7èlÿßfµ® ­§5÷,“’S|¬ëÔLHкjoôã‹¡HŠæ+ÃLÌŸ2±dˆø2È$¦6¯I-¨ÚŒ+“óôV­ŠïG§ê è\ihæ†eàdG8€UF[‡M±Úx#´Á²v3LsóçýÌ̳t–gƒ0žB9ÍšÖo÷òÍ,È¡Á Ò1Úû—†˜Àp«vÚBdÿ’RÒC½ƒÊ¬Å¡!Á1ƒ«Ap¡{—¹?dñm§{ÙÀ/u3f•ßzÃg8#"´{×AKWACgÆaöKÓØ}ÅæöiÊݵº} Üú•„:Lj~.+0AŸ*¼÷4д™ø»t·6wǫ̃3Cš×Æ8h72¤´ƒQL†’L4Szä$™é]ûÚA«0+ƒôÐYëµ!DTmÛ\ûعV*_šÎÛ9páòi(‘€§¡9… LfÀ*À3ØÞæå¨ÜT¦h߀HAœøÌÅ6lD#!uÿ‚H>iÑ×Y—}i³Š|ƒþñæÓëC¶ƒäÇ÷D0ÃÌU§g¾%)ODe@qg³þ[aç @Ï–áWÊ$„Æ BÔOÏ(Qðó¾ @‰iˆ¸°çAÆd˜`˜¤Ì ÉÀðccp`ˆË•C…ˆ4Îj# nÇ/M€©H>˜PÛÈ;}LÈÌtxŸÏ>"†¶ÑÚá=Z!ó´<:?njcjÍ!¥C&áÒÿòDz ówM_|Οu¶\Uu6=Xgé¿Â1–õ©× ,ßû/ ŒK÷HÕvÔÏî}`ò†ÌOüÉofàPΗŸBU)ÜÕ¡Æš=Ò›ôôµ˜1~g_}0ðHÅÆf™röE’(d.Ý¡÷“[]ÁÍ[®Ki¢°lè·ŸM›67e@Û‰Ômmûf1± È´¿`èUueÞÊìçñcBÊ+ Õ3£?!úYÀý>óisµî#ñå¹¥¤ ²–„†›÷ãÍ™8®41عá3§ïÇOüÂRã_Da/ÕôÙÈe¿„å 5–q:}µæBÑ›ïAÄ­ÿ¥É»¢‘‚ký÷êWfCÿ&á(hÁˆ7ûE`ÅëéÝßÍ68Ì6WŸI çü2kÂendstream endobj 56 0 obj 3012 endobj 62 0 obj <> stream xÚZ[Û6~Ÿ_AÌË&À #ŠÔ­X,lš¢ÀnÛM]ìK^4¶l«µ$W’gâþúý)J¤,»ÓE‘Bc’‡çò ð ÉØêå.`«õ]0ýõþíî>¬îÞ}’L`t{'X€ÿK—YÆ’Xð(f«êîÍêíê×i8ãIà Ÿå:?Î.•‚‡‰GöÀÊž•+<:™ò@Æ.Ý×c±î‹ ë÷yÏÚb]”î„0H¹J”;áÙ’ËÐ/ÚŽ½”‡ûµ)k,[°üx<€ç§CÁªÓ¡Çg׳]ÛœŽ,¯7ìÉcQaÅ$õXÜaCÙõE]Ö;–ï‹|Ú-ë˪à45à‰$92‹xA°Ù(Ñ}Q?hVº¢Þí—7Ý—·†É¾Í뮂¨ÖM zÖ7šÐ°·mZÈäPjÞ5é¶h]n%ö ½½8cŸ<Š4ãqèR`Í~üüoÖõm‘W¬9mÞ—M=hLŸÈ;fËÄÎ.«cÓö¹á´núÂhŽx¦™ï>©™ ° w‰ºi+C;7F‘ÅÜߎmŠª©ÁªfѪR7õá̺ӑøéXÎ:hç`EÌpª¹¶¹ÙÛ(®<À–°à(zOÉwE˜E\)é‘°OåÁxd=Œy jåÛ>vÀ(¿ëp"} ¸´Ë.øiÈâ4åaª'~ž;J¦xäQxn’e\&î(„sE[ìD —ö†ºdÀcå³ÊÊëuÑAúü©+´m´_×ùz_lJ¸xß´gØ{U‘÷ÁŠ:@@¹=C…f›hØæÍ— üß‚ÏpÅŠMKiÔ`/ZÏJRF3+Ž“Ø²Ùabq 7B„†P0piO§­NÝ^i]ï&|è ²0J3(ŒXáÄr‡18ß‚Œüÿx(h7' c9;Q”`ulKB‡ñ™^ÈsB™¹sÞo6%í0OÏÃrU©›Ž²Óq“÷E÷#%TCøä¨qãÏ%at±@Ì5B§ßh#îÁ°Se²›è2»‰Ò½^¡‹“þ½ÎÈ5cûÜ/‡»é¬®€¥;\@ä²Ïëy^Ëò͆ÂS[ÜrdßaênEÑgƒU¨xšÅ.ÝK§U4èƒP'g÷û¦·¡Y…sãIF¼jNýSóõ~ˆ¥dº(&lš„|º¤ô~¾‚T“Ä]õFŠSž¦.­5­í̈§¼æO•æB3©j`‰ÝíÞ#û'ÿšRþ±ŒY6¶(½ilqyK9Û:?æOå¡ìÏÖ%Ö­1n]\Bœ/~ÖzÌ]=÷‘Ŷ3Îu†âBr‘˰™¥(êR—Æ„Í׉¶¨?'›„¸Úy)ûýˆ ^Þ2³sVV²yH‡KdÈgäªÅ€‚#ˆtŽæQ8‚S2¯ÌÍ€_‘KñÀž<,$€“ÅÉäà—-"Â! í¤gù—ØÇ‰0àtZg­ò`ªõ†óµ)~þ/¸@’ˆKw£•Éb½pw+) 4ÿ¬/ºoAš_*ô)Û„êåÑ©^†¢æ²fÂiæÎôÅ ¾‘›:ÃÔ ºÓSWÀ‘?¼ÎjŸŠ-mµ×®‘¨åƒÄ]þå/æÜäL* 5Í•”IŽÒÛNó¡i|:ù…Å$g7òèÊäMÓ¼ G¹Œ¾‘ {!;ÝGÞ(ÐøÆK °-dNÃþ=Šw;ÐúqJГ{™*"‡Gè ¹.!îŸÎ}q?–áÍùÛ >†û Ù)Âî¸Ê }xZHësð‘™E4ñMÙ÷Ö½Iúªòa‘toñâ++ÓŠ¦6”ö:-Ô½þ3$ !?A tfj§}%\){6ðÍžDÖœš•ó—ÛÈgU_Û!%ï›usXìã‡Àa;cêâÇ‹jÈ+Ý{AÙ°ös އ(“'·>!Ì{““ã5sHeKë‰,á™TΊ ’Yêßà@†xyU‰ª, ¦Á¡wSåío~Ÿ7åQ4 bꈘûQ üâ廘¸« )Å8j«D5¤Kƒ.‚‹žŸÍ1^öE½t#ñ0IF*_z8§§AÒ…Ïñæ{8ÇPÛ艹7·òùrÔ351`O;oGPVêª`BœS嬋}y]øÎ@p›@üvç¦ý@ÿq)Ã¥‡¼.ì,‡ŸË~–)Å\Œ£ƒ¨!àXÍ×’ÑCLÀ¤,Õ厑ç„JÐU½]Áj <éD,›PÇ{®+‰ŒQÁì—“Šnê§A,¢ñïÑ×ýt?(J——ú<öB3šß „Êx:qSÍÜ•À½ø¶@y¹¥‚—/5drHÚîà½Ò Î×óÑ(ãwXáq(³/Ú–¡4î’;½q·¯“„ÍV#Ž­»O½iÌmu¦»ÖS{l: ¥÷–eKîa&ÆÚÝd¥kª y½3ÌÆÉ¼I…ŒI3r(=$IC€ì8X°ý :x$3Õ²ÿ&VÔ±Ô_ûVôkhÏF£%$Þé®ü¯0æ$%øíâïw~ßYN6æeýà¼á¸–Õ†\L‡³)JSqý©Bd·b‹^ˆ-vˆ4íÝ3ºœJ§5ü×9C“ȹÜðg‡)N,ÝÙ_ÿŒÖäw\‘Õë'NvâvŽ%*„­fÙòÙT˜À¦Am:ó@` >" Ä:{™â(1‹î"1~ç=Jàg6Žá¤ÖÙ…«<ܺ@TRrZèFSGÒ5}4Rz•%M§Êø×]ʵÔp{ñ[dH?3çTŒDª…;Î4û4n˜lË/[Ê‹DlÀ†®QQ„¼ôz¨Añù¡Ü±oëM™×šGÅP¨qDEÌ¢Ù®³\"LBý„ÀÒΦơx;ª³¿ÏÿbÕ®¨‡w$÷»)‡¨Gú}ß¿y÷nÝñ²ßðº=ð:÷‘õ\2Ñ?ûMüÈ´GÞIÞùñ%••ÎIßo~P<Ì&šØ›\Ís Ú†@ÖæÛÞµ’‹&7¿ˆEå'ŸÆs¹)&ŃþJ‡ è™u£C€"Õ­%ï}LsÑ®EÒ‚ˆg©IoZg®Ù;瞆‘'À~UäÝ©r9ë­›â0{'©P‚MóüL&@åâ,Z´gzé¢@%‹¾*:~¤bž·d*'#hˊ⥶C¢7SŽ‚<ĉ‘/(§›n5ïºS:«-a¸t£Fs~ìI¿|ü‰®T~›·@"5M+–.Ä B|ó €‰Ó/Ü«à;Î>ùáq5o‚„BKK÷(?ÙjìË›Ïþ« ų`Zwõ€Nßèhoר·gvߟêº8ÜkÂA€—Á<Cq7ø¾mN»½1È(3˜£ ’1Eãì÷WîrP>óè|3ŠIÙ48> stream xÚ•[Ksä6’¾ëW0ú²í ‰MÇž¶Û±áp·wFsÑ…ª‚ª8f‘5|H­ýõû%@‚ª¨n‡ÃvU!$ùø2‘J¢û—›$ºßá?¿âßÃÍßîo>|f±ˆîŸnX”àåi”Ë<–9‹îO7ïyÌãŸîÿm‡K Á=’èWÕª¾j¢?z—’å,.KŸ´;+&Mx,ŠÌ£k5D_ŸÂLÆiæ³ö\+¤q¼A3QÐñ?|æKÂÃr§…¦þ½ƈf|ø,B;M —¸íú“¡ e,‹9óˆ£]w:Uí~ˆª^EO] gµ«Í|9Ïÿ$‰¿äû]Õ4¯Ñ Ú½ê#LëÕNÕî©yÂâ” w³g<ƒT¼qZ ÷PuׯQäQg,.2õû£ËÄöÐÔzñXQu>ƒ½±£5î’X”%ÉŸÎH×\9§é²äc7ƒ!ߢ.öTT·»fÚ+ìFŸ‡±jw–ÂÂM=€<ª¢w½:u#‘´cß5ï0iô5‰—4¸t·º;÷ÝN ƒ^xjëMôäNe‹gë‘,·ÖSz”Ù2ûË׿ÿN»]×@L{\˸–´3ÆßšÚFòíÍÇ·DÌY‰3–î"VÄuëûŒº˜y”þ¸Œ3(„3ÞýéäR{‡@E=Ã%ìûî|Ö7óD^p¼êeRÆ,e›HÆã’{BT‹ÐyvÍl³\\÷ n¢:À<ɇð=ÄÛyêÏÝ ÜÃWhMo{5µT‘Ç…»: o¿ï±(Lil@ßuçÇj÷'¾~;wýhìA;±§ðÈeæ®ãÑFXfýÕìµb?ªcåé T.¡~®qBH]ŸÿŸ?ÿ_µóÎ’’IwŠ#q;œêa˜U[_ÖYGcWGF»— àׇKýÃÄÃodyÌ áQ†xƒÁµ.:4xÑLúÛ^à 8¸€dÆ"›x#£@1›äÖ ­…%| h°Xf+å‚pÑßG‡É €%TщàOEÀdìÍ[Íß‚ ‚ñÂ9W=,a{ðôÁȦ`i¨¢‰–‡ÿÕL²X© dCý üìQ‰"³T]ÿâ놈9_‡«~ýÒ÷ÐðO]Õ‚xxÿù—O?ý5ñÝFjÜ…( .¿ÌíftÓt6‹[ö æ|ª[’ϦH»ŒÙE- 8!³Mí’E©ÉgMðÌQóP·޹àGüÿàpÞ}p@í8)ÖåèC ýyœƒ‘…âp"<pP£9Û©úVŸ¦“¾2«S³“Š2P ¥5ÏÕkÓUû!Œoð Ü!#曎œæ¹êgDf‰ ÚTXbãP« ă?ø_Rz/¦¤%b ð2/Õ@TlT£úÄítzTÚsäõѾ«@t‚Ë8O¤mDóŠ óI@_È&“Fì6HvSƒ»ÝÏǶc%³ÂÎÔÛ Á~Z*ëš°ú*Ïëd—ežÃN9×2HyxOR>ÁJtÚµq\Y]ekþ)%ŸÕØÝ—„>];G¨)¸|™K;EkJÆtÒ<³4gÓ4¹\GŸ¶T¼>9â뻩Ýß}}ŽÆú¤Lü~öÓ †”a嬂ÿíB‰uãÐbZMìÒh&t®RÌ‘éX? âô¢(,ÙÝcE©É“R{T4Lç3Áòðë®Ã&ùRÑ¡¯Ø¼ñ=ÿEQ 몡­>‘ó±¢™ÙMØ…z§åœ ,²Ó@KïÕMç ¤ 'è¹ÌúH®µª‰Å‰x \j?£ÇQç“—:r/Ó¡’Ý4qŠZÈaKòVأůח†ñÎ<ÝÍËX®c”€2À .ƒ/Ä1Ùgä‡+:˜í»Ýd d¹¬wz¹ŸÕ¥Ý®lyc07±²¬B¸Õ_'äïæ› •†—(Jã>¶†ÃC}hˆóv«üÂd¢AÀ²ò˜(GØ,WÊ-­ŽŽß¼„0Åõ$Ä2kz cãëèÓº^ù° ³„ ­v1Ç@{µ kÕî¨lE,9`怢˜}P×ßéKè[¹Î9¬º`%âÞ¹ª)EÆ:8Ègß6xœÃ6–°çõ«áH®¼º7Ê\ÐK‰}{UV`IÕ„Úf¥\bç@¥Yçéµ|M,µÃ@Ìó¾ÓÈàYíÿª*g½§À[Àº¹ ½QÉcÉוï7H¡$äs¯sJP_¸,˜#5õ©ž5éÝ|sð{?k/¸ãËä—wÑËQµ[uŒ4™XOûFC`]¹R^ÜìjŽå&õqïFïJ5¯°êG ½°¡‘Ðiv°´„‹_Wyö³V’Õ:H°£©‚¬²©Ì’6î$É‘O‹•YÿNX'bµwrª^)"´—5a$Çúpôy„¿Ôûñøß{ÉC¤""MV¦/SáÅÊ3%ÕkLj²¯IÞC|-ô‘Ï 2•jÿºó] B¦@õØ(ª÷lÔ aG9³{n+¹ÏÂaîRwœ"ïyŽÚM]²Ì–‰ráØˆ#.¹ E’α¨Ý„»Ñž·¦Zñ—ðµB®ÔþPóu¥O¿Í i‰Ì·Q="Þ"›#´Ôõ#ŽF窨:×4svI¨ºj_»/ Xvi"Š4F XÆ€;v¶žµ 8+^®\¿øyú¹&ÍC4(æ$ýÁ?a? íà§ß iºŠÌez¤Äfv§•·‰Pé¬ûì–¸÷uÊx Ä¥’Å9ù¬ïFR¤ l]ï  J¹%$ÉS}é¨"aŠR&tâ÷áØ9zï”ç¯ÚלŒÃ&üÄ$#µŒ~ ¡Ý:Qõ»zP&ÎY%±/,Ê¥)ËÂN¦Š\X€“ÂÇKy@dÛ<7~äsÝR&æ±W-Y‚[*T{ãbÈò×òÄ[¾ã›#S˜¡]’*ÆEˆÕôI¹^êñhÔË)’ÜnÅ,F‰Sf×#fñ¢_)  ˜MtˆTKÏFía~™ÈòPh™qWs‹sÀù(•Ykf+ë»Ý"ÔªˆTmYN§ ”é Ì•%µªý¿§a4%­’×´‘K99"ÍEË“ –­7ʯ16aKùU^+¿º$ÑßÉ <_`á'I]ÚË_ø`\—æz–p|îÑ…õW2-Ÿb.¿¦‚mÈx" ài'?D$aÈNAÝtõÓEçÛf™aGÀ@g)],רU_b£“C'ö ɪ=Nn}0"ó`çPLº¸ä>Äš[7ï°K:ÍCËO±×¼ÂUÿͰCØãÐù‹Þò˜7®–Ö÷L˜­CæûB¼<õ—!O"è½"Ú8žþv­ÿPóæ®¯Ï£iRÕ]Eþ:Ü Û‘DM®Ö÷û—¶@—³ý‚¯Ë«ö›Ùh9©z5íè)ÛçF-•^ÛõF_¾Iö¸˜ò‡·£Îœ~ì X»/«XA»f‘ʼn-ÛÀTVñÇ}±‰„éöv‡`ÁÓדkz¤GXØÚPóH)ƒõ~DhQ[–‡Ó¹Åß½,¹†bS h*jpókVˆÃ üJ|Ðïæ¸ôèOO< wÛ…³Ps¦½ú¯—PðSÐP›éYgJ!wá_&5 &¶W!/yãN,S5Ì€CúJ½ÑHáá£gã»tdyhÜÆÈ¥Ñúà$ˆ¥.­ï»R©Û§ñ•ÇÛµÔ°´Õ"²}m©0L¸F…‘[ƒÚØ)-….º;!KlTx1Y¹Í®¾˜Âg·o^mÁvãY<ldÞÖoä¶8§ØÉ߀WT„bþa‚"x*|>Wi¯Ã¨œW·å®MÓù…§Kmx«çÜÿ%,J–¹tP䈿5òk>†Mé’®jðѾÃ̓ŸÏå!™»3ŸÃÞœyãê㣮ñ{(²«&R&VZˆµuÞ¸Òï•ÆÛ«óíÔ G ‘Xæ uVj“4z§? 1íö×+·Ð/¤‚Î4߯rNoCΰÒu\±‡þÈd=.€$°_â­ø1¨§pô…Gñ­"1éÒ€.ËÚW/_™8Ý ;oÉ`ê§|jÖVcÝ]ø¢L÷%RawKlœ9#»U-ý …ÀÚóöÆýñOí§§ÑÔ‘óF¡º¾>èªÊŪÅÏOŒ¸P¿6(pa£’( ùÓk–3®¨Ž5¿ÓÎéϵg¢ÒFœÌ÷‡x~xÿ¥¬P(šî/™V;*ÑÄ_îížItW„ˆ¾;ÝP{·þ¼|,¢æF¦\·\^~¡÷ã«™GŸŽ7OôW‹«w—º-KÂɛРN\FrH¸nþL­/ÎfW~ÐÔþ™0 ÙÏ3K׺# {ôgPȨ_û;,¢w‰µ´—n»ùXÿ{óŸšp ±°Gšö.~H4{†Þýíb‚³Øñæ_Q‹}þ¥V–áendstream endobj 68 0 obj 4586 endobj 71 0 obj <> stream xÚZÛnÜ8}ï¯ úeÀ¦E‘Ôe`˜Ùl‚}˜dwƃ}É‹Ü-ÛÚÑ¥WTÇößï!ui–Ôê‹ ]ŠÅb±êÔ)*»{Þìn‡ŸÏøû¸ùõnsóI0ó0awÁü,Y¬5AÌîªÍ;Åßßý’ÁR2 ¸5‘®›¶êåÏhRòx6€MfL2QÂ…$"ä}œð$"ïsû¦D±]ãÍ'ÉD0_ x*'~÷”³ÞD5Äz"áÓzæZ…X •fÙáP»¬+šš†•Ù±Þ=å{öÐ6ËØ®©ª¬Þ_—E³¢îòöÁ_› % ˆˆÊl—³oïrþÈÙŸuñš–}üú3OyY~{Ïû-«}*й 4ÑñÊšÖ­.[!::»î€ÃžU¯ŠdpÈڬʱ"Þ膆1c"û¼—!¨®œísâ¡C.S"“ËŽQE±â •)¹¹b÷¾Th.;v¬{=`ÛÊòÕ¹éhò–=e‰ó写¼cYÇÊ<33M•50µ ¦*-xHM}ÈÛ¼îœî¬¶£ŠÖ¹ÖúÕ÷fMCfëOGpûvù»ïKAGÉQäVuQe%Ëé~žh"ù’U‡r-:„FÒ¦DþBR`¨,\WïáNúæµî²dÈϽšˆ%\΂+ŠB2!Ëöû–ÝÚß›CÓvœæO ¿}Àï„߇óVYmŠÀ®iÛÜšz_Ô“£VÃ3 HÅ%̦ ¹@9ñÅ‹Úi´[hóÖò]Ñ/U¶¼ûݪwÀã„Úæ† “¸àª×ƒKHø„ޱX‘±®ÍjSk³ÎF¤Ø_÷‡yÚ*ÔÉÞœûj6 .iL¿S„‡Ô’¹³•MP•.½½˜M ɵŒÖgÓˆ9S•OÀ樆 &œJÑ¥mBb#Ü™éšŲC½t›¼]Ù;K :Ï®gp*á"¼’à ˜í•æbÊ­Ï=I>¤|9¦@”Ηë¡×i"%Èû±öp°•:%rWÎ fç(Ÿ±Ý&OðyÐ!ÊQo:¯ Q\jI†¹8ð+Þ:eá¿D(2|%"%R ‘žgGËd÷¥Eæú17ŽAá²k›’5‡¼uœŠ÷”$ìOCLqmwT¿‰è…< ¾Dô‹J¢GÑ,௑Π)kìÉ¡-ê]qp\ã«.±ÜkЦŠAu…}Õ³ÇÑÏþñOV¡Òc&ðŽÇ¶9°Aݓۙ6¿±Çb?üä ÕgyHnãO®Ð±q‘×µí±®-àb#­ìŠ*¿b‡Ætׇ¶ÙåÆX¢ÈppÍÚÜ2ÔQC‹ú2àÏý!Ûxž&âhq¾8™)ô4pƸýÃ$kæòß¡°":è¹D®I*0j4O®=öÅãzÂÚs}¼"ë]çºøq^~ƱýÛîÒrRYÛ‘Ó'à…×í')ªálÓÒÓ– «îOŤáDõ°}¦ŽX³¡´_×msf∠´§ŠnBð4%ïOv°%Ê+s£qqzòùè×:ŸûšJ>AÑ• ªt\©kiújàò1I5ìPò²³°Å"w=^ú¹½¼… ¹—=´ W6½]ìýzçùu‰¥þŽ,Ìñ­‰áÞ$eÃ5š åÍx擦"Õ[5][»Æ,(d„=³ÿ ¨¨£1Hp‘aö§q ÅçcÑÅ`YÿÚüwcTøMÔhží¯aÞâAàÌëåýg‹ž²§Í¿Yyþ‡xÀPendstream endobj 72 0 obj 2722 endobj 75 0 obj <> stream xÚ[Yä¶~Ÿ_A0¼v´%ê6¯76b¯xŒ¼ hºÙ3ʪ¥¶¤žõäøï©¢DªŠR1$C©XYÇW¥ÞPüù&7™Yä…ØÃŸT"SA”ˆúFYç9[§q>Q³uŠï§ÝÓêéfçíØ›uN8*¡LÙZf©“àÞO<}‰(Ô"³ßê˸ °¸Ú@)&‰–ô¤F8)Ö Ç֪ɠNÎLAÎ.§‚­)q„,œ)°L™¢ôÑjÜÀ)¢ù:Ü’™b¥85,[§(}`L±r(…;Ü ¶¦d†…3–9S”>0Ze¾±Ù$sæ/nÅJqjX¶NQúÀ˜’ùÆfä s*x2EF Iî>ìj5m  ·¤¦8)V ÇÖ*Ê )NÎLAÎ0§‚­)iBc—Ì}Ø£Õ¸RÄ4VÜ’™b¥85,[§(}`L±rfŠ˜Ç “¦(•ÒXÁ%söµš6p +nIMqR¬Ž­U”=@SœJÁb…IBSŠ”Æ .™û°F«Â7¶Hi¬¸%3ÅJqjX¶NQúÀ˜RøÆ)& LI“œÆJšÜ}ØÔjÚ@)r+nIMqR¬Ž­U”=@Sœœ™"ç±Â$¡)YFc—Ì}Ø£Õ¸R¤4VÜ’™b¥85,[§(}`L±rfŠ”Ç “„^4VpÉ܇=0%vÜÀ)H¬¸%«óVŠ+ô–­«äô)õV¥`±Â$¡)i1ÅJdÊ,9Y{ÀM +nÉL±RlQQ…ŠÒÆ”Ô76-x¬0I#î"Q¿Ž£<«­ÁþŠºì:’óPÍ ™,o™y ä¾òÆ _[oi¥\;^¹Ÿ±„cä-c^®O!¯öÎ…Ý2ò–NÌà¹Ê:¾ÞÒŠ¹P“½ª4—<ËÈ[:1 ¤W"æúãøzKÅSü©jååë¹XFÞÒ‰¹P:¼ä9gfÇ×[Z1ò¸—Éæ4éâ€/˜ IÕK+sΪýœå‰¹¦gZt—›¿‘»®«YàúË-ǢẮéXÀîËÁ¢º®'X âË€}Ñ®\Ù õ2ž^t×!ꦼ w`ÿ:À»€|—Ñè‹_‡Gˆì2X\@åëàâ0]Ær ${š[à™ËPk4¯[ ¸q -p J"ãsMù$3ΙÖßøkO†¹ 5žJz£”ó³ªDŸt·ÊWIoÐq~ò±˜û0I6Ý­2VÒ›CœL,Æ2L’Mw«Œ•ôÆçç‹© •äÒÝ*c%½.þ|[¿j0I6Ý­2VÒk²ÏwÝ‹™•äÒÝ*c%½ø|S¼ 0I6Ý­2VÒkQÏ÷¬‹ŽJrén•±’^y¾¥\4ÔL’Mw«Œ•ô¼óߢße ¦»UÆÿgC¶hGQ<ŠRq÷é&w›yõ§»›7ïcÁÓÝM$BøO$dQŒUÇHÜío^ÚnÍqÿ »/ïþé(càx”2‚Q€[¦QJ)îž´èôFW”. !Á¥’Ò=ó÷EEì½îı©6e?|(7{±i÷û²Ùâ®Û0ˆC….lJ2»¿jõVüø·ÄЕM?ꨨXfVø¾êûÑtv‘182^äLx÷TÁ©—(ë¾Åsìõ †Vè_e-†'|`X­Ü±½yŸŠ<ˆ©Çe µ~øÍXñÿ÷+£C„rÜzÊWÓBÙí÷¯*ˆÎ0¹ÿÌx§wÜ%‹@©„n)õ À˜þ¥ôþ¶­ð spûjà,dç±e´"rAŒ6ÁöUn)ä¦Ñ‹ÞiÔ£À‘ìIîAÓÑG‡j¯o‡ö¶æq¤ò ÿ"\x¥2È{¯Åý«§öñslðÀvÆa 4S‰Ýƒ1¼õŽ5–Aš1*s¬Ï㶯ÄQJ]ðŽ8ÔZzèo6zøäç²,e´m÷QTÍ ;nhe*d„%DFÛ|;HIìÜóålËè_sl&«!S»}à &ÏÔÞV\7(l –®y èö¡ÜÃYÁ7ð‡=¿û ™ÉQ¢Ý]L¢ñxh,ˆµ|Gg.d|á ÁZ<Ÿˆ ¢©ˆQÔÕvå‚$”­„Ò¸ ¥ÌÃ^&‚$áNbFÇïâ*L¡öJÃéÄJK7{ÆŠ¾)”«”‘£¾£Odë>¡òÔÖš/”uý"tS>Ô-œ‡ÀõЦíö_ÀEó4 @có ’ 8Dù¨{[¨T¸.|yÚ$~éõîXç¯Ûöðn/ _ Uóˆ²{Ýlu÷fYî½@&¬žýpAéä=´MÛ\.…G–U”ŒÏéú­ 7ND¶øû¥#”œ=æâ³Ö‹C€kœp÷Ù™ôFîÁã¿áúþ‡¸ûïT/ÆÊ}:ÄT’:É’Üò¸¤w\]ûÀ-DИR^GpZÏ_s@}ŠÒ”›¡í–ÂbOèTUûªÑS"ÑÊx€àuib¼þŠ ËZ]Ø'*@ìGsèÚ¡Ý´µYýãëÞÝ¿zÿý/?{ÿ¥ókw󟸉٨á78°~g¬³5ÇïüÂeHéA n¶C<ܶ»[›ø1Ÿ¿O<6ÁÉÒˆ2ø$¼[J fŠ =!Ú¾*îÿœó”’>ó÷PXcö^ãûN?Z’(œoýcÓr°©í rLؽ©ºÍqßèñà-ÚAâlÏe ê-Ài½íñ6ô(CÊõD%$ õáK 6÷Àõ²+þ…㜱,árú€'#žòdojÂ6*@È2¥ô¼–…YEô5pšp4”ÌUkC"â—¦®¸£KH¬3‘ÉÂ>`‚†‹¼ ×à uÈÝ@ÿz¼’g?#KÉöÛ†¸i«úêEÅÅ\ˆ·‹Ž £ŽP€'VÍ/Ó`O½aXÆ%*È¡Ñ! ¸Ö0™”\æaØ ™xUõÌEŠ Š©Ô‰']¢xã§®6ƒs&;Wf&!8 Õr‘@úʘnzR¡²¸ÔªŸŒ‹òõ{ISb¿ä£x®¶XÝZH<…ú\ø­li‡ìÐuõÔ¶Ûµâ&´ß­æC0€rn&x¯?œÝØŠSAPáç‹:†­,´)„t.cÜ.¨Pà„ÐLá¿%úi;ºXøP>Tu5&wãQÙªr‰‹Ÿ)ù­¸ulò|B‰—Ó©ˆ½‡ y´£)hý…Õ,[×,v12£9Hn„£‘ðù¨Ò1ÝüGtæìý×éÅ®k÷ë¦C3 ñ#é/u‚¶’½‡ œ Å ˆ\P`m¡Â¦ÝjÈv A]á0bœqíøP4‡’²ðã]E``B)0ÞÍ8¼¬Å³o~c ´Ñc£­W¹8tnt•xèäŠÒžÆ9Ùè93é9œ(\2bH[};6Õ ±ËÓݸO7]—Sc‚)i½³E²È·¥éÄzèW&/\Š<ñÇþIðÎuÙošöÀ!é]VØ”½Ⱦ¹µ3ŽUW“¹ H¿ã„Zo~í1S¬wœÇf¨\¢|-ô°1߸êÐôÂ%^SR:92’™ —áåPmÌ 7`»ßãÁnìø-Qlï4D‚úãZªÕoRÅv þóu† Ù|†SßÏ,(¹¼¥ÜÛ›GxU3Kü¶å)ÐWà·¦žõ~´E¦çG%2‰ì6+ AYCS·}qº˜¢3Ø$p…é[ñÖò»½0ä&š;Üf7æ–๗l‘…e4NÝÇVÂ|™ìÅcåcš0ïá@á‚dïõÔ2<à õÇ1çbÁ;í¡ÐYº/-æ@oý˵Cbë|Q”¯r‚È¥QžýÉJ(î094¼Õ|Ò‚ß F}|Çažnxß­  BÅ [Æ–Ö FÚÎfûxUõ2®:1vHröÞ¨­}¸’ŒhЙ¯Øeóh\ÕÔÝðîËË(I¨Xúû|Ô è2.(‘ÉÞ¡!^ÃÙ!;>ž¼ö(Ë,U­¹É©ùzE¼Þ!2Ù‰¼×5Úø/ݵg&Øäb@q¸Î·æÿ¾×ϺþÊ:Ö…ÏtQÙ)ø7æKÆ›mÕÁ'¼¶U€Z„©¢Y=ªŒñŠ«²Õ.>JÜ/ œGþÀöæã+ÏþX·Ó玪Áºlça~zÊÅûÖ`¾ hßçÐufB~OТE}­»—%‡ö2ŠSF6ŒÃh·ìû€ ǧ„âh:ÌØ{3ô+\èžK]ÿL‚…ÓB8}&9“«É­Ž÷Á?”œq/Ù‚û®Û!‡ù‰ U*FéfÚë+Ïe¢ZŸ‰&¢¸—x»«jÝØ2½wz¡ E¡û¾nr5 Æ \:ú0¸©ëCÌ4HAõ89*ÇtŠ.¼>5)¤å[·í@϶k ÷¯Ð“í'Àñˆ¨ûµßaà”¿¦ÎÌ&'±'óZZâɤs‡8Âð6¡âí´Éã7wŽ8„ Á_löãoõñoûgÎ~³æ/­cûÌ_øÓ«¿±‚ð3't]¨bºÐ‰ª”îŸgÀßÞ¿”\yàý&¸qSßYå|<'SÌŽPºpº›‘9”ÝœãWáî‹^üùX] ˜õ×›_opÃþ7O¬zp ¨ÞâAhÔéé³ÅÂìéæï¢9ÿ–¦ endstream endobj 76 0 obj 4055 endobj 79 0 obj <> stream xÚ•;kã6’ßûWùr`F#‘¢‡Ù³³™Åb‘ìÝ¥ûe€ƒlËÓJdË+É3ÓÙ»ÿ~UIUQ²Õ›I“.Ö‹õ¦‹??ÄâóC.E.u¤Jq‚¿#©Í2KEû ËâOõ‘2‘¦2*8’êÚŽâ"Žb'`„'Þ~ÌD)ª—<¥Ü÷ßÚnÄ;{è‡éÐM]ª$Š3sðOÍpi«çAì»Ó ¤C=Š¯Íø$†§®Å¡ö}s›î<ÜceÆøT·— 0I¥ n$¡åĵŽdDRê(M¿ÔçCÝ‹{‚ÿøˆ‘¡H£,ñ!VEF¼ˆ®Qä š­Uæ#Ž[Qçvø+;ŒÎ¦é½ÀQ Ÿ«l…¢ IãyÇ’s&D¶çí O»¤Bx*N Ö±É6POg†ˆgÝ”°E& Q8Qp©(£l¹²(„œh: vIEñT­c”m (žÎ !g”°%ӈ‹ËŒ1J7 WÓ‘Ì·â—LGųáÐzFé†ÅÑ¡ ½F DQ±¦‚Kf>l¹²8q¿¤¢x*Ž Ö1Ê6PO‡B(z+ŒŠ¢sê+JÜ|؆áj:@!rê+~ÉDqT<­g”nQ"ç¾Â((©J©¯à’™Û@®ì ¡¨¯ø%ÅSqlx´ŽQ¶¢x:3„â¾Â(¡(™¤¾‚Kf>lÃp5àÄWü’‰â¨x6ZÏ(Ý0¢8:‚ù £„¢”1õ\2óa†«2„… â+~ÉDqT<ejÙ†ÅÑ¡ÌW%E'õ”Ü|ØrePˆ‚úŠ_RQ<džGëe(Ч3CÜW%%O¨¯à’™Û0\åAÕyL}Å/™(ŽŠgáõŒÒ #J$QxÆ3_ɰěo—Ì|Ørepâ+~IEñT­c”m (ž…`¾Â(¡(En}Å´`¸d®±ºÁ…-rê+~ÉDqTh]Â6Œ(E(l‘s_a”¦’\ÊzIè+M×s.VÆ•¢4(ÐæêÏa –ŽÄF©Ks%æðKOe£n *—¹,òxƒ¥#³QDeÄ\£8DÁÒ“Ù¨h‚œ> o°td6Ê‹ ÁÎÙÛ! –žÌF®²ÝœJ=Þ`éÈl$Þ õÌyÍ# –ŽÌF òÀœd¢`éÉl¤¤ (Ïßã –ŽÌF~"ä~¢`éÉlë \ͱ° ca@æ%m墹ÚîûÂ^÷eߢõÙîÊ=éËú²Eg²Ý4-ZÆ—µM‹Æa»§Ytt/ëjuýv˱h¸^Öt,ÊîíŽ`ѽ¬'XTÅÛû¢]yYɾ(Z·ëéE7ñ²ŠzQSn—»‹bÿeï¢äÛ®FµøËêÑEE¶],.Jå—•‹‹‚i»–[T²t¨ì -W»¤ù´kV•Þš¥…뀆1…5œZs­ûƒ®pÄGÉøÀºŠWË`êt µÂQJ>°®"Ö2 ÝŸ-fdŒ’ ¬«ˆµ f6÷‡8‹¥äë*b-ƒ‘ÊýËbÂÄ(¹ÀºŠXË`âq²QJ>°®"Ö2HÜŸP,æ3Œ’ ¬«ˆµ æ÷‹ñ £äë*b-ƒvþ~¿˜nPJ>°®"Ö2è¶ï·ß‹á£äë*b-ƒfø~w¼˜ PJ>°®"þ›×EënßÐâ<šeyÉb~4Ÿj1L*§ê[sºžÄØWçáÔ CÓE_u${¤Ê˨RÕû¶µXÌ»X”djím,ƒ`OP"ƒøôê:‡j¬^‹¾¾TMÏ(JpŸ4§ç_‹Kßݾký#ݧïñ…îæÃ\¦•;<\w¿ÖûQŒÈß FHÑ6§f\y’K²(ÍÙqû$—¥â·ÝåÞÑ!ñÎü·9‹]3o‡zo^åàæ´’È2>|¦>Þ¹@•ÃEœ?ž«][oÍ`þ?ÿí¿~üQ3‹ò’züðoŽ}—Õ>‹}wþŒÏ’pÑðçØw­9•`Ñî5vÁ€ÔWw©A"8XˆJ‹(UòïOõYŒ×þ\Dw~-*£ó7»j€™ y7ô9‹±ß‹vçÿíŽÇÿøÏdwiœN§oj’Ã0 ,†ýS}ªEÕ¶“!/"dôÄ×A¹vu”3°[1ÅÞŸšó¿›ÿWß~°™Jg÷#†V™Cý¬ ø¡Ù–Aœ»›iC&‘F>æã&mX.ÞZ. ¼¹m)öìÙ$r¯[A ÑJÍV°î_*A_Ì)ômSªŒÒ„»T+.ÕsÛU14¿×¼‡š{<”"‰¢?£1hHÒ˜ÿžA{ÑMÁSH[Žd W•€gHbÓqË” ¾a3OC=qõΜùar2ÌôwÍ!-bV?¯§¸˜†©`@ݵߣ˜Ẍ@3PC(È)‰áÁ|wI|üñÃmd…;QŸ÷ÝÌ®íö¿--O ò ;â –;š!<ÄâUÐà=eK5Zº ¨æq|”¡p< è)«‹}Õî¯-øÇÁ©BÇm/1ææRú]Åä**3vÀ*FÉ{Š™´r¼ÛCà­Zd¼¥¨Öó âÞPMšÈ(Õì¨ÕÿT¿Õ~lÂ8)cIOq”fŸ×ÓÙdTä«a%Mú ”5v'ˆæp?í3¸KxQæûauµš”ïüa#HN9WlZÊûŠÅoìyæî¹Ê t‡z…˜Ô¦¢ #Í(Ü{ñç7¿×}' o`œgÔ}¨÷X§ôØ—æPÛ€©ÕVHAhñË}·ãijŠRS(ÈÈgˆ¾oûºmª]Ó¢Õ­Cú™IErgôì{žÁ $ûüÃ_ÑmŽ}wZ~mRƒ-rN¾L¾E¾*Y®½yõÐ[Õÿ¸6ý"í+(õ (Lô#¶bü;™…Œ2HÐS¿82ÄZ6PºÄY€ Nå_w3P X,èƒ_ÂÂ+‰Œ¡ä¿ûˆ'¬¯ºJ0ÌøY ©…£pßÝD80’¸\å Úx›“þrÆþºç}98F_—î|˜þÄîØ¨Š­ar_9¥­f¥æO¯˜‘(ˆ‡xÏõ‘æÙçþŠöîÙ°…öb½UðÐ¥ÌU‘sß N8®ƒ0WÊz <ùåFØ « v7L‰¤l3§ÉýfZáðe´ã!ê„CÁ ðŒðõÉ6 ˯ãh¸d([†èµù¼î!nNí]ùÈë(Á²’žACçÃôfIA¾AÖlPUë¹ÚÉ+ˆîöŒûRòJÖÔ ìœ3³†·Þ@ür…ñìæ î4Yöò4Ç^ƒ¼S–IĉxwÁ+šk»Å-¥¦uÍè¹/Ü$cÈ…ìs bØY:ëJu%±^Óª,ü BÔø-jhA†§îÚ€©ô]ÕylŸçÆ G7ÿó—Ÿ?þíþ•ÉÒÐó–P €£uP¥o†Š¤ô0òº»šz÷—Tï“¿àøbÄQ;6s»j0žã-K›yAèîxïŽF¶“N²Ø‘ä~žƒ&ÕvF7§êU(Ã'èÓÔÞ.ŸÿT žßP˜aQïk&‚?¹3>3ƒZÂYðIÁ V'wùÎ:ç×fšI¨ñW[©ðY<‡.ìwÌ÷Õf€¯ß ì¼-ßìÑsJvO›k÷*z3 ”þÆ¡€°Ó•´ŽßÈR ü )l1¸Ã~ ä&›?¡ Eö‡n<oPkZìOÓWño÷gÁž¬Ã%²µr߉4ákò‰ :JT.´ùù$²•/8¡Œä%¾Uû·œ`j~ºÜH‚ŸŽ–þ—¿óß–¥eÈ”dð<HèR²) HKÿ=˜¢òÏW;±±þóáxàÿ-RÇÖÉæ;EÁFlØ›àéÞâAöôðwq:ÿDJ8üendstream endobj 80 0 obj 4111 endobj 83 0 obj <> stream xÚµZ[“Û¶~ß_·:3» Þ3nfܺI3‰íÖÙLf:~¡$hŘ…¤¼Þþú~$@¤VrÓN[ s¿|’Ͼ¿ñÙÃMÊYyaÎj|ôxL«$bÕ ÏS/Ì2k„Ù´ÛZô^Ÿ–«ÃÍÞ9QËufPŒyèù<±Öæm»Ìd<©ÂãŒH(UxœÏš“ Ö’j:`îÈFžŠÂ´4UÑ\”š¬Ôz@ªh>óŽl¶af2Vªä’„VËÐÔ| ¥Ê]e󉧢0--U-†"«5HUrWÙܰaf2žT yj&-­ð±TÓ{‡‘$ziª¢¹(14Y%¨õ€TÑ|Ìé‹TI“|Ê•ÀKc¹´Rcõ¥,=0rE/MU4—Y4† ÖREóQªhÂJ‹ÓXµŒøZ¯Bº¸U“‹•iœõ:èÔ„¹à(*ÎR±¸Pœüœ“_Ñq–šË…Rá$Ëœ‰š®³Œí`?—·NäÎi¡9KÍæB9a4ÇhåÆ¨Ãæš³¨³—[€Ûö®ë‹*x¹@/ÚÓu%zQ¤.×ÏE÷¸®‚.jÈåò¶(î׸EŠ_®>‹ÚKœ !URÕFå¹±¶ZÂ9Àá®R™5š1wšÿóhÀÅA&r«tcî´æç{õ©˜œtÈ­޹Ó9Ÿo¥ aqR!·J8æNc{¾Ó-ú¼ÉI‡Ü*á/lD‹6Lœ|/ #vÿ,}¿W¹¿ùú»xº¿ ˜ÿ)¢Œj% Ø}}óâþPö¬Cφƒ`_Ýÿ†cñtìÅßçã#EéÅÐM_—Û[Ø´§f×/…Î1P/Vt‚z±cCKïû »/J•|;1ˆ®.Áã™ikÃYbn}duÑX{²{"sÏ;veÛ1­F»ùMl¡ýåö@|êëï–y¡i¿42M7|–6MÀ^nñïð¦l¾?Ÿ¿éË üû-‘¼ó=?ˆGºgÝÆš¶vFäläyš››¶«m{ëÍØÅÖf8»Ù‰¶*›ÿÃûC11ÓtQˆè ,‘d¤ˆLJ²¨ª'V•0`?)sNÊ‘šâB7ÄîB·ç­Ç¢„OÊfg;>I¼Ño|ddékƒØ¿}÷þ2D»éE÷Édˆ-Â3 ¡ôô£@'ÛBÇ PûÅRèm³+›Ä<›têÄï'Ñ#è>¼xk=FʹIç•õ>‰¼4°ÞÿõÇþÃWlßµ5¨ÞM2FQ¼–UI®Cw+J˦ èGÖŽOöû‚YïE×;!"dòÌÚtÿ-)EÕ·ìç¿¿ûå§×l#Ý÷¤«šgº Ô‘'6‚mÛúX 妲áÀìÚèÜ:úDµ‹µ{AÒ‡',CÙÊ“ˆž¯rO㹚õۮܠnD儵p™š›¥‡Ì$~}±GÈàãJ»–…›ˆÁ&Ñ*ëDG°®Oß²ƒ@‚Y^Ž|„}™‡Š *>t‰Ò1(]Tt"MÁ†z´Ê9Ö1Úœê ߯Ăï8µ=+©±‹kN}½+;Ôñ¶£²Ô· ²­N»;]Íò…:J¥E0Ð‰é„ ì—s‹ôSr•‰êÎÊÐÃ×D R3q ‡Ùɘ!Rs·ô’ìáC«,ëSÍ´ÑUMÖyúsËq[â‡W‚êjž‹âúXVÕ˜™«©ç:Ô>Z:ú‘Ûï…8ªú)Ö-V®YGì÷ÐÔ&Yt;Èß«”¾F[ÙizRŸç$H²ÕŠg“~@Ž7qý04·Zî,>KwŽ>™BTµ±CùÑjÍ‹…®C˜më,hÌÍdk„7ºûhÔQFÓDjÒ}¼\Õ¦#>S˜DîGŹçç|UñX'ÆK…À\›ËqÊØ(MO éŒxØ< 2²GŒ3U|Òs æd·ÆÑ\¼¸…Gc|{X±Ý¶B=ü<´ ì—äX3U®§©ÆbéP‰C²çÞÛ¢„qì06~*G9)ödRÿùh·L „$7‰ã ‹ÎT¢@ÿš‹Ú$+²³x*æ:'¦š´€Dˆc£Q9ÉïÒ$iÝ‚;ú÷þT!{E3çO6VÆÙÐ 1|{Ϲ€†›¾­í¢”Ñ¡X$¥k hÕÞç(…œM;œíYQ®-~Û!B‹f'ƒºQöˆ‚`cVFô™ÜV¨gRTÎ/«Aeñ³æ!”Ò ðÜÛvcüÌïZ!užú$¦ŠNT®Ñ5HÔUŽé¶Q¼)­’¥:-—×íÓeã¶@¯î¯vô‡t£3^þÏQMŽÌVÇÌ ‰Ü%d%ƒd¼’¯a'×±QˆnÂiœž;OÁ¢WÀìV¹Çs†<Úw£¹¼56´®áéât=“áGe£Noô·±uú.ppOÍàëþ‰t0–ëÃ-$5H–Ǫ¤!Ý._nRtŸªˆõþšïúD›‡^–æ&‘=]¨JgÚÉQf¡¹õÁ~Ÿxyh½Ç°© SQSÑ?Ûâ1 815¶H9·[Â&žÆ n%™u”À8@¶¯~ì«Jäç«~}›56ýŸb[^N*/β¨Š'ÄÊð(D3%U§Ó«/GQÖ«ïë¯áþ¸€ÐcªxüÖÚ`4™Š£:¢TîzïB/7,Õ• fËOEÅ^N‡e/ÿÛ½Þï% Ëc¶¥_•±D~V3ã7Ë%6ZëpüéÙô‰~Øqæ1ºMÊâÈ£/Ü!e¶É)ÅÄ<ýHŸ¹ý뙕ó[> stream xÚ­[ëܶÿ~±_jwŠH½Q×€;©ØNësÓÝ.ïV‰VÚHÚ{ôñ¿w†)ŽÄ]­› Áe% çÅ™ßÌPŠÏ¾¿ðÙÝE"2/ÍØ~{"b<ô=²òBd‰¤)½©^`QÀ)úr{q;]´S7R›m$Ï1½!’x”c(4cÃÖ¦?DÚ¼ lEÉ ÔjX`S½LÍa¸´M1R´†­V”Ü@SŒœ‘"}˜Ú‚µ)QŒ,Œ)pEíJ«~¥à㮘KbŠ–bÔÐl¢ö eŠ–cSp{Wˆ$4% ‘…1.IøJ«~¥¬]Ñ—Ä-Ũ¡ÙEíÊ-ǦȮؒÀ” öí\ bNÇÜ@­†6…o犹´M1R´†­V”Ü@SŒœ‘§¹B$)!ì\ÁK>äj5,°)„+æÒ6ÅHÑj¶ZQrM1rF As…HBS’Äμ$áCn(­ú”ÂÊsILÑRŒš­QÔ¾¡LÑrl ’+D˜’ÄÙ+ÜK"uIRÃyƒ‹7¬\1—¶)FÊŒ-*¢äšbähS cm ‘„¦Dö¦ôW³1ÖŸr0yr©× L« \µ@ó™\) •c‚#0¾“K-fÆ'@6¢¤a4¹Ôb0u‚*#diF“K#fà&)>â‡f4¹4bÐf’oc2¾“K-f!õ'Á?fV9ͬ‰’&­(ýµ£ýXîŒLvF_ÓÍšƒå¾eÖµ×¹Ìj÷r[1kªÎk,f¥u¹êÏzžóêþ¬ò-åYKr^Yž¦åš9ëÎ«š³º±\Òfý¼¢6ƒõåŠ3«·(É¡˜ ¥1“nÿtûoJU&«vn¾‘˜ôâ§›óÙhbK2Éäd‰I«|ºwžMD’N&'ãHL:ÙÓ­í¬±'’t29GbÒhžîL´xà„|e¾Þ²e-JÉmQÝ©5m¾“ìCÝ쮑JË£ÄËRnË@½öuÓ½Û°ö°Þ*ÕP­o¾‹Y궃’ÐöM#;ȃd/Öõ¡ê^âÂ+ß ÓWÃ/?èê~"ͫۢ‹@íÝ¡ìŠ=XBüÅÖyÅn¤Ãb⃶+ºõVnæ”Á„’uõ‘V<ÎŒâ1*>SBjP÷æI)Ûȵ,l÷!À„OHïéóÌó3a?‡x)ª®f9z-ÛööP*Æ{Œ&ÉîʼnúÑQö!ômÄf_±â™C\”r05JR“ 3+97›bm+Zv¨,¿<;´ÜÖÍ9ûR”²ê拱…°¥ÞÓÇà°Ä~Üï—ck}Oð>nÅ[œ™ØÝÕÉò²†dy(º­ÚÍe#òCWŸXû¼)º'V«üòÜcŒnV¢Íõ¼ ÿnŠöjØ"V;°!NMÞvEµîØmSï†XD˜Q©8H†¸b&¯¬Çƒ³¢Ø) 199piφÀmMb= ½Ìæ÷ÀvyE<ás/ c›æiPTnÀ‹m«pµ©wj‡pmäùAêT<&qÛ™ßl Ê®nžXY´]ç,lÀG‡p[‘$ ¬fà\K¡wQ¨!F8!&ŽLœÏ ;©e„f„î–±¼Ú€“€•˜ÅF6àÃVB,‚7Ù‡¯q.‰&d3'Ö7¿€ZŠ 0‚mháïÙGÁ=„öêbù–ÐÀ3Ή„[PÑ«†ø>8ÃÌYca¢Àgc|°£¼…ú©”Ÿ‘ÎC­)ÖyG0)LD·ÅQ˜McèíÉsy,È[Šl±'ˆI·àæÞü,æNóù˜K¥œÆúÍ¢º#σÀ Cò²zÕkÎS7ªøÁ‘®ÝÏ0ƒÛäy ´ÐÁãÝz¥Îoˆ*? /Š˜eüAˆºVtµbž+”î}eS|b2³´ßÌê!ó ÒžôXU3í»~O°²°†i”Ù _Á]QÂLƒ÷…+ùÁ=zÝ©-ŠC<²ˆõ]qðö³ih‡ÏCѼ‘Ú°M﨤ïÄœE&ä@˜\Q,ŸÀ‰i‚RìA#j3~B]æ|w@ˆ]†™Ié]@‰Z÷£Oúv&:ÒÎD¡É‡ÔÃ~ƒñ±*ŸÎ‘:€ð\×07M#KÚzÂÀàƒF–PЉP•’˜<Ï«N5?ºp@Þö5#ÐYã`ÌD2NI}®³ß•Ä“Rν4´Õztd“»”GÜdáZÊMŸÝãKÞ@,À²-ÛK|RÙ‰röŽöÀ&üxBùÉXTÊ`z :³@ÏÚtuó뤧 ˜ ›èRí’ ‹âYŽõ¥Œì_h_n` 3“‘¶×òõºn68δhYl¯Á îrhÞwTˆhíèܹêd¥ºØUSTl¨;ðuÂbåjœ‚ÁBíÔ¾ifëG,<PmÆ-[m!ëëCwS?®€ß>¿)Jaéžã1$açõèâîôÅdê“èÛüÐ’ž œl!ž‹ެ5Ì?4m°.Ä&ÆÆkƒsÀ~hç±{­'‡' ‡ºÛË! ò[p·î1Ì’ÈeMùz•Ê'ÚYs/N›æúŸ?÷ÃçOýùÛïüáíõÛ7e"Œ°½ŸÓ…ä9¶–Ã0ÆÂ®-%Óhg]ÉvØ €‰žB“á„îX‹$©æán¯UÍœ¤Êë'¶¡³NÈA–ØìW/OD„Ê-˜V¬%Ç#"„Q;M¸ML#b,ÎıÑKÅŽBËæ€G(ç÷˜ôh€€rö†Ö‡;'¤ ‚Ac‰„t·Ë¯6Rµ´ÊϨ*ö*<¼‚ ¿êÎ9—iðhÉœ*9KF¤Z¸‚MJÔ¾n :YèÅ`ƒµ†ÎÀ3ŒÉs@šõ¯UM v¡a°¨ ²ÞÉ]$ µÞBŒ[^Ð|×´ìzˆ_â_qÙû#Ñ«ÑG¼¿g8>{ÙWTÆÝ%&€TðfìXË{55)“bAh”IÊ"sLwîiÚ¸å•2©Ðï wøÀD>]×e mpÀ“Y5)ë’ß9çGZßHX+UáW{¸¹r€‡³ïÅjФŖ¬:³Ñ˜v”QhØì®—€öߊÄ'ÊG†‡äÂ&&uC•*èËÙ¶n»?µS,Ãsßìåˆe§Fd&Nßýˆ/‡Ù¶jr¶Òyx3ÁMöïäÇåùp¾UÕ¬ø>>¼>€…ï,Å" Ƕ\ºŠ¥œžËrHkÙ#:¤/•MûRªƒÏ9:àÄ”Agh-¥çùIðË‘ „F)‰…M}"(CHí„ëmZÝ ½ØÌb#Eçl|Éö9Ô èO×oÞ}˜5ÌPdÑO4* .Æä9T ì·\ÕöoPµ×å?½ÿÕ‡ ñÂ~ aö×õ} üüøùZ½Ì…™O™÷Mo¿Ø.—‘ûb?œX9ýŽ=Vo8d=(L蜬8(¾ 'ÄC ìH¹zÉgQy8Á~®ŠÇ+œ¿<÷ô; !ôAF˜¸°‹Ã07´0'£=ñ¢ˆÛÔ'Œ€ªï'Ml¢}Îï¾"à€ËÁ)ÿãÞb{~Ô[‹œQoëºõ–Ëv¿3ì9~MÁGØ{Üý*ŽÃðbœ¿ú1ÌõÖŠÓ¡Ÿú„øHèg™°©`_Vïû°jWê¼y2‹áiáû¸ï;(Pžž|ôõÍ&u”7ûññêÆÃÈ L\!Ê_²×Å{ MŒôC"°¶ø—9µ8·Î÷½„;» ktV‹·©O—±8 Ä:±çêóé‰u»…øšœ4a_k³»/ Û°qšEoªÏ݉èoµõl1i8ÃÐ ÃÐ&ýmHû÷·Öó¼,6榨Öå Ú¹J®.Ù ß_ÓS³0Œm³S3‘‘çÈ(¯6K˜0ºç¶D/¾Pÿyxù’¼P<~¤Y¬òõdâ}2ŸÐЉÊg‘çr5ó.Œ6ÅOÓÏbBòPíIhuÏ ¬xØL¿1ˆ/N££Ê‡1l }^ÿJÀá”@nþÌú¨j¨Ÿ:ÏŒ`?‡äì·- ~‚Ò¡&<ü{0ßä]®^_ÓBx<³ùM¾‘éÏŠÆÇyQ^ w¾IÆö` ½qt 5Ê¢?Ï™CÃHÊòrúŽ€ûÜ" ¯’ÄÂ~œ?©ª”e©Î#~~C·¬á¡µäÍ·ÈK„ý˜~ CUæ“Õˆ¹Êqo¯ ™Ï®ƒ"¶Æ¯äY¬~럩õ-âüÉuÐJ?ü2$¾¾¶ö'‚¢ŠoÑð£(Ô)›©ck“d\ÿÿð[Ð>7øäóI¸¡ÿGóõRŸGNcAÄ8ô'@™,Gƒ·ò”³Ï­l` þþPôݘõ·‹ß.pÁþ¦¡V¼€êÍnøJ½žÞ¾7[`1Û^üÄ*ó?L__“endstream endobj 88 0 obj 3780 endobj 91 0 obj <> stream xÚ•ÙŽÜ6ò}¾‚˜—u,’:¯ÄGvu‚ÇÈ‹@ÓÍñhÓ-µ[ê™Ìÿ¾U”HUQê#à Åb¬“du,~¼ŠÅ׫\‰´Ô‘.ÅþŽTj‡Y"6WªÌ#]üC¦ ·€‘Ë(O§áÃÕ}¸hk?mªt«ŒPy6ÑÁé!“%ÂH DÉÒœŠ‚C& û€ÆbÅc˜‰â©8Qh!áëý•1ü'…*ËaÛRÀ(ÅíöêEW}5¨V«v¿®›¯¢oEÿ`Dgzñº3ßÝþË/Nd•[üukšþSýoó&‚ÁæIÄéüʦ %ŠN×ýƒ¸ÞU]wƒpq”ä%J1c<Éý ŠPÇ gó|>bÉæÍµh÷âºZõSRDq™Ç”ª¨L²B¼úŽÛýâKËá“ÓÀ‹C÷€ÛkšêncÖ/í&ÿôó/E×ïMµu‡ nâ(Õ %‡¿bU¢J'¼³ÝЩãa™¢Y‹'ÜYS­ĪÝî6¦‡o[Ó¡ÚEÕ¬Å#WP3ЏÚ×ÈñMZ^#¬Š²¸ôö6c Lt\‰ÒýöŽï­Œ’”}Ïçó(ÍØüm¸÷yÂ×;a:±­žÅÞt‡Mc–D¥Òt·Æ\GeÆæ­9†¦‘‚•±¢pl÷R ì¥lÞ\;­¥Ój.ÏhUÊÓZ;šìç··ß}yñáŸ?ýíËw^³5ºtÈ½ŽŠ¬¤è9÷qA…‘7›çÁ5(å˜Æ³Ò;q¿¯šn[÷hcO¦A&÷–™¦몯DÅöÌ!†hE0pkLÒ¨l¾ª7h6JÄ"»ÌVÑ€¼8+¼—Þ>Ôh#¿‡©3EÁÀ¬[n[àüzõPõýóµ¸c|¥2ÊRºèЋݾå6•ER2Ìõ­ð:7J—B\–{ßÛ·Œ®FûÊÄ¡ë_Š £¬u¥¹¦POfÏÝ‚sÆ n6Uošƒ*ÀYƒBÿÚ@8¨7uÿ,î!|ŽÁkÔż¥Ê¼OtuÛDïÌ=grgÉÀ*pdñú¢Àú±]›7â¯âºis9—S>êdÑr!Ü@°³ñ­rÞKÑn œÑD'Ð'Q7;P¸µgô³ O’°[%_À敊’BÑùê¹O{ôšÆe_´ÀQ Yèã®azD2*bϹ×Y¤tJᾆæ/ 6_í׈!¢½;ÓØŠ`ovU½÷:FõuA„ÅØ’”9E„îæ­áÕ‡L‘¦Ñ.Oèì@‹c¨Iå°âXí’a4¬ºK€"cóUXȘÍóÄq¯äóí¾ ívTB%@O¢Úí6õªêac« [%‚°'ÖG™°a#eófï4ÐÞ6¡ãbÑǤôœoÖÆ{'ò ût¨{<Ñq Ϙ\Õ‹U…æ·9îÂ)üßóáB\;T]}Cbµ-) ÌÕàzŠ(E‡aR!<'…GëØdP *éÞ”ð(ŠÒ…‡š2Ê> Wã 1ÒtÆ!ÅSqlx´ŽQöEñt&²‡%ìD3Ö“Vp˜1FéËÕ°€CÈI+~ÈDqT<­g”~°¢8:BR­0J ^Á!3ö¹pâ$~HEñT­c”}@Q< ¡©V%êâ+ÿ¸ù°–«a…Ȩ¯ø!ÅQñl8´žQúÁŠâèL÷F DITI}‡Ì|Øäj\@! ê+~HEñT­c”}@Q< ¢à¾Â(¡(…¤¾‚Cf>ìƒåª°ðøŠ2QÏFZöÁŠâèPæ+Œfå’Ép£­‚ì±ø ‹ˆ¯ø!»»V$¥0´þâWIÅÓñ׺Jr_a”†´H”²œæ|ötWí³Q€q!ÑIgÊhK0 rƱô$€)»8<ÁÐS9“‹‚h<…z7:2gC§¸ëCOæL”âÔ=Þ`èÈœ ™AИ"’C =™3ñ+ðà)_G̪¨Ë*‰Y.=ŸægEÎe‰~–êÎgáY rYže¢óIrV"\–&g‰â|›epú†èŒËY%I¶ã˜eãcç¢pа¦°„3UÁåô¡%<®Q2Þañ¦*8Aœ>RÌT”’wØEÄ© üÓÿì¼Ã(9‡]Dœª þ>]ÏŽ#”’wØEÄ© ÊãÓõòì´À(9‡]Dœª z=]ÎΊyJÉ;ì"âTÅåéjsVk3JEàG ÏŸ,g¥ððŸ 7³?ÜÎoO¥ŒTa¯X>™¾³7_ëzoV}»Æ×²½™_³% Pæt-¿-V)ðM§Ízá):^L6xÃÓô¦éñý¢†—] •¨¥›ßþ?¸{&wvá=£K@Aàß3âÓŠJð|4ÔižP ~if™(6¼uØ”Á‚· ÑC%LHûTˆO;Àз(ií®Äðj$GÞ(’"¿`@¹øšM€/SîÒ¯Q£#·°aÄ&¦[SñzWõoÆW„D&§_Zð±"n?í̪>ÏœéüF}yÿVìÆ;‰‹(3ŠøY´»á_%†‡ˆ×ïŸeâ"²¥g°$-:D²k»þf·oW¦ëðýª½_p¬8³Ed)÷,ؾ¬TtþB× ŸÆì#6#tû°äéd–Bg·Ž1ôúަxh$³Õô6U׋jÏãÄ nZþõ€­E¾éBó[}¼Jðer@í,Ôv(ð'kH$ :7yTòyþ(£AM06h -8sµ§:DÈÕžöÉŸã»Dë£ÆQ¡³Å ‘€yo«Cž[7®C÷®Ý÷œð2£<·‚¶«ö}]m6Ø+0ör¥r™ðÁ‘ƒ0êãCf ‚§Zð©’ÍܩðG_p—6à(¦ _ƲXÇ+ $U× xÑ1¬ï¼ï¶OÔ’èÌÓ7Ùý®z4ßãnwC#‹N²e'Ó±Žtœ@ÂJÜZ %ë°“"tNl#ÅyàÇü¢Ì(Üc 2×£*'cx¹ Ò%uBô:£N±¨N2i°µ&·6¶­-šç‹R.å eîµë—YÁ^žF`8¯ ŽLÑyàõúî¹77Ãsûµúp+‡o²¡?Çû>°g$þzÍûð ç®*S^3ô6‚€•†ý|pìÒš.YÌB‰,£¤H(œËB÷NxD6dØeyq—ÓØ¡ú׿¼8t›»¶À€¶|â›÷ Cu§EeO‚³ªÍ¶Ê¦ µ=çy³?j± \Ö“ö,„"ÿòþíÏ?¾ÿéÝûw¶|tè[hFƒN4¦±Á þŽm¸ØúÚ®ÍÐ6 ȶ)ŽwN zɈdV:ܾ¼™O Æ‘3è ÄŽ!²yƒ×S…9hÎý¶ÝônÓBPg»G‰ä›öéÙTÏ®ñwÓ»L‡#ïÑíM}sTÐÀÍÖI®)6pûRŽ6}ÖÛ­TÖ£ÙÚSew¸ëÌ·Ã¨æ›Ø6Ö5²Ä7_á6ŒòWK÷Ø“ÍÌd ßë/Ø<ÔÅA”‹ñŒÁÈ­ñuSo!SvXOWϘŽà:üþö…’¿%Téb7»„*À7Z¤`£û±Mv¶“!«V ɉ'ÃR‰¦P‹É&—Áß8L6Gã²TÞÀðTÔòh¥‡Ç êÄÀ±2p¡ì¸'¡f°E–¬x /­TÊæÁ‰ÍØÆÞNlZp£ªsÏb…+ãÉ·[H•ÍêF@Ž1‹ ßà°ëƒýÝE‹?ꀰß? –Þe†8´`ȉ²¿%+—{ñ‡@CdöX*Ù †ÀOK)É0¡›º¶E‹l‚MÅjk1iÿvôw~³!²±¢9ü…÷þìº_Á`#g„??vd> stream xÚ•ZYoä6~÷¯ ò²3 [–(QG0 É’q²‰ƒ}XfÛÊ´$GRûXì߯¨£Y”Úv2ÁLK,V«ê«ƒÝ¾øtâ‹›“DŠH¦^š‰ Ÿ=©ð˜yA$v'2K¼0Mù‹8L§ üELIà%êðx{²u7UæEj³U2ô|ó2‰rè…’ññB0I¢£¤>;J8G±_ÛÂ2rðWŽ2I™2±b¿0G™ä(üÃQR[ðxkLG¡ÇÐV”½ ­Æ 6Åh¾‰Ãøhe–2©1³e/è(³œ…©-xÊ,eRcf;)Ê^ÐQf96E`{…IÂQ>6^1‘N «/Øa“ÉžÃQæGû(³”Û ìe–3%±ã#µOX9{'ð¨šáí<¾ƒNB|bä<Îb^„‡x›9³˜¢ÓñÏÁù;×ùŽ˜×e½î_NI‹„üº¤´€åËc‘/_—3¨yЋtö:H/‚úe¼-² IrJMµ,5ó ;ƒ?ŸÒIšü´ÊXI'Á>ŸqõÆ–4ûi•±’Nþ{>!.Ê-iöÓ*㿘¯Ùš$Á´âò-Ëe1?|wyrþ1^nOáãO d–  À/—ÕÉ›ËÛ²î;‘‹·—`“7½¹ò}9¼šø¼i›kz3ñ cß $ã·ïz±e4Iìeœ&/ú¦] aâÞæù©çûœÏn¯EÞ‹Vºd´*òÒ˜Ñr^xŸl]·èoÁl£{ÝVgD["ËÁ˜ ûEÉ´¯¬u'nvb™xIĨÄ”]¯ë~÷AzEé ó¤dÛ¸Ò2òü„­ëV|a$aêe'ÑwðoŸ÷Zl›R«¦×´Ç§ƒŒEê…vŒ$‘m–ö.‡O·ÆgâÝ=Ùü›Ñ8!BÐ09g¡šuºÞÌ6Î[-ꦞmE¸B/¤½ùT@<7V(½ˆKàÆ O¦l]“áۼïËúFlò>÷Æ£DQd;:ôOÛ ðf%ßu(hÝÝ5õÇiŒ3«ü±¬ö•¨÷Õ5œÒlE_Vº3vžÌ´0NL¼‰Åü‘cÉ0ˆ¼DJ›¸nÚŠ#e&ÆaÓ/Ã,T¨”dD÷ÓÙ:NôPîv¯ÈÞmÏʺìË|ˆ²~ÁQ©¼,b†ù–­“f1[ÿþGr$œÐí‹ÛÁÚ~®Y;Îi£eíT"êd`Óq³ZQÂÖµ‚Z\k@K‹¡>²:cGªîïñÜÝé¢\ZÖw,«7â ÞÐÐmÇ“² ·X>\½==’’¤O΢]d¤,³—§H18Ù¶_!á´OS6]=\2C°jöm¡ h»¦@ mLÖZõX$• k¿“`Ï€­ÏCê Ï„ROØ»€zÏWl×·C`Áªöñœ!Þñ€ ‹’˜ÜIÉá,E¾ïtw¼(Î{awÓ­Öq& àZ¿£eýrøÁzÈÊ/Ì­—¸šÍÅfa:5ãx,ÀÇœDf„—°×Fó²$g—ïw=ïÂTyQʉ¨{@ ÆG±è/âUE‘Wi›~ØÓÜõeSÓvŽú0‰à:ioáz$È)[×õQô¡K ££¼¢²R¶¾h”ïQjQP?°Ý£CSÐÔ#6•oò&>ùè ÐI.¬@½g<┺1Õôÿü•˜:¤ÈÃads>š#A"%67A£uÎìu]‹‡[ü“ºÅ#K•Mù$nšWáÅÍ<ÊGs„GµR(PYÌd+†þܸ¯·b–çær1¦#?y¾ùСŏu(ùu㢠ìm:§â%€ [×Wo]ˆ*Ôd /ÑDSjéb›Ê@ôZßæn⡶J%òÿèP  ÿSãˆ*8uèQ²Y…G¯,—àL¥æHŘÌÛgÚ°xÛÄ”œM9¼æñ.3c„û­ÛCÄ\ìjªpªåhMÆX3Šôdú©¬NøÍ·=ÕDS ›=Ü’w h †Dÿè }Ê'[D6G ÇÓ¼JææAáK3¤Yëó`x¥Ðæ+Fs*ZW£0ÂØ0*YÜ"‘/C”bÊäÂòz{çݾ…I>ýêN‘Žr——Œ ñ½Œ[Àœ$Õº“T - áo¯ìó†¢+ÿ«ÍÔq| K!.âxGAj:q‹x¥‹á“;Pm­{ïŽ( Ì’æË\[¥Áó©>B•™¸è?÷e«W¬€|g6©ëÙ0޼ ±)öÎ]ÿðµæaaØ@h~ bi“;ó-ºÞ€­Óµq[å^Ÿº^W˜3Ž÷f<~¦ï´Ö z7P º:f^fTM"D{6;Ô½DŒ@übÔå‡!£ÈÛ¼¢ïÄ÷MÝ•S¢ðipfæ©ÛЃî¢b˜ê.¿{ý¾ìŠ}7$‚ñ3ÕA35ÌÓp0nÛŽ’ÇÅÏ¿~¦6`T¯Ó;*nM 0\½ÑÞgJúLÐ g6@æCZ³óQ4ÑÇœb;´c¨P1»»¥ó¢5›È(ÁA î 3†^˜+ˆ¦š’^G·9ݞơ–&ЮhËkì†9Æœì½v¿¾ÂˆÅ„8wá ñÌ ôŽZŠ¿uâÓ†& Ÿ£©0Ü«Ê"$é JòºÞ¾œøl\ÒwM H²—6øð˜Ww;”‡ŽÝ:§Ì¡½aáâ§^¬8;$VB8Ý 0ãg‘É•6ͨ]ÑTÌz¶+k¢ßÀ¥;º Ü,n³%` cò@íåQa†„‹_‚«>úp±h"ÍgÌö"ßÝèšÐÓ˜NüZ›;{ªK9Âj˜5¤JßÊÌŸYЗJb˜Ë£™™ÑfQÀÈ!§¢ïÊzK‰Í\*"Mb'O©í)ëb·G¤mšÅíLÂx=Ô»&ßÌ—5:äÝnàGíÞÀð¡› wKD*Æêvež§ƒ&éLÒß}}~^t^Ùo¼ºÝy5)b¶ážõHAyˆ$›À«ÊÝ9kÍQ޼L1"´æçœä†'a“}ð@ª«x^ 8P"¶ø.B#F«óê+^³YKí’½yˆà«7¦Ó7Q7Ì‘Wo¿ 5öõROjÑFNtF¡ï5¦€ÿÉ´Áº£œ™¼n:Àú‹Øt½ÀìGΚtKÌ_…ø·ô!E*ùŸv¡ËN ï„ç}^›ÛbâýÛåûŸ¿ÿošRÖ›ÒäKT¨E¾Ù´x‹:OΕïCßúæ?˜ç¦¢3’fÈ\R}¡y èÌ÷@@Œ1¼øÒl·Â_D%I [•5é E¸Xo Az鯂½ø• ÔS7ÿ<|3:Ú[Ç\f‡Âr¦ö‘½R¶Íù )òÐ8Øës(­GPÇ/;`6&RÏàæÉ¯ÂDݽN@ ?57Þ¦-Ž›5:„o¸0«µø±„el\=w¢gCJÒ‰äRj)$Àw[ȸ@“òÍquýCØD u­E£îìùgtµòÏqUÍU˦lÅy_ݳ—3_œÁçJ‰¢~~GŸ§)û1’ûBöN¿÷3ŸèwBG~Dß$B!Ë!; ¥lL®ãOñYò_c­¼œß6áÅôÛÉùó¬ÝbÔ‹é ý”ÉË£ž¤z¥ŒΡWõÏ“?OhC…¿ÓhR/SF½Å ߨ7ÐÛï,f·'ÿ5äüî³endstream endobj 96 0 obj 3419 endobj 101 0 obj <> stream xÚ•VMoÛ8½ûW |ÙH’")ê˜"›¢À6ífì%E¢m²¤ådûï;”-G#;û %½gÞ‡ôuÁ!Íñçþ¯ÓÅõ3i!]-püKˆµf‚Çn7ìCúýøÑZ¦mB°ì²U¿„GŸM‘"ŽX]€UÌ ppÅ™ŠMˆ÷ú.ÁçÁEœY©|ºqpÿðÜ}ø¾Ùu¹ƒ¼)¥ï»òyºŸ–qAÌw}ÙÔàwmÛt½ ·‚EÜR|Ye½†·]>¸ªÌž+S«È(FmnÚ¶*ólØén U"aJ+n:âMÉ„Iý¥i¬Þ,ȺÆÈêõž.öúNÍ’¨â„Å’f²#nmÄ”¡¬ñÞÛ¼$*QŒÏ¼=}ÌmUö?Æ‚* :-#–c„÷›¬‡<«áÙÁλ2l\Õº²I_Ë~ç%UÌ„ÄoÝtÛóAKc™Œ)úú!{¸ùãí7(²>[wÙö°£>ø¸xâ\P· !Õ,2š8 I°ø‰"R®X¤( $º‘vç—[ç}¶uÃ¥™§™›£=JÂeÛåá ×D3e©A×ùl ­æ†  …„N˜Tð.…„I˜y#u?p#oêÓRðY)Ö»„µ¬°¸:¬öå "¿„¦ ³ªúß›²rF矿Á—]Õã~~ˆ©lÔ,•‰>F·îš]{‰–4»¾ÝõX—Ü•$ ɩ٠í‚%š0ò!ÔìGÕd…BKì—á(%ö©?ÒÛ¯¤D1gÆO³òFƒæ)$Ý”þJLÑ®«/Ç$·e‹Q”uPÃf$Æ:φ•GGÐç{hVCc|‡0Ò²$މÙûò¹l)šb…ò—«=­¡ï²z[zŸçg$3Zo7EQŽD Ú•LŠEÒÔÿp4%“!ûÿéh¡eG1EŸ’GiTÂ,´?Á∰?ø²p—ïÅ™HÇš˜Ð¶Ÿ¦¼«YÍcÆgÞ…„Ñ"„ = ï8;¦Ô‰ßnŠÿ­ê,Ï]ÛÅ÷°êš-ì ÔØ¹+WçYëwUÖ»P5¦ýÜ\ñÛ²ï>Á·./W®´•¦1ë·>\8ß—õžˆYQtʰwh0ì|譹=]¤oñ’$àš¡Ì¦8ìO~¸_Þ•Cß "£}Ö&LXb„%Ã[4£³a<"(2‹IÉqX#ßÝþHd3©#fi„ ýnç'xAB‚£ƒ•d‚‚þζ-Þhx6¼ý÷—ü( _Ó£!‡+TšÖo!ŸÃz\Z¨ZFx©›3$Ï>îíÂj³Xí§á“)cPd.‡H…< jSœ†ãñaçT“}ϼÐô…QûØŽëct'AqaK“[Ö¿ <8Î KÀ8±»îŸvX£Ã±~_üµ[üµj /ÑCx'/øÞ?}wb0q¶Yü 5îóÎñù[endstream endobj 102 0 obj 1128 endobj 4 0 obj <> endobj 9 0 obj <> stream xÚÝ x[Õ•¨åûÞ;÷¶ ÓÞ;Ó¡´Ó¦Nl·‰ÓÈÏX–€Ä¹` ‘ 3þ‡6Ö±c%XGÇVÚp"9H–-4!‚Iü h:Ρ ¤¡PZ ¥ôB胦¬»öóìsô° HGt3_‰lm¯¯µ×Z{í}ö‰ÇsÝ>øéC}=Š¢ôôlìÝ´åží?rìø#Äÿ’Ûԙㄙ4ŸÌ›âóÝóö¹¿H蟻§¯W…FÍúqºxç/ þÝ-þ€ß¯bûƒ¡P( -Ô´€_Ùxè/þýÍJO¯·€¿`Cð¬uä`÷u¿øÙgŸ:¤(½‚í‡úCÚ¦Wy(€›_ÙôÎgûƒÍ€M©ƒáþþþÈtä}Úüþ{Þý¬b¿Ý£ôôQìÂFäáiÈjóoÿ,¹sÛÁkS2lÔBúLMÞûÐg ýx·Ïß·%ˆÀ¡p¤_l:îþˆ?¤!Wúþ,¡ŸñAÄB³Øû#ZlnìáþHÚÐÐP”´AÒúûtÈï6}fЧõøüÄIÃ:lD΀y‹jÚàXE©¼ã–‡?Ñ탻¨ºPùqmÓ'¢ÁŒô‡ž¤v}[å?ú¡nÅ¿…`h‘|p(iÖ©œ›À“¤v˦‡ò\Ý}TÝA>·#é©“«\m,Ÿß2•ÏêV˜ºõž†:=ø8|‚¾ñ\þª[ö°ºtó::<œ<…­÷ó\Ð{”yšÊ=,ê«/Ø×§óäàÁÓcOcë$úAdóuÿ8¹{3Ç)ˆ{thú–<Â3œ‘ÌÔÖµ“|·~¶;!Ÿ1Žû™9¶bæb¨?EðÁ~jìŠÏ°õùûrU8âÕ Ø#Z”O |Z{ŸO1 ¼[¸5úÆA{ìêâ™Âæîóm6†û'²_äÕ>öIÀ‡´à$uõÉÆ88_â'Ž ë›“³ˆ. }ªà ô^ŸÏwˆz6Î=¨ÁÑgm4“I¥;1}`ë>2¸)Ÿ0Á1÷ JÑE¥ŸHߨ ¤vë¼*à=F¤l~-7kU>ñZ&ĪþGGG’«E8¤òc¹.%ËÓqkÀ§Ss2p }4a’#๎iw¡µI;¶ ÄK#TœÃ'¹œÛbû;ŠßO+É‘aÎŽy3šÚiÀ±Ï”®j<ÐãóuçÖdÉÂLßd5¦Ö1 Í'g3¹õP8€ÈsÒ¦ …ú£\Ý:p@ÕˆþÉÀGU/en=ĸ֧ âàºâ)]Y‡Ö¯©C)ÞÜ©üERMÆX¸™«à¬ˆš-ð¡MÊww®¸Ïq…‡@ãºr¹€š-ðÁÁ°¦—+•߃“tô‡#¸Ö$–5¨ÙçKlì9Z¥“ žPB×&äYG \˜Tc”îܨ|‡B’|~M´ô‘œ‚CÒ¦Åß¶œ€Ë¸°J =*xôDz J§à9©B½+#×Ɔ>ÀB]EæœUåœT$6Ëäœ=å¤Ê6œ†rÙ— ׿SÂÑÙ=!Y<–ðH“÷Ê9ØL{@F® )<2˜!¸žð5ÔèdJŸ “xö“˜nÃáò")7¥géÏ_›~A®‡ Áy@–嬃{ñ&aˆs§ÖøÄ'l‚#r9ûîí]¯ƒ‡±¡GÓšzÖÁv\ôå¿¿`S0à›²íÓ NÔ-‚£ÊCð4¶>~øñÇ÷\¿ìÚÇö>»+|ìÙë®þ¿»b‰àÿät:‡ý߃=rÖýº—€CÊMÀGG“”E¶{W.w6^~Í3ãzèý+V¬X;´¯?¨?v£ øöûG…Š3·Ù9 Ûÿ=­—õ<Ý:,Ä£ÈÖîÊ éó{n¸òš­:ðñU®&Ò¹ÜnoØ-bïonnvâä˜Üvþ˜ þd‹ËÕÒÔ?½@(·p;&okks·-ß(ËÙMÞŽ+~ ùþH_«.Ï`öÁÇŸlr¹\NFþÇ>ÜÔ‚>Fcâjs»%©]r»Ûœ„õ°ËEZ›$IWª[ ˜{»ÓÑ`—ÚI»EñÏ*ø6NõMÍØ v¨à×\ÑâjáäŒÛÕ‚„oi2hn×3dÎ/…ñh‚>àn§5ÉÝrŒYú'¦ÆŸ?§’#k[þÿ’â»3ˤķ…Â×4µ`5ºÚ;¹D÷ÎÙB ¯dàãÍ.DÞ&©dðÙv4nI€¦Íó3 ~é§›}ÑÃÿ ÚªÚì¤}áFEÉî$÷õP§¾å:±Tžanê³?Ç}!öãv¹n–$löò @î–Ú“´õë(ø£ sø/HÃ"x3uþ³k³ Îk¡/ý•¤î@µc5¿t6—e?ÑB樎ì(¿Üf“’r··w¾EÀ¯µ7¨æ|X¿VkEÿàÙ¬F| ô¥Y(rßì93ÑÕ»ø56.ç:¹›“r·{&&~>q•Ý&þ`ýj·ú~8zþÙí*øC0£š\üÛôèÆ‹Yuꨟƒþ†£ËÙñ:·7p¥!ðýM*·GÀ~†Àv>IƒF©a¶02|D9õ3§› ¼´/«y[ܨ¼»¬ÑѦê‡?jçæ»~¢Yà~å6õ¿ð+j/#`oàê•^ÆàÀíTG‹ƒ?ŠƒWxǽÜ›Eð»¡ú¬?äLª;¨­Ç®ºÂÎ>ý%ÜØÂåó¼:ñŒÍ¦Bp·j\µ—öŸà8à.õ;lF=ÔäjiQÞÞ± weû¸.ìnƒ(ªNPÏaº“p¥ã Æòp߈¸ñ¯y@¥Çìêìh{p¨àĽ&4ÿ྆Wµ’öýüãèbð,æn>ަ¸³Q°AêwÆb D&ωd$^IŸ^;a·»ðq‡úË¿AàÏAÚíÖÌñeN§[ÿWFoÖz{ûJüdš÷ÇYf ‰fË…ìûؘê‹<±‰•ÍML/'&Æíê`½Š89øü ðÆÆF§H\ÉpölêÇÒÖ€ȽÙÛW˜’Rw mvjTAs˜Ønü—±`èÍOHtà/Oì<öOÐÏÅtßíhÔØ•„Á¯o¡†ÎðÆ‚Òõ@ÖÀÏðµÙE ¤—%œHÇžq,¥‚z^ŠÝØÄõÒq=/ºèŸL\'üóU´RC«6/!ðgÅÐAÝúƒMÌÐy.›uðwPþàáЕÎF—&#ùŒ;áŽØsÍêDľ Ù¶SÈÝ Fÿ7ìŸÃZÆ¥NŸNœ²^KUÑ®Ð:e¸…:ÿɪ0©®gïQ•÷ªñ¾F.£G˜~±«—²Iº.ÖÔäâ™x'ߣ_êpÜÌ9>×s³ïµµÐ\Prñyr?W¼weoûÈ«øE\›·Ø˜Öñ¸¼Quên'÷ÿžŽWXu BG a»‚­Ú$ÂÜíu„xö2··ÉþÑ–eÎFâ·¤è?0ðÎÃ#»yf-[ÑÈ3;’¶M „E][wžœºZ‡éxK-ªïU»k¸\Gy\6®+#jêÙ‹ãïxe øA#3cOô^›“#Fã3 ã±Fç ®ð7È>Ê21š½ñ¸>F£ßìxIØM€)ÎþŒ•j$’üKÙÜ,ñ)NÁ³˜²zññ•`Æ4¡ŠÚhåAêˆ]ídj~ýjf¥¨"q”€ ¶Ý.½ªÑ?›ÞãâþQ#Ÿâ·ÚXð0·§I5éžP„ô;”½’Þ­šàƒCCç3e¬F–Níï…Fañ¶î >.¬½ ÀArÒ”Pc<*€Á0R 9bk ÿEº¿u™£Ñ¡FñH€D³ìÝÎ!ð¾/s‹O>ô5VOºýˆäÆBé·“ì>îl»Ŷ›‹«øóÎFºðœ8ŸÙ&—îotˆ¾¦êYÔxÀ•¾«¸boðí¬®êYÍçdÇ.G£Ž7ýop:¹mKGŸõϽ›$€_Ï7 ‡9ž6ºxöÄž³r³W¨ÙH'þ[¸/çN»] ãϯà±ãW±›ºQѱ3ºT¨pm …ƒÙÀ—¢íM" ¾úã|îx¨¾û†f†QV6Š‹Qÿë&η¹´Ëß³œÔ‘ØÈWm¬ðì¹=úPmï çõý½>o67Îx#_nÞŠŸ5úÛדXô‰m—#ãtŠ«þî­‰ç„axcâR›Cg먯࿱;6²s› ÏD· ¾­ƒå핽Y½+Ä×Ó­:ì›ðÁÆáûæ°ÜLÐgìzpdémªï¾^X´¾4ñ¨­Aâê'à0Å—Ñßb##ÌfŸht»]Wf=Ù ãÈ»)ßw,e&ø ò8Êð»¦0æ j>â>]RW©Ë„ŽOìæ‘¡}=þ:pÌ©øÈ½dây>žoWCá6êÛdoVïî}QVì|yp+}îê‚9n1¯z=Ûe··iÀO8UR˜ÇÈe‹Óú|¾«&½€À¿ŽOñN >rNVwáÍñÏ« ÜëÍêc¦çdå œÉCŸÛ>ÛåÑ”BGwëÁWªTéÈÄıª‹GÆýO6^“è Ý—/çõ}ÐøÁŽÎÃôT@ôoiЏ =£Ñ׋ŠËY~É«ô~ž3í¥í¾¢±õ]#c£šÍ"âMBÕ[—k b«jëÒÓø<ßrÕûŽŒ¢ÆÏ¿ öu4F[ÑÕÝ!´qÖ+wÊ.øŠâçÚñ ðmŸskv“FG„=´kŠ6øVÌxÁ©£ llŽš’J—Ë?S’ì"äöÞ0Ú7ëñúÞÏ.øÛÞÿÆ[n¡+ч¨#ì'­FOÌÿ A›Ø¶‹%!Eitr¬v4±¯ÍQ-D²íŠ= ËŽ%=Ç¥·÷á›,»º³ü$9,ÐÀ•Ü·õÑG÷n÷³ûY¢§‚¿ŽÀGç¨;LGV6¡sO’š¡ŒCH仼ø€Óƒ³í©¨†× Ùø±‘ä’³ëš ø]ñ,·n¹W¸)€>`^y‹ ŽfãWÕÓJ.'2tz`WÔžq8ÔÍuRuøÊl¡#µ]%üÆ C©O.£Û¹·ìËúõvÈŠðÈü;´½åvæ–ñ#Å;ÏoS±‹&{$V¨¾H|ççĽ8éF»ºÊy:ùõ ýôvn|i«·+ëO`¡º'*d—bÜD6“:ž'ÏRïà¶ënãÇÙ:Hz²[Àê ‡¿v ¶\Hç'û‚”¶u|Ee?½/wH>4Ä•>íýN1íå!¯Å2šâø3t 5´œÝˆ²goØÖÙ¤CZp®ôéo¶¢¿Äè3œâ‘p¿…qw劒EÑ\ZÈÉ5×&dv¥—8+’ÌøDpüJ• y€º'§ Çwt)üšiõNqý=´`ï3àfô¨ê€´Ã7ØŽè/òC.L·ËˆÂ½¹ãŽOù|J’‹¦£ ×ïÎ|L!·ØŸpý4}¿+‡àñºTc/KH¸nyFw×%Þ_§¹Õk0¤çVä\4ôXú`Ho銷«Ë€—åÇ*gÆé˜î=cŸLázKúÛ7 ùÿß|8á~ùoéèõ¦]]]†¼R` âÆžá«®´ïHÏ=œÂÒ~üê;à6èe1çc5ïtIчØg ð!ñ-1HÝàгøÊ4팗;~³Û´oðKÐûHzß–ÂÒƒ~gܰö޽B›¾qRO>œ\á*ûhz‹–Î\ÚEØHᾸíÇr ò”ÉŒ&±ÍÔÒ‡Aá‘p(ˆ/ÙÆÜ]ƾ1d&&“ŠTj…ó÷= ôZK×\¾;ˆ Éœ(<'•ô´í{IÉ#¼ÉP¬Íúd 3ú*WZxÀwïbnÃß3åCä~övYí‹+U'7<í+Îð+FPÓX:Y‚‡Ù«2ü~bèòûqÃÛ¹®Drñ¥†¾Ú-Nõ’3z ]U¸ìÍ‹·½I Hxsg& ×½ðS|U·FáŠÜ•'/u|ß›ÄÚ§ êéÁE…‡U…cÏÖµ-ž'í &§Ü½_º(œðæè'Røšß§ Gú÷âyÓÞçäÁÀçmî=‰oÞŽÌLá‹鷯_ßÞæØHnÔŠ,ÍæŠ,û}ÿ_;\Òú žDõ…£K῾㎠íR›—š`aâçUû Ûëõúü/ c m$¡ˆ¤xO©þM¥ýªÂ;︓»¾ÀÜwæÝ+[·É€þœ˜ûŽ wÜI2]C¡h& W]›ç ¾¡Ýíü˜¹÷x<ÿÚqŸ÷‹6Ê„½/< Ÿ®LíÑiÎÁ;Xgˆü‹]¾ü|!õßg›D$Q×÷âk©ûC -ÉPá¹Û׫äŽûâyÚw;2s,hûÕþ@h w(DJ³)=¿1ßár·“qÄΑ§ï^¿?M}ƒmB"CiÛ@7|çeJCÛ 4nPÉ]Ëó’ûÈ÷ˆûëø^š@(œ’›À‡ÑåQܨK‡oéQ¥»Ï:y ËÕyÈýk»Sbq»zñQ,=z$¨g¹.«g(jûßv'»@þû¼ãþ}Qöªü~=Òs÷i¹ê×zù¯ùzÞ­Ûñç<ãþ3 d÷÷{Í©èá…ë¸{DnYþ[G wpÐq¾9¸©97–ï‹]^Eƒ®$à ܽÂ7Ð.p×G›fDóËÁÙÔN,òÉnH/»tè}¡Ð̸½]ÝïN5hlÉíº1¯™KÃí¼ Ö-1º¦mêÝÒ—v‚k¸»º¶¡ÊÚŸ´ÞÃíümþ2»‹9t"Ú2²p¹S‹Þ‹OnȾ^ô:¡4Ž­ì”í=D§óa×. ëŸò„›&ã|Ív·—£÷à£Y¬‘7Žõ†Ž¦†Œ¾ÓåÊj+ì.­ƒû(/¸ÿØ wè‚ã=·mjÊÀ-'4ů™~¿#£ö=í“ :·4¸Ïjèã¬~ñòŸàé¼²OÑbûÐ:VlŒºëný"lJtž(wm΋@&È„ú“* ðŒÞçKŠííÞž¬tüg½ƒû/ÃÁE+œÆçbxD3Y¸»·½2;ù­ÞÁýÑ`î+q Tqû4òÁ™·mÞ¸yÛæMwݵ±»»ïx»7Ÿ¦Æ°JëàÜ;¸Uö·&­ÈI®€]‰‘¹ëoõ,‹îvJçÚtp ,«Z8«Ë]ëŒâþHd²žXü^ïà ZœkƒkÊ@ö©Ö:Z´ΘÅyƒ~e’ýÅÄ·0ÔÆ8¸«@Cÿu޳ƒç¿Ö;ôæ¹íâüÖ\sÿ¿2} iÏíüJÈsÈôkàõ†-ÎsÈtU­ƒËŸþèo~ûÛû~xàÍ7L¥d¹öiçg™ÐÞüXVxêÛ ,øö³Ùl1›KJJæ-zó¬6‹ƒžã‰¦[œ‹ÕÇ“‰BÏÌÎ.ž‡¾\ZZº°¢¢ÜBš¹dîñ^™0;›[ó'½ƒ#‹ó— ¡-Xè2UèeÜñ”˜KÌ¥ÖŠ2Ô*JY'0Œû¦ dúµÑzÝâüGóvr¡˜‘Í/.Bº.·VTN*¬ÖJøïò²2èÂlž¿XW 1¢¶Jïà§úGÓ¢Ÿž[b1WÐf­ªªª®©©­®ÄÍj­€,*ù–{ƒÑ›Ö—kÜÍ…Hh«5¹ÐåÈàçíK/æ‹Ì–…VÔ*¬•Õ5uµÕ¨ÕV±N*½¤¨èfú'×U격ä¾B—R¡¹¶&‰ÐÅEE§Sw÷¸4‚m­ê4n¨Õðѳb­—ü«!LÌ lÌÁy`j~³Bº&…Ð'Suv²Ð¼ wQU][[ƒ[é¤Rè¤üFá·Œdúœ9¸u—k…&ÚbBW¡ËK-…O¤ˆÜ…æ…¸‡Êj7 ^ ­Z-îÔJÉ¡“ÿ¾ÞÐ"H<~,Î7løV¡ù›åXè*.tmM*¡ç'›—¿+4—–Àظں%¼ÕáV‹ÌõQj..0"é ¼Àm!BצñS¡ÏKìæ¤ ke µñ%Kêë“õQ[[Y£g.ùoï䀃Cn­Œøa.ôòÿªÐKˆÐV,ôe ~­Øl©@^±õQ[§~[ìƒWWBˆ€”ð|8á£ÿÅ„®Ö Ýšf|E)}@ÛLJ ïRŒ<ã’ÄV§Q9¸9è¤øwÆ‚Ÿ&BWV«B§ÇBƒºŠßÓô1¿º¨¨Dܵɸëõณ‚³†‚#¡¿Y¹µB·¦Ðº¤à#Í·X€ÀkÐ ƒ‡f:j´¡0œ¢¹FrŸ*¶ @VY-ÍDO!4²ö‹…>ÀG npèujõk&×B»´5kÖ@W¤ ëóÜÅú¶B$´„®ÍXèJ,´Î÷¡>®ªeàõõkèwY¤áŸÖád–¥ÅÆù·Å ÝŠLŸ m)âBŸ->ðБ> ƒ5ü[Ú>Ȱ֢t›‹ Sùi¼p¡«™Ðõé…®«eBî£},(!Î2ž:¾Åo%GÍŠú0¦rÐuCè÷pʆs€Zì3ë£ÊZ^qÑ •ŸÒ]—©Ð”ó`ÎBd¸4N×qVLÆ€_B^ÃsÔLÁ¡ Ì¥(ÍìÚÚ€WÁw`ô ž0Ä¥¡+‘Ð3'BŸ‚>ž(6—Yqµ|òàääÚƒb›$}ÔkÁ+,æÂY†¸t"t^Aè´J+dàKHP`N=E8#B)A57½–¨B/™ÐL[³NÅOà §’ÕJ 3ëz¡}hRÀœe«DèªÌ…nÅB×0¡ÇŸ*Á}TVͼ%ýsqAîÁÁ/YʘÐKfŽ*¸T| ¸ Ké û à5UUU• -#ÀÍ\èÖ:&´u!ÖÖ¼âRÜGõ ÀÕ>ÊË-FäësAèòdBOj„^›BèR¤­¹(È´µú>ðBåÜû6G¾­f¦BW¡üñÕ¤z¡ƒöQRø¦AN½º²V/ôdÆBŸ„>,V¶¸#¿2™›ûd~ ¡«p3ǃG Si|ò6Ú¬e„>rÈ?¡ŸÀù‹•ä@uõ­kXk“ôqð6qðªkhûŒ(¾”ÍLèÿP…®@B(0›Ñ¥šfêh¶LNÞªZ xõ’‚œ›úG¨rB×e"ô ¾„ ]Y…>iƒÇÁQ7è·N&ë£^^N¦KÎM}æB àeeeæ’‚S&¼°µÖÔ°Eé’dk”ƒ ù í£Â<¯Àp&tm¦B·ŠB—øï..Æ¥ ¼?Hë”lI»6ðò’yÀ¤zm‚Ðk+¥B—‚ÐS‹ÐQ€ ¼c¦)Cð09™ØG½¶ä‹H=<•ЧúÂøStYжÜêêZ™ÑÐ"é tÛmÉú(6|_!© s¡5•—µ‚ÐS}aül!ÍYqu­lE[âÿ¬©omÕg¬–’¢Eœ‡(œ7½Ð“鄆ܣ€¨+ia¾þ?ÄQ£é+íƒl£ñ™²ÒRC|šd½$©Ð§âñËŠè–„ºô5kÖ ßMÚ:e`±€›0±s8¿È\:¡éŽ)ÚRRb‚åIO²†íº’ÙÒ*Lñ…° 7h'å@z¡Aæ5)¦øBKQÁ…<Â'+Õó/¼ 2’­kÐN³Ð>C…ÎDRUÇ•õ¡—d,´‰æš(àÔÒdHÓÇñ¸Ýu´VT ó?³ ⎟‚0ŒW*)„®e^B¹©ÐüÐ×|pìd§íD މëÈAÉ2”é›a²|hxüjì]Ë….¡g™xuôCÓ\3鄜ÄSn gh*!û)/…>LÿhÜQÓ t©Fh‚>Ð%&á¬Û¢‚y”÷ô`¤î¨Ù{ª%Da^aYÀ¼£Aí2.teFB—1¡ÅZŽi{9\ÇŽ±²£câØUÓ±++5—šž2byj¡µ ¯Ò­©†Ÿ-€¸h&‡¾Ùœ©¥2Áhª­ çièx†ÎDèÊ *ôe‰3f!íÄŠOIJÃϤh_§±ôRH Œ ájû½À\–™ÐeDè„0t98ô|zÀ ©O}WÁÿ 'ÐãèH(˜ŒñÜñø›i…®…¶¤zŽ™=Žb­a]T‹gôñágÄm.*0åÃýb‹g$t e=§ÌBÚ‰•<â y6ÁZ†ºÀcg2çC[< È- \YLhø0:~† ášš¤cWbºøtµVVQiM2v`æOÅó¦ÎXèiöf曊P'¥¥´“…rÖD}®Ö%ç™NÇó¨M]„¶j„¶j„ž5+½Ð‹Lü›‹Qg:ô9E3~Nµ¸¸¸¨`®i~¾Ý {zžNhìÎÀÀ±ÐçMŸsœ¼ØTXŒš¹´¬\䆞¡˜Lˆç];y¡*ô¡ÁÊMïeÐËÙE¦Y¤H…- Ki`EÞˆçeûPºT'ô¬L…>»ØTPT4·Z!þ<ÜEÑ,“é?Œçm}}BŸ=yôpÞ¬óÀLL&øú….Z<Ïïöá›z¡/þXBtê©ËíÛ÷ÄâÅóŸz/ß¡¹ÆNí[´˜} ­Ðÿ6mÕŽendstream endobj 104 0 obj 9586 endobj 105 0 obj <> stream xÚÿü*† 0‘&4‘+5˜+7’-8š,8œ-E™(H*]ž&k€l j—t‰sˆ)}“”~”)Yo>ZpP/EdUj\tsk€.f~CiNhcgn=Ž6rŠ9rŠJq‰Vr‹eo‡r;•2D“;F•=z’;|“9Q—Jz“c–J}–[}–q;Ÿ0@Ÿ6LœC[ TA§6I²=N¹BP¼DQ¼DUºBw·7U¬LT¹IT½Ia¨Y_±Vs°lYÈL`ÑS`ÔTd×VfÙZjß\pæctífzöl†œ‰Ÿ"–­$ ·*Œ¡9™±5—­B´5µ?¡¸3¡¸=„N’ªN—°NŸµM…žfˆ¢o”®_Нp“­k›²]™´j¢¸n«Â1«Ä>¨¿M¨À^©Áo•ÌA¯Í?²Ê<²Ê<³Ë;³Ò>²ÌY´Îe³Înÿr€ôs‚øt®Étƒõu³Îs‚ÿt»Ó;ÄÞDËäHÒìI¿Ù]¸Ðp½ØjÆáWÑëTâúUìÿ[%~,‡0 5Œ"9š.B’,Bž)A¤4H—9L”7O„Jc€@Q˜8MšEV2H¢?S¢M^£+D©1J¯8O¬BWªMaª5P¹>W¼> endobj 107 0 obj <> endobj 108 0 obj <> endobj 109 0 obj <> stream xÚ]“Án›@E÷|ÅtQ)]¸`˜y/–¥ÈUT/ÚF¡ý˜¤Æ ÿ}¹\+•º°9æ¾sùüé¥Ú<…¡‰›âkf^ãe¸N>n?ê1IÇoǾ›Mú2 ¾Š³i»>L÷{LO]Ÿls:?ßÏÖ¾/®n—9ž};$eiÒ×åâežnæaø%IM!N]2Õr^]Çñ=žc?›,ÙïMˆí´¸ü¬ÏѤOáûà7Ë­ÿ.ü¾Ñäëù–~ñ2Ö>NuŠI™e{S>?ï“Ø‡ÿ®¹—4­«§¤Ìqk–-‡…=Ùƒ9€#9‚[r»pÁµÖ[òœ“spA.À–lÁŽìÀB°’\“k0Ý ¸ô)àc9×b®å,‹Y–³,fYæ[äÛyf¦E¦e_‹¾–ùvÍg_‹¾Ž½z9Îr˜å8Ëa–c/‡^®!7`æ;ä ÎÂLA¦0S)Ìd 3™Â.‚.Âg%xVòH~³£ £ÐAà ì+è+ô‘Õ‡}}…}}•ïWñ~•Î g¥³ÂYé¬pV:+œ•Î g¥³ÂYé¬pV:+œ•Î gå{W¼w¥¿Â_é¯ðWú/|ä÷¯Ÿ;6âÇöñ×iZvÖº[×½ƒ]ÓõñcCÈUëï/\¤endstream endobj 110 0 obj 493 endobj 59 0 obj <> endobj 111 0 obj <> endobj 112 0 obj <> endobj 113 0 obj <> stream xÚ]PËnà ¼óÛC¥ôàâGÕ“e)rҶQÜ~†µ‹TÂøà¿/`”J=€fÙ™av®}vzÀ¬zÎᆋ^-Ǭ}c†Ð¶;uJ: W«yF©„Mp’Š%É]ªâÍç$î·ÅáÜ©Q“ºzóÍÅÙ ñÇ'B?¬@+Õ‡¯¶÷u¿óƒ3*9i8z#ŸåÍô(.šgžú×øÜ BëbÏÀµÀÅ0Ž–© Iç ÔçsCP‰½—]1Œü›ÙÄ,ó¢j<."._.÷wpµcý’28‡™ïIùj­".&Æ ¥ÂûîŒ6AÏ/~ z.endstream endobj 114 0 obj 250 endobj 12 0 obj <> endobj 115 0 obj <> endobj 116 0 obj <> endobj 117 0 obj <> stream xÚ]‘ÍjÃ0 Çï~ ï0èY>ëP’QÖöÒlÚJXl㤇¾ýd+t°C¢Ÿ¬¿dKz|8µÑ^™ DùsÂÏ0›«“5oeqs|9êqáñÉÙÂÂûQ+·jø†Q³4ãj”Ëê…¿œÖäö6/0uoXUñøŒÁyq7¾ 7>±øÃ)p£øæ«iÑo¯ÖþÀzá «k® ÇBø–÷nïÕ«‘JÿŸ7 < ~JoFÁl; ®Ó°*Ij^5­þÅRA)—^~wŽU™—& d ä< Œ¹ .  2é ¯/zây›Fƒ,ˆ² sáÏÅ–xëyG¼óL5…¯)¨¦ð5KÊ-}n™ç¡Áµߪ_Â}tòêN5l*ÌÍOlÔp_¦5Ög…ï>¨˜ endstream endobj 118 0 obj 310 endobj 11 0 obj <> endobj 119 0 obj <> endobj 120 0 obj <> endobj 121 0 obj <> stream xÚ]“ÍŠÛ0…÷~ uQ˜.R;±~fÀ†”¡Y´ÆíØÒujhl£8‹¼}utºHü Ýûå\sóñÃk»ys/›ús¥Þä2_£—Íá[·åáøå8«*_ãì[YÕ0N!ÞkT/§q*¶;F¿ÞOùÛŸïÍíí²Êù8 sÑ4ª|K——5ÞÔCþÅOEù#‰ãtR¿m:·×eù#g™VUû½ 2$QÊò½;‹*ŸÃ×ÙoRé¿‹Ÿ·EÔ.Ÿ·Ìàç —¥ó»é$ESU{Õ¼¼ì ™ÂwZ³¥üï.Í¥U•‰w䨑XÈ’¸ÞfNĬ¯Q_×ä¬ÉlÈlÉL ¿¦SééÔpj:5œš ¦GãéÑÙ3‡Ä†sÌeè4p: œ†9 rú ü†N§e6‹l–½½–½½–½½–Ù,²Yzlö<‘ŸÀ=¹{²ró[¼s˹,ærœËa.ǹærÌæÍ1›C6ÇlÙ³9dsÌæÍ=’óÂÜ7«ƒ¥~_E1miÞü¼‡ØÀq’÷?Ç2/èÊŸ¿«ÙKendstream endobj 122 0 obj 431 endobj 10 0 obj <> endobj 123 0 obj <> endobj 124 0 obj <> endobj 125 0 obj <> stream xÚ]PÁNÃ0 ½ç+ÌiJ³‚àRUšŠ&z¦> Mœ.ÒšDizèßã¤Õ8$~–ýžŸ}wj³ƒ´=fOÎ8ÙÙ Ìêα¼nÞ£ä'oE‹”6Òo=Ðã  Û µ[–~1näv™ŽQ–•%äg*NÁ/°KXþå%zmØýÔ-åíìÜG48«*¨Hˆ¼|v#B~ïVdÔúWø^B‘òýêAX‰“ëúÎ ÈJÎ+(ÇŠ¡‘ÿjÏ+£WâÒyV¾Hêäœa\1F¬V¬¿ Sˆz3*ÇoNÅì=-‘“lFƒÚàívκÈJïæ&{endstream endobj 126 0 obj 252 endobj 14 0 obj <> endobj 127 0 obj <> endobj 128 0 obj <> endobj 129 0 obj <> stream xÚ]’Ánƒ0 @ï|Ev˜Ô:(-q+!¤ªSµ¶Ueûš˜iè¡?;F´ø…8á9ÎãñœomwÆùò9Q'º«78ß½U}ï/׌*>úΔ8ªºqÖO9ꌗÆE‹TÙÆŒÓ(¼M;-.oÈíÁÕ]”ç*>Ñä0ú›š…?>Eñ‡·èwQ³¯]IãòÚ÷?Ø¢U…²XÓFäò^µ¨â­}íÌœRÿ&>o=ª4Œâ`:‹C_ô•»`”'I¡òý¾ˆÐÙs)È’sm¾+å)§& âµðšy#¼!^¥)¯„WÌZXgò=ãïz˜ñRxÉ,9:äd³ì£y ÂÀ,>š}´øhöÑFØ0[aËŒÂÈ\ ×Ä 5×R p- nÀn nÀn nÀn nÀn nÀn nø§Óäãæ‹poŸ¹zO ·%ôŽ»Ö8¼_¨¾ëyUx~Ú=±"endstream endobj 130 0 obj 357 endobj 13 0 obj <> endobj 131 0 obj <> endobj 132 0 obj <> endobj 133 0 obj <> stream xÚ]ÔÁjÛPн¾âuQH®eßûîMÀ‚K¨mCÜ~€,=¹‚Z²¼ðßW£1)t‘x„$ÏaÀïã‡×Ãâ¹êŽi!Ÿóð–.Ýu(Ób÷­è³ånÿeß6cX¾]yHc¨›¶îÏ„c:5m¶Z‡ª)ÇûÕü¿<ß_>Ü.c:ïÛºË6›°|›n^ÆáæÆOÙòÇP¥¡iOáá×î0]®}ÿ'S;†<ÛnC•êé‹&Ë÷âœÂò¹úÚ•‹éÑ7~ÞúÖóõІ²«Ò¥/Ê4í)e›<߆ÍËË6Kmõß=w¾r¬ËßÅmÖx4ϧ)¯™×È‘9";³#?2?"?1?!Ìò‘ùˆ\2—Ès…œ˜rÍ\OYèxdżB¦M`adeVdšf1fC¦_àú~¡_àú~¡_àú~¡_àú~¥SáT:N¥SáT:N¥SáT:N¥SáT:N¥SáTÚ6¥MaSÚ6¥Mg·Ul¹mĶ‘Îg¤3ÂéŒpF:#œ‘Îg¤3ÂéŒpFn±adoD¯qÃ>Æ^C¯±×Ðkì5ô{ ½Æ^C¯±×Ðkì5ô÷1ìc4 Æ­ [·2leÜʰ•q+ÃVF³ÁìÜʱ•Óïð;ý¿Óïð;ý¿Óïð;ý¿Óïð;ý¿Óïð;ýÓ~¼÷_)~Æ8`Þ…ò: Ó‰1ŸBó™€Ó iÓûAÕw=ÞšÿþuÖ,Dendstream endobj 134 0 obj 558 endobj 15 0 obj <> endobj 135 0 obj <> endobj 136 0 obj <> endobj 137 0 obj <> stream xÚ]ÍjÃ0 Çï~ í0è™t!P2ÊrØVšõ[É ‹mç·Ÿí˜vÐ}ý¥Ç‡s›…î1Û?3¸à¬Ë1«?:Chݼ5J: g«y‹©„M5Ðã(É ’»DÑó)5·ëìpjÔ IY½øäìì »¸ñ‰Ð/+ÐJ5ÂîZ·žÛŘ_œP9`¤ª@àày-ŸÝ„@â]óÌ—Þß«A("ç›®Φãh;5")« <*‚Jü˽lýÀ:›*;¼½Vžó;óÀ…ç‚å1Þo±ˆsÓ„°!Ü~SÌký1ñAQn*Þ~h´ ]Ñþ‹{þendstream endobj 138 0 obj 254 endobj 99 0 obj <> >> endobj 98 0 obj <> >> endobj 65 0 obj <> >> endobj 60 0 obj <> >> endobj 53 0 obj <> endobj 52 0 obj <> endobj 51 0 obj <> endobj 50 0 obj <> endobj 49 0 obj <> endobj 48 0 obj <> endobj 47 0 obj <> endobj 46 0 obj <> endobj 45 0 obj <> endobj 44 0 obj <> endobj 43 0 obj <> endobj 42 0 obj <> endobj 41 0 obj <> endobj 40 0 obj <> endobj 39 0 obj <> endobj 38 0 obj <> endobj 37 0 obj <> endobj 36 0 obj <> endobj 35 0 obj <> endobj 34 0 obj <> endobj 33 0 obj <> endobj 32 0 obj <> endobj 31 0 obj <> endobj 30 0 obj <> endobj 29 0 obj <> endobj 28 0 obj <> endobj 27 0 obj <> endobj 26 0 obj <> endobj 25 0 obj <> endobj 24 0 obj <> endobj 23 0 obj <> endobj 22 0 obj <> endobj 21 0 obj <> endobj 20 0 obj <> endobj 19 0 obj <> endobj 18 0 obj <> endobj 17 0 obj <> endobj 16 0 obj <> endobj 1 0 obj <> ] >> /Names 139 0 R /PageMode /UseNone /OpenAction [5 0 R /XYZ 0 841.9 0] /Metadata 3 0 R >> endobj 2 0 obj <> endobj 141 0 obj <> endobj 142 0 obj <> endobj 5 0 obj <> endobj 8 0 obj <> /XObject <> >> endobj 143 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 144 0 obj 44 endobj 54 0 obj <> endobj 57 0 obj <> >> endobj 145 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 146 0 obj 44 endobj 61 0 obj <> endobj 64 0 obj <> >> endobj 147 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 148 0 obj 44 endobj 66 0 obj <> endobj 69 0 obj <> >> endobj 149 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 150 0 obj 44 endobj 70 0 obj <> endobj 73 0 obj <> >> endobj 151 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 152 0 obj 44 endobj 74 0 obj <> endobj 77 0 obj <> >> endobj 153 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 154 0 obj 44 endobj 78 0 obj <> endobj 81 0 obj <> >> endobj 155 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 156 0 obj 44 endobj 82 0 obj <> endobj 85 0 obj <> >> endobj 157 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 158 0 obj 44 endobj 86 0 obj <> endobj 89 0 obj <> >> endobj 159 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 160 0 obj 44 endobj 90 0 obj <> endobj 93 0 obj <> >> endobj 161 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 162 0 obj 44 endobj 94 0 obj <> endobj 97 0 obj <> >> endobj 163 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 164 0 obj 44 endobj 100 0 obj <> endobj 103 0 obj <> >> endobj 165 0 obj <> stream xÚ+ä2P0PÈå2µ4Õ327²sàl C= K €‚™Á®Ç%Ý Îendstream endobj 166 0 obj 44 endobj 3 0 obj <> stream Untitled Unknown XEP 4.12 build 20080425 Unknown 20090113T154120Z 20090113T154120Z endstream endobj 139 0 obj <> endobj 140 0 obj <> endobj 186 0 obj <> endobj 187 0 obj <> endobj 179 0 obj <> endobj 178 0 obj <> endobj 167 0 obj <> endobj 172 0 obj <> endobj 168 0 obj <> endobj 175 0 obj <> endobj 181 0 obj <> endobj 182 0 obj <> endobj 176 0 obj <> endobj 177 0 obj <> endobj 183 0 obj <> endobj 174 0 obj <> endobj 180 0 obj <> endobj 171 0 obj <> endobj 169 0 obj <> endobj 173 0 obj <> endobj 185 0 obj <> endobj 184 0 obj <> endobj 170 0 obj <> endobj xref 0 188 0000000000 65535 f 0000071556 00000 n 0000071729 00000 n 0000077974 00000 n 0000047034 00000 n 0000072013 00000 n 0000000015 00000 n 0000007980 00000 n 0000072503 00000 n 0000047222 00000 n 0000062926 00000 n 0000061477 00000 n 0000060355 00000 n 0000065004 00000 n 0000063761 00000 n 0000066809 00000 n 0000071469 00000 n 0000071379 00000 n 0000071292 00000 n 0000071202 00000 n 0000071115 00000 n 0000071025 00000 n 0000070938 00000 n 0000070848 00000 n 0000070760 00000 n 0000070669 00000 n 0000070581 00000 n 0000070490 00000 n 0000070404 00000 n 0000070313 00000 n 0000070225 00000 n 0000070134 00000 n 0000070046 00000 n 0000069955 00000 n 0000069867 00000 n 0000069776 00000 n 0000069688 00000 n 0000069597 00000 n 0000069509 00000 n 0000069418 00000 n 0000069330 00000 n 0000069239 00000 n 0000069151 00000 n 0000069060 00000 n 0000068972 00000 n 0000068881 00000 n 0000068795 00000 n 0000068704 00000 n 0000068616 00000 n 0000068525 00000 n 0000068437 00000 n 0000068346 00000 n 0000068260 00000 n 0000068169 00000 n 0000072794 00000 n 0000008000 00000 n 0000011086 00000 n 0000073028 00000 n 0000057916 00000 n 0000059540 00000 n 0000068033 00000 n 0000073299 00000 n 0000011107 00000 n 0000015026 00000 n 0000073533 00000 n 0000067897 00000 n 0000073771 00000 n 0000015047 00000 n 0000019707 00000 n 0000073987 00000 n 0000074225 00000 n 0000019728 00000 n 0000022524 00000 n 0000074441 00000 n 0000074712 00000 n 0000022545 00000 n 0000026674 00000 n 0000074928 00000 n 0000075166 00000 n 0000026695 00000 n 0000030880 00000 n 0000075382 00000 n 0000075631 00000 n 0000030901 00000 n 0000034208 00000 n 0000075847 00000 n 0000076085 00000 n 0000034229 00000 n 0000038083 00000 n 0000076301 00000 n 0000076550 00000 n 0000038104 00000 n 0000042273 00000 n 0000076766 00000 n 0000077015 00000 n 0000042294 00000 n 0000045787 00000 n 0000077256 00000 n 0000067761 00000 n 0000067628 00000 n 0000077516 00000 n 0000045808 00000 n 0000047012 00000 n 0000077735 00000 n 0000057018 00000 n 0000057040 00000 n 0000057895 00000 n 0000058387 00000 n 0000058760 00000 n 0000058950 00000 n 0000059519 00000 n 0000059717 00000 n 0000059818 00000 n 0000060008 00000 n 0000060334 00000 n 0000060722 00000 n 0000060876 00000 n 0000061070 00000 n 0000061456 00000 n 0000061915 00000 n 0000062193 00000 n 0000062398 00000 n 0000062905 00000 n 0000063126 00000 n 0000063198 00000 n 0000063412 00000 n 0000063740 00000 n 0000064163 00000 n 0000064349 00000 n 0000064550 00000 n 0000064983 00000 n 0000065509 00000 n 0000065958 00000 n 0000066154 00000 n 0000066788 00000 n 0000066990 00000 n 0000067081 00000 n 0000067277 00000 n 0000067607 00000 n 0000078887 00000 n 0000078924 00000 n 0000071796 00000 n 0000071932 00000 n 0000072654 00000 n 0000072774 00000 n 0000073159 00000 n 0000073279 00000 n 0000073631 00000 n 0000073751 00000 n 0000074085 00000 n 0000074205 00000 n 0000074572 00000 n 0000074692 00000 n 0000075026 00000 n 0000075146 00000 n 0000075491 00000 n 0000075611 00000 n 0000075945 00000 n 0000076065 00000 n 0000076410 00000 n 0000076530 00000 n 0000076875 00000 n 0000076995 00000 n 0000077376 00000 n 0000077496 00000 n 0000077834 00000 n 0000077954 00000 n 0000079513 00000 n 0000079612 00000 n 0000080122 00000 n 0000080322 00000 n 0000080071 00000 n 0000079561 00000 n 0000080171 00000 n 0000079969 00000 n 0000079663 00000 n 0000079816 00000 n 0000079867 00000 n 0000079462 00000 n 0000079411 00000 n 0000080020 00000 n 0000079714 00000 n 0000079765 00000 n 0000079918 00000 n 0000080271 00000 n 0000080222 00000 n 0000078971 00000 n 0000079299 00000 n trailer <<7E70C16B76188629431685E832FEA0E3>] >> startxref 80374 %%EOF norm-1.5.8+dfsg2/doc/NormUserGuide.xml0000644000000000000000000015176711156550135014431 0ustar
<inlinemediaobject> <imageobject> <imagedata align="center" fileref="NormLogo.gif" scale="50" /> </imageobject> </inlinemediaobject> <emphasis>norm</emphasis> User's Guide (NORM Version 1.4b4) norm User's Guide Background This document describes the usage of a demonstration application that uses the NACK-Oriented Reliable Multicast (NORM) transport protocol for reliable transmission of files, and byte or message stream content.  The name of the executable binary is "norm".  It should be noted that this "demonstration application" applies a subset of the capability of the NORM protocol.  Additionally, the current version of this application does not use the NORM Application Programming Interface (API) that is described in the "NORM Developer's Guide".  The current norm demonstration application source code preceded the development of the NORM API.  A future version of this demonstration application will be created that uses the NORM API and will also serve as a reference to NORM developers. The norm application supports the following uses: One time or repeated tranmission/reception of a set of files or directories Transmission/reception of a byte stream piped into the STDIN of the sender application instance (Unix systems only) Transmission/reception of a "message" stream piped into the STDIN of the sender application instance (Unix systems only) The norm command-line (and run-time remote control interface) allow configuration of a large number of NORM protocol parameters.  Again, note that while a considerable range of NORM protocol functionality is available in the norm application, it does not demonstrate the full set of NORM protocol capabilities.  The distribution also includes the raft and npc (NORM Pre-coder) applications that can be used as "helpers" to the norm demonstration application for various purposes. The NORM protocol is described in Internet Engineering Task Force (IETF) Request For Comments (RFC) RFC 3940 and RFC 3941.  These are experimental RFC standards.  These documents have been revised in recent Internet-Drafts and it should be noted that the Naval Research Laboratory (NRL) implementation of NORM that is represented here has been updated to reflect the revised protocol. In addition to this demonstration application, NRL provides a NORM protocol library with a well-defined API that it is suitable for application development.  Additionally, the NRL source code distribution supports building the NORM protocol as a component into ns-2 and OPNET network simulation environments.  Refer to the NRL NORM website <http://cs.itd.nrl.navy.mil/work/norm> for these other components as well as up-to-date versions of this demonstration application and documentation. Building <emphasis>norm</emphasis> The norm application can be built from the NRL NORM source code distribution.  For several Unix-based operating systems, "Makefiles" are provided to build the NORM protocol library and example applications including this one.  For Win32 and WinCE systems, workspace and project configuration files are provided for the Microsoft Visual C++ development environment. Unix To build the norm demonstration application: Download and unpack the NORM source code tarball. cd norm/unix make –f Makefile.<operating system> norm Win32 To build the norm demonstration application: Download and unpack the NORM source code tarball Make sure your VC++ environment has the Microsoft "Platform SDK" installed and is configured to use its header, library, and executable files. Open the "norm.sln" (VC++ .Net), "norm.dsw" (VC++ 6.0), or "norm.vcw" (Embedded VC++) workspace file. The "norm" project can be selected and built.  The "norm.exe" file will be found in the "norm/win32/norm/Release" directory. Concepts of Operation The norm application supports several different uses.  The most typical use is reliable multicast of files from a sender to a set of receivers.  However, on Unix systems, the option is available to pipe (via STDIN) live byte or "message" streams into the norm sender application for transmission to the receiver(s). The norm address command specifies the destination address and port to which NORM protocol messages are transmitted.  For multicast operation, senders and receivers must use a common address and port number.  Unicast operation is also supported, but some care must be taken with usage.  Typically, for unicast operation, receivers should be configured with the unicastNacks option to ensure that feedback messages are properly directed back to the appropriate sender. NORM messages are sent in User Datagram Protocol (UDP) packets.  The user must make sure that any firewall configuration allows transmission and reception of UDP datagrams for norm to work properly. Most of the NORM protocol parameters are set at the sender and the NORM protocol advertises parameters to the receiver(s) in the headers of NORM messages.  This allows for somewhat loosely coordinated multicast operation.  Typically, it is expected that receivers will join the applicable multicast group and begin listening ahead of time.  Then, the sender(s) will transmit content to the group for reliable transfer.  For NORM stream operation, it is important to note that the norm demonstration application only supports a single sender per multicast group. File Transmission Receiver norm instances must use the rxcachedirectory command to specify a file system directory that is used to store received content.  Note that the post processing (see processor command description) option of norm allows received content to be processed and/or removed from this cache directory to a permanent storage location if desired. The sendFile command is used for the norm sender(s) to specify the file(s) and/or directories that should be transmitted.  By default, the files are sent once.  Directories are recursively scanned for files and those files are transmitted once.  Note that zero-sized files are not transmitted.  The repeatcount and rinterval (repeat interval) commands can be used to repeat transmission of the file/directory set on a scheduled interval after completion of prior transmission.  Additionally, the sender updatesOnly option can be specified so that on repeated scan of the file/directory set, only files that have been changed or added are transmitted.  This allows the option for a "hot outbox" to be set up that is monitored by the norm sender for transmission of files to the group.  A simple multicast file sharing capability can be created in this way. By default, files enqueued for transmission with the sendFile command are transmitted immediately, one after the other, but the interval command is available to pace the transmission of files.  This can be used to allow time for post-processing at the receivers of subsequent files before new files are sent. This is a synopsis of the most typically-used commands for file transmission.  A number of other commands are available to customize the norm file transmission behavior.  The reader is encouraged to read the descriptions of the available commands given later to understand the full range of options available. Stream Transmission Currently, this option is available only for Unix-based operating systems.  Instead of transmitting files from the file system, the user may pipe (via STDIN) content directly to the norm sender application instance using the norm input or minput commands..  At receivers, the received content is directed to a descriptor set using the norm receiver output or moutput command.  Two forms of stream transmission are available: raw, unformatted "byte" streams, and "message" streams.   The distinction between these two types is the presence of explicit message boundaries.  The NORM protocol allows receivers to automatically recover message boundaries that have been marked by the NORM sender.  This is useful when receivers may join the NORM session while it is already in progress or if there is intermittent network connectivity.   The input and output commands resepectively set sender and receiver "byte-stream" operation while the minput and moutput commands similarly set "message-stream" operation.  It is expected that the "message-stream" operation offers the most utility for most purposes.  "Byte-stream" operation may be used if the content is something like human-readable text, etc where distinct message boundaries may not be important.  Again, note that norm receivers should begin listening before the sender begins transmitting for most effective uses of "byte-stream" operation.   For "message stream" operation, the norm application presumes that the first two bytes of messages are the message size (in bytes) in Big Endian (network) byte order.  The NRL mgen (see <http://cs.itd.nrl.navy.mil/work/mgen>) and raft applications can be used to provide messages to norm in this format.  The mgen application can be used to measure NORM message delivery performance for testing and experiment purposes, while raft provides the ability to capture UDP packet flows (e.g. Real-Time Protocol (RTP) video, etc) and reliably "tunnel" the UDP messages through NORM transport.  At the receiver(s), raft can be correspondingly used to reconstruct UDP datagrams from the norm "message-stream" content.  The usage of raft is described in Appendix A (TBD) of this document. General Properties Overview Most norm commands are for specifically sender or receiver operation.  There are some commands that apply to both.  These include the instance command that establishes a "remote control" inter-process communication facility that can be used to pass commands to instances of the norm program that are already running.  Also, the debug, trace, and log commands are provided to display and/or store debugging output from the norm application and NORM protocol code.  The txloss and rxloss commands are provided to invoke random dropping of sent or received NORM protocol messages for testing purposes.  Other commands, like address, ttl, loopback, txport, and interface control the behavior of NORM UDP packet transmission and reception. Sender Properties Overview The norm sender configuration controls most aspects of NORM protocol operation.  This includes transmission rate, packet size, Forward Error Correction (FEC) configuration, etc.  The rate command determines the norm sender transmission rate in units of bits/second.  The segment command sets the maximum size of NORM message payloads.  The block, parity, and auto commands respectively set the number of user data segment per FEC block, number of calculated parity segments per FEC block, and number of proactively (automatically) transmitted parity segments per FEC block.  The backoff command sets the maximuim number of round-trip time intervals over which timer-based feedback suppression is scaled and the grtt command sets the sender's initial estimate of round-trip time for the group.  A detailed understanding of these various NORM protocol parameters can be attained by reviewing the NORM protocol specification documents and the "NORM Developer's Guide".   Another significant norm sender command is the txbuffer command.  This sets the size of the NORM sender cache for calculated parity segments and FEC block repair state.  For norm stream operation, this command also determines the size of the stream buffer.  The stream buffer size limits the "repair window" when norm stream operation is used.  A relatively large stream buffer size may be needed for high (bandwidth*delay, packet loss) conditions.  Some other significant commands applicable to norm stream operation include the push and flush commands. Although NORM is a NACK-based protocol, it does support optional collection of positive acknowledgement (ACK) from a subset of the receiver group.  The norm ackingNodes and related ackshot commands can be used to exercise this optional protocol behavior. Finally, in addition to the fixed transmission rate operation set with the rate command, norm also supports enabling automated congestion control with the cc command.  The bounds of congestion control rate adjustment can be optionally set with the limit command. Receiver Properties Overview As mentioned, most of the NORM protocol behavior is controlled by the sender, but there are some options that the receiver can exercise.  The most significant of these is the ability to put the receiver in an emission-controlled (EMCON), or "silent receiver" mode where no NACK or other feedback messages are generated.  The silentClient command is available for this purpose.  This is useful when using NORM for reliable transport over unidirectional network connectivity (In this case, it is expected the norm sender has been configured with some amount of auto (proactive) FEC parity in its transmission to overcome nominal packet loss).  For optional use with the silentClient command, the lowDelay command is available to expedite delivery of received content (even if for a partially-received FEC block) to the application when subsequent FEC coding blocks are received.  The default behavior would be for the norm receiver to buffer partially-received content as long as possible for possible repair in response to some other NACKing (non-silent) receiver.  The lowDelay command overrides this default behavior. The processor command is available to the norm receiver to specify a application, command, or script that is invoked upon successful completion of reception of files.  The specified command is invoked with the received file name as the last argument.  Users may employ this command to move received content to a permanent storage location, display received content, or other purposes (One could even cleverly control norm receiver or other system operation in this way if desired).  A related command is the saveAborts command that causes even incomplete files (aborted) to be passed to the receiver post processor.  An example use of this option would be if the files transmitted were pre-encoded with the npc (Norm Pre-Coder) utility such that original file content can be recovered from a partial npc-encoded file (See the npc User Guide for details). <emphasis>norm</emphasis> usage The norm application is launched from a command-line interface (e.g. Unix or DOS shell).  Many of the norm parameters have default values, but typically the user will wish to set at least some of these differently than their defaults.   A minimal example norm sender command-line syntax is: norm addr <addr/port> sendFile <fileName> The corresponding minimal norm receiver command-line syntax would be: norm addr <addr/port> rxcachedir /tmp The sender would begin sending the specified <filename> at a transmit rate of 64 kbps.  The receiver would receive the file and store it in the "/tmp" directory. Typically, it is expected that the user would wish to set the norm transmit rate or enable congestion control operation.  The norm application was designed principally for long-term participation in an IP multicast group with the receiver application running all of the time, post-processing received content as it arrived, and sender(s) transmitting content to the group (e.g., using the "hot outbox" approach mentioned) as it was available.   The norm receiver command-line syntax to support this operation would be: norm addr <addr/port> rxcachedir /tmp processor <postprocessor> The norm sender command-line syntax would be: norm addr <addr/port> rate <bps> sendFile <outboxDirectory> repeat -1 updatesOnly The "repeat -1" would cause norm to scan the <outboxDirectory> indefinitely for new file content and transmit those files to the specified group address and port.  Note the transmit rate is specified in units of bits/second. Unicast Operation For unicast operation, the following usage is recommended: Receiver: norm addr 127.0.0.1/<port> unicastNacks rxcache <cacheDirectory> … Sender: norm addr <rcvrAddr/port> sendFile <filename> … The norm receiver address is really a "don't care" value since feedback is transmitted to the sender's unicast source address and port detected during packet reception. Command Reference The following tables list the available norm command-line options.  Note that if the instance command is used, many of these commands may be issued to instances of the norm application that are already running.  The tables are grouped by the categories of "General", "Sender", and "Receiver" commands. Note that norm commands may be abbreviated on the command-line if desired. General Commands address <addr>/<port> Designates session address and port number.  For multicast operation, sender(s) and receiver(s) should use common address and port parameters.  For unicast operation, the sender must designate the intended receiver address and port and the receiver must specify the same session port number.  The receiver unicastNacks command should be used for unicast operation.  IPv4 and IPv6 addresses are supported. txport <port> Specify a specific source port number for NORM transmission.  This can also be set to equal the session port (ie. rxport).  Default is system-assigned transmit port number. ttl <value>        Designates session multicast time-to-live (hop count).  The default value is 255. interface <ifaceName> Sets the network interface for multicast packet transmission/reception.  <ifaceName> is name or IP address of a valid network interface.  Default is system default multicast interface. loopback {on | off} Optionally enables reception of norm's own messages.  Useful for loopback testing of sender/receiver configuration.  Default = "off". txrobustfactor <value> Set the “robust factor†that determines the number of times NORM protocol NORM_CMD(FLUSH) messages are sent at end-of-transmission, how robustly positive acknowledgement collection is conducted, and how other “robustly-transmitted†(repeat-transmitted) sender control messages are managed.  Higher “robust factor†values makes increases the assurance of protocol success in the face of significant packet loss.  Lower values can be used to make norm less “chatty†but at the cost of reduced certainty that protocol operation will succeed under all circumstances. Note that this parameter needs to be consistently set at both the norm senders and receivers.  Unlike many of the other parameters, this value is not advertised by the sender to the receivers in the NORM protocol message headers.  The default value is 20.  This provides about 95% likelihood of protocol success even with 50% packet loss.  This is based on the probability that the receiver gets the sender NORM_CMD(FLUSH) messages and the sender gets NACKs from the receivers needed to complete reliable transfer.  The special value of -1 will make norm indefinitely perform the related protocol actions (sender flush transmission, positive acknowledgement collection until success, etc).  This is typically not recommended.Default = 20. instance <instanceName> Specifies "name" of the first running instance.  If a norm instance is already running with the specified <instanceName> the commands given will be issued to that already-running instance of norm. debug <debugLevel> Sets verbosity of debug output.  Higher values are more verbose.  The range is from 0-12.  The default debug level is zero. trace {on | off} Enable/disable NORM protocol message trace in debug output.  Message trace is timestamped logging of information for every packet sent or received.  Default = "off". log <filename> Directs debug output to specified file. txloss <percent> Sets percentage of messages to be transmitted that are randomly dropped (for testing purposes).  Default = 0.0 percent. rxloss <percent> Sets percentage of received messages that are randomly dropped (for testing purposes).  Default = 0.0 percent. help Displays command set with short descriptions. Sender Commands rate <rate in bits/sec> Sets the sender maximum transmission rate.  All sender transmissions (user data, repair, protocol messages) are subject to this rate limit.  Default = 64 kbps. cc {on|off}        Enables/disables NORM TCP-friendly congestion control operation.  When turned on, a rate-based congestion control scheme allows fair sharing of the network with other network flows.  When turned off, norm will transmit at the transmit rate set by the rate command.  Default = "off". limit <rateMin:rateMax> Sets lower/upper bounds on transmit rate adjustment when congestion control operation is enabled.  A value of -1.0 indicates no limit.  Default rateMin/rateMax = -1. segment <bytes> Sets norm message payload size (segment size) in bytes.  Default = 1024 bytes. block <segments> Sets number of user (source) data segments per FEC encoding block.  Default = 64. parity <count> Sets number of parity segments calculated per FEC encoding block.  Default = 32. auto <count> Sets the number of parity segments that are proactively (automatically) transmitted with each block of user (source) data segments.  A non-zero count can provide for robustness/reliability with no NACKing from receivers required.  This value must be less than or equal to the value set with the parity command.Default = 0. extra <count> Instructs the sender to respond to repair requests (NACKs) by sending <count> extra repair segments beyond what the receiver(s) requested.  For experimental purposes.  Default = 0. silentClient This informs the norm sender that silent receivers will be used and it should redundantly transmit NORM_INFO content at the end of each FEC coding block. grtt <seconds> Sets the norm sender's initial estimate of group round-trip timing.  This value affects the latency of the NORM repair process (and thus impacts buffer size requirements).  Default = 0.5 seconds. backoff <factor> Set the factor used to scale feedback suppression backoff timeouts.  Small groups not concerned about feedback  implosion may use small or zero values to minimize delay of NORM repair process.  Default = 4. txbuffer <bytes> Sets the norm sender transmit buffer and stream buffer size, if applicable.  The transmit buffer is used to cache calculated FEC parity segments and FEC code block repair state.  The stream buffer size limits the "repair window" for stream transmission (and hence maximum possible latency).Default = 1Mbyte. txcachebounds <countMin:countMax:sizeMax> This sets the “transmit cache bounds†that are used to determine how many prior transmit objects for which the norm sender maintains state.  This essentially limits the “repair window size†that the NORM sender observes has for responding to repair requests (NACKs) from receivers.  The “transmit cache bounds†also SHOULD be set to be compatible with any use of the requeue option described below (i.e. the safest thing to do is set <countMin> here to a value greater or equal to the number of files in the transmit file/directory list, including the count of files in any directories).The <countMin> value sets a minimum number of transmit objects (files) for which the NORM sender will keep repair state, regardless of the file sizes while the <countMax> value sets a maximum object count that the NORM sender will keep in its “repair windowâ€.  The <sizeMax> value in units of bytes) limits the repair window according to sum total of the file sizes in the cache, providing that state is kept for at least <countMin> objects.  The <countMax> limit is most useful when the file sizes are somewhat small (i.e. <sizeMax> is not reached) and the user wishes to limit repairs of  “older†files sent.  Note that <sizeMax> does not directly relate to memory allocation since NORM recovers file data directly from the file storage system as needed.An IMPORTANT caveat here is that the current NRL NORM implementation has a hard-coded limit that NORM receiver will keep state for a maximum of 256 objects per sender. Thus, the value of setting the txcachebounds count values greater than 256 is limited. This limitation will be  fixed in an updated to the NORM code and will be reflected here.Default: countMin =  8, countMax = 256, sizeMax = 20 Mbyte gsize <count> Sets the estimate of receiver group size used by NORM for scaling time-based feedback suppression. sendFile <path> Adds a file or directory to the norm transmit file/directory list.  Directories are recursively scanned for files.  Zero-sized files are not transmitted. repeatcount <count> Repeat scan or transmission of transmit file/directory list set with sendFile command.  A <count> of -1 means infinite repeats.   With each “repeat†pass through the transmit file/directory, the files are sent with new NormTransportId values and considered separate transmit objects by the NORM protocol.  This is different than the requeue option which causes the file(s) to be repeat transmitted with the same NormTransportId.  Note these two different options can be used together and the result is a “multiplicative†effect with regard to the amount transmission that occurs.Default = 0. rinterval <seconds> Specifies a time delay between repeated scan or transmission of transmit file/directory list.  Default = 2 seconds. requeue <count> Specifies the number of additional repeat transmissions of the each file using the same NormTransportId such that the multiple transmissions can be “stitched†together by the receiver into a successful reception even if a single transmission is unsuccessful (useful for “silent receiver†mode along with the “auto†parity option).  This is distinct from the repeatcount option in that the repeatcount option specifies how many repeated passes through the transmit file/directory list with files getting new NormTransportIds  and thus considered separate NORM transmit objects. Note these two different options can be used together and the result is a “multiplicative†effect with regard to the amount transmission that occurs. A requeue <count> value of  0 means that each file in the transmit file/directory list is sent once as a distinct NORM transport object (i.e. no requeue occurs). A requeue <count> value of -1 indicates the files are requeued indefinitely (and thus any configured “repeatcount†or “updatesOnly†options become irrelevant).   Note that if the number of files in the transmit file/directory list exceeds the txcachebounds limits, then the “requeue†option will not work.  Thus, it is important to set the txcachebounds accordingly to use the requeue option. Default = 0  (disabled) updatesOnly Upon repeat transmission of the transmit file/directory list, NORM will only transmit files which have been added or updated since the previous transmission.  This, along with the "repeat" and "rinterval" options can be used to create a sort of "hot outbox" capability. oneshot Causes the norm sender application to exit after the NORM TX_FLUSH_COMPLETED event at the end of file list transmission.  By default, the norm sender application will run indefinitely. ackingNodes <node1,node2,…> The comma-delimited list of NORM node identifiers is used with NORM positive acknowledgement operation.  Acknowledgment from the specified list of nodes is collected for each transmitted file before sending subsequent files.  The norm application uses its host's default IP address for a "node id".  Default is no acking nodes. ackshot The sender application exits after completing positive acknowledgement collection. input {<device> | STDIN} Sets norm sender "byte-stream" operating mode using input from specified <device> path or STDIN.  With STDIN, the STDOUT of another process may be piped into the norm sender.  (Unix-only). minput {<device> | STDIN} Sets norm sender "message-stream" operating mode using input from specified <device> path or STDIN.  With STDIN, the STDOUT of another process may be piped into the norm sender.  "Messages" are expected to have a 2-byte, Big Endian message size prefix.  (Unix-only). flush <flushMode> Sets norm sender flush behavior for "message-stream" operation.  Valid options include "none", "passive", and "active".  With "none", no flushing is invoked; stream transmission simply pauses when no input data is available and norm always sends full NORM_DATA messages according to the set <segmentSize>.  With "passive" or "active" flushing enabled, the NORM stream is flushed with each completed message and variable-sized NORM_DATA messages may result.  With "active" flushing, the NORM_CMD(FLUSH) message is actively transmitted when there is no data available to transmit.  This makes NORM more "chatty" but provides more robust, lower-latency reliability for stream transmission.Default <flushMode> = "none". push When set, new input data is always written to the NORM stream regardless of pending repair transmissions.  This favors new application data transmission over repair of older stream data.  Suitable for applications that can tolerate "quasi-reliability" and desire low latency. Receiver Commands To invoke norm receiver operation, one of the rxcachedir, output, or moutput commands MUST be given on the command-line. rxcachedir <path>        Sets the directory where received file content is stored by the norm receiver.  This is a required command for norm file reception. processor <command> Specifies command (and any options for that command) for post-processing of received files.  The received <filename> is appended as the last argument to the specified command when invoked for each received file.   saveAborts Causes incomplete (aborted) files that are partially received to be saved and/or passed to the post processor.  The default behavior is that incomplete, partially received files are deleted. output {<device> | STDOUT} Received "byte-stream" output is directed to the specified <device> path or STDOUT. moutput {<device> | STDOUT} Received "message-stream" output is directed to the specified <device> path or STDOUT.  Output messages will have a 2-byte, Big-Endian prefix indicating the message size. unicastNacks Feedback messages are unicast back to detected sender source address(es) instead of being sent to the norm session address.  Default behavior is feedback is sent to the session (usually multicast) address.  This receiver option is RECOMMENDED for unicast operation. silentClient In this mode, the receiver sends no feedback messages and relies solely upon sender proactive (auto parity) FEC content for reliable reception. lowDelay For use with silentClient operation.  Source data for partially-received (incomplete) FEC coding blocks is provided to the application immediately when subsequent FEC blocks are received.  This minimizes delay of delivery of user data to the application.  The default behavior is to buffer partially-received FEC blocks for as long as possible in case repair transmissions (due to other non-silent receivers) are provided. rxrobustfactor <value> This sets a “robust factor†value at receivers that determines how persistently the receiver keeps state for remote senders that are not currently, actively transmitting data.  This also corresponds to the maximum number of times the norm receiver will “self-initiate†NACKing to such an inactive sender before giving up.  Unless rxpersist is specified (see below), the receiver will also free memory resources allocated for an inactive sender at this time. A <value> of -1 causes the receiver to be “infinitely†persistent.  The default value is 20.   rxpersist If this option is given, the receiver keeps full state on remote senders indefinitely, even when they go “inactive†(see above).  The default behavior when this is not specified is for norm to free buffer memory resources allocated for senders after a timeout based on the txrobustfactor, rxrobustfactor, and measured GRTT. rxbuffer <bytes> Specifies the size of the norm receiver buffer that is allocated on a per-sender basis.  This buffer is used to cache partially-received FEC coding blocks and associated object repair state.  An operating mode or network connectivity with significant (bandwidth*delay, packet loss) may necessitate larger rxbuffer settings to preserve protocol efficiency.Default = 1 Mbyte. rxsockbuffer <bytes> Sets the size of the UDP receive socket buffer used for norm sockets.  An extremely high transmission rate may require socket buffer settings above normal system defaults. Parameter Considerations (TBD) Discuss the considerations and trade-offs of NORM parameter selection.  (e.g. FEC parameters, buffer sizes, etc).  Note some of these issues are described in the NORM Developer's Guide and/or NORM Protocol specifications. Example Usage The example command-line usages listed below assume that NRL's MGEN packet generator is being used as a data source.  For more information about MGEN, to include download and installation instructions, see <http://cs.itd.nrl.navy.mil/work/mgen>. Message stream" transmission example(with MGEN sender): mgen event “on 1 sink dst 0.0.0.0/1 periodic [200 1252]†output /dev/null sink STDOUT | norm addr 224.1.1.1/5001 rate 3000000 segment 1252 block 40 parity 16 auto 6 backoff 0 minput STDIN "Message stream" reception example (with MGEN receiver): norm addr 224.1.1.1/5001 backoff 0 moutput STDOUT | mgen source STDIN output mgenLog.drc File transmission: norm addr 224.1.1.2/5002 rate 5000000 send <fileName> File reception: norm addr 224.1.1.2/5002 rxcachedir /tmp "raft" Usage The NRL NORM source code distribution supports building the "Reliable Application For Tunneling" (raft) utility that can be used as a helper application with norm to tunnel a UDP datagram flow over a reliable NORM "message stream" tunnel.  The raft application can be configured to listen to a UDP port, optionally joining an IP Multicast group, and output received UDP payloads as "messages" to its STDOUT.  This, in turn, can be piped into the STDIN of the norm application for message-stream tranmission.  Additionally, on the norm receiver side, raft can be configured to accept messages from STDIN and re-encapsulate these as UDP datagrams transmitted to a specifed destination address and port. (TBD) Finish description of raft usage and provide example of use with norm
norm-1.5.8+dfsg2/doc/npcUsage.pdf0000644000000000000000000035423611156550135013413 0ustar %PDF-1.3 %Äåòåë§ó ÐÄÆ 2 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xÚÍ}[s[Éuõ{ÿ ”Ÿä*îûå1‘g*){äù¥òâÞD2ŽHJ¦ý€8»ÏéÕ (“$Uöä ÀFŸî}Y{íµ›ý¿Ùo3cWÿ7·^ëg!§yŠZ›YŠÃû|1ûŸÙböç7wfvv7Ó›ÿ½;[}TÏ­+›ÿQ›ÿ¯üãÌÄüô³XÜÜX­ãììföïïg1n>¿ý÷7³?ÿlæzffï?Ì^½ýãìýÿªú¯øüôï¼úûúÁ賫/~zð®y`ä#¿Ìþ¨&¬µÛG¿~n>eËðèbóä§÷«­i7G=wsfÍæXŸæV´1â˪ïL}粂¯vOÖ¥öX×›f#ýð^–Ó*ÎÛæôdëGObÚ>¿®õé0ÅmŸÌÚiÌöÉ?^aËœÎó¸ú‡½vÍÊ®-Ú]}ÛîÚðàlŸ³ãXª}~Œ‹ó¾ygUsþñÇû9ÿݵO°ìñïQë'ÉLÌÜè3М¶_çœm–0Ü!üÄÍ·zXÂ/Í/ñÑÃæ©Ñ#Ù vS}ô³þò)‹}VÓ—ª5ù­A,÷]ûdë·¬ „@~jˆyðå úæ Êkmi”—×…X4ÙÓä†íùÇÛGÁÀºÕÓ‰knÛûõðc—í>d?ü©åYóú²¿e{„Š„Ø`0å_7﯄DÞRI‘}Ûö^ª­·Ý0mØÑ7ÚÉN೬¹ƘBî¦1Þt–¨6äÒ,?ÀÇ ;e«`+·C‰oy¸½]¶/Ó8ye`«ÜÊH?ùžkx”†K²¸<–³¶yîVAeÚÇYÃÏö`yúp‡oJ‘°tÃ]îïš2Á?bbagLîÆâ®¹‡Ö K¸imrbVÏæÜÜ 1ÉšÝ'fûmηs¹˜5·ÐKާÕ{¶w>dr }® L¬œÓ 0±Qw5[D”ѾÀ(Ý>$oðí“&uR¹™íÆ&q4ŸÀbGâSSÈ,´H%‘Åeù­³Ö(‹å#ïip#›ÐúÔjâ/ ðudÊÖ:©W_àCrÀÛÅùCwhÈ‹ WVË~ߣ6üꤵÈ:;ú±’˜}0f_Œ ²qÔBÏ}F2$«0&³ZùöJV~aˆk{¸Æ0•EÃÆMqñV9±—Ã: (ÐyíÉ]yJ±Ü p±^ð§Gø{aí~UMÍÇòSëì•<’·%f€4òJê»P·}òµç5~ýú Ï»#­ZÞ‚ÍbÇ=S(ÑØ}»eòÛ1$)MD2rˆÚ’0Òšáœ/àC‰A6´0ÕYùJÍ"Yg9 níáUÏÃ;êáxøê‘“"O¨‡÷#?‰åÔ9Qó0Æñuš‡Í;è` P‚zÁÃnPŽC–Öæ:âh0Œávµ†RŸšCj< VöŠ™¡À×3)©×ôSû$Þâ8óƒ…~C#Ç&UNr´·X–¬z[&—k}JÕ‹gÒUʇ…›æ(8fãâ°7‹¼»Q€Ðž„áëæàf, E¶V¤8äáͽ‡#2Ø—«k„ˆ±4ñ¶¹L`òÑA y·ãi·“4áôº‰¶½$ÝíUñÎQó—ˆ·ñQâ ÈThvS&ñþè(C%g|4ÊzT›õ Ž–¡h]Üf§ Fg#É¿¶Oüg".`ÅâXÖódõÊŽî@,ïšYÜ-h¾!voõWâÖ׿ƒ[Z|·ŠÓÙµr‘]EÁ#NR:¿h/£/Ä9¹È®¶“u·h²ÌøŽÚx¸<64†BÁ%].Úˆ8';\ÆË‡Ö–†Âö¨bpâvc®Ø@ËÇÂ^`ÒÃq5InyBoVkM35V‰¾![”§%àjŸ³¸£èȯ2ÅU²ýL3ýÈôÅʵ®P[MAñº7ð(QLSŠMοÁ¼?c6ŸhÊkÄ%~…G.äEÖ'šéKä¼Ý©ŠbV.øÀOðh…¨> ‡Å@~³Z¥ùÌŠ˜ê·¡ÌéP•oT5¢ÈG0ù ´–©…œ{ µ K=CŠ´KH#M” ᶉµýÜb)µžó†mV ÓZÏJIICü¼*¥wÈë¯Ò«oõmà¬:C ¦µGö@Âż5–„WƳâ¥3vF|¸zµ<¿¦õX„'œÜ‹3@凸 3IW,9à^üáäCjƒ½3_äc$VÇÓrBÐ ÿ bœ!zSÚÜ8@ά(ÐZA¹å‡æÆÀÂŒH ÆQÒfðï…Eïɰè=Y?Øðï‘¡1IŽëå5ø÷Âbþ,ß×úêœ ©ñVÿ~~WnY»ENP{ÿJ ´ðš)„®i®«M¦5YAèü³'xš1–倯8R[yxY°r˜(Yür1G“fë6ò"¯°~n÷ªšåoÝåÍv¯Þ"œJ)I5•~.>>“”Ô`4j?ÆaÐsŸÖ u5³m9è;HI㥩½ÉÁÏWçæ u‚åeÕÚ8ýƽ<Í\ý‘ê`Ÿ¦TÏ>¾ÖfÔÔ7j³½k+ǼxMkˆ“²XÐÚÂ`K`Â,’PÏyŠ­fM($5.ø µV¤ò’Š»V@¡ÜŒþ¡  ©çUrU'. áÊû«û؆i‘ñ0FÞ.­¤ÖzÜI/SïþÖd‡ØÎ6e@Ô*þƪv{´ÀÅ{†mæHÈ~* Üó)<‹ZŠ„wÍÑ*Î}» å‡YwgÊ|M'ÏÜÈô¬h'PfAª™––'EúÀ+ËŽåœI³lB® Ôe³ÏÝ#¡¨&$dØ›Â Ë œb7_îGŒ£r4òq•ý:£%ÈÏ-nïYyÔK<0¢ÜÖÛ墥½1[€îÑmÅÍï[3#º'(ã3ÃÚ“ðÀ VF&äq ‹‚ Êöy‰ýs‘öÊÜûñ}|ï¢OÕ«ß.(!à,xOÐñÚ³ƒµ2VUµ§ë-F$R®±ü›–j-U¢¿BÝË3Šž) ¯/QÞ°—€ §5ÉÃGœ›¸s†Ö½<¹±HD%ÿä˜ö_êæTˆc,¤½£¬17JÔsÕ6#ÆÌRËX"IÀ64®š©qµ&ô+QÎmáîŠôiCϵÔ0o1›Ê„ËkMýK®6RÝ<®òºU°VÕ" 'd Ð<^<À X j¬ŒFâìmC®óè0wMÊ4ó(‰¥…ÖìPÿ Ü´ |‹ÆM¼å1efßÔÊ&RðÑ•H`aT~¹¾uH¬Ñ'Ö+e| ÄÙ›ZÂ\^*{‹ó?ÃÃ2÷ï]#2uXûTÓ"JÄ hArC‰½Éb}À4fKâ_• ´i€–»ÙýÆdeÆP+S]›—OîWçe£‘¶WrO[ —-¥8ðÖ—]ÒrÐõ¡à\QRÞÙºjÙ$¾šyNg(MÑVN8V¸ Ë| ½ß‚sž^EQ|.t Ì›M—]_ nUØ•4¬W«æÄ3Jú´uœùêB›ž, ÀRbuÇš.Ã4Ìf;[<~§ú¸Ü.µË%»í§å’í,Œ©ïŽdiê›ÑBšgغ ɬ|†“c€ùÂí¯ZíÏÖiÀ|¸÷Q1ÊžB›“uaDRK‹åA³Êvdw·ÚËkÚ£2b€mùJUG­P åÄKÄ0 þ•ÒR1ˆI]É4NÒ4Nb$ìŠ:Â*ùÔ²*pð,®Ù°R»<ÒYq6jÊ‘ŒAŸQ-/XøÌ¤j-ª7O7Oñ{ºÅMÄÊ& ÞÈ,…}Ì×VXíŒ+ñ²2£<#!Þ##Ã$µ­ŽÐbœ¡z,â–·¬÷Iu PµVF´«Œ¾T(ú‘,Å  ¸³÷¬QÁÓ?ä“!UµÚË…=&«jìô™êqÃ=M‰Å[…]’HAÊè YA¢sA³£Š°‰Š’gIXŠ,ÂM©Pi®îþeG"Ü[$ìD6dÉœ>®=Sî5ZH:ócÄ#ÞÍWazcƒÔÎ`äHè²q#kÿï ©@úß@”ürB§T|:+V}ÒR½CËj5Êаæ07ú©5Ö3Ú‘ ôx/×ão kÅ–Pë)§h]&%àZ/½§ôgøºáQPº‰žöÊÕf¤Wñh2× R§^ ðo/k:½€…B³T i4Ì&Ò++cfð&J@¡Hû×Õ–nV7´Df*Kfn)‰0 ×ZØTKÎÝí'¬¤²f©‘ªõÍÞÒÕÊTþR§"j(™·Š‘¢ °§åK»ƒ1`œu¬.3R®Â%Þ·S†²-XXã9»’¢ßræóß‘ÞìÈý1A,ã/ 2M^M%MbÑ9†Ñ˜–ú\¦s>úDå%VóTýeq‘²é+fúç©ÖÎ󚢋3V‚åþ¨~ÀŠ Uó0‘ªË% H®Ñƒ^HW¨öì0Ž$$üÀ{ U”ž­ÊðËG˜=gJ˜«ö}ÝG›YiJ™Ûz ÷åO¯™~Á=ƒåÑ93ßœQ‡@ ¶ÕA—þ©#Ø•Ôèi¦ŒWcÅö-1g©å{¶ê³3ÍQNO•úÝ'ž9æöÀu‚ Õo`¤·¬}¦í«jÜ£ÝѤýšÊ.Zí«Ú£ý‰öhϨG¼¸«]­Šo߆ŠêˆoG²Iú¹„¸,Y_ª%0ßúxŽL -Ð9GU-ùÞ–•^*B w8ŠÂáâ²…a©rh¢™gr“îÅ. { /0SX·öqÝ +øÜ pG(«Ä²ÅÑÉU¶Çl 9ËœÊv^¢ð‡íË’(£¯GqÊA0Z ¦ƒnð<•&yaQCý\ofÀˆ•Úy=JÜóÜÄv]»ã¾¿°\¬`níBGRÕRãI ®2}P“pñW C?±I´ÏŽAôŒZcÅÊ`Ïšö7t 4•Tè1dë>ÎèÔ¥Õem*Ýæü Ìí°!ål»ZyÅo¨MÅ^a>jºG^¾bÂþrc€gò #ÌSŠ£=^kbÑB蜟x%yù[Ã<—pl’hÅ(pFs莹T{Ïo>¿æBd`¶sdê~ÆfMm™2›ãC«kMtÑQ/+l¯jk èÚTØOP¡>Ëð®ã!~‰—Ñv¦š§`Po*ÕÊkÑÐÁ°Urâz¥b„/´$nkvU&ITSD£9rb¯ÍF{-ì…t_°fñ–€Yª&xö-Ö1¡F¨€ÂuA[Âqj¢ÖVѪä–X5ÞJäudvyÓ T`ßçu†ÞRÉN o;0Šdü¡¶Ìžõ4UTÕÝ9nÁ6ÆS­²ßïé.d¼˜@|ª,¨³:;&6¹"SõÚ݆ƒA“&Y}%d½£’zÇjøEÎÐù12Vçî ©,Ã><ï£$Ónû‡-mo ]Eª¢»þ¶¥z;6V°6ÊaªB pžæ !¸Ì„¼aBžN©µ-‹©ºøOT+âr  "ezG#Jì•×qCfö& 05Šæ"°4¥×hq„C¿i'=üÐcTÇüZ¢ó@ýqA—ÓF$j/Ðà-ÉÞõUk3†“lh†¶!Tö'É…¾ÅÊ¥’ËæßPûpA‡’,xËìÉÁ¥ŠÎ4Д¨ÉóTÎǶ„P{f™ ôMã®,´©²‘7ži’„Âæ˜U&ùa’+”¢¢r]µIþN¬×Ël6fJíâ*;6l3Óû*®jB›˜¡Ð5Ì ž+)TÈÀãoiÔuˆ.a¤–­ýØÑ!3ðLµ*Tý AtM©“™ ‚ZªeêP©Uê¤ÄÿÃç‹¡¥ÍF¥£Ç®:‚~ÊÎcy»º¥ÐôÿÎ,0oó<ºu•^–vl&¤T/ÍÒäX êócìYÌkiŽƒ6ìiƒOv+Í1>f¿SÚðâxŽKnµ@Ú»äDÅåë^3 ¡+[¦žØðÒ}zò.ÛÆ;s¡šH$&™Ú€Ø :N3Ĥ†EX4ƒèÏÅm®i²ò{I@ÀÓÁ¦j ;4n1*jšky2¤,d†ÍF*åí^€¨/•D¢sÆ#´)) ‰|¢²€PWH9°šÎ–¯“ØO¡DW4mײ†w´³³_…ù°:¯åÚ^¡â¯líåt¿ÙsTÙOtj£Éz´t¾°±LÜeá i¶”„B‡G&Ç‚0[hÀ稈©ùÓ ¨öÓYË«(‘Êéš*»X¸êD—û\¸”þ š{zÁGºàÇb#—6Ñ[utV¶dê´¥S˜Å—4«5›ZMš‚I~(sÍù˜ôΰ=Ø ?,b-«<;j.>ֺ؟iŠ*, ÎTšZòš+¸‰U‹f°ƒg$I—‰³]ìZ2ùÚ“ V})Z©ªÈd3¼ê8ÂTIÊItöƒS *7@„_F«S­Â þ9§³ãT¯]ó5€‘zËÌÆ!Ê棊n)XÒ=žÄ-? ©’6Xº¡<AÛ5±ÈR˜ e‘,ö-ßZ»×Á7ïZ#¨%túoeè8¬&4lF°©}Ùo² :¨d¢v ò:º6&2ýÉØ\ø”ÆÌZÜœ5Ôz:jÕfR½kæ†õ—}莰éC•ÐiêsDùi”šê;PÞõZÙçØ# çoǯžõ¼„'â)õQj¾þý·¨¨jDE%œm6ô±¹?晳QŸÕ™³Î˜}ܩ¥ö’àëè¼’†v:çöŠ„‰‡;ʦÀÃ\=)±ö SÈdå}ýóÚ… ›Àg©N¦– D T'ÓqL‹bmsÌx–ŨJ€º‚2èH˘Äl‡ß9*†YMÇŒÆm®w4@ËyD‘ÜÀDî¨u–"fÃ$²¤`á34ŒÏ‘LuS9:8Ç0âM‘\І²C7NœLÓS‘¤‰«ç3#5i†ë®:¶ñôS5@ôÊŠ):ÕñZAèŽØy—%[b*Íõ,‹*Yá'L¥i\4\¼N\TõçNQ´a—ú½b‚•zøñŽgÒmÌÔ  £¶LçÉ›8E$T—•ˆi5 è(:˜áB„GîȽÎÙF%N=†—BÇïòjŸõ´ù%3ÅHšøI|ÛÐTYJ&·”Ln«èìMÛ @‹Ð޶)ÔH|ñж{‰X;„N:dnd6Ûqá…Åèßæõ+t,Ñ0t *äÃg|d㟕Þe‘˜J‰]BÍ=²>ø*n´hÝ|¦o½2ûgtŽø“5CÒ’~ƒ›ªà2(¾Éøx~Í»p)Ý^Kÿ"yÚS ¨Õõä=…"D…î·ÔɹØl˜M6^ùÚÕ†B@–2O­:õ¾ÄnÖ*ö¤×Ôv´NÌæG+>K|6š%Ž$~>œ6ðá´ÁqpY‡[„!i5ÏDªô½ò{tŽo”cüx,fòþr~¨ºÉ† 1íãÅ!=š4Û£ý‘§’í]á4XʤÁ6ôz*ÕDØ!^!uÞµåB„ žÜ«nßí6¾[2ªŽf8Ç‘§–Ž<õ2µsF˜NË-ÓÂ%jóF9 (ˆSdå'•5;GtÐÂ,wÇÏnâG1“rÏ …b[ࢄHg1oT5õ. “ 3ŸÚNv‹KѬ³ÊðZf¥Ü ¡Ì qù€…NÍht#·‚üDÚɰ‚ë¦aÔ$£q”q6TÅ&ZŽò¿MdˆyŠ÷+áã‹ –wyšƒiê÷‚t…všÆÒäW«0™`äE0’ÌÜ=Á´à[¾ÅÖQäèꄎêDŒÀW%¼ÖW>ÊüÈVöW…ûÊ@j˜³CÓ Zs¬B °[f#€…šCþpŒ„ȸHeîâ”A9®¬F:~#QmŸd"‰S%˜ßQnÕ=™PÞi8çUöT FÀÖtÜ88XÆU…f©%ÒÉ¥£y2ÈkKç:ƒºÏwÈ%|øÌŽ_tTeHÐgj Úézå;D.«(µšArë®#ÍDÆzN»Ž´•Á8H´mªê8n–K´mè7WÒŽ´cPµÝQ´Jã¶WiµVpiE pì#ì ÌÈë|‹¶=°(ª2«ß1ú´Â(*5Ô»G¸mJû˵QBóO@SÙþÀ7¤sMI·ù¡x‚ÇX’Xm%­³ª*šŸPfÒ#ðìT;.¨ýç•jk³¥Šb_ÐÆësÔ]ËîóœüË«:µ¨Ó¶ÚŽæÒ@r錱X±f±lŠJUX;GÜ[±!æÌ–gíØ|aKõŠ­gÖ}ĽaSÖa,r=™Ø†q1ó.*–VÆ×q¥"eÖ¾Ç×m¼Ö§Î¦4P´\v¤èÝ2 ¹Î|È´¹éqPÝåGÃmS‰a°WQ€¸/ØQÂŒM?4#APlí.å;úêÕ3ªJ.l”èöÂ}ŸÑWšðlže%qþD§½æ-~s³êäÍ´ŸÌfF'YÅïŠÜçU×Er'TML!qvÅsB&ö“©mlï8!“‘gjñµ’ƒØ¨¥:k($GXÈlÄF¤yQÆô}¦e­‹#`²ëøo]ҙޟ߈±]O±=lYçT¤ 3áD$fw3 QŒ¨†(ËW'cã$&xS‰—§PºÜg2ö=´óRr¶¥í¼Î2Ëî(VVûéñ^ [l”ÞkMSómNu¤´˜ÐG¥`/ñ0°vì¨Ùû‹vz´FwA}?6ßÜåõFì–ú¸Š& åÚ™uçÂâ‰X®LJûÊh[¥XÇBµÊAj_§²”2^{”.èoõ ]0¼’õ‡ÜE&LÜq‡VùñNý@õ#£±à‹0JäóÁò…6ôÆýLë*ÐY¥•ëX“õtÒ‚˜ý9˜i&,b)OÉ bòŸ=Ž­êKÚCÈ .Zb]¦w€2X›¬áè<ŽAñe_4ä[í"1¸h¿u™q¤ëܶÚ\ƒ3Ãb„#åû@½ê×%?˜dì³Í–²Š¨„ƒIŠ)$ÑBg–ºFkÃT¡ÚŠEÌò#m{iIkµÏöí³E¯¡™É_bM¤lX-ûf:âC!ƒ:¤kÒžænU b†# Õõ©jå_‘¯ë©h›§JU2¿BµF¦ÀbêԨ΀Hj–ÌCùG96Ø3]¡@żœÉË{ƒBk.ª·©âú'ð^ßšòÆã¨ÆW‹Rñè(1ÉÛDnj…k>BOŽ)ßwì]ò(›bå¦"»»D¬žâ7˜“r¤Ã)¸&&Y(ÛߡӻÉÈûïëÏVßbKصxæaû5;ºʦH=Ϻ®iséá?6k2ëØQ­×ôT¨­ÿŠÎ_šyÊ7®Œ xô„~™isy¢l“¼ÕÏØ†¦õÒl˜Õmøx²j÷v>ç?—oBž{½§`Ú{F‹EçióÐP8P;vؘù*ˆÀŸÒ§;ª'*æÙQîö\ÛceíÝÞƒí8ÛÁvTd&E¡·9ÛQ}“íxO5_¡Ú ÑÍÇ‹g´&¾nI‡¬­ó°å"1`>­ÁÑp£±×·-¸eØy[eÈKqí5v‡Í)ÒSé*£*z6ÒawZ1–õ7Z'“±.4«J«0í®óÂUC–ùDõ –—X`6¤)-Ñ”J dâBÀ‚l# ç:qØ2e8 _®{|»:àëé-TEO{&Ü¥)ò¤=Ð.®=W«§-# ÛÄàÆP XCQU®ÅÈlf_ƒ¨”­bÇ»Êâì@Y¬1\™*lòú:H¡õ—A¶Å*jK·/.¤³ú›sŸÑê±}Ï[a×MN-iRnxY}¥Õ)š‡8;èÇÿé„~c×R¸‡­ `Úi(|û‡Åù ¥½.ÚwY)¬`­greCÙ«3½¾ªBCãð7?vðÌ­MMOí™s„Âê߀—Í„¬ZǶ ¹ÚñˆµéB«ÉÚP#J{çò›õ¶¼—fdܱØí¨æ_Þjgfü­×t Q!¦¿ªU"×:T;éAx¤VÙºU}‘ÌS¥o T•hç æpxKûyiQ±öó>´3©¢grÂ1²w8@òXQ‰%SéKfÖ6LDÕ 22Võ–aHvŽìPæÌ¸ƒY€©¶‰¬8–ðO5ª$º¼:R™qzå÷t8ïZ¶‚££°fßÀ÷pòÂ!ãh¿ÓìSVŸÞõÛ‚·±n²®½gÑΚY´j×,Ú1¸ëét—H±È€­Ù96W†Á¦PN©ƒWNhz~ŽVTÜ þ±@Û´C§ä¹-lÍŒž±\ú`ŠäŒµƒd}éƒÈˆÛµàxŠ©+U8 ö?‹þ‚*ð=ÜP:5ˆ(•¢AXsáÜÑ÷І@§À®²SJP4Æ6—Åð‘'u>bG~è›zÄjWâ¥Më¨ß*&Ü'¨Ë> ëØ‡NºùL7ÊÃ0#M΋Ž+.úèX–”iuNÓ0Á à&Vçš™/Ä›8ÏyOYZ/Cè©n$ æxñTÈŽP˜ ²<£Â8')š4M¿¦\eäÊ$‰8Ù@]¤]ˆÙ[ZçÂɯ”Fà~…JZhð` QzÚü6à´ÈÛ«r³_te¡o¾ÊÙ3栴ɘŠTœ«jQÞQ»%HÙTåH ÑʈÔ^t`m¢:;…ö·ÚÊ£ÏJ¦¨å ¯^uZwÄ"wú+ªÐ@‰ÆRšEEB;˜&4ˆ(ä,v̾Fo3¢­µb6š–‡ê5]κ\þxîÚ3‡1¥—œnùŠu5»ÅA &xÞØ#¼hp©y,öüÐyõ¦j:c‡ŽTæØ¼Ã™">ÓIá¼GžHW£K=ìúD‘Cª«0m¾ÊR÷#¨"—™áNKšÖ@qÆ«åRƒžr†ø\ŸBÅÄõ¾i)ªžiøÕÎÔ7jï £BcÎ3Á€A— Û*]Aö¼!ã\ûÀÈÝžb:>“Æ]4b=¥±;¦œ2C"Í*"LW ¾¾DÆ<–Fšßm[¬a%¾”¥oð“ê{Äàöf^ض³%¾u‹'‡³g†tß‘7µ2Ÿ¯vÉ3Qe IÏ@m<_rZÈÕRÆò ¢b´P±Ä² ?ãZ†"µ @>D«Óî=!h©7$K¸£Ìc\‰NxŽlijŠÅQ¸—‰*ÖÖ‰D¿]þ‡(°"íÈ )m[!ðGeÄÙ|ù:fYCÏsûœú­š ÏüÌž@jj¨3>oyPY˜¼S°ìÛFâ¢8z,3ˆHñ[óÜ™Á.à ®~ô¸¬ÂíòÇuzØ~×9õ´‚‰…!ª,±ºö”©¸Ihª£jQ˜Ù§ŸÕ´¬n\ÕÍ;n’Má¨sE0dg/»@ì_M'Á9Z\ì@Ó;…6 ¦^]"k¸)TPªÐßj´±dnüÊŸS’¿®sx>s1 $âì3â R7h1_u<º¡cr ÊTb0&ÈžFGßU"ŽæBêNõ—NoƒfÙ³7 7ž Gl昩~Šd“(b»*üj*,ŽŸ ÔRÇØD¸˜ F"ô¯ó#±–Ò*„]®{ÿ:|5²±ÙphÇS úÙ„@Jò4u02g¦Ë-ʲi–C8–+ÇçKÕFÙkÚ(;o«½‰ó‹ AC¼ici­µtt‡c“Ù}`ØïPlXíêÇ#H˜XãVÇpÖ;ŒêÉ0¬Ö¥—a0k¡ÞκvT'>12ÏI?½S¯/µ¯SïãNdkú×)¼¤Ä.•(¾C»:Uû±Uì§bR–ò=ª°ô÷Š€ß.08¼ÆŒŸ{¥ð§¯»€íL$×Óþw/×ú×6½,†,¡òá–CúAUêGA|92踥:£Gá “þ?iYýWÒž+/YÆëMŽ‚ž‘ßSˆ?ÿ3‰@‡Àk2¥aÄYœíCH¬V<ïâ§]ÁÙ‘êl‘þ¤–[Úü<\£#É#‡üò3Œgç¬Nn¿ÁHÒu¦µþûa•à endstream endobj 4 0 obj 11895 endobj 1 0 obj << /Type /Page /Parent 10 0 R /Resources 3 0 R /Contents 2 0 R /MediaBox [0 0 612 792] >> endobj 3 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 5 0 R >> /Font << /F4.0 9 0 R /F2.0 7 0 R /F1.0 6 0 R /F3.0 8 0 R >> >> endobj 11 0 obj << /Length 12 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream xÚ}’OHQÇ¿³%B¬e&RðN¶Wí`ŒÝõoʶ¬k¦²Î¾ÙÞÌn%Bˆ.AÖ1ºXÑI:†‚b]"è(‚—í73»îˆÚƒ7ï3¿ÿ¿ß{@](mšz€yÃÉþ(»;>Áê7P‡A+­Xf$‘v™lqdí}…䜛áãõÿ] ‚U€Æ¬ÇמöxÀáû¶iO:¬äÒb“¸M¤’1âWÄg³>žöq†[ ñ2ñMÅ'"()Y'æ±ld4ƒä—‰»2–’'&ßÀSg^™öÐ}8õ¹&›°€åwÀ¥Öš,Ô \V:k²Ý¤;©iÝR;;\‘Œu?ÊåÝV þ°ÿ¼\þûº\ÞC9¾u¥(J•IÒÀëÃ]ýÜàBS˜s_ QP5ûFz¼Úë׋Gõ%«t{3qW°D÷0vz ¼ü \}\ø$€Ôu¡ºmþÀÍ+˜…–ÍÙ¬C–;XØ9:Y„^g±BÞ,Ú\°ACioci]g®©Å·¸(ñL;òz±Úï9ÚAnŒŽÐIó ¨Üê­°4“I÷ÐÝ x#Ã{zwA¼¨j}ƒÎ…Ðþ¤Š¾Q¥óš=˜ò8Ðmèñá Ã(Äo{1±cÚÑd5¾Ué­ÊgÒ·t¶üÆlaȱi"ßÐ\.5æ±”šËÅâ^Å8tph0èk€!‰~D† TÒhd¡‘”»6‚ØÂì±–:>f¤ß&Ÿm×çŠäíxÝA4Ž…¶ƒLþ&ÿ–·ä%ù­ük±¥ªiÄ”¦¬?ûCqÌÕ¸m¥&/¾By#¤Õ‘%iþ 'ËW©¯:ÕXl©Errð'ñ=_—Ü—)Œi7Ò¬›©äê,úF|ÙNšٮͯ6×rm^™Ü ®ÍšUáHWü «Ãÿ5;¿?ÿͰh endstream endobj 12 0 obj 706 endobj 5 0 obj [ /ICCBased 11 0 R ] endobj 14 0 obj << /Length 16 0 R /Filter /FlateDecode >> stream xÚÍ]]sÇ•}ï_1¥ËUZ¸¿?R*?ıž²vÖÑÖ>8®EP$W$ÀP¤>¼»ÿ} úöLß>À€$$©²œ€ž™îûqî¹çþ£ûîÒýÿfÚJébçb˜/¥ê‚Ϻ=ëþ«[tßýðQu§;¹þïÇÓþ£r¦MZÿG¬ÿ_ú×.É.È8KýèîôºûãÛÎ=|pó·×ÝwoÌLvª{û¾{ù—o»·ÿ½¾&ÖELJ¿óò–.<|ֺͅå]u%Ú|åtsEl®(£ò¥«êC*l󲫯D³¹ò·—ߊÑ%-ó‡þ³ú6~såOõ• ×WÄàV7Wúǵù¡o«KFy°:£W|uå´¾âòÍ^œÕ—R~ªÕ‡„ÕùŽ>|¬¸ÏÏõþººäè-}¬^Ÿ³Ý“£ï›ÕWBÞ­\‰ </õæÊÛúŠ1å9ŒßŸã¯ûñm&±ó(tÕQÐÎÏdXý©:b뉸¬÷c~l‹zã;³Ù õû¢”;ÒƒïRô®Oê+.ïOÕš…¢÷¶8¯ßœvyï¾ÖûTªêu :ù¥ÎÙæöyïë+´¯Nª}eèèÝ×Oš|¿wÌiZ¨ŽJ~àõ˳´ãØñÚœIÁ¶¶S –£’ïèCõ½CÈûîÕ“áìÔ³tþ!¶U­{5xUmÖ¼íoöm)€GU^ö§³j3DïÁbDÏ;¦ü™ûÕfHV‚”åsvþ¤ÛAIrwì’‘Èæ+‚x¬±ã~_ì0v½ß÷ÉÍt\ÝÈv¿/VV®^.mfåh\2+'vX9öLÈ–²‡¬óÃzÏ̯¿¯\l[S¡\AB;JKߨºbýh"°!ÚômdOªÃ££FŸIx#óáYž_VÛÝÓ€„¾¯>ŒV…ÍfçÖWÕYzÌÂÙ˜!³pŽȇú ÆWÕÛs=Uó·½»gÛÔò7û`üŠ-­ŸƒYÙŸD¾&‰»f'% ?3°}!(`[¹ŽÙ¼êå¢Ú nÈH’…ïÁn6³aI£Ý :•ÉF,IŠK)AÞ!”ÔM&Á/ô @%É«|b&E;È'¥6¯D0C ´„VJ«|k¿³KV¨Ïkl*È&”†þ·OÅ($dßhh¾;«Ÿ–•Ðfg3 £²”Õ9€²xÊxÓvõìEûSL.™‡ÐÀÜ åh…Üu;Ú!lË9zÂ7uŒ¬¼A¦AyKOÿ”]K%þ©žU °›­1dÝÕÚ܈æ{ ÁÃ/L%gâé8E¯ˆU¼Õ¬Oz{:§¸CYO2‘Í ìVŠ nøf•èqÑùœóHBnÌÄò=  ówœ í3âÀq… ¦˜bŠG¼²þ–û,Ú­þ4|s¢ýæ,½¹ÅÍé1}cC ¼¡¸oÚd£ÏN.ErË9 <ù‘ïꪲÕg¹´&C|Ê`¬Ôü±U,a(ôáNËRX{Ã=G‰©&Ç(ÃsÐæƒZgdŽö6Cž|„¡žBé9W†<‘µ¿`¹±×¢½lŒm;žp€éå[ýÊÃ6S;Ù¡F‹ÀÐèLÉsëxM Þ^"WÿžY:p—@WJØöž‡m„ýÞ²k‰ðŒÚá¸^Ç—»Úe+º/öcÊ@¿VÒÄëÚa«RM¿ÅBMoÿký¨úØLÁEè°Ì›Ý˜Ñù Ÿ³5š CÏV×#ø{§ß9‡®çºåzDÓÁ8d¦Êöºã®G´Aq=¯¡ë©îT˜ÝÝÏ9t=וA¶ð¼׳€®§>ÏŽ~ç¯Ðõ\B×ó{e½DkóÐT×ó[µ«üÀT#×ó¸ÁÜHq=KèzN[®G2HËõtÐõ,¸ëÀÀ}]\ÏŸª]•ܘ°Ór=wØõœ°è‘~é7ìz~Å®ç¦Ú ×s‚]Ï-r=‚;…陼¯ ×β¦aàzêðJø²T±a—Øë"—j|»Ôb!îjk\L{ÅFüv„¼Õ®ÈQûù¨Ãã§iִͧÛoŠ)~³›æ7E9!—0e»†~ó¤òåx|)[ýæëjÖ³ñ¦l—ÐoÖ©¡q(])çâúÍ?W{ßÂçfás³”^îô›ó›ß·ü¦hÙQý™‡ÏÍ“õzýfíMŠß|_íªâ7ßÔí úÍÛjW¸¯KÊöúÍwÕ®ŠÐhEh÷L Œ;‹ßüúÍߎj3°CûÙFqH8Ëy?‹ý Ý^¶Q<=§@pÎ)ÞAÛxò8ë´çκ…9ÅÚÆ{g-`N1‡pÖoÐ6þ sŠ gáœâ ÚÆgýsŠ_¡mœC8 çÓlãÎ:‡9EmãkgÍaNqmã;gÝÜâÚÆ?C8ë æŸ œumãÎ)¾?BHiŒ0Q‡)m˜Ùþ[½˜P™˜Vø¥ðùÔ–œ‰ô ¥VueºLÏxYòQ ¥Ó¬ÿâ-+{ÀX[¤ÍT<½B•±KÄ̽«¾Jwà+§Š;І¡b©ë Ðüó••£5OÛÜ1öŽÑ8ú‘² rÔ‚U=j1¨ÓTjº?e=> vXr¬ØôQ:DwvÊ€¯s: ½÷°êíPí½t)3æiôôè*Æ·D½-~H¯¡™`z˺‚d„æzqŒ2uJ3·®¡o5!µ…>[œ.7Äâû«gAOY\±"/WtžC†­C¢¿¯ûKQWF‚Ï1\´H]‹“e X÷°;Šöôœ·PËÈÆ÷›­û#3/y?0N 4I«C/š „%úf½\µ^ KÖŠ7ÌK´ˆbDNjEzâ‹ù‘ȋΘ­´â±rÀ¸>J. ú.ñ¹€n, €\oLÉ‹Xr7gG…Ü¡›‹P%Ã[H®Ê¾ñœ5øS ̧3& aZob½Õ(9l ¨•ßn¶ì,Á ùåâÍåÕÙ#Ö'öu4^ÎúÇØZœ@†ü{ÆÍCº#Ö¢FŽ€zê Q+¦«Øá€Ÿ­N­“šõî?½Ë"<¼7ñðhægÛð³í+cì,¤‰ûjªî¶ø`±Ÿî¶ø`±§î £.QÔZJíz'ìöÓ¨òÓ"©2ßlƘýÐ7ç°’ý%3,¾Wª å:<ëÞ2õ®²æLÆÒ1]ÞsA”^EDùZ÷¼:‹:yu°¾9O>`uN±çÇÐZy{µJ†ëøU´ÍÞgö{W‚MENîâ÷§”õ‡‚ߣø§7l5 Nq°8±+˜!‚7Ô p¦"jL°!\¡/+áÖ‹£tà†ÞÌ×oSlMgGzÉÏ䤥=Ò‰–[qHê‡NÙU£õA tlñD¢Ý¬Ø©`¡ µW&Xh(]¤I-eÉäL£…@T-Ìå8ø¬}í¦HŒúïÏ…}·Ð7…N!™Gò"n"{‡…¶:ØÌZ®}Èä´+Ì MO·´¨³ß`Q—g ‡Í¥^Tã9ˆu?#À¢¼‡…ZÆ€X«¨Ã\1uÞD‘àª;W’DQKRHË éT°ªË8 •­E•”D[Jj$l¦¤UX6Æ K/i¬·¦OKZ¡x0œTEÚªáqÒ!=pß…½Ãèÿ%‚hhK¤pøÒ¾“z£ã8aqGïWqÒ® Y“z¢k䧨 £ê#Õ:zÀ æ¹â)’‰[2CšÆ&{šjÔVHé× p]§eF»«,€ÔPL'Ø ¸‚·ÖQÄOf]ÞÁAæ;+~ôÝBµKµ• À„£YRrxq„2nŸ>gØ+o91¡~±¼¿»ÙÔ¼>ï×°×îÅí² rÂOYmP².N`5âºvH)eh O‚V ¤(@ÈG±v7¾©CBcÐã)M¹ËÅ [z†HÏX‹B+ë.±„oý‘½U…êÑÎ$$÷SJš¼[Ô¿D¡é0 O[è–4_Õ∰Th 9ƒÊ".DÀg¦–„Âéhâ¨i*±" 2Rw;ƒ¸”ÁMíÖä‚qiPXüUÅãJ³Ø$gQþ I³p“¤,âe8ò`¹•öYc” Áä×X|à  ç`¢%¿ö¸*’Øa zÖ¯²ý¢EÛ—>¦„ô(øG+·Aó†ëÛ‰æÁ*„pE :”ÙMN 5g "9n¡5\2"TŠºá×’GRë©wÐfcFeQU÷Ûe‚Ò߯ü)ÙÉk¦´ŽRgK@Á+9TDª¯ƒ†æ3Inäæ ºS¶K$ÀÐïŸ{óxÌBU½ –#‚ƪ+Pì®@ß•n¥›vVwÆå³càj‹6ä›åBa'ܹ¦Vœµ áþÝ wPƒ¬é¥É1ÜÖÃ`rŬ%´US]e)Dó3åš[K@ÞN‘›yN©$üÌÛ‰âŸû–ñ8Ø\—ñFÈ#bàh‹IBì›cÔjtªmýĶ—‘þ~”’àÃWªÑÒvßÀ“^3ñ%÷‹9¦Üri0nGQ p  0dK…EKþ•±h4ut €]X"‰Åœö¹VˆÀ`è–æLïÖÒʹ³tZ‚ˆ«”y.΀þ+¸Oå‰)mH70ŒÇÿ”ªë£ ]#ãÌ“ÁB¬ÅgŠZU §Ót‹†Ï4Èñ1í{–&$fk”‘ ¡´äËŒ9”ˆ+•߸û‚ðaðhé¤pœÆ9”»: §"~¿dQtBõ^£ÜÞ{Däö4MùÖ„ ~A!ÙÀ ³Úð‚ƒUc5ÿÃ:1›Ö εœÇ{æŒR-Lê¸C…¬×3KOíÖ¡B,¦ÜøšA~0²†T!~ºo!¡]rvðu…x_sѱºóiÊl¦º¡2ã ‘îØHµñA;0ÓÌ=ìw¶A¶ÄÝÿv&’™ùP/mg9g Jñ=G›úTƒà#…2ÂàóZ<§¹nâѨQ@¥!¶¦­3ÚEÄG"Å¢Û˜À#;×@¢­¡é gðŒ0ƒ_FÖð*uo—ld³#8wˆ9s,ÄýŠsæ­ žÞ,ë)Ó_ë+ã±3Ãb Y²ß™OTp„Ÿ¡þ㪧AEƒ OÑæb ãdEB/ê÷—ŠØðâS£è™=oý”ÖÀQ}. ®`¥ðŒ#yVJ‰VbTêÖwŒÊ“o3 ižRpê¦aµ|ô”ƒËÐZ+ VUN÷Ä>­§7‰[gÎOl_@û^WÈa\Á¹¢£AÕ¨ÁT(ô!ÈxSiYP¢ëDhÑ‹#d8F¹ ïdc‚›>ÃQz*Àãâ¦Å ®ïyž:ô{³¾Ý3=Y¿b±Qu`“fàrÁl Tkpf¤J6¤#¡‰VÅÛu­Ññ¢™Ùþü%‡}Çí)@HKå ç5ÿ\û+8RžYçæÚÄÚj*4T« we l=è]–…Ûû™Z1|Q§õ €cª¢ X5r÷À„^W=7[î]<5¤¼Œ^+÷Z×äô»§ßâ)éw7L¿H¿?BÎršLÌ3-!ë’\ø¼A”fAÓ +ÞzO¨R¶ ã‘2N Û¸™ñ ˜™"#ÃË:q³Š§Iz b#5î$u°‡È“°'í—dNÚ)Cìy (î"ZTÛˆM™Í)­ëÜ„ÐÄc 3VæècŸ³|$™«ì,è­Û†#ñ9â%ìàÁŠÃ“Ó˜¶,ZÀÛ,`u0ZyS·EïùòƘ*ÌÆÃ‰F8oèζFc-ÍnbŸqë¶h£pjl`\èU+ñÐý6ÕêŽaÍú ¤Ç²7˜¼™çTÕv³©G‰}ßÝ_Nn/ï¾c‰)Îl¿Ä(ö{£¢Ð[VÓºon+d:«ÖK®mFiÿ-L$–WLz•°œì®†Š•3WzÐH1§R.ÙäĤ!SUaŒŽÀ™ñ€«©^¢€|>"J,¥2ƒÚ†©¹Nb6k€±p½#µIËòåâË=ÐëóôÎß1MR­ìŽÿÀˆ/©ÐÔ2››Ù_19&´¾èh<‹ÿ26a‚^29¤ëW$¯yó=ÙûïšèˆºXçp‹¾ ÈhÞ^w ¨V%qÿ•ɼ‚…"âqÞðU‘në"’1òR‡U%áç“Ê-Ù2F]-ÊæÜ6*K”oÞ$£ ò£rMÔD<ôÖ@´# Ž9çë–C6gwçªH«PªËǘ„šV¬ãm;ÅOÝ!=Iæ#à&£-ö÷eh—t°^0Peh©Wâmp~® è jQ…H(6 ”?«2¸µµÐ:5:ÀQÁ´»šÐbö¬‡'¤R`¸ ÃE€›Y ‚˜þÏPmõ—Ú5åß™»“ 6÷xµÞ¡ˆÝä¡*Š·ˆQÎû%×ðÁ… ´\‰’õ·| 6Dæ ËàeFuÔ¡íèDôªî2+zYãšELêJ²Í\*Ç!…&% ke„q­¤òXCØÆBPhà¯Ð4m‚í­r7Á8ÿ³° ëìFøf/“ê%ÕŸ“1‚vÒ|ÝŸí¨‹Þ­==WÅB6·H ñýÎ`ZÈègn–‡(@w-.hÖwJ»«"K„i ca3‚‡q±%³³®üHÀ\¨¬e JF&TŽƒMÀÄSyÈ E«qè ú©ÅdßÔ=TÛ45"”‡Ëu@Þ´R2¹Œ’‰ô1BŒ€Æ•DÄÃ-"i7°(Fäù¹ù1g6¨î^‡¼&±(¨0 Ûß(’ø‰Y>¢©ýü‚ZGÑTï$(- 5*ˆhÅÂ]ØdSúøT"‡r ÚÙE²&B[‰ìˆÕˆJdM‘ô™ÕO pT„äIåñ-¬Æs@¤Ú§Qùé¬Õ¥kÝÜ>…µúúÍÓ~}¤*Kà ¼¸pø‡¦lX+ÚëÁMU»+ lžG[]PŠ´¼¿…=J§­Ì·Ù  ¥‚ZqÖŒ“!JM™5$˜ñ;€tˆ8¢›`Ä™=ã ¬*[³ {ÃŒ„¸³`DJšBÛZ}ij=e½zÌÛ­»Û íi-—“AǑŠû¶Ö\…U†"ÔzÂÝ û0x0»®Ã˜.3iâyr»a8aRž¸14i¨¹P…Å«âì^âääî°]iÝ0½Ïü’ún«˜‘ú<ª@… 5 Ö°0LáˆVÁb+)Q—ù„Žw¦ç&K¦ßWÀÄ9§ãÐÙ¯)aV#®%¹‹P®áŒec¨¼h¡tj4 v˜Œ”¬:Øä¨ýhÎñDTê(ªˆ\ûÛg@‘ÍЄø.ÙL¤@…°9gÿ¢娑Vg¬fÜQÀ€úI#ÒT/rƒ@#3QJ˜ –—¢«*¢VØnž¤‚E9(R Ô¢w‰[ô¸ˆˆRÔrÊ!Eò´¼]°„J·uá©Ô¸R•0ιNŒDCë”QHöUeÓ%¯àYØ)`%ÑDXâ2)µPéRÙfÛ¹x0©ù…~¹áu?UpÊaf<]DMîÊS?ÖüXX¢‘ÓU¼a‰î– D¢!†eåiT,í-Ø)î UÝ£^ì"ŸÉÚaä•2Ÿ»±™g/3Œ„²ü\> õ½˜š=¢¨§,™¿ócl7ˆjnÅ)4BµçØ .Z(Nˆ(8^G8Eñ_<į}T Ê'J*ddÖ­‡Í®Í[ƒGikˆtmصa×f¤ðsÃé³Ç9¿Q — X—¨ÌuQ‡´)á&uØÙ{ÛD•fV¼wxŽg.#¡lv© VeV2÷¨Ò·ÂÔ—JÞå3Ÿ”$aŸú˜­!šmå\hÏÐ3¾áŽ3™Šk£©/¬½ T@J#òéb»ý"7 'C·%& ÄhÎbÄŒªüŒ¦øýµyþ÷D!=:8ãôÁ¡É—üEåãª0“ý·ZñäˆaX¨{jÄ0¤¡=1b¨çL‰^ˆ¡¡ÅW¡U¹·IG¤«°žGozêHœ#¬,åáyWÄiX.®ƒ´uâÔ¬)…¦oeÈæ ¬U-Ú¥<;7t‚æ|Œp¶Ó¸¢ÝAiËVpÈ–6Ç æ2`"[™À²X0à"àŽðuT ££’C½aÜ«Âi­‹Ý€ÒÚXŠÈ¢àÑÙ.á”JÔHê=rÀç˜Pµ;I8ý*FH.¢P0J4«ŽOp¯¸4œs?ˆêø¼n™òCgõƒ>ªÃÝÎÊ÷¨!ƒF¿LiT¼ã@‰C’•}즻'‹îÓj¤™™-Yü¨yï'¤ý3Òbü¥v‰Ò¡¨ggø f%XdËî@kG£¾£KѱÆÚŒN¶ªQäœa%ѰºE‡ëªÁÒ‘®*¯×#ä³°ÅL‘§šaÕ’'å]ݾ¡w–àÈ•à—œ0èE½au= *’‘lëLÑ‹î ð¬4p,Na¹W$‹a[ð¤4ë3ϸà懢PBIBIÞrËq.kQ0Ù[¶ˆÄTˆp[(=ÀQjêRúTV¡_[“ð€Æ;Å,?qX¶OÄSìNÀOÐþ@º*åtžý¦=¶rƒ–äZ¾™ªg×ÜÜÁú7Yiáü¢Ñ-h~ט”ŽërtL3k'ö‹cê‚ém%A²é9'™ ‡k4QC*~sXçÅ@º"¶ÑÑà9¡™¨¡PLo(¨)}n MlëÉi„îâê—FŠHœ‰ê×ÖèÀ).D£¾J¯,èžò—Ô!àìKoô²®3„Å·”„ˆ”—×>§Lþp‹˜w`N›h®¨æ˜Šü!CH’ašcÿUF²Ü3;#î&Txà/ɤ/Y*^ÃSŒÅòÞ\ÄR•ÑeWÜÁ04鼡P£vÈ’BÿR»°¢!ôŠC± W#5à(¨2á´Ñža-rP/¨˜Æ-ˆE“'F}ȉ†‰ù2ê0 p:$1}qåxÂp\ÙyÜú &ÉÎCµC.i Á—>&(ÚƒºbU¦}XN›ÒafÍÃL’‡’‡^œ]éFL~mÛê …Æû6pbT<¶ÓU4­…ÙŸ0*ÎÐPQPñØÝíMIjªikâ‰5jZÕ¾Å0²Ù]ûæüµA·6cnéfÌ>;X°>…³iYgG°hŒS R—ü‚S$å°«îä- õâü &Ô ™ra®O¨%Ì úȪdjÑJ Jí¦ABœÃÞJXØNª ¹™'Çh²¥Ò”Ôñ@¦só+~%ÐÛàG‚Œ4§½šÅQÆ'á`9*e”åŠTÞÁ<[×hÌAwÏK.”ÿ4+×Pgš‡ŸeôI@Áú”†ÄF/ ‰¼ùHArì ¿£r ¹©¥°ÃÄÅcnÎb ™ÓjˆmA,%y«!76 O€-¤‡µtnÕ-ØIå?e´Dío¢D4ïÒ­Èä3 êYÁG úÆ $CÒSÔÀÝ<@ 5ß–,¶G’œ‡èlè­Þp#´3Ð:8‡RÛ•ìïD%Ôã\²Ð÷¤¢"µ2ÊÂjØ>¨5좴h‚q1˜ïáÀFÆÌœch—D¬>mˆ19åc"šÊf5¨ü k!ñ²‚Ø˰Ñò!¡È{JLhßYÞ^ž_.N®V3Ïgw_íJ³¤VÊy{íþíúüC± 'lÑPéˆ)Ð"Òa8©)ÈÐÕV sµX4Ž B` 97̃øÃÖ1*´Òo„:†»@<"5?Äâ´ÙŒûž°¸ lA&+î‘|~‚S=Ë—×Ȫ‡€l€¬Mcó¼(ÑÚ> =0Žj°jûÙÊ샅‰G%:Î$ëí×öõ=ÿˆfüÀb'ÖJ×íÍxÂeægGEØ>'5B‚JÂ}%³ùõ ½²7¸'ŽH ÌHXÅÒ *#_ Dw*µü[(€Â¤, QgÓ,B„Ê(õ(D÷©¤zµÂÔ¸Ú[ÎÏô)GK÷Ï=÷ÇMl ;¼™9µþSóÔÕÆRlt¡ÐàÓ³é:ÆÀ“ù-|ç´¡¨T•’îl½ªKΞ~f§n÷„ȳÈyçœw°Wˆ%ÿD¶üÊ”¬B<¢R^úò‡cDƒ!>ü‹˜¶{ö™—ðtÆz—íÒÏpÃØ¤;[œöùSw¹¸¹¿ë@p-ªí6¢â´ô)]üGRŸV1®5ÙöLwE5~â }DŒ«J”$”<˜wh¤ðF5n  º;7,ÛFô„ÒʱœßóžÁ\q9ƒv ƒ£ØyŒ¹­ëã\ékŽ‚•3åb! _/ë×!Xyä ºYæ€Ç‚Æ¢…2H (Ð-ò0÷¦É„ N(ŠÊïÆžÍ¼ê$g~UäÎ^ ÕñòÁ¤ý½7i³½²G±ÆV³tÌfŠ6¸ç™éWO‹¤¤†µ2@)Ïê·èxº„5*èñÊœ¢ ¦4uzðÔNÊãV…V½B+-7¥*ôQÏy53×±?ðz‹XYê9Ï J† ¥)A^ÍeÓë/©»'C?ôµöŠ~¬1|à1u!Íz7ÈßÜ?´•rvk¼s¸ÑV¼‘Êu99gó¯©ÌPÑ'»ò† N)Ž¢Ç\•lPJá¬;•tŒ‰ 8[¶ì ÔJäc¤eòŽë¤(v†dà­®ŒÐb<ÊD‡š)›–…Z"<,8{ (çulåÛ5É—°&É 8Á¡ÁE:­Ñp¶Ù­âåœ@#D¢R‘;þÈüA;xènXf©5´ª$ÙÅ‹ÆäqØÔ%Ç£áEsÆ×Æ úÌ~z[Úül ‹‰9ÏÛe÷F Ë‘¨ˆÊ¸]¥VGTÄUÚ1æÓ}ã|Ž1óòÅÔÔùÁ’r³¤'Rh°{©³Ø:wÓRg1!uî&¦ÎbWêÌ‹eV¢°Ëkhè ì3‘º¢âÜ0Ëc¡"IÑõ}q”Žw7s›©ÇõæÙ²¡×ÇíðJýZSJ·{uUJ'öÓÞ¡1íbï1í]kLû+æG`MN#"k‰Œ Z(,j#šŸìãædMñÀEC?‰0YÔÒS³Y˜œgebkÖ@Ρ÷¬m×F_Ái#í)¨_ kzÖô<œöåÚ§žl3ÓžŠh§ú„¶êš—ÖžêB„ }T‹*bp¬9ï¥ZÁ$×øâk²# Ýhiâ_‹Ó›Áß³°pP<QmD­{¢&šˆZ×BÔ ¤­ElêXìDÔ†¶4³p®UzònaE¼F¶„5v,ÀæÄÒ‹9¯‘z8„ÊX^·H×y˜Q'(N[dfo™›Î?ôu #/‰€”ÉžQSÞ[†üçÔø‚Ë´@zª¬s™HY—P´€é—#afaâ™’åýèbÄñm†?kïfõI»‚º Ρ*|«%€›Rˆµ©”3X¿Å¡ND!«(­-LÊϵ+þ¿û endstream endobj 16 0 obj 9792 endobj 13 0 obj << /Type /Page /Parent 10 0 R /Resources 15 0 R /Contents 14 0 R /MediaBox [0 0 612 792] >> endobj 15 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 5 0 R >> /Font << /F4.0 9 0 R /F1.0 6 0 R /F3.0 8 0 R /F5.0 17 0 R >> >> endobj 19 0 obj << /Length 21 0 R /Filter /FlateDecode >> stream xÚÍ]ÛnÜÈ}ï¯ ü´nß/‹E€Ü ˆ7ÉFA^,di,)fid¯óõáŒØÕœ. G£a²»ÀÚ¦I5›ÝU§Nªþwó׿ßÒÝ­¶RºØ¸Úà¥TMðùW‹æͲùöwª¹xläößÇ‹îVÙj“¶ÿˆíŸÒo›$› c›ºèæâ®ùíYãžoìÿwv×|ûÞ´²QÍÙ§æ›/¿hÎþµ½&¶Åøç¿óÍ9]x¾·ãó…ÇêBý…¦zT’à%Se]_Ѧ¿²zè/‰|É»þÒ¢¾)æ\6Õ%­óM7›+bpÅä1,ÙMôFŸê+ÉÒãÄÎ#óô?M°i0ŽÏi% I5±{!16?V©þž«»úR@“jSýüÔ£s´FêÑ9›'uUMpI›¼´`5x•'õzQ­-ï-z}½wÛ+8ë6Þnâ°íÖTÛM»ÐêX¶œ€[ÎÑ–k—÷s -úV†Í¯&Œ®„wõš—ã-Œ»ÄÉáž~šüÍn«G…ˆ¶¶ÌÏúç/êK*¯ÂvpElHkCY´•Ëc;«íNÌW®o˜u1`3j«‡?hhw\Þq—õË©ÁŒ•È*Wv‡Þèé– ö•IÙðÔÓ`eÞ<ËÚþ[š!fD’ãÜ•Ç]1[A–ì‚™Š<«åçz’|$»]¿VбZxù[žXßíR$»tQ}è‘“Œ6"¯c¾éã¢úˆ‰¶R3Å.ì q°]èܲO¶²{êBãažAÐÀ×Ñ·y¨ÞPIl‚"ûrÉ6„ê‚ñÑ&ßöñë“&^cL•—m· »_ çNì3¦Oµa°v|Á«å³ ”¹[×&ÐXî9³=S‡,¶côm ;ó†¥y›ÉCjÛv^dÂÈÊeßÀŒ¢ ñ&à~û9‡6ºí€æøöhcõ´¾Ú®qˆ]9<òÐÁm Ð„Áq°!ö€†,äê¾6û)ˆ¯÷2«ßmç𰽊-®lXth¦¼yß3„à{ ¶ª¯Jª¨öh¿ëG…ø:ü|΢Œü¶‰±÷Û÷5v°: ¸€÷ËÊ‚Y<© áÛ¾3F(u4u_ŸÑÁ`5x£€Óö.òŸ¿ÃVG³‰‡¿µVµÆm6ÐA[ek½Ý.6þEcè†fº¹\\¬.ÍͲ³2Íêáæêfy~ûþævñÓúçõ&Ôiž-Pó©û³¶û³í¶:­)²Aµ›Žåu¦˜Êf+¹™bçZÛ=ÕOùìg5?£P4™X‡CÚÕøÂ¼ZDxÍéa74·Þ‡wå”Ðræ­w_Y[­²„mV—OÌO(d"A¾Å#8_,$”ˆÕ¬ âYúvÌÜZHÃŒ:±5…jެ÷3¾úA‚轈H4OáÎ,ŒŠí6¤Ù"ƼO¦˜"².§açl[o¶Öeÿ!V˜·ÌŸõºþâ 8X¡ˆ—ÄÁÛâfŒÖ;›Ÿ=Í;ô´jÂCTèh$–×ðyšžW‡åF"oˆ¨a$‰ îHcâ±–Ü,äˆõ‚!*²ZKŒ‚êí,¬E,—# V¯Gtïêp¦a¸QÄd8ѶJó¢¯ÃrœÿûÆdÛM8šÜÞ¡‰(jl¦š™#)­Æ¦O¼ÂÀ´3 ÚÎ_·I‹iß{fH«L«;˜²•ŽÏcŠeLšÆôÃó$Ò_)ÌáîAi†uuGªB'ºPxéǸ¥cÛ*zùfÂË—"N €]êÖ@÷T{f´$ruDñ¾¯0ñê`07ožß10‹¨}•ð?Ì./GƒúÑœbÉ62ãoÈEs˜ëzÄ‘A#'=‚Ÿø Æ^Éûù†aÖ¸LáúF޾ë=ƒ³çV{ŽÎ¸W{‡ °§ŸÃ‘”‘`kNÙáØ«!Ð ±„¹CáPðú‰*ɱ_Ôˆ]‰}Çó<Ñ!¨1¹ÌI©×å/^åRmpø=´#GPñÕ늑Ø^U”úÄдª… y‘*¯_ݡٓgÇ™‘ÙÙ±²âõ„{58qè§ jÛ N¼‚sçÆ/ç‹.Ø&!΀(ÖÃ$¥–©Çß›ñwfгùû[Ø‘Q:c$-|Sý±fH-L Y‚~œ¾Ý%ŠÅ0 Iã Ù. EãHÜr[,Gúš¯3%5]HmÔV´Hj2.þ#ó”ÄOó¤‘Acð> È‹üs_A#÷È'¯ªÏ<e¨åi×TeA¾è\ã‰\Ñòªö8)ì÷ 9”„Îx|š pCu~*ÃF¾(EÖ‹Y¨¢•9¯EÅÝq‰¿EVTÓϪÕªì_~WB”…2½©#þFC^DµÜ9'£¬„Þ*Ò¸ÊÒ8îx` /ªb2±“¡‡B%gàs=Ã$˜ES.Áz O±ø»dhªŽw`bRèTëô¾Â—>ÙÄièÀPÚ>ä|â° ôEzöýY㺠xÊÌ”\×ãâên±\ÿíæ?‹´:ZÙ^Y;íóõƒüu­«ºCÉ?éÙ¿ŸCÙ½ƒ>Âòéî÷çëó9†»Nø ®03~#Mÿ9¸Ya{QÉÿjÔ| Eë9guZnxã=Ç_PxßÏ2¨Ø†ñq ´j¾Ü\®¯?œÿ”Ü0Abœ`°0Þ“Ä­8oÇQêúïY­‰*õû_q­`Á®Ö2 ~ÀªŠš€mŒ˜È•7÷œ·¶} µ»âÄ59]8['!à‘¹êÎüÀÏœžÂ¼g¼5-F®Ž".‰É£¼Nh]yÚ—œ,ðP+T)ìeoV´4L#Õ9«T¡qÚ§BëãÄzØxã•Ó¯Q9ý5.ìXêyNúo|âx¬ÛmÛGª)³¶«S9}0¦lê æaß“}ƒRÙRëð€½ ï¸ºz`ô'4­e†…¾ÕÎNG–Dá’K 4Èhàƒ&hò$*TÆôÊq®¸rÕLXi@)SÉõ1¢3 |º¯×,µãhÖÆ„JkLÚÛ@Ñãu!#1•fø*OÏ EåWýPËX Ó+ÖhÁY 1 `²&hf++Ÿ³, š$Ê%' ŸÚZµ`ã”, 8eÁÏjÕBÄSœ¿±0•!]BˆA¡\ÊYŸžl>m>¸ X2µ0É ö¬ú¯f(áè S&,÷ Mìô±`•zH 4ÿЉ sŽ|Mõ­‹XLsÄ—*¢€PCÀ«õ ÙK%=Ôê„b—Œ¬s­û¸h“¡/ñý¿[Ÿ$(Íöû*Ä6߸”ŒX8îQò2°§P©}¨U_¥þÁt²’í ¥;ÝÉ™¡<â­ªŠŽ§þlìPiœHý3|¸ˆE`ó—i¯¿M5nAÖŸØSP\cQ±¯x›ôäwwèu«VO#ÓùRÀp‚φ»6¸ò±M“F-^S\š0A±Wwp7¯¾R1(¢%RNh…ÑÚ"EtQ²°¢hÀ–üe5Ðn–“FV¡Ödóì`ÆŠ™ ›EÑß@¼Ïß©ô!Y®¾ÔUF°†ÚS0p ›ž±$‚UF;l¦#ª¦g {AuÕMç´õ¤&D1Á&”ݽh]¦g4Z9)@’A=/hºF$ ŠÙr=àH,Mž«ý=JËhrÿO÷<„*I‰5ÜDCŸ)ÞˆTÙÚ¬ÊgÙvNiZu0ëi† )lìCñý²ò¤…¿ÑÝBõõ.ücî”ÚL¨þz³]£ll»}³š'V~½ÝÀ¼ï¶²8h¼\ö%XÙWóbÙ×vüäŠí„@s‘£^ âžÿD:t ­:äºÛ–Å_5HØàFe¡¯;ƒä†AÚTaIšÊÄ®¥‘ Ó1l«¾²'@Wž ¨¼”—­YaA»¨t—LâçWê5TÔú€”±žWâza,pf¬EÁCob@ Ö OJ_Óz1D+‰#Z1•œlÉ6…œsÒ–"IPÐ<‚Z) ŸXJ‘®Ï™³7æE-®`òy1üÄcpiqʶLU¤Ëá¹T‡*õjퟘ¹äYytIJÖ?³Kô…¬§ÊІúÀ¦rF˜:{å|kãÄvk$ ®S2¡Ž†£ñ:Ô1Ä  –î¸ÌM‘„èêš©dd" £a×yƒjq ´Ã†ì0oD1&µ[oä æ&"q†u¨"Îz¤k±$Fxâ>ÇÂbR”+i&º¡ÕðX»…êÅ<1¬êÎ ð‡§WÆ‚Á££ƒ‘úS a/k“`†.Á ]bºbÚCs|qÁô® FfÆ“ÿaW…ôo32¸8ÉÁkxJ’¤#g¨äo¤J5«Ž`×¹dy>$¾Ì}&Ø^W¢ê3 +‚4,*œ×—j½—DÉŠ›SxXk)˜Ñ¼;ø£yùà&GtH,d«0'n†ëÝsç0/ý«ÒÖ§Ö‡m%Žá¡nP›GnE'¤·SWw±Ê»ñ2ùÞì%ßßlÅlÒ}›†fê°3S¯9kuëüÄŽ — Ôàó®2&öQFÛúœ:o*µE‰dë ­}„jmÏéÒÖdÉ[o&ØíÝj‰ÿLªòˆƒÕ´N!­«£âôk~’Æ8Èšx‰¤žÜÏs”Îc_k [~žD Hc’$Z$Ôù#ÑPlÇÜÌP)˜\«¶)Úe“wþ©ÕŒrÓ)R·qª9RýyF§Õ¤*Ûi#óÌPžt\]zÐt½eÈws¼`›æ›ÞqPv{þyñ›=3pâ¤)b8d„ëÇ9ÆÖímàò˜íæ}ò–¥} ÓVQÖUõk¯¡’µúz‰ö§„&ƒl&š‡hXÝdÊ’—sÿ¢A£³±Œ®N LéE»vQn¦ÎÒ–^$ì‹x`ïJT%@EKà“sýç7Œ÷W@åhMòÞ°!ÁƒÆTŽ|yÓO I|ÀR‰èQ[ˆDÑ2ß0Ö¡ƒ?ƒ‰‚ËÕH[“aIb]ãvaÚi» :i3ݳk†ÄñQ鱑m\ç¶*y^ yîìuu1rPÈhƒWU&EÅ:Ò-K £q«/úÌïjQb‚‚$¦|dfNDzŽåÄ$–ø,¤è;ØÛ‰‰J&t;d‹2 yæ”ã—x‚)-,f–,u;bhʳ4ªN€¾wØYQêxí)Jˆ‚¼V‚xZŽ×ü,'ØÃ9h ðuõ °¢1송;}Ÿlƒš–l-Ó"DzWÖVÅÅÞ}ò\@ô¨ò'Tª“dV‘²ÒîÂÜó.°#däñïyQªQRÞêGv »&7YlFš, Þd‘w¼òækK%0ó^EÕ5¢7Ò)ÂnSJCjh¶3ušx>Lxè|Äÿƒ{{›«“Ô^ðˆšbï“ë9ö®F&&ÅÞ§M×[j×y ¢ìH–¼Ø×òÝ–²Ú{8mb_°|»úòûÅíù×Y!÷­óex§9j_ÈÜì ™E2?ÂÃà®W,¿]˜dæ"‹:)pSÙÜS–dåh·Ù9<–ʆšg;zÞ%o£à—p”Wd;¦à¢†wã…kEÅÆÏdGGcyàAÕܧM¾oêý☧å-Ž Å^7.£7Í¡×ê´@ é/êÉG 2¢Ä­—Ï Ö4ö®ð0âÛÍNбý»†9w®j·¥Q¨¥¼F¶€ÑHo“ûòŠ·jšübâÖ—Ûz;©HAওwHDƤ,Uô,ÞfÙ„Z©…%ÞPUP´‚·L@áÒHcÞÎÕºe P´b lvb¨µïk¿ ™MjÏúržŸXûe «‰Ð°s«'˜9HG8LG8ªzcŽ%*XÛ ÔÖÂ+Ô+ÈÃíæGb;MžyG'ØÐ„øÓOv"V3` {H訮(QWº@qïµÏU#g û6iÔ(<ÙŠ€’Ǧ<¢}ÓJìœJyÚv»&™çS¬÷ÀÈOÈÿq˜»î\Wµ¬8±@¨¯OŽe Ä[i—Ž ×Mîé:ü:{Ãõé\±€îáP®ø¹´ ÁÓÒ”häp&2KϼæP‘bÑÒ´ i†Æèyвä›ýVsòmF âe›üD rŽŽo`¢pTò@#³ºÖ(+”KÚ·8žzz7z:u°Og0â¨"º7<VõŠÄ ƒ›PGwÉÎ_@GCM<>mQ‹öúùßCVü® è¿"› Ì endstream endobj 21 0 obj 5371 endobj 18 0 obj << /Type /Page /Parent 10 0 R /Resources 20 0 R /Contents 19 0 R /MediaBox [0 0 612 792] >> endobj 20 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 5 0 R >> /Font << /F2.0 7 0 R /F4.0 9 0 R /F6.0 22 0 R /F5.0 17 0 R /F3.0 8 0 R >> >> endobj 24 0 obj << /Length 26 0 R /Filter /FlateDecode >> stream xÚí[äÈq…ßóWðqeX%æ= °¥]Û€YÚ z™™î¹x¦»GsÙÝYøÇ›d3É ~U¬êž °,`Wf;IffDœ8qâoÍŸ›¿5ÚôÿÝ×¶>5>Å] m«›¦{ÝügsÛüî÷tóüCÓŽÿ÷áyÿÓvgl7þGÿßü?›®mbëwÚ´mhžß4ÿücÂøÃý?~¼i~÷½Ùµn~|Ñ|sû›æÇÿ¯©qˆÛùæ]¾pÿÛ¤÷ž¾û±~ uÚS4ÕShvÖ”'Qø$:?ISMX§ý„¿¼ BÜ_¸«ÑNWnê+ã¿ÖWTÿcüþÊÓê7&Øý•ÛêŠmÝþÊÕþŠš®¸éJý46ßí/Õ§§/s=\Q³+nz/®«ùü¨ïë+ÖæÛ©å•¨á‚^.ŽÙ•ýÔýäŽ-›-‹_ñ²1Éì¢Ù²Æe£Ê²yð¼Ô¡åÜoÊ\?µ¶µû9ùûîÿ1ÎÉî—²úæÇqNeˆ^ï«ëêJL‹õR.tzÿÞ_Tt;ýäîm}ÉM‹B\ ZíôsuɳÿÑëúŠ6ÍíËå%e’‡y›nšÞGñÌb§Ý_QÃ;íšgõÄm´óÍ1¿ÒÕSPû+.¿¡«úGÎO?úP_‰n¾ÔìJ[­\ñÚ«ófúÏîwáìRþCõ|g᥆6,váìŠI+/u¼âÛÅžž]é·X«ÆåXÿ¡¨§ÝÕë.z³>»ÞT8øä1/o±ð“Y~¾a«/fUM§ûeË&vŲ¾»_ p䘙m{K9þÛ 'Ìþ¥Íi^‰õǶÓk¾»©O˜47‰‹{EXSÚwÓ‰pÅÇ®:÷ÝÔÇ®õiç{{Ê‹ùí¼Ì.ôÿ#•o¦6LM×맇Ê{úV˜ :vS6 ï>V§«ötÀ¯èîöÃÞ›ÓÝ®=ý½U~ÿÓ~e†ÚÝß¹{à CÂbjNƒöÿ§æóÔî¿O’µÛåUÆåù‹ÞUtÛ.œÌr/ÿJýçuþ3M}%ÿÿ™]QÔ[úMq¯Äc¶Õ Ôt%ÿúAmþ;õ“ÚåßQ³+ÕßÙ¶Ê©£ÎŠ]Òl4Ó"Põ"Àõi¬»¿Ùln¦³û•ÿ°¹õÿ²óz´ý û0úÈj}™–þA| X@.©¹%/ý"[ø÷ՅΨyÄ5[ŠfyîÍ®XÚ>ÚGZòÕ‘8»’}ÔŸë%¯§+¯ê…méï˜ì9~¬—|>EÅÝò©|->À§œ/yÓ ¿è‹/+Û‡ë½S8_SýªW+kÊUÀÃìaõx˜­©ÉÛ|~ÖUç¸Úö@ÖŽþÞò–›D­nãÙúѰLsÀô¡Z ¶ƒ¥èºæÈ¶º«n•ÑšæÜ—¦Îp·ú°»Íóñ…`Ñfܦ^!ÃëQk¦ÁG° ùp© P7Ý Q‰xZô?öÞ¼÷7pýöÝÙÁÈÄæ·íÎÅþbÛØý^ÿõ0“­ÏyvG,a0¹*õ©íüëî¡Û…Åé³åI¯èô©V£räxùD‹®#¿«oääU§öo%?ù|ÉõŸ=n_rêø‘¹Ñ97~ÿ5žšÍÖSóceØò©Y[IgÁH†à0»Uœ.¼¬KžEFlªîuÀ™v2Ê.Qà<¹œõvÑôaò–C».¯7.×û“öûz›|×zBÎßuP«èKº¾í}›®v™«u­ÄºþVx†û‡ÚÕVÍVF2áU*à"&|x·si8S6˜ði5ˆ½ö«á5™ðõ2±à%»¿ÕîÕwrý€¥mT°ó:tmt·èj³òÆhÃ[h²Ãø^|‹ö4ƒ¿Õ¿é¦|ª—è§^Df`óÜDì’¿õUuúÙ*›1»’–0õlEehûVÄ ¼¿’Žö`ÕWW•‹px^y=ŰŸë+––µÏVã¶½:åŒÛ´í•n׿ájÏ6Ü¿)ù½iùfp¦Þóaú¤õñ‘"‚] Ö®6“«/¬‰€lÈv! 6åÁžÕWòî‘¿†»)“½ÎÚ1ÎÐ9‘wöOõ9‘C׸³EH•1äÝ~µ©‡XÔm) ç3ü}Ê‚k(›rZ¨6`ãTzG5é]êoЯq­µatœ‡)iï7çáÍ‘áj¾GËð‚,Ö77ÖÏÞÌn>ø>Z%‡O_¥ /_¥íMÜ™þV±ŒVe頄 ^¾DÛ¿p¿x+¦oÒÚsæáûçœ W+s™ß}œKustÕ  {&¨¯‚ »®¿i6€ú‡}cµr¾#Pÿ‚ú1iÔ‚ØçëÊPÿAýïÔWòä¿óAýë5P<·¿= º?Ë××ýzìS«‡C÷û¹©s]ó~†ËSó@ráŠCÌêÀ~ç0ºF@ù²{s3qOæËƒ>MP·¶SÌðA,lCK>“¥„£ZMtçÑ€[4àÓ•â5'2àÌ}[ð iC€®…´‚Ín©Ì—Ñ{³vºòLdÒȹ°ï–L^kªrÚ-ᇚ\ÖѽÏÁŽð~\Q>‡Ap@¬Ë­„uÃ ŽŒI´CŒÕ÷™VUèhÆpÏ>„×Ä9Z£1²©ìmU¯”L-eÉ“¡ð1e2Üî‚PœËi„Ù!¯¶¨›]cuÔ5î=s³kû?Ÿj_w)g[¬Êø¥³»>óç·Ï^`¯jw7_º»‹ÛϼÆjöƒw¾6ùü°z7¾¡ù³ê¸ófpÄÔï«ùÌ—ƒçYÜyô^—cûï¥Îsi6óÁƒNÛײAÔÒyýDÑûGr^ßU·*Ϋ Ò=ÙkÁHQ•¯9¯wè¼~ª³ ø8Åyý×Ú}.Œáðztx÷G=ŽÃ;ÿ¸*aËòè·œz‡÷4g|æðö3˜@=Øá•éÙoqÕCÞâ´¨;¼‹Wux›Éá•æÒ8m©ƒ¸ÎkX¤á×p)áTfGG¸µÎ«ugÜzrŸm„m¯lþØ"‡ÑÒçÌÒ§Fç•ç uwÑ‚kïe8|‹Çõ2÷1G!,º¨Ùz!œWGŸÏ³hx¢õÚiUÕ3ÚóÅKr’IÜ- Ï„ÃK»1tSαo ÕÄõðFmqx¯ÐáýT­ªÔ::© ­Ñ$PïLÊáçNÀîtî¤D9ö”ÏÄ?‰ÃÒ¬ Øã•Ù‘¼\U]~;‚&]éÒmŽôߢèÖMà¿@"Z óz àˆÑmë¡ÓÅr4—ÃìgƸ Ü…9ÍF§Ù”$‘8iìܬÌcG ']^xo11,ÀSí/Oš4aí•B¬woR­l~QŸ­wVu8¼FÔVÒ™LVU†ªé‘7â$‡­¦æd‡-œ—H.vaQú5wËÈY)äbñ=³Yù©å ’‹Þ-çRe\ ¡LDy°í”L߯’ñ°Ž’©Ök0­6›¢?‰s–{ÿÖÉvHwv͉P LQÐ "Rr¡ßÛjUùœžÞ]ŽËãÚtxÔÛQ]Kêò$,)߆%Ío¿KÊã·aIÕìaIý¼–dº‘ŸÙ91w+Á¤jô|*V IÕà?«‡›à$ŸºséNú@pÒ5ÁI/ NºA8éá¤[„“>"œÔ œôá¤']#œôᤄ“®NºE8I‡ùïü JO¥ßîo~Å‹ü¢Óß!@K=|}ÖL&Ó{èñ î`YÚ§´Ý‡–€–øAƒô†ˆVŶTp’Ó2b1Šð,,*tÀÛT¯%´.¬¸KåõóõÝÄ–_[L«“_ÂNIö§+ŒëuÈ„ØíqJý×þ^‡ç¨ôM ¦ë²ësrùWñµqUuú(Çö¯ßÔùzí!X*ZO±pï¹ ÜMôF›˜-Ï4_‘¯7yZû×zMÄÜ ˜ü*²òƒOÛ䯿©öˆw®W˜¹žV „йû©V¹´mÂs¬°·  ï2>xLØ“ïP0Ïïæ™ ôù´ ûlíß‹T¾ƒ4YÈø¿À<óî®ßhÔ„GC8itü³:œ*a-ÖP9ÀƒR›+NšÖA2„³¥ìל4¤ËW²Í<„Ø;ýCíà–b¶'œ¡ó{?mà ×€æ` N šÃa€:% îŨsðÀ_è\ªµZ!¡.Ÿh‹›ùmÂЉŸ­ÑSr3ëšô@¬¥DçfGyúâx÷š£ªW¢Ü‰þÙJ¾ž ô–Œ¦T„Aظ‰‡&ýäüåÂ#+Ù€{³f.X+Ÿü.ÄÅ‘°%OÿÛ ¦§I7¦šáa$ì¹â¯WJøÔ*òH.]ö)OUm‘iø‰¶ ã«ä8tÀ8.éõí­L‹­/o+3»6n´D§§O”3Íc¥OÔægòc=÷IûÓ'â@IÕ“Šô‰Èc·IyUçUdÖ’0m¤ËÂþ(6åUbK¥Õ÷è÷ˆW¦‰s\âE!ÚR¥‚/ -…þ4NCÁÌ›/¾E€hÛRVÌ“[–"î-ze9¿%2å6APVV‚,{éV¾ƒúÂiòÔN‡Ò)ß¡*m{ð զùڹFÕÞ_ ¥ñ¹?£ÕÆг"A/9|Q=Q½Þn]Cl&UYC¯ÑLŠP½Jåý-€©in­ˆ ¦¹™º\;Ï͉Dú”©¥*Ž }Æšˆ>Õ¤‹¸²ÍÁó_sÁ*f«÷äùmKûxÂSUWÚ„Öí|% ¨8á9¿%á©·_IxŠZÑ<~5á)J.«ÙO埔ðlevWýÖ›Iû¨Îx¶kÙÚjør2ãðyåj5úT’´:]ÔÑÛ° n˜uµ Ô ØñŒÀŽ·”ó¼«a6A,`ÇÌy ÇgCýç-ä<•8z Øqƒ`ÇÖrž«A®Å˜Ââ[?¹—¬ MÁÿ™ÊÐa†Ësïï¯2ô3ZôFж@Ü]D[^a| eç$CuGŠtFT¯Œki›D€¼YžÔ˜5"½5kfhA”G<¬djªƒí°bS“(‡› ×T‰&oaM¹ˆ´ûLôm‚ *6&Óµ°ª¼Çß /æSK‰¦k9‰ƒ8ÈÀª  ìiɦÆðžâë˜×µ”còhŠ™ƒ(b…èaH-Ñ{sP.—60Ù®jò”<ÏÁmŸÎ½½;'·äÖµ µ³-DÄC Ü¥„ÝeÜèAnO\æä$`M9±gk {?¾7cù$†ù}]*4m×ïÄ'”w"R—að{ãú1‹· (ÍÈ ¦òïÐG¡j'³ÂàŸ% a!bÁªê H¬ÀöoŠä€çÌÔÈþ(Q™ÊF_¦º –zý­ÕY\¸/›éÖvÑãéà ·ÁPJÂP—qĽÛ÷âȵÅAÏô”(_Ÿ¨Hæ­`Œ…Ä¢ ª€ŽìäT2¡V¸`Ó“t⧉%¹E¨Þ+›RÌÓFOVH(¬åt±pБL"EWÛR¢]MX«…ØŠð/l&Ó¯x4_ÛoÉä”\º-P§`g½“=ŽÛDÖÊð-"k‹›Y+÷ˆ¬åÑjƒlÚ8Ú¤Á·š?§kw¾Ÿi˜ßbx†Íªá˹Ìï>Î%VgÁf§fº¡õ• éûج BYp(g¦f*°Ùg`¨½PXybU6M­ÅÂ6»ÁRÿ°™"á )ðÀ_R6’•(¥Ÿ±TàÛevíKŸ @̆%µv<©ËÈ3Ü|€þ@¬«wÛÓjP|¸]­@8µ„kŽpj;×áÔv®9©í \s „S[A¸æ§¶€pß‹ºƒÞ+O´„:*È©"©ÃC4fPÛk¡/÷ÏXصò‰½yÔæ z:ä_Šb PnÅd <6¶¡6‡P•lj¨ *TÄ4{![K¨Í¬D»£ô„uÈé4µYh|“bG®pêBm°Ã¢0!ú¾dðI\ ¨=‘ ŠE´eôD*ô­ (1áIO}БPìpzÚËuiïVM=¬·Ó ¼?Ú÷· #?ú$KýU8:.Ù ÞΞ£ó=%ô¾µ4`"Ù±0! fâèˆmã"‚%j©Oˆ—ès ŒnW0Á‘ËoI²¿¯ß¡ŒÕ󚣓Íòá§c× É¼Èº²:î+NZW_EómÈB´ëü9u&,(ÝhµâFŸÉN[U“9¦€áx:;m%vÍ;Ùˆ}”p%(é4èO¾É Ì7ØÔðEßnEî…ZºXl)Sz‚ϼ µ÷°&úz¿Èö÷ŽÝú¢W—êðºƒ÷°Q¨£Œß$Ô±¸ý¡Ž2~“PG=û#BÃpãjU’#Jµ“àæÃÜlør2ó»gn}9ÎO\¾M} €»!î)p¿ × ÷¸Ÿô- gà ¸À½Bîgp¿ wA=Œ·¶a|e=Œa†íV²ü¿‹ï­»˜,C5i¨—ê°z­¦Öµ³-Ö¥jª€XY“–*¹jÑi5î ¢îÆÕ‡”H˜ÉƤ¢e2kìeÍ'ÓØÌ ÷ÀùÀŠ£°Œ5"Ð×i.ÐÈN;,ðªVÛá \Gú”¥¥˜`šƒŠ B¬|Ž5ÙSû6¿Ú¤M\7bè¨^+É\%¸§(ƒ ^Ãð»÷y ›•£Ä_G"·Ñ‘¤qÄÖ=q¿âÕŠJ!Õ0±VqR徚·(Ö*ð·Dë­k§ƒO0Ðt€Ò‘¡ê†LÁ‘ôëª8°ºw,bbxVè6?×áYë¶ b}™eúQеjVE²hì$ät'Ë›HþBkÐ¥¸wl¨ºj/6¥ßž\2˺fè3´ñ3•j¼&—W¨3{*±n±ÄÚ€[©4zÖ:.ÝÊË´†ûÜãEÓKU[•$šãJ uP=//þšHVWJØ—éHn¾ÃáI/n«ö—²Û‘x˜…ÌõÌÌþ'yÜQ!eÖ[úIàqd~ ˆU;©žOéµ™TCZ|E¯¥N•’²ºÍ7ÿ…½6¿oië¤êÎ$w‹ÊR6Mù%~Zô¶œ!ꌳüJçÍľ[ÊEw¨ïVs¸ï–@弡Œ¸·è({í=J±Æ Tëz  $Ø[o î¥%h2¸Â¥TGt¼¡ã%î–H¦t(¸ ñxHÞËÏ-ñ#ÊšÛËËšßs"»êdêÈ3÷̶»ËÜ ‹\ [Û)ryK‰ÄçëœåÑèV¨Á¡QÖ­´v~¢·ØÚYÔ$ƒõõAŽ·v~†ææ-¶v¾J“T\èJo޶ÐQ¢|t¥[̦|J“Øè=%ÈÍZ¦×B“Xå‡x€Û{=J¸‰f.QÍ•o-Ð=*Ì{ãÀ×÷¹)‘ L:ÐQNRù„5ƒ-dÈfrž‹Î$¿XÌ„NPÃ"Ñ¢4äRAb^„«*&Êë¥ÖB5a¡”ߎ†tÊž ö§‰a§Î^Óibßv&`ûŠHx'•£Ž<}Õ%Ú%V>ë6»’Ï….»%œV·žñ•å,€MžÆ•TEë6»8V)‘ím?ÉnäÙoJ­`Ïk¡Oݱ5­‡@%'òxk”_­sBCÊ3iT¥@éÅ@,WH¨Ú´D{7e-i¿šì×ü‚Ò‹¥èlIƒ}ö èF #ø›àpq¬•2Œ•Fê-ç ë-ï‹n;–d.ª·º¨as»Kç[ŒÓf;GA—;‘Ð8°w¦ƒ^„¤JÿG)RG4ß‘d1ѯÐD‹FÌù ÒýÞb̺ Ø70¶X(¨×Èzj¡-âÎ C t¤v®E @¤G4¹ßÉj¨WHØ)3’ߘ§G*pKwë4Ý­³܇b¢…+€c/;µ^³ÑzÌfh(cV½æ_ezæS™ñÐáH·‘;à%d½Ë.J°O±ìW5]"éöþ>›úo ž•ÞäÞ7dÀe+vÚ˜$W“#¹T°ƒv¨§‡\u·U%{%y‰¨Á™:Èÿ®‚¨¸7Äã0"þ/\Šÿ éÒ½\*ײȌ´3™ìš«@yS›èxžL»lrYL»DÉ«#éU¦giÌ \lÀé:R<)-þ&"iRTòT¿ØGÒÄ€ñ1Àªò™½+ä*4EwAt)Wê‘4YÅžÚýÍg«ÑL0^Ñb¹,"ûÑSì[ø ²ŠÈBògŒ¾×›,X4ÓŽ°–ä§³êÕ Ñ7U¥ˆè…0í #$JYu£ï@!R‡.Q‰ËhmÛ|óo\’ôB„Ñ õÑü2®¹HíR·ÓFÍ-íÑú¥ D\Ñ~Mï¡?–wm{ õ® ‡ l§ÖQ`OG}$à¤ëHž9ûŒW'è¢Ë=§J_ú·( +âr,·3¢Š2|‹¾˜£IÅI¨W•‰ˆ&tdžŠèníÛBuQ¾káh¶>aÁ6ÊqEƒ½Ȧ敀è-€ÝcžB‚¼ óØz?ÈÍwéQvü“uªd§£Ÿ’ÍÓP…ÔyŠWØÔäkT¡õ–"-QM%ç°`Çï¿é? ;þ ªºþ,ˆ+˜zB†Õº<…ZÈS¼ByŠ?"F%p­HÌ}ìdùe­£îרڰFOÉ9 Ü&w_âr^Ç8iÏé8€ùƒ“;ÌŒÝ\;uð—?ÊL¿Lö>ÇñïpŽZã9mPÌ;ô»Nï&?ÓY‚N!G.ë¨è®bhŽTL?ÅŠé—Ø¯ì)b-¯QÃðVÐç°Eg"uÃ’Fy*ès”v0¹ žHSÅtˆ»á{³3ˆZÄšp‰,ÒçœÜÄ¢T¬E©X›¸Q¶s¨Žì×—çÀ¸Sà,…ˆ(L„T’dž@ÞPšË¯Ö¸I ˜¾ˆ¬|B=ã›7q´Fƒ§F !.RVsÜ$aBB·°FKã¨ñ W¿È >C$4.æ¹ý*X ØÏL«j'pd ¸¯`ƒ|«zÜIŽÀW©3´ÑŒ˜7Õ®ˆ ¨“[Þ ¨€:½å ‹ ¨[Þ°¨€:µåMƒ-oÔÆ–7âJž[[¡ -o>`¡¡ð05u·X9:'») »‰CeÖî ó\rì’ŽM¤ ç#PŒ¶s/Ù÷ˆ^‘ž—Å»£¶®Þ¢t¾Øx]µKÍT»Vú cí`kÀ?!O°qˆ”Þ)½“E‡ä–ÃEÔЋ™›ÐŸ9 r¢Ò–™Ú*¯ ÷ù• ‹ÒÕaL¿¯ú6É`bÞû5å.`w˜~ÿ„B_uL‡mè wN‹vzÙÿR£÷Ù³x†<¸Ï2ÇÞARH·e[—¾&mÍ=6˜Üd©_SXu[¨Txê,ÊïAÇàH4žñ•Pƒ+*Ô?¡ õ5âÖï…v%ÚÔDáÁ„[K·°´ þõiÚE¢êg¤‰Ktš KXõJØÇˆ} åx¨»]¥ŸÞóÖP¡2ÛT-ð ò ògæ„}4@¬ô-1Š}üŒª–uë©”ª·ØC8×ý葨3I½Pž©@Šò¹Ê¢†¯sJ€£²3^Éèþ?Õ\M¿9Ä9)`oþP CÚaIQj±©EI"k'eÆŸ°òç)öÝt߬J"zh·¨j ª¢÷h… + ƒ¢v¡î nKNcÿŒJ„÷ ›ö7Q§ µE=B©ÞÜê‘ÄŠ&í× ŠÙ4v~=xZ©­Ô9Qæn ©¼³(ÑE5Ǻ:ÖûŒHh(Ñ+ÊsïÑjÝèB¦V»­ðšµÓ1¦PçdŽ+‚ƒà¤Rl9P™¢Žp¼XË™œÉ˜ü®Îþ²é69Ì­&wÕ‚ ÷ÙŸÖ8«ÙX0—VmGË ùOE‘NHù¥<Íc颪ދiÇÞça ž‚Í×äÅ ‹'á*ù‹$j™°V eÌ ÒõFÔ*Ü|¨Yo>¤66zŠÌ'QœìHçó‰ºë•²ål§òh±+ÅɾýMªŸS ‘t¬œ¦'uŽžÔeÉkq·@³…ßôùMwX‚,5%©…jÁ7nQ)ä%êüNð›¨R(`ë¸à!RK«ÐQ7¼¨=¬ªhH".ºHéÛ@ö´@ÄÀzº”W•¨ÙДP.!½)vÔ±#…ŒNu»#ÎÄŒô¬¦7å÷&ʉŸVçv/¤®¹‹›%mÝzZ º ÜÈ0!éfÊðªðÙ8úÊ'Óî‚ÄfvQ¯t›õüªÜæ6m ÿŸÛ|1ns2¥É`GúÔyÖÿ‚ÜæFxâ³ â¡÷îZ&IK~ÅEÔ~¦ûægÛ°:‹G±:5µàQô?J禚GÑÿ»n'²@Éz–ñ9ë©Äð£XÜ~Σ¨ÆOGE¿äQ,†êB=û‘ºP†«ŠG1 ”Œ—< oví@¼ˆk“ÏÃ÷“Wõðådæw'SþÒùÞ}0>ÖÞµ$äŸQ~ö)%䟞ñò/1!ÿòw˜ÿ„<Š[,ᄎ 'Âoú_Ùlš®Ýn6ÿ"Â2g)” /'ùîÎ&Üë™ëCoáכּ³‰a×ù“¿l#|[ŠÞ—$ïË÷'ƒ¦N&LEª§¡Ü”ȳӭ")Âgò μ Ç„§£ÁÓ±ð0jè–² †ÛSžIöÑ5Ž U(g4B5jBi ¼6kÐ]³ 6ë= Á^½Mšª‘ØvÆt‹á¤ÃTqQ˜«a1—(ê‘äõb!ª5þЏ›§¾Òó®VƒðXß0¨ &BjÏyªC€²š=OÑjÀOÖ˜Yç¢.3¨¦^U){$"àLùõü§x NUÂë¢é]ŽÒ¬(‹UÕGN3™DžÎ™Ím í”À†{çŒSþH$´Ü3 Ú°Òy%˜˜"¡<~É(§Hh~ûL`$4¿%Rõì«H¨f”ÛÖ/¦b”ÇÑ=L“Ÿ /Œòi¸ˆ„ª»ôöjôùdÚm^Þ E»!Ú‡ÖW'—ë<£rO"!JØ4X®óåW ]c¹Î9Œò—u'•üwþÛ@_cúô§´AýÊ"tõ…®¾]b6¬Q8ˆÙ Yð Kj:£¾]ËDsð]е~ ž…ï¶à¡jއŠlQ_»5U-j ^c3$Ùƒ!ÙµÐužóÒµ„b‹ åøKëè1ØïÌDr¬¦~ ±¥{²­·Ö:Z­2 "åø‹³,¦IGë'lÍÞ×t-G‡Uq–õjµ=Žš­s°±=Ž75 ¼Ðµ"µšô”éòK†Zs°ÿUDš$Ãt«*8Ò A#×»ƒÂ¥@âÁMĦK1.‰j+°ut"{Šj­IS°Yz#§Ül*m Zå¨Ñó&A¨Òáz#”Y+‘ •ʘñ̹›Ú v«è€$3[üšº )غEúŠnSâ‚ÖguhT¤1Ýîì ‡´E^ïê ôòK8Š}")$ñZƒ#* [G’xž¶äÿêz,áuÉÿ – ¥VE,ï=J¢¸iÖ4‘”…¥%¤¦ EYXÀSÈn)¼¾ fåm…ѵÍë÷ÿnz¡w¹“Û˜ùÿ¬üö]Wú/«÷;±÷Jÿåz‡Õý—•èÝ%0"Ûv—Lj¬cµ_b§,¬ÇLjLJ'aDeü&Œhqû Q¿ #ªg#šò/KŒÈµcò¬JL>®`DyxÕw1¢jô%0"{Ÿ ô[0¢W'cDo #z÷eåÛžR÷qαÇTÔù¹Uç:eVW;û@ç?ˆS‰’5›ÜQ}µ è&?AJ£LòÄG^Ÿºtâ;†~•­¼iQ"ó÷’õîzGȯ¯žs²ÞY!š„Dp Wû€‚Û‚á©‹~vPn¥w”'ºÀ¦÷ÅègÆÅÿü&ŸÙø%ý d|·_‘ñ©égeü&Ÿzö“A]ˆÍ6Œ:¼I$]ú‡3ÂüšN¼šC"Akã)"•ñ›‘“_¤€†É g`>™ã/~6¾„û_üòMÞK-^älðtoµú•pxÃÃÕrùûíËÿØ‘6¸$ZïºYŽÁßÿpÿôqÕŸÿ^5t6 endstream endobj 26 0 obj 9751 endobj 23 0 obj << /Type /Page /Parent 10 0 R /Resources 25 0 R /Contents 24 0 R /MediaBox [0 0 612 792] >> endobj 25 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 5 0 R >> /Font << /F4.0 9 0 R /F2.0 7 0 R /F1.0 6 0 R /F3.0 8 0 R /F5.0 17 0 R >> >> endobj 10 0 obj << /Type /Pages /MediaBox [0 0 612 792] /Count 4 /Kids [ 1 0 R 13 0 R 18 0 R 23 0 R ] >> endobj 27 0 obj << /Type /Catalog /Pages 10 0 R >> endobj 28 0 obj << /Length 29 0 R /Length1 9572 /Filter /FlateDecode >> stream xÚ­y{|SU¶ÿÚ{Ÿä¤i’¦MÛ¤Ié9išô‘>“>ÓÒž>R(µÒÚðlBA" €`AE¤¨ÌøÀ·àø 6M2Ú;:£8ן3ã8£þü(3u¦¢^\…ä·ÎIå1Ÿû¹¿ß¿³³÷Úk¯µ_k}÷ãœlÒ’Õ}ƒà„'±äß1–/¹q½múŃ„à7.\¾º÷ØŸ<š-ª¦å«6-ƒ›ï= ŸˆÿÓ@ßÒ¯›·|v¿\ t[Ù[ÈËíe ¬^¿1c„d"ÿ%òé«Ö,é‹û_ºÓVòÆÕ}¹tíȧ#/^ß·º?¸ïÔYäk/\³n=°ƒ(³"_¬Án…Ýð.|E´äZ²‘†Ù¡H]tet<úÖ®À~š`Ž{+<ˆ³{ŽÂüÚä=2´“ÉÜz•çÂöÈ"§¢©Ñ¯ Ç:àz‚]è›'à×ðœ†s„#’H~M‹éÌÀ=¡2G!ºSFA=Zk#ì„;1ÿ!"É!^²žü™h]Eo¡#ôŸlcÿÁý=Ú}>ú*Úü3àÁÁèÕ­èµ=軃ð0¼ŸÃ—ð Zr%ÙMÆÈò=M¦‡è»ÜyÕ{ª/£GÏC„àb#U䲓 “{Èd/ù˜|Gï oÓØ^öKdop„óp+U»U§Ô|_doä‘h+Î΄m—"njцýˆÅuˆ‰ÇÐŽ!x^Á±}?¢]L8Û,RM:ÉF²…l'{È~ò>IWÒ5t69X6»“¸îܪͪÝW$-7ZDC5Ž»Ã"X†½lưí0 'Ð[¯#j?C4 ?boýORˆd?†9èõ²ô‘²•=N(+•!v§!¾D ÙPˆ+§®‚…8þë`-br~?ÇðÎaÃkˆ¸?Àá#øÃø=ûeNßÂyœ“…8H ⥂Ì'‹É22H6+áVòy˜D¥ÏÒéqúôòŸé_è'4ÂÒÑ~6“-` Ñ"›Øvö${‘ý‰½ËÞceçÐ6úÈÎ98'çã–s·q§T9h§¥ª•ª}~­ŽW¯TªÇÕ¿SÊ«ù~&ßÎ?ˇø(®”Q¸Wée"îy’Kçá(y•&÷‘·hˆ›¤ ›Ð.1Þgè.æ$µl#±á:¾Z(Cèãt¢[~:q{‡Ýªw¸òn¹wÜoÞFü´¢ÎpœÑ÷ ~½Ž3®¨þèø¶‘V2kh9]K?çÎ3#"ô¯ì}ÄÍ\û¥d¯úw0ŸºmÓa¤Búó#ØDDZsáav'zÚiÇ­RáN¾f!8@÷Ò]ôpô$ø'î{s¹¸S¸ïç@þ/àØÞ¤ïÐ]ä§&O’Ù8†t¦A|¼YôqègG·ÑÿäÞƒ÷iËòÉ×\ cÐŽ~º äDÉ^zŽØá² gÿ ùýÖÃ’(½ÀöÐòy¤R7i`Å¡%‹q4Yð…ÊL4´בqu†`ËÈ£ðŽê×ìC®޼L*èy&Ò&ÒÆ*£“àTŸcúÈ»ÑFh¢Ñè½\ü…³hµð~ô5VÀõq³~<òãÛÔLîe«U=ѯ#[U·ÑZX¦úŒŸ›h#îoãY4 yä,µ¢Ý,ñ¡¥ÌÜÏ~ü‘vÀ4ú%ù6’=¸:²p&ݸsŒÂrò<êªðlªÃSà:‚»fÛ€ûÌQx Ѿ÷v]‚çÌéЧ§œ ¾âVÀ&¼e´Ã¯ð4Á\†ê©¾[ª«^Sí«ª¬(+õzJŠ‹ òÝy¹9Ù.g–#Ó. ÓÒmÖ4‹95%Ù””hL0èuñÚ8 ¯VqŒÈ÷;š{Å «7ȹ3gȼ£ ú.+è ŠXÔ|¥NPìUÔÄ+5%Ô\ö/šRLSº¨IŒb Ôä‹~‡|«É!†ÉÜŽÌßÝäˆÁI%ߦä¦äõ˜·Û±‚è· 4‰AÒ+úƒÍ7 û{›°¹±xm££±_[cÚxÌÆc.hv Žs-Q2Ôì÷QÐèqPA«£ÉLs4É#2§¿oi°½£Çßd³ÛùAҸı8ކ`‚[QF¥› º1È+݈+äÙÀnq,bø®°÷ºuKKûæ÷Y_@î#Ñý6Í›O[.±ØxRcÏÎË¥66ì·¬evxx§ÜßÑs¹Ô.§¶u©³¹w¸»¾K6¢¥"_žJlRý¿\Ò»R Æ9Ã+{ÑÖá tn²‡¬VéXôXýâpwì³9}MécÉ0ܹi‚µ‚KÑ +‚q½ÃFŸ\.תœF‡8ü- Û“ÿ¼²¤oªDí4~ rVÇE|¡ü§|ÐíæåɸàÑ‘8ÆZ…/+È¿1L¿p E$h>hïÁj_ÚÜn—½º;,Ábd‚Û:zb¼‹m!ŠÜ í•%?IRæÈ’m?I.Vïu |+wé” Æuñ—`L5ù|A’ú?ˆûcòÖ.GkÇÜÑ?Ü;eÛÖî+¸˜¼ò¢l*45ö0ÊQS¤ˆÄù•e¦GäœøS+H^æ5E¥„ˆÍAcïÌXÐÚíÿ•ÂÑ/åZ ¹Tmj˜AŸûJ¾ú þŠá醘sÑÖî¹ÃÃÚ+d͸í 7;ÄæáÞá¾ptÛb‡ht Ã;^pxÐßû“GÃÑã»mÁæ»8‰âC´Rh(À}m®’_eÞLëSrN͇é2É*î-Ï#¦Q«ÎQ&³Æã~ñ¡Åmü®æBÍÕÆojÚ.Ô@æç1))¶'Ú˜àáçE6q^RáNä&е5ÑOÙ*¶ rˆ^jÉl¨Ë‘“BÈ'îìœZ¨%>UmvmÎ]t·}Wö}:ëˆ0žeÀJ­\šÊš-ä¨w¸Èæìáìgí,UEòÂщPb™BR"eûrFsh@Ž>-1L¸ÃÓ²´¼3ýhÜf¬Cú¡”™QåÌfñp2y0-[¿­«¬H_§Ÿ­_¤çô‚žê­y™a¶]ÊP£¨N=[½H½FÍmSïWÕêß«Uê´\÷57NÁZwÛgW#2œ< u“nwÝä$ILªª2ž\PRLÜn÷Úдwµ ÑË/€/†ÑO++°–¬]àv;ÕjG¦«¬4)ËëÁcŠqµ´¬4ÛåÈTóê”äT¯§¼‚Ùþtã=ûFˆ}÷êU®ô\!7¡HkšV¶x¢©sýÒ¶~°uÃþ“œcójó3s2LbAr|Š!yxè‘G–ÝÔÖ>pD?U]>è¢~éö4B’* H nžn‘þÚäù• | ªÖÌé0­H]™¿I·)usþÆš]lwþîš]³G –?ÞøÑ?YñËÊѪQßhõ 5šžò©<ê;:Óy]ù@ÅÊ&Ö ¦ÎN¶«üΦ‡ü¬¿jsùßÍM7Î|ªJCœUÙ3Šæ¬éVÙ3»"­a’.uçtwµÞÇ“–z½ÖG µ´$1±¾„ç»~ |rZš[œœ›[¬õù„êÚäêêZ¼~wÍZZ“[ZZ]ñ-3gVWû´¹Ý9ʵխ-ÆÌa{˜4ާ%;‹Ã$KÒ¥9s%CYoîǹ47LK®ñ‘Qñ…)“Rª%GYµdK/]SMªÛµDë¬=T}o3);Üz¨ód‹ /s•Be 2Ž•6-Ææå+¬d.*-]Ór¶…¶¤uçš«Í-æÜn­ç‹Ûm¬A<ȸqÇž¶Ó§'¿ùfrq­Û=¹`-–O~3iünåà6Nàâ’su;U…nÍVãkH-nƒœ1`)XêN×'ñ'£#Æo'ÝçÉ·Æ“ÂÊCÖâv%%ê-ºªŒ©«š…´\žABU®$\Œ@¬°+FÌXxÔ”\›™iªr_z°€°ò 1àòI?åbÖŒ E™Ù@róÁ åMù3Srîò;ŠNê×èLIiƒ{è“ÿI,¶Û¬–ì(l¨ˆü™ÞÙmŠKuèœÊ—¡lÜ¿áÚ)'{¤8‚–+À¨EÓH¡m’Ñ6š¢T°Q[×ÁwÆuftˆ›ÈÍ»2žÍ~:ç8=Oæç¼BØÜ¸¹sE¶B½"neƦ¸M7»Ô×äu”­ráÊ!É™ie&Œ„Ð<·LÉåþ‚¹9eÅåm@ù ö9ˆ£„ã€çu:Á&&Ûl"¸¡Ü-ä$çã5É­µÄÛ*rD[A¾1yØ$/ïÄ;fVHç´É_f ÓBe' N,pã»W¾ñü˜P!>…Œç•–*Ô‘¥ÐPºR,™Ò¬¥góI~Z…Íœo¶U\‚÷åèž<}ú›Ë­à¹®æ"–/Aá{™ïEäî4¶¾¦©QvQÄokЃ›h9n¢cbfe€,@øáÆ‹aI—o wê©´â"ÐdØ]Â"íµ/½>ßS?msŠ1N—XV',èò:ó3×§ZMéÙ³öŠÏÞ£¢ÃªËp©PUÄl(«Y™×b4˜ôyטvTe¸Š7{[ó’Ó,o?9§ÿzÃZsªSgᛪ|æ#fôø>yHª×Ð8¦Ö²§M/XöÛBI¡Ô—-êy–@ÚÓ]–L[žIâËM¾´¦–´k5×$u›x­N—˜Ï3•ÊœÅÅ'ËçR¿­µ«”ßÖX¶‡ßÇS>Íj‹³•#$”ÔX’cF™üµª$ØGü«6÷«ò¹õ]ÌCòÑ%;«í3<¸äMFNbÛš6™r—Ž%^6Ul›ÄÆ÷ENß±ëÐ/‰íöÛGž7ó¾ï{[îþž¶ï|ppt÷}$çà Í –Dæý~Ñrò”òµ4š™ÅÞ@;8ÀCº¤Ö9änÝãºCºzUUJ+4šSfæÍQ÷66YæÓœÈ=–wÒjhÌl‡k ø¶[š)#ú¬Á©Vsq*žkÅ)¿-Lž“ 9™ÅŽ6È"E.¶¢0»[Ê”HÀa¬¶d«ÕæÊÒÆc­+±zslVcþq¶x„ta/#;7F²"¥ˆe¼$”Íæ‰Ä·óƒü~~‚WñÇY5ޓ܇mGØŠj/zʬRFRœ—’Ò‘±M+=k%¶4¯ÕlõjÃÌ7vMlaL-‹ÍŸZŠŒ“b¸u¦H&Öâ._7‰ËAYnKLmç \$bë°×’î4kðÙúÚEoñå±è³le¤zy{EyùEø—™ÐyµLaÔ<ùõH pKä‘/˜KŠå} mr²‹¢¼e».~—v"¥h9 ültO‡×îÊ´˜íå5ñ‰ Ö²®¾¼Œ<µøð11!ÙžRÉ:*#V⾩)ÛÙPS!˜ÔAZüXC× æ[èêU…I:c\Ìþh~Ý[mÿqQBÍ·š4òIíU¿é«Ÿ¨¼"U׫ä2â.þÔ·Güp­æºóªóÍw`Áw‚Ë^]EÒÙÝP©z@6Æ¢lšòI)|Gïg/pUžês¥]¾Æ>p÷¡`„"˜Àݦ}ß6¨ÒcÒTïj®n\Õx•»{ÅêþuW÷ßÔ¹fußõí]-ëûV­XÒÖûç¢gü[ÔKá¿{äñ6C;t@'tÁœãÐ`/ûý)ŒÔ]¨ÐPN®ç˜"°º<ÛêMì%؇qãÛqV˜ ){‰ŽB6ÞÚ'رPªM©54LeÊ+c™ñ¼ÏÇõZ†³ñM‰ƒœX­ñœBÏ—õñX€3e/ÁÈÐ#;ʶ‡|BB½™ƒ‘…@ÄØŽqã)ŒjÌ8|Œñ,Æ(F’Øó¡¿í^fûÈuälä!¸OC$0Ä ©èbtÑK4$:AÌ¡´eùôî·.Ãan#ëä‚_±Û‰Yî?:AGC%^)Œ¤P!ãh…º²cÔîŒÑtQ¡!GL;Í»ÿš%ˆñ=Â$fÏÅŽ¾÷¹¦{N°[å> $ç|oO¡ùKQá‹qg¡W>Äd?¬x7`ÃJjËŠáBÍò†º]ŠsÍð$9{¥Ç+× åy“dՊ鞤—°Áéà~#¥8§{-βy£ÓUêQ;ó¼:ì?HYίÎWäõ<ì<à<î<éäTÎr”z*=i¾\_¥Yœflðp޳ÒÉ`ÛåN HF!A/lh¼PìÅY}5.(ÓÞ&P)E¨XÄòt‘zTM3¢~ÜÁ"¯üî©=(dz2îNyJC¡\¯B2e£ …2Dlíï/f¸½ž 4† ¬¡£WÍöx\ùÞzmô 6U8±sHÝH?Ç*>¯ˆ5Çëš=2-òy’ä– ½ ‹ TÚwy9™m™U*S4¤Bì^ I7Í›é*öx2]ÞJìÿœ¤uaçq.›Ý3ü2vEØÀ…+*u‘ºNÍöÑQú }›rûØ({…½Í¸5¨µ‡1±:6›-bª„ú2:‰Î]„é>ŒcdP„iÆ5 7Š"0SlWw¦uJ®NF±"Yô/y}b!:‰!ˆ[‘¬ЉD(!G(hÀlÆÍ )Q#ÕÇÓ›©w'=™®¤Jj“¬¥ú=¥úÛKõ¥ú@©¾»T?³TŸ_ªÏ)Õ×iÞôÔ&§ä¼’¾ª¤íJš/YEý—¢þeQ¿¨ß$êWŠú>Q¿HÔ7‰úz=©%•xï›®¤ÅJ:MNÉ…Ã m ÷ ¹øÒËÆÐ´)xn¥„\¥B˜&‡\uH4¡Œ—„ú4ª† xT…q#7Eœ\N DÞÈà × }!äÊÂäPŒŒÈmÖ§ÈÞåZäÈ N¤OÈÂÿJúä}<äX…Õ“I}y÷xì;ð*Ür¢xU¨ä¡>‘\‡}ÊÅ¥¨ù"2­›ªæe¯gŒ{¤58±Z‹Áïºa¢í˜T9H0©Z»,¨¤w† t÷„IT®±Ã&ªÇ3‹H;î¶É4°ãî@Ro¬³Ô%Õ&V57ý7IïTzÙW‹ûÊÇ2-¸·µ«'x`Z è‘3ÑiÖàŒ.q~Ï1º•Þìo:F·È$ÐsŒ4Ó­þN¹œ47.ª! ¶ ‚zKLm2d5D÷¢¶0¦&`mTsÊDV{EM ÏËj3YolDð7 ‚¢Ã ˆ¢3 ÆtœŠÎ™ËtTF8£èœQ•îÌŠJVª”dÉ*c™Y¨0–•©ˆ;.‰1ñÖ˜x«"¾þ’؈‰ Øýÿééoø¿iøWt5Ööž1 4çÇhªq°VÁAâ‘éÛlÇñî÷>Ä»A­£!ïhÀ·y ^ŽIѵ.¨Æ2£¬^m·Üb;Κ\V×a±~JTP_P/‹Î²È ÿÍ4%²ÜRmÇNžŸ±8;Av!.¯óóz‘8š`ñ¯hÂßY‡Ï† Ö­[¿A~°‚««58]þTàrùƒi½M·ß²¢iýÿ0h æa¥:¹ÏûƒVZ·Î­Ôs»7Ä2ضœý×g}¬LQ÷º‹åòç_X'·â&hRù#tFºrêq{-.·÷XôK¶},É«|N#ëÖ˵±­X ëb­ÂÿŽ;ßy endstream endobj 29 0 obj 6996 endobj 30 0 obj << /Type /FontDescriptor /Ascent 891 /CapHeight 670 /Descent -216 /Flags 96 /FontBBox [ -498 -307 1121 1024 ] /FontName /NBYLCL+TimesNewRomanPS-ItalicMT /ItalicAngle -16.332993 /StemV 0 /Leading 42 /MaxWidth 1052 /XHeight 442 /FontFile2 28 0 R >> endobj 31 0 obj [ 444 778 778 778 778 778 778 778 778 778 722 500 500 500 778 389 ] endobj 9 0 obj << /Type /Font /Subtype /TrueType /BaseFont /NBYLCL+TimesNewRomanPS-ItalicMT /FontDescriptor 30 0 R /Widths 31 0 R /FirstChar 99 /LastChar 114 /Encoding /MacRomanEncoding >> endobj 32 0 obj << /Length 33 0 R /Length1 10668 /Filter /FlateDecode >> stream xÚµz xTEÒhU÷™sÎ<’9™$“™<˜3™$fò€„"9yñŠHx$&A@¢ DYÁ'QâêŠØÅ_a]&‰â€î’]ùÅEXX]vuuqE]]ÐU!s뜓 Üïýîw¿{gR]]ÕÕÝÕÕÕÕÕ €à€õÀA»fIû2è„o‰sˆ ÿšU+Õ)çç?€Ä'.»vɼÑwÈù–å×.^³ðÁÝc[žHŒ-ZÐ>ÿò&@æLê_¾ˆŽé+ÑÔr-YySÁóü=¢£Dç/^zM»ë çb¢ß&Ú½¤ý¦e–æ„~¢Ï­ÞоdANèª$€,…èð²¥+VÂõøO¢«ôñ—-_°,òä_Ͻ’QN<}=úŠDxA®äüÿù°ÿcIN ü7®…ô”Œš VË^È0àÈò  þÑ \ÿHoXÿˆ}L Í4aðs3ü ƒèsè‚]˜iõocÖÂaœnHƒó,TÔçóÀLØQ‚ôÅ?ga6ü]@xN`Ì‚C˜HÚ^ OÂ˜ß Ÿ!‹Ÿ Æ@tcŠe•åm¼,ÈÙ]ñbH žw@ Œƒ'à-\k}1~ Fï„Ëã_£èa!H„eð78Cú² Ö_í°~ƒ"¯³</€à<¿;þsÒD‚4o+Ü Ð¬ã°Ÿí²Ì‡L¨†‰0Z` <ϳ…–3´§ ò`1é~Náóø.?Å¿dája£%w šæÌ†QPA+k…y°6£ðkrNÇÇ,%n#›¨4ÂH’Y·Ã½ÐG­‰˜„©8 Ÿd·²#ìsá9ËÛñ#$U «H§;à7ðŸð|…"á¼÷à²5ì;®Æ!þ äØsa5ÜÝðôÂ+dÍß°)¼Ž¯æQá3áûýä›sH§[ ~Çhß\˜ÉòØß¹ŸßÅÎñs´’dá’=A«A:^Nß´þ´Ïàøì„ݰ—ô9 €wá#Òº¯Çµø¾Œ_ãwÌϲY[ÊþEÙ^ö_Üͧñ™¼“oæ[økü-!I¨…'…ÝÂ_ÄBñ”Ô>°}àÃøñæømñŸÆ_Žÿ6þVüs°Bi€è [wÒºÖ‘% ¿¦ïëðgxþïÁGäu€ÌÀ2œŒ3ðJ\ŒËñÜ„ã£øŸø{fcI,•MeMìZv7{á•|, ùB‰Ð Ì®V w[Jè;ŲÑò¬e‡e§åŒå¼èwÈ ººðþÀ¢UÛâ‰ñaññŽø9:;Ãh÷ÚáZ²Éãd“§É;~ý°Ÿ¢×à¤Ý{ðWxŽ“†ÿ€ó˜‚nôÐ7 È·®Àëð&¼vñQ|Ž»1†¯à«xâðM|?ÀÿÂOñs<Ã8ó2 °0ke‹Ø:úÞÍb±-ì ùÉv”ý‰b§¹Â³y1¯ o¯áµ¼‹ïäG…T!¬=U¸Q¸™,þŒÐ/üFøƒð¡,Š%Ù’c)°4Zî³ô[kN=bžxƒx‡x§¸]ŒI‚ä–Ê¥Û¥{¥Ç¥ŸI”S䀼M~™V‘^Lÿq0Áf| vñË1‚p&&`F ……ágB'›,<Á6±Û©KŠ•BÔJÏÁ™SèæâÃð""Œ…;q¬ÆŸÒN¿†ËÈ» ` ßÇØx¤°€Oc|ÍPL:FÖ*Å‘8&³×…ß[ÌÝÀrØÕøŽpµh^ƒ‡ØËB›P& Ùv á{øýPŸóü$Š%B7ȵ(Àel,œ%ü'ò!sYTã$îÅ&¾Óizßc%:X«†ýø0»žçã-Xç`ú,¯Âc–é±ø‹q•87ÆØAãDõ›‹· Ãã³¾Á ÜÃ~ÃóØeø•ÐÎ:~‰S±”}ÄGâ ¶¿Ç>Ì':Ȧ°LgO“¿“‡/¡WxˆßŸï˜Æ^Ë\x“"šÓØ^ü¼Eñô×ä2ÅÜç…rx‘ßgx‹± ø ûž‚_RÞÅ‚ø.Óà´Ø*œÀ–&â0¾bƒí•çñÏ¡&þøpeüH|fÐyÙKqéKË«l)ü”âů)¢ÜJq¬¼y18p €Dúö‘ïEñ!¶ÇB1ô:§[(^î¥xqŒ¢Æ)j¾¦³û¼ËšÄ'Hó3ð[Zßw(Ã(¡;#‘ÎÒÉø×ÝÞtwÜË^•’ÅqÂÝð+Ë>iœV;S«wYÕØ1•£ËËJG•ŒQ\TX Ïæåæ²ýªoXVfFº×“æNMIv%)ÎćÝf•%Ñ"pš¸ !0¾MæµE…¼Àĉ…:h'FûmQ•Xã/•‰ªm†˜z©¤F’ ÿ'IÍ”Ô.J¢¢VAUaÚP£‡ëj çLk¦úýõˆ=mÔ§u!Ï ˆðû©‡ÚàYT¯F±MmˆŽ_µ¨«¡­žÆë±Ûêu l…Ðc³SÕNµhZ`Y¦C£ÂÒÆô0H«hz ¾!ê Ôë*DynCûühÓ´æ†ú ¿?RXźkó¢¨:ÆÔÓDź¨dL£vèËûÔž‚þ®1æµ…óóÛç6Gy{DŸ#)LóÖGÓn>éù¤Á]uÍ~ÜšÁ»<ªNvumP£ýÓšÜê×ËH„Æ ¾,w|[×xšz£nEO1)¢«¯/Å\Ô‚@ƒÎi»NZµE]׵ц¤wEaúozº¶‡ò†ôµkfsÀ­ÎDÚë3{R kúš>¯¦z/m),èQ’Lkö$:+Ž„W\l3j†¸^kœ~Ñœ¨k˜DnU¯QI“æ-¤B/T@×5$FŸR¯è|Ú†Ž¨µ®­K£óõþQK®P»Îm{àôß/å´rÄ\åèUÝ9.:µÕ£áp4ÒýBª£$ÇtYaÁª›X¦¨„È|ÐÔLÝ"cŠÉæ~¿¾«÷Å4˜GDtý´f“Va^F/hÅáH”µé-ýC-©Wê-ë‡Z.vo û¾`d¾©Q9ïâŸSq'7,E÷ÿ¦yÙÞ8#Ð8mN³ÚÐÕ6hÛÆ™—Pf{ÅŶÁš dð¨K–š ›>§YgП%w| ¡£m"0Ò1š\×Ì3XĬ± n En;÷âÈ:ÑìÐÇrEÃíçG9¹­Á@u|Ti›h–›ßÿ¿ì“äuŠÅÏè½ ôC·Á%EÇ„/¥Ç^B_¢£‹“¾Bkœ9§«ËvIÛxŠQ]]ãêø®¶®öX|ý¼€ªºöP6X×µ¬¡mh÷cñ½÷eDÇoŒÐ"áòlµ…úë'‚E=HPõ×D)ÆÎi°/q°IÂK^Y´¼ÄxÔºï}OXùºêBÕÊÙª)ª šêÊy*FŽð'ù“r©@z„œWyÿyÍ߃*ô‰å¬ ¦ÓûÂÊ ´í(¥3fÆ’ÕšŽ©,Í’.É®6Ÿ]'mf[¤Ï¥3’tœa. Ç|Êé'ðIb“}^ËW±›¥»Ù=Ò#ðnfZ¶HÏÂ3Â/¤gåg­¯Ài¼×z^Çü€pÐòšøüLü¾f祼õv¤—b6Ê)ˆ²Èy¶`I‹ô$°'-V™ÉN×’,£EP †½Zµ¦2Ô&N*E­ªlÁãÈXŒ­Èõ:ÜJ(Ž%wK^Ðìhç1v›–Ü/ØAš.TÙ0MH‹±=wxÂa²`KçieùÙ–Îåˉü:¬T)º)©4 å´rzƒ¥(üeÿ†"ŽzDV7³yHñ~Íš,eRL§†ù‰¢‚¨mšUq•²6*Ì6G"µQAÔzÍe·—²ùT8H,ÎÎH Z:Ã?‘‘# 1êA@©ÏõûVRQ!n.qƒÿ[DÜ¢AîÞ6Þä–·äR.v¶Àò:0:f¯dž”JTR*-„-ªRÉÊ•JÒò`R‰¦:Ž` ´øýÈýèÇd¿pjàã•¿øK(i»ÿ0zø;烖½çÃüù×-ñ…;…jzÓîÖ*220䈰¿ž2¹[Ø-üf˲¬{2vÁslÿEús½ø"{))š•¶U°‰Œ£]Nˆ±lÍî vŸ÷9Ñ©ÓÕ® ]‚¬Æ¥”ÇÒûŽÅ‘ šr»M´ùûè­æ¬‡D%QMä‰éYîI%ÿ¤2‡ÏÒLËé+¨˜rºRßñâÓP}ádËr*’\•ô7r¶´Ð{Æ" ì¼²RWΨwš%//-Š©)îQ%å<Ó¾ê}ãónÌ~þ•‰_Ø"gtO™Ûа» ÷þö«?>¥=û·eEf®ýfñÕ çëÿr°šl²Œl’Fïò·µïquùXš]÷YïI¸3ñ´UH–«ÛÆ3åt›ÏîIò¦&û\jD–»” ¾_Yw'²¾kýP–ì’Í¥ Â®Ê0ÅWïkPm³&Ü,ÝäºÉw¯ôoêÏ­Û^‘öÉGäw䣶¿Ø?‘¾¿“¾•¿Jù>ó¬ÏNºÇÅfû®õý»«²gŸŠ›T¤ ê - (%oBÖ„¨"¢èÊ &KÖC29p_n~©ŽµTï°Ò&§Êt6Y•Êgd‹c´Q.1è°Ëk­‡²<÷{X½¾êÁ­¸U7w¯ÏVsî !sÀ©8Uç§àüÈ?´!t©\ÞyVß Ã3Eš°Ä[-ꦙ8?ÅÄ—{‡9«Í³¢ŸÝpødõiêªy³4꘥Q¯,ºdi$Ÿ¥]NÒ÷½¸êBËò*Üî–N -‡åÆÔJüŸ½¶J«>ƒ­R6‘AYMÊjR‰Õ“X CGV?!è7d´EÙPV:ºÜ_Bùq.åк IÂÜ #pÍìMdáÆïŸøÓÀÙ5Û±äÕ¿ |‡×E"÷{qo’õºÛ?þ8:ÿeÇß¾|gÑÜdÛªUwßaÄíYÂËäC^¼^{Á&Q6/‹’$;—,ªM2÷2ü¥òžô‰ô‰"œ‚SÎO~P9à>àyW^p¼”ðºtÀ.<“Ú+ï¶½`ÊÓÆ‹ÏØžIrÓFÛF'”§¹cËKàoÛþl'‘ïpâ/¤ç¬Ï%ò5Ò-Î5 o›0ÛÆYšÇƒ”í;œV›]NEl·«g 1ÐãQ½âõ‚Ýáðxm®EBð*öéÝ2'”u;ð GÜÁTÇs:ŠÕ®:Ö9˜#ÆJ4‡gúT/zHw¤y)Pïé™2¨OÓNwÒ^Ÿ ÒÕ§ý£øœHéoHÜ¿C¢bUæ6_üèÛmn¶?Ó«T:cñ· Ùb•@h(ô nªT^>JßF‰û“‡vR$‚ÄJæÂžyw<âÿÉÀ·fÖŒ©ÞR æ_5ð×ÕܸymÅþƒ]µ!}tõu³Çí¸œâÀZŠoÐ: ~©•NòÍüÞûmºð†÷`:΂r¾+èàšämÊ\(Üä½Ç{&Ó®è>­è”3O‡ŽµÄL Zí 9¢Q*jÊD­¡l—xDd­â&q—Q›Ä3¢EŒa£æV313%GÑsB•Þ†>Ê>Å8Œ-§•ί¦Óx:ÖA·™,Y ¤R™—‡¥?ÄÄÑåkq :?Cy`÷Àg›O-ç%«¯nénZ{õª¦å¸ƒØ:páÝ{nzÞ²âݹËï^°IÏyâç®Þ&{(0 ¾×0Ñ5ÞݹÐe)µOp6© ]ËÔGáqçã åÎÝÎ>×ïà@âåc§²Ñ¹Qa9¶7=Å­Ü™¼0é¨jaI‰Nd˜˜âHLb\A§SU EÑ+f;¦P¢ äÉÙE’ɺÕ6Éq™µÊ:ƒ›Q­I^¦G5l|IUq=…GŒ±GzÓéVzDS@Á£ƒUYOaØë‹áæŠe”ˆ‘妜¼pRiÑØ^~ÚôRòÓA'Ť´J0ïÝGu×ì4]rÈˉBGœË¸mÝM$*i³ýoìÚ|ø­Å+>Àãk¦O¸söòæé& yK&ŽûÛÉ^{nç…wøœµ÷^ûÅÂÕënüÐÌ÷ Éç®#`ïÄOP¦â¬ö¨TäÆ(ÜY+„´öJ¥H-Q¤5Yl‰òðrûÇêÀ» ÇrO%ÈRÀ’ë$çæäŽ·5$‘YÓqµ¨4»<·!{B®VÔW%ÎLmrOO›33¯µ ©huøîð–Ä©ÛÂÛ ¢Eo¤¾áîï/ø6=Ãü·ÕŸÈÉÍKH €i>:=>O«g©GðÄxŽære†R$éJjÃmد'v…ãÒ;òñ¤w¼Â~q¿òþI^’÷%íÇ‚ð´¼ÝúŒçio_–ÄõIë36Ë›­Û±Ùs“ug½¸^Z¯ˆÙÞa‚µ™7[#©b¶œgU•œ¤ÂÔ<˜Ër¹*¨¿è'MìvÁãvs/wƒ$ v,‚EÆÝHmB¢-1II¦ÄDm¸ Øn§D&…ä%'`œ,Q¤Hp†|'˜lO:Õˆò ñÔ-a\¨„ÒËl.åÁ2kЬv<´•úòƈJµçt»£î~77s¤~÷Y·Å½—]ôë9lºáé“g—ŸTNÞ¬ü“ÜÑS|ölçI Ê-ôÔké¬ÚX–)¦€§XO_+Ãzá¤ÏýÔo¾K/> Ô–.P#×I=jt.%ø`×£Žî[É[ 6pÒ”]Ñohtòå…“¯x´+7§ÛñÚ@÷±º5Iþ\é˜óÆE#{p§_èÅê8¼ë›9£[Uçd¯lü“ì« É_a=Ê/NÖ‹¿Ð–Æ \uÖð÷w_X`­ÿà¯cC›¨ÿôSI¯â0WX·¬>„Yk…ãçˆ.d;` É–B)ÎÇϹ¿n¶ˆ“¥¹ƒºÙPÏ¿gÓÚÑ-S WRõ¾£œta†„kP#¼—74Mš<3\³¼£}qaíÒÅó'­l_ÜqÍ”™Æ¯ñ³Aøó¿üÍÏfüî7ÆÃD˜Óaåk³zfj1>¥¯xT‰Ž{Ç2ȆI&Ùd½sL´`Ôz½1#Ãhìs¥˜ØžPâ¬IåS`Áª©œJ°‰ N €s°ñËû0Û×ö+ÞHt#©­ñI}uu%ëöñI°•à87¸# ¥&õ••™¸x¤‰ƒAgçÒį&XGpd°»ÅènM.)®ñóÉÔ4™æÙDå>‚#Ç ¾ °^“¡˜`*AÁÖ‹ÜãF/Oî>FŸoòà‚'÷Ù•’¦…O¤'R‡‰¤®^"u™HÃN4ºMì³*%®=ñ~ö^¯VSbV*«ŒÊû}U5%¬ñ²÷©ÓöhMmG Nœ! ‡£²›`A”FFw×d³7¨_7{JͨkF}„QaÔU£®Êl$XE}ž¦‘žÆžÖr[Oˆ'$¶OÜ'±]â.‰m·Jlª8UbNÑ9ÈsÖ´ðZ2P-¨–VYkle-Y¼Z vôÄ D(få°Ž€“JΩ&˜J°‰`+Á>vQ‰†ÜLë`ï8….VFT™1VÉ”‘aÊÈÒ:Öj‚©:O¦o-¯e£é[Nß2VFV>Ôë/5ÌýÆPåàPåwC•×õŠ~K.I¯2ð'éez^ÕK±v¯Ämƒ¸ÈĽ¡ÒQe¢4Ñ›(d¢á&Ê7‘ßDi&r›(ÕD)&J6‘ËD &r˜È®£¾Ð 2AS™ ©LÐT&h*4• šÊMe‚¦2AS™ ©LÐT&h*4• šÊMe‚¦2AS™ ©LÐT&8h!¿ŽirÊ|1Ú4ÑïLôºf'¼$§Ê÷‰NãUšðZ‚UmE!‚ _—áÕ½ '4®O øZk¬ü2XJ°Ž`À+ûT¿ÏGñ¨‚ܶ‚µ‚\·‚Üv+•»öð‹mŒ—í¦q7UWÑüÞݤÊ7†*}††¸ÓD³Lt¥‰2´+Gð)Á›« n ˜Mp9AÁee£)†ŸÀ3È\Ëp=v#G+¥]2¤¥QLv%ÉÚËÌM5+»··#™Æ±7ÿZZ¾ù‚û°ÕÀQè0ðNb.á„gþ÷ÞÐSÔm+y¡'ÉÃ-èÍÏ"4¿7_%tMoþBí½ù5º{ƒOùj¬8‚²>à,áÂWö†î¥æ™&šÑª#ä3GÖ›ÿ¯ÆŽYÐÁv’l ì…ÛÙëû.°×÷m0Ævîö}šêû4“q·ï“Ðß±üCÍéûcÑaß›þþWó‹}¿í IÍîëï8ìû5‰÷äl ‘µ‰ýX¨Â÷`ˆœ¡ˆØD¯¦®«B;}Ëh(šn©Ï¾ÁÃ-Ôº$øoAè6_[èݾÖPÈ7»(†¹½¾é4 ^NԬݾFš|ÒàÄBa_=M^§ëÙë«É7FÔhÔ2|—ùOúÆ’£‹^ö•…ÆúFôB ¾ìè%ß• Öëèî´r©û¯R÷r©ûJ©»Tê.–ºÃRwžÔ+u“º³¤ÙE¶DÙ!ÛdYežu §Äè¡S _ð)¢¢#zS)u…ñ¿JŒ ¡Ì`2¸¢É¼‘5ΨV„cR|ztt¸1*7]Õ܃ø@DçFû¯Æyjôëڦ͉Zµu5BãÌZO”ÝC˜ÙL^®w¸+Cÿ=n zïº?cG"uÍ{)F»WDÀ½ªÚSí—T9¾þ_mƒåÿ,öü¨nlZ³‡ÜãÙ>ÉW.9ƒÈnìÖIOVtsãŒæèŽ¬H´D¯Ä³"Ñ{g¨ôŠaæn¨ßÃÒtiÞ#ô1OÃt/ôÕG"´Å†Ýn’ƒ‘\¢ ª.j¢lȱ¦œ¥érù:"9Ïvðr>ÏvCN@]®§Cm¨ïQUC&ÐaÈtàG2{è–CR99¦Ô6lÕ¥°5°M—І‚A) "˜ Ac  f"e?ˆøEZ/Š´" ™"|ÇßA"áÿŸµ 3j±±©¹G†Ú= ìV–3<#Á;n{Æ^x“öp$j ÔFíºø«)÷¯Âbýßè{×!¶DŒÚzMtDE“ôÆú=·fìŸ5Fp;a°©°¦°Fo"Ÿ×›õœ›<·ŽõgìÅg›b'Ѽÿj +V¬ ¯ø1þïÍž†ŽzóÏ34ü¬\±Rÿ¬h¨§¿•Ð ÍhŒVL›ÓÜ#I Q­­~è'ƒÇ¹Áë±Z ·×GV ~Â+o\Ié/í‘e ¥ å % e ¥ ]àÝÞ]ÝÝÛ]ÚÝØÛjlF>·ÍÈç¶õ­t}ŽB² R .tnsÒngò ®u -”EtÐ(ü£àR®¸Ä‚ÓŠõ†•„̦øbˆ=d-øx³Á endstream endobj 33 0 obj 7522 endobj 34 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 722 /Descent -212 /Flags 96 /FontBBox [ -560 -377 1157 1001 ] /FontName /LEPIJT+Arial-BoldItalicMT /ItalicAngle -12 /StemV 0 /Leading 33 /MaxWidth 1146 /XHeight 525 /FontFile2 32 0 R >> endobj 35 0 obj [ 278 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 722 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 556 750 556 750 750 750 750 750 750 750 750 611 611 611 750 750 556 333 ] endobj 7 0 obj << /Type /Font /Subtype /TrueType /BaseFont /LEPIJT+Arial-BoldItalicMT /FontDescriptor 34 0 R /Widths 35 0 R /FirstChar 32 /LastChar 116 /Encoding /MacRomanEncoding >> endobj 36 0 obj << /Length 37 0 R /Length1 6440 /Filter /FlateDecode >> stream xÚW |SUºÿÎ97K7šhKšB£4-…JmÓ%§ &L‘”R)R-›BE4lOAG\FE}êí"“|TQGQ„qÁqDæ‰ó}OGéÿ¹ •¾ç{¿ÉÉÿÛÏöÝï.‡%Rˆy—6´•ŠayÈh\¹\ÝÑòöJȧ‰Ì£®kY¸ÔÿèWåD–AD¦?-\róu¹ËOb€3ˆYÒÜ԰࿺Ö>C”TýŠfR—&Þ}3ôáÍK—¯¶N&i Ö%Ëè 4JŠ@7/mXÝ¢„ï…Þ]½¡aiÓ{–ëZ Ÿ”z˲ÖåúHÚA4*¹[njj™ÑûòÐ/'Š×ac$‡—;2è#-¦ndšž !Š›2ˆôÏ3’÷.ÒÏH¿äü¯è‰h=ÃÑ3t€^bçÑë9ê¢NzÒ©Š 5tmÄ,s`¹‹f ™`¿‡ Ñ;©€F>¦Ãˆ½†ÖR7¥± ý ZGÄ;èµ’h•S--£-ìj}ÕÓ å6*¢«éja!ݯoշ뿧ǨK¼¦_ ʤF´Ãú—¦?ëS>zÜK;éÛ÷gl¨Ä(êšþ2¢ì4—šiu³qlwšêõ)úaJë1êNj§½hz>d‰¦óúïõó4„òè*ì§“Þb=¢÷ÂúÞ2dÌ„,  ð,£ÿ ?ÒQæb/òe¦DS¡ÉkºE—Ñhš…Õ>žÿɾãkÑÖ‰W•j½uýFf›^¡OY&+`ÓØl>‚/㊛P—yè;šÐ"äû>Œ~œyØ^žÈˆG•§•ÌC{OêpEÜt?ýŽ^dIØ©ÊZÙ¯Ù1ö¯äóøýü”¸GyRyÛÒ€]_KKi =Mß±T6žMg¿dÍl ÛÈ~Ãv²Ãì(;ÃËy¿žŸÍâFñ‚R6SiUn3ÝaÚd>Óëï}¹÷O½ßé…ú4õ°«¿—Äκè}€v‚N1K`ÐTæd³Ø¯ÐÖ²-춇=É:1ËQvŠ}Á¾fß°8¡™ywòah.~_Åïáð#hGùßø÷"] 1N”ˆ€X†Umw£=/>U2•#ŠŽ<šv˜v›ö˜ž6½d:oN´üÚJÖ7|ôBî…ã½Ô{gïŽÞöÞNýSŒk˜‰,8¨«o@[Œë½÷½Ã‘»L–ËJÙÕÈÌ<¶˜ÝÈV#“·³]ì1cíϲýÈÒûìÖœÄíÆšGòq¼‚OC»–7ñùÝ|;ïäÇø?„E$ˆd1XäŠIb®hËÅÍb‡ÐÄ›âqJ|+~DÓ•xÅ¡ SÜŠG™¤ÌSV(*Ÿ+Ÿ›êMo˜þbŽ7/5ßaŽ˜¿²\a)µÔZ¦[æZ¶YöZÞµQéyú]òc'ÅzáÏÓV>FÂßâo¡žçÑ1…£Rùv'¿•uòá¦Õæ‰|"›Jç7rý*ßÍ¿åÅVÃfÒb>::šyòX‰rÎ*û±··0òjs"[ËÏ™©Ÿ€9_£xƒ>'˜Ey˜>RâY:;ËŸµ¨‚”R“ŸœâzVÜÈn¥ç¹O­¬›QÇSÙSx.Ô±Böw¡“àSQEEâ3º®ç¦³¸ï¤ß²ÊBÚJcØúœÇ]1Âtƒ9×<˜½Î)a>uWžÄî&°áL˜Ñíl®Øe>Ç? tD‰§ãâß±ú#üY1E9ošÁšqÜJwÐúzºÙäWÞf I°Ù”£œÄÓm(TœàëðT©Ç3m/îîn<ÊÅX2P9W£.fá ± í><'TÐ"Üã×à)öušëx„š0ýﮥô%f˜,zhLïTÞ¦W‹ì÷MןÐ,žšõ%4öÓc5X<ÞÊYuåÞ²Ò+K&O_4nì˜ÂÑ£ FæçyrG\~™;g¸k˜SudµgeÉHOb$-ÝÕÒÆÒK™!ðt_q'k¥eºª|ÚW•\&r| ´Úé~_U–ÓÈÏÓXe£k¾F® -Ùc„P¥1f®Ô,Æ4ê"¹Ú¤¶åõ„7Gl4?èI\àZÐPï×DC@ΑâÁ¼UZú-§3~R1xj¥ã¥Þ,öe,R¥oTµ‡¦û/õ:% 0úòœê`¸SoFkfª˜oø5¶Sªr'rWÑý5¹|Ò\¬jq® Wsxq—&3¬ÑŒ›í™™Þ.ý$eúÔpßåÔʲ\†*{Û Ï¸¹cˆWÒß“Ÿ×fK‰&¶m@rLHLºThêó’.¥š}™erE®«PšÚ¨b%~ö4^’¦ñn0ü ½´¸"‹´¸Ê`ØV,í²¿fʱ¹Ôð7„ pý[KCÌbα}CR”uÒWjð_”5GËÍ•%b©Ä5ÅK }\~ÞÊw¹Zl*ÒGµÈmC ¸éw:åÞñÒ|(Zhº?ª«4?«¼ž€ÆƒÒÓsÑ3x–ô„.zúº]¨äNãp°fu÷ý“mi}ÍÅKûÜMQÍLWÍô9~ÕÆr[S×O‹úÇ÷ùb’6°Ò/²xLâYÂð¢(ëû‚¥âOÔ”üÍFQ/ˆX¬¨JÃÂÔjÍœ¥x§ó_ìÑÏË^û©[l™Z±§¿>±ŸÞoy‰aã5XS7'ŽïçC©E'¼*ÆPñTçwª•Í™ƒDï/ÈÒ¼HY¥ @ýEM1µ_`VLà'«3?¯ºp¸Ú¥V‡ƒá†ˆšïRm®p‰¿nñ/NDïÞ”¥Uo Wͬ7§ yWÖù/½@FÕòåë‚3ãÕDøâµPE'g§Í–ßéH&å´ x‹ršÑ«Ùtš‹ýxñÇá3p$exlß–\(™jûï’)J¨ ²íGÑ£œ)Δ†×ÞªèùÑk¢HUzȨ0‘xø³D÷¼ä’o¬YVãuÐ7ð«‹¼o5Dq±3‹ÑÏRÚ;•*môçzÇØŠû<ÜLÑo y¾’''#Bîãt`µáM=oÛ$œ‡t‘Ç,NSk'—ûgzÊoZÔ°dJŸ~™ÇÐçð&pŒF^ °ò£í˜&´»+åiø$ÿ#ŽÇ~˜¿fð7ù«ƒ¿bð×Á³ÁñWÛ³Tž?¡ Ü^¿‰¿Ø1<Õ¡—§ðH´(¦ó€m€™àÃÚ8R1È>:„»ÑÁÛé ƒ?NXÉ»ØáuW¢ÆTIÜÅWBÙ­îvs¯{ÇN¨’¸·n‡$‰ûöÍ$qß²’$î%+!Iâ^°’$î9ó IâžV $ÂüÃðËEÓ®gjy2_…,­B–V!K«HÁ‰¾WäÚîoÏÍEÆvy=#r¡nÚÏB3Xèjb¡µ,´ž…JXèZò°…²YÈËBûØx¤"ļýÔ Þ :ÄBϰP+ ¹Y(‡…†³Êмîl¿jŒÁ|ë(—÷ø•¥…ÉX£u¢¬¸í€tCó"H ’-ù°ŽÜ²¨>²¸pYùd~â2¤€‚ tetƒÄÉ eÀ< 8è€ÑððmM-Ê€yÀ:à`6–sà´,¶Ä猅Ä=Mjü šÇûjDaíŽ÷`yz¯ã]û]Ž× "VXö»# ¬[5B»ìãÏ2B×ñ«Ý±V²½Ž[í“×Û GSÔqm+4o²c†{Žc2Æ«²Ïwx[1æ^G™ýZGI4jœì³×1 KðDÅ\,v„ݘԕm 8«(š½y–¿eÎß…–<‹Óâ° µdYYS­6ëk¢5Þjµš­Š•[É:(¢Ÿôzä»gÙ&™Y‘T1d—4új»ËÊqHÓŠ^3³‚Õh=T3_վ銰x|£˜\LK­¡šº m¼§&bÑghEžÍRûKc[°jüÎÃF„éÒ´!Kžºˆ±” [²$¿|Ö@€2ÒV–e”¥–¦L¨®úŒQÏO¿Œ~òPmGÍL¿öÔЀV(}h Fû7y\èb_³ó¾ª.ö•d—(e_ûfH»(­ j"l¶G*û q¨˜¯Œ8k6©2ŽTkv4nW4.ý7\2ÄÅÅQŽ—gÄ)LƵµ÷Uµ nĤ«ÔjÄ´¦«—ÆÊALNŽ“¢CFÌ¡´ŒÑJ»!Ùv#„e’ݱ³L#döO!±»úBî2fì§{4&éäؤ“ˆñü«¿¦ ‡uL 4ÖË£VÐåk‚Ú¦•ÍZh¾ª¶5bg0wp~c³ä MZÀÕT¥5ºªÔ¶‰õ?㮗ª6ª÷ÕùÛê½MUí½}®†ª@ǤڱEý溫o®±µ?3X­l¬œkRÑϸ‹¤{’œ«HÎU$çšädÌEF×úÛ¬TÀ—½Á;xB<ê5˜å T¤ÙZJâèÌX›Õ’=”€ƒN"ÍI€tå—ç—Kî)é ÏÓ1WÆÚ‰Î¬n¶'æ²Áœâª Ïò­+(÷¨*úoŦå+d£ÔÓúýàóáh\Õºœ¨FËY£•á»Íb5(·¤_´%$øðE5Ž„±X…è ”¶i‹‹‹þïë¿"Æ+å]âû:˜7›-§Ö€Ð²kê8u±ƒK7>—äë¡5€ ¶2k½8†±lŠÊ$÷{ËWĤX–Çx´º´^LGßOf‰þ -]¹Ò endstream endobj 37 0 obj 4296 endobj 38 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 723 /Descent -212 /Flags 32 /FontBBox [ -665 -325 2029 1006 ] /FontName /NPHAXS+ArialMT /ItalicAngle 0 /StemV 0 /Leading 33 /MaxWidth 2000 /XHeight 525 /FontFile2 36 0 R >> endobj 39 0 obj [ 278 ] endobj 22 0 obj << /Type /Font /Subtype /TrueType /BaseFont /NPHAXS+ArialMT /FontDescriptor 38 0 R /Widths 39 0 R /FirstChar 32 /LastChar 32 /Encoding /MacRomanEncoding >> endobj 40 0 obj << /Length 41 0 R /Length1 18888 /Filter /FlateDecode >> stream xÚ¥{ xTE¶pUÝýöv»Ó{–îN§»“tBBÒ!"¹$«i4vp#t¢"KpÁQÅ‘è¨0¸Ðé $,cÔuœqÄqCGŸy3(ê˜'ã ¢’îÿÔíá=ßûþ÷ÿ·»êÔvªêœ:uꜺÝ#„ô¨1HÝÜ6¼ÿ Jþáµù7®ð~ýôÆ $ŒZÔ¶ø:ßm®-‰Gâ&/¾ö¦E¿™¬~‚Ñ‹PÁ•KÎ]pjö­o!Ty àX–—õ/A~äó–\·bõލaäA~ãµËæÏ}bÄCß 4²ò ×Í]ÝÆÿ»ù;È÷ú¹×-ܱü±ý ò¶eËW0×°¯Cþ$äµÝ°°­Ö·€A¨ª!e”aDé¡ñè0íEÓ%?=hM=,ú¿}8èXðŸJE$!é´ñècøo°LHAfdA¶B°!;r 'r!7ä2QÊF9È3öqQ–v¡,65(yü\H,M§u’/àìTH?qô zçc/êÁ?@ÿg° G€Òï€ê½h=£Ï@[±åÁ f¢ ˜…6atÞ‘¼1ùºý=ž<€oOîú{Ñ+è ÌàßXŒ*Ñdh?-D_0Ÿ¢hòa P?MÃv4½Ÿoa÷£Ðoñ-É30ªÝýU£ZT›|1y¢»Ø-Ü1éyt:„ùäüäR :u’pò½ä'(ëõkô Ì)ŒûÙñȇ®Aw¢íØÅ¼©Ñ(õ¤…ǽ#M@³ÐõhêD{ÐëØ‚›¸cÜÉä/’'`µ2P>Ìi)úWàIäIVŸ“ü]úÐk@/ýô³W°»¸+5É_%_‚õ8€e|¿È•q÷ Ý–|,ù¬j ŽL†qæ¡;ЋèèŸè²6¹GÓaäßãlìÅAàø{ÄEÖ5ÌÛhPÛ³]‰v¢¬ÈAtÞü  O±gâ‰x¾Côdy“ÙÁìcÞa1ûà·€G+Гh?ìÁ7Л˜ƒþKq¾/ÃÛð¯ð‰‘¯Èw¬ÈÞÁþÈqÁÄ@âÇäää· Kntº­Þþõ }èÏè]ô ú:</ÁáÀ_‰ä’)¤l%O’g™ÉÌ}Ì‹l;–½†}ƒý[Ïmæ ‰³O%îO<›x+y ùÈŽú¢àèm O¢ÐÛÐûècô7*?Ðÿh<_£,ÇñøYü{üþ¨DÚ'—Œ&u0ê2rðévr?yF>Gɇäcòò-Ã1¹Ì¦yŒ‰1½ÌQæ3Vaƒì0v8;…Í&aeʸK¹éÜnîiî%î$_Í/àÛøÏ…Û…u⟆ ‡þ-K±DÈ®’t3pâQô8Èý>Xƒ×£† S° nìÃ!˜wnÀx¾_‰âÛAÿýoÇ;ðãø9 h Ì=LjÉt2—,$ëÈr7ÙŸƒää=rŒ ÂÌŒŸ 3Ù Ìlæ æz a³†Yœ½Ùüɼ͜`>gaÕl»’½™}ˆÝÅîcßâ.㮃ÏãÜ \?÷w–;ËÞÍgñ%üÕünþo/Œš„MÂ;¿Ä6œ… aæÞ‹Ô™ ö`ÙC¬ìZ<Ù˜ms Ã:L‡]ñ/TÃ$`]Œ´æf#.–j!Ä«l ðWàC¨ÿ­å º’@qü`_&— wq+v±»˜ë¹×‰= Úh 9Lá±h©&³È# ŸâÝèS÷Õè| ^ŽžÆƒx¾Wâµèbg¦ãu¨:ù8a±„'à“f€nc «þg•‹«ÐGè‹Ä£¬½ôS/Ú +ú úÿý€¹äW ÝÐFsAËÜò~'¢Z¯öÙZØ.Ð ×òo¢}ô¶PÉaoF'Ñ÷è î HÔXФ'KÙGÙ¿'+“ŰÃ`—¡Ý°ï– KaÇ| Rrò4w%ìttIìê&4-@·‚Ö»/K>’¼#ySrú#àþ€‹ð¸ vD/`T£×às/úo†}x)úz P?ú;q—Á~änä¶p{¸}Üo¹7øáÀíuhHôß@še `>z }‰¾Ã"¬ ¡Ìw$̽]K¢Ì4»QìÙ|ÐãcÓ”,‡^nî=ûùì“ '®D¿EÇ0Á h>Œ/B?Àç9Ðú)XÁ;p”,­]ˆþtñH²ÆS¡§­ µúaN¡Ï€ÛIm^E êð,èë;t9Z#Œ@M¸5$÷ƒ¦šŒê˜?¿ó°‚Æâ\üàµÂ5ÂiXÅýT”˜œI–2GàŒIByœ^™èܳ0CȆ§ ŠÄ4˜ÃÛ©µ3Ôš1—TU5²²"R^6¼´dXqQ¸° ? äùs}^ONvV¦ÛåtØmÖ ‹Y1 z,‰ϱ Á¨¨ÞßÐê[clÐ?~|1ÍûçBÁÜ Zc^(j¸¸MÌÛª5ó^ÜR…–‹þSK5ÕR=ß+ÞjT]\ä­÷{coÔù½½xöÔfHß]çzcƒZz’–Þ¢¥ öùÁ[ï\RçáVo}¬áÆ%õ­uÐ]·Nç·P..Bݲ’:HÅþ¶n샵qÔê&H4À¤bn]}Ì寣3ˆ1ú¹ bMS›ëë2}¾hqQ ›ïŸCþ±1SXk‚ÆiÃÄøq1AÆ»”Rƒ6{»‹ú;ïêUмְ~ÁÜ+›cÌÜ(ÆqëbŽ›;ÊBç–qÍ.¬Íd:ëK½4ÛÙ¹ÁëŸÚ|a­ÆÑ(ô¸$ÐÐÚÙCßLlœî…ÑÈÑæ¾†ôRJ(U)úúëiIëÕÞ˜äë_Òyu+,»3†¦Ýä‹»Ýj_r¹ë½3šý¾XM¦?:·.«ÛŠ:§ÝÔãR½®‹kŠ‹ºsбÝFS:¡7\˜Xx¾NKiÍiªqÚyÎb:#ÿˆ˜w¾fÒìšFÒháHÔ9$4ƒ'Š+¶VdiL×Ú©Œ¢å?Æ¿·ó[àüêâ’¹é> |‹h’ÊÉyQƒúséX8+,¤""Œƒ5…9ŽÑòÅE7ö’þ6Š؇š€·s££J€ý>]àͽ*š™XÇÔæTÞ‹æeÆ‘ZŽÆH+­é?Wc›Ik:ÎÕœGoõƒ$ïÓLu[L žÿš{Fý’Q1lÿª¦ê§û§ÎnöÖw¶¦yÛ8ã¢\ª~äùºt*–1®™É$éÉd´ZÊ+Ï7¦™f}Œ À—ׄzAŒ¡Ô °·!¦´ŽOÅQÙçûoqzñ¤ÞäIŠ¥ŸÐÒ³Œ _œ}Qþ¢Ùé;˜/$3fwvÊÕ5€êìlð{:[;çö&;æù½Š¿³ì"»:Ûê[Ï-hoòàæÌXÃ]Q b ÂJÐØbj^`Íý᜶»à/ô’5ql‚A²À&0r‰<— ÌaD™Nä +§«‡ª'+§ª' U£H+g!^ê3û̈0Üg½LÿY•C?"/ÛO½·kSÉîmð•Tc¾iCD #IAñÎw CŒÈª,ýK¿ÃË–²„í%[{ÌO^CGl:5¨ ¢š¥Z±p öI…’1¢²œ›Õâ°“…/>Ô5ÖºþM‹/©ð'¦žÀß|¦ 8’x+qù<‘ؽc‘f~ q0U›ËÕ"!y1Y,oÆí6 ’¨ øZ:+4k³Ú'þ‹Û¡§ó±\=ŽÎgpèøÅÓÉÃTDSn·Ø¬aê§×ÊZ´é…m»Æ6>“˜ÿí™OVþþ .y?‘sæ­¯§?¦æR‹7¥¤ Ö Lõ•bèJX…ñ2¥ ËÔq 8Ž¥PíbŸ¼Öž¬o™¤|Ö‚J[†—fÇkI>˜¶®Ä Ú'5âæ™hEè˜Z³ª/1®.üŒ=Ͳ’Ï&ñùE¾€Ýâ±M±‘RÛ^±Ù¬þÜ€%CôZ‘ÌPߦjc~h¯ë{“ý=’.´ßó¦kÖ:¬mXǰ-ú†‰Þa¥ÃÈ0k®y3J3HF/ÙÜS<|:ç©*“”–öÓáöIƒ§Z5Y¡Á\UÒÒ{¨Ù’ñì* wSÐÑQ‡£Ð›-U0·1¦›Þ3Áfé–½#£¸µdøÊr`ÙyÁg=Ïà ïÃæò²Ê#*"ÁPÐϘ}éLп•L|îé ³—ÍY¿¥å±'&>MpþKÏ^vyãÄ¢·ö`KWxìtõ¦×¹ƒÙW>4gñ3áÐáµ Ž´D¾’x–“.¿´n¦Ä õ%VKú–Éc¯,¤ë67y‚» dÈÞS'¯—6Y7Ùw¢íü«Ò;Ì;ºo) åëó ÖûJn¥´ž… ÁáÈp8 H!à„|î!n›ôæ÷:®OUŸ¦ <FA”åfgDƒ² ž­:œÅ¬hT–ˆ±qŽ O1a“jsFL½8_͵ËŒékã,ô5Òºr—fá,[¨KÀ&Á#” lë»z2פ×Vc²ÒrºÖdèT¸¥ýx˜Bš©B-¸¥¥s<ë÷"³‚|^‡ÝÁ#sy³b//ÁÖ`ÏØÄ_%>JlÄ7ã6ì^P–ø«ûÉýÇ׺nÜC2¯8ù¾¼Æëñƒ;¯Š5ܰîËĉ/¿Úš’ùÁ9 2ªC[ÔKDŽÄoñp¸”ÛËŽ“6@0‘¥€íÖÈñ2ÒaÛk(5¨ÆÀJ^L7° äM¡¼i„UO:U}ªúgÄ9Ë®â@Î@ܸ‹Äá”jØÈåfŸÍ—²5g¿ C^¦œ;x&qè»DûwÚüïËó×§ªÓ1A1¨ƒ­ŠèP•²FEdï¨Ñ©79Г†êYà"^å¿K_ɰe9ƒd±Šä‘ý¤ˆõJ% †–° ¥«åUd5û„´G~^:(Ÿ–~í;Ù-ÒNùéòûäûžô|‚|Î~*})VI«å;È]ìÒ]ò"4ë’«ÙÅÒùFr+Ô‘F¶Nj”//—šeÁ)—#d‘FË5F!z–—$ÙFܬCºy2nF³ê!,#Kœ^Êx£¾LSFDl 4*:CDT¡ˆŽFPôˆªÐ„NG“ÅDÁM¯©ö›-ÊbxZpÉ òÎ -ÈìMŽV‹a/+JRÃZ†%:Y.c$ tÃèYBô²,I‚è1bc/6ôP;þ I—±çŠ–,`¿ê˜>#• ª°VÄ⑵° Gt^žô’‘ªN8"¡2UgÐaøJPá§ÚÃa¥ú?”j·Kjj¯v;•¡p ”ãí0yªÙkªa¶¸aá ·þnÃ0'ᨦ‘2¦ƒ<‰Énw$UIÚÓ~%…Û[@Ž0¦"œ@æûð!ð˜|81˜ø8ñ÷Ä¿qÏ:™Ïh`oÿq SÛAoûA¦$ügÕ(1¼èb"k ÜE=] Ó›"›Bµ(bÊÑ*"#"0ð xŰ”b–RÌ–ñor˜ƒ=¢ºT]“®UÇ´é:t¤Kׯ#^]©ø,¥;¥P5NŸ‘Ê´­ÕG Ý\2åUzs…ÃT‘§Ó9`R¦§«„ Ã(ñÀ¡”õ!_©½)é? Q©Ñ–ÀÇqZ«Žýº ±CW¡v‰{XDœÇØ™2FeØæNq‹Ø%ÆÅã ÿ;æMñCÇ1ÂŒ§ˆ¿dvŠ]Ì^1Ƽ êÚƒT± ‘@wž¡¤,B¼4¬P²M•|Ã"dDZë†/ä ‰ 8 ãŠHHMÊ…ÉD®$³ÉJ2…I¤^xXxZø#ù€|NNß]ˆä …ÕÂFáÂc`Ë ás:' Q¤I‚™ZEæíØKšqFâý¡n€bæí˜ÃgëR7×Q8ONÀybøquæ6n›¸]¿ÝÈŠX0Š&Ár®–VY„UæÕ¶õì&q“~½ñNË&ëFÛFÇFçz·^°€,¸m·Õí´¹…Œbƒä*{h¯Œ‘¬È^™‘éî-ÍV³[³Û²;²»²yoöÉl’­„º6!fgУ"kÍËç í§ T3X3HM–v8#pºVŽ(O[-p0Àq ‡Dt\Ù³‹7õà:|gbMâH¢/±ÿ¬»ûï80@ÞØÞJ\Ÿx8ñ«Ä28&–|ŸH&“gÏüHù@φ3°(V©žë³ö9™K9¼˜{#sÀ`4¢L…&$yÒ6 =åT»'»4M—­˜.<(².6LRv‰&ÃCÕ–ª͆E-í˜.yiÃÂïw -mW<ˆÿŠÓÖì™·mòÕxññ½7Ž»j|EwÐîûxï†Þ¥fÛÐûìK‰Öaój›–d˜Úc‡ò¡3êíU¦ ¦Ë…«uWë÷H»Œ]þýÆc’Ì‹¼ìíòcƒ±Á$ˆŠd¶­&«2Â8Ât©i¥ñ&åmY·ZZíº1{£´Ñµ>›—ìVIo2N7®4®3>`üµ‘3z z«Á 7ém‡=¡Xq«µËJ¬VäõQvãlHEzX !ƒb †w2C]|Œïçò,¿¡Í½þR?ñûlr-wøüŸ¸¦ÉBÚ–Óԣƹ–ö´½Fu@‹ñVåwØœ¶ÝÀ–ho¡ -Óø æš#ÃÇ #~¿ÙüWÁD[öw;^z±õÖ«{¾wÃŒ«UÿõÝ««§ŒÏÛw‚;8åõÛŸ|?käú§Ã5OG}C0“óšÇN¼BÏÑóø~Ø;yÀcêTG ¢ °SºT¼T.—f)[•mæí¶ö]Êûû¶OùӼΠ׃­+2$½Îkx“0 &sÕ̦ÌÖL¦-³#“x3K3»2û3ÙLLÀ¾u•ºú]Œ‹²Ä}RÔ,Ü”F¬¦;¤:í´gøÌV"HØÿŠ‘øsƒ@lÅý8_—qï-k:Ü8¿ô¶cÏýåƒ5ÖlPŸ9ûºÅ[ŸcÂg‰3nÎÝ1sÍiº'&$?g‡±c•ávu‰à³¸l»{bæø¬ ¿*Ÿ˜¥®×åÁE®ÅÁõÁ_ºîw?åîË|ÕýZ¦žç 6;ﲇø[ÔµŠ¬'OñÏó¯ðú"($;¯l¸¹È§†‡EòÔÜ|ˆ\Ù‘eygóH^C6U¥FSä’lŒ²•ìXö÷Ùlvv.G*”R}AÐLŸše®ñ©™ DNwÄ×KV<Ï zƒ\Dw%Ôiª5-Š …ªZu9Ãb”oˆzô;õÎæ$ϪÑÑ»§Dp¤ÖõžRŒqyoŽâÀSsËŒÃU¾´6­n¶}°…}áT  ya[Ã>Õ>®Ih8u*ÅK²q{tðÜ•‡RfvdFÞ‚<Ò޶ˆ-c[®b{ Õ¡#Ê©ø2V»Ã+âyXÊŠU€•)•‡©¦°YíÔ©Q&Ãyópo#“H|©Sfü-O™µã—¿¿¬iYã |Õˆ/ó*›ë.«/WtäoÃ~ ºé@¢÷®;/˪t‰ ñ³ïnÌ x³¦ÖNüÅRæ UžU¬Ì[¨ÙŸ3Aj@\èßթͦ¨%j_bZjYj¿Õy“kÙ¦EyÅù¾òžó þ ñ‹Œ/lgøŒ‘#m-í Ψ~©^e©´W:™UÜ*Ón½i“k·e—½Ï²ß.µuÊŒPø¼Å1–h‰+'¢A“9b8ˆY$Ã*ZÌ:¤BS¤B;T¾Vë ûª¼ÓRìC%š0ø¦À&sg >«ËÝœZ@ê‡P7$|j0L‘–ãá”0¥ŠÛÁ Ñ·#*9ÊzzäÀ‚°Ãÿ0Ο²ôÖµ×4-²akøÔ_$þíƒ/}J¾*›>ã¾=G¹bYÉo_ÂAÌ‚õØE÷Ò àÝ\í|Éï£Øå£rÔ2Ë>ËÍÚ.<$‘¤¶œŽ2ЉèGÙ"®‰L~¢­Îõ$YArãœÎMبŒ&X ÙQ`4q/.PM&ä¾7ç(>Ñ•Ý\}žÂöÓÕ“‡ª?ÓNšÔªiÅqͪa)¿T^jYd_ä\šÅ·D}¾Š4pš:Àf rþXeç&~¬íž} ñcâ¥øíØ5d)©»yîÆu‹lxäŠ(a±ë¢œmÛsÙõO>qà±@o-ÐY±¢,üë>¤$Ϩ ºª‡¤‡ [•ÝÜ.ùtÈÐëE+O.åä)9» ûùýîWå×ôïÉÇôg„ï †,S–M…}bSæˆÉö‚íMcÓ¤!§FƒF@r· G’¥ÉØj$F§CÅ~Wf—[4W6Û›ris R0\œ‚Î, ª&P*]ô&PiϱX€Í=¬Îâ¤ìÎÓ È‡Kl)!*É™“³,gg›cò‰ªÁ†§uBø"ßv¼>ÕêTó­5N5Ç("'ÕXšqV3¤y…˜´°ÐÉ@#KZaQ?×”fÙi*,UtÒq±I£ek}5ajÜFS=Ò¢ oTKF:¨‘N¼£&eƒÉƒgg¹vf –0¦"î…c‚Ê8b|Ú ’A÷€À;ÈØ9⋽‰ܹ[ßÄ~HenŸ;vvˆY=ëÊêjŒ§•<üØó÷} ²N¼š8rëæñøÚ›×Ž·œê 'l€ÏÀÆ´£^¼x\Èz¯9Êv89‘}ÁIlv3±Zìfc† )Æ Œb•D“ÏÑ%ÁY  !óØl²ã¤Ûi6G~OB×|†U–ÊkÀ o$_)1Ï1s/fUƒ1#H¬sP—½ßNìT&$}Äîr¬î#KQjÍÚ«'Ñij-Õ§Z\Ç‘¶ 5) Ô@TUf‚'­3ʩޅÍ!hZÁVnóÃáêw>RõÐÊÕ˃ãÆ\Rñ—¿$N<›֯›ž÷;¥jjãÇg0´½Ÿ˜Ê¶jçh ž¬Î[•½!›Xô†¶áë ÃY/Û‡)Å夜Qñ82޹µF³ fÁR]c:c>“am(·Î//j4ÔÙóëŠNê‡ò=préô]¡Þ2Ú¶bƒÞagyt<¯íMÐfMHztúÌ/Lm ‡GRA²ejÇߎ*)DQ.¦ ×Ù§‹/,ÐÝNªt$—Ëí¾w8*¨W•QyžÏâ*=¯}N¥õ2¨ G)õ6í©œ;‘69mð8,Ž&¾˜úéÔ†«¢lRjƒ:ni×ô–i©ui`qÁ¢ðÒÐ[¨ÅÁÙçN¿ PaivT€–ŽË ëOºì&\+fçϺ¾2aXÓÿÞ­ó0~á÷XÓvèÞÄ7;{Gëâ{6.YxGCh¤-Çgî¿jÇ3Ïßû.Öa÷³ž½ôðÁ««ûî1’;~ó«Ç}²ëW°¶÷ƒ >zÞe¯êCð±Æ,רR“D:¤˜Ô/•¾–8Ô*­•º €cxq,Z\EGÑ`¶dŽX™pfhkáË‹°.±&ÅÐpúÊ[ó@<µK#%m*ܦױÔ×»Ÿ^Çb»³‰³?Ndƒ?~¨Û›À·™£Ý{ý‹ú½÷ÌšW¯Þê*ŽŒÂdð!i¿W~A~Mú£ü¡,OgZbœR¹x#Ïí—>aÙ³ì·<7Y˜,.âoeïbw°pó ‹²‡µða6Ìò…B¡Xbhd9lI–D™“%†guËÓ«NÀ'”ul/¹Nus%b•|©…¢ â„=0a—¾æiS‹RîRN·;A¦èÍÈ9 uC"‚Í/Vÿäø¿—|àåG5wôÚ `Y•§nCà+˜7až€g'ñ­Ä·w€ù{ߘ¸eè*üñ¦Ä3Ô¦?¿žÓµ{;µ€®&×Ä‘.ÆõsG¹¯9Îõrk¹.(à€$Œ&ˆÑ¹uC.ö¿¬[z¥ÊS«Äü¡ÆZƒ¿ôBîC€ÝcÖÛx»>ÂDĈ3â¯#õb½³Î¯÷2%Ó¥Ö‚Ž‚O𻄧ôÏóÏëcG  Œ¨ ¤  *^(ø¤€/PÝY‘Èwh•œàcw6UœqYðiú“³9”™• ŸÎ›” Å¬Î®h5ãe J½¤A5¹3ƒÙYP¶, ·fá,(ÛG‚Úq„BÚ1,ÕP¨Ž€y‡ iH­…P !/ ©£.‰”„Þ }bL!O¨#Ä 7TJ†Ø+ÿïÕçŒéôåEJ[TƒÏ¥|º½…yÚ•˜¢)‘ nçoSÅŒÃ>µ“šµì°Û€Å‘Ýì¼– žK®ÁÌæþE[K¿råãùى١©£— KœÈ©Q»¤8q‚ Þ÷›3gΘseÝö¡(™óè°êñ›·&iØ1»¨aÝCCgSw°lÖÌŽvªN!Ñ1[\"²½,†ÕRêÄ:Ó ÇSg›£×ët`¬´#Õ›Ù‹p: \³çæE¶8»œ¤ÍyÒI¾vb§¬ ꔿàOk¦  téñIÐó.GZ¦€_iNM¦`ø´V0ôÓÆ8gçù.$Þ¬1)‡ØØhâDÞÔª + *¸Ío·<<ÅCržY8²i]<áaƒì·dÝ/RwCÓÀ†{h5€Å¿Mÿ9>!~—ñ}•|΋‹sI$ªÌʘe:·‘íüvq›¾Wz—ü•ûHzW‚;ÁnPv‰$â__Ñs+ÅMü:‘1kr¨sP&YYÁZ%¸[3Û2I¦Ñ‡.2ÑÛOŸ¿ü9HK•E`·.u²˜ªÜ’±aÈfEþܼ`à]?­sè‘âHâ_ý2ñ]'ön½þú¼þú­$÷.Ìw&^ýúŸ‰—×%w?º{w×#»wSz7'®e·½ Øè«ÃFfŒÏ –Se¨ÊˆdÖ1 2ê2¿Ï”fñ³ÎÛî§…ï3EØAnÍH¨­®Úu:ÅdtøDwØåæ£ÑTÍX×µ¡É•]“¢³}Ò`5,¥rü¹©£Rså’©Tj“XɽֲÓBæXÖZöZŽZX‹‚‚˜Ñè'¤wa‚]æš>œ•2ÄÚ/èÓ-®I)S 8ò]U–bE;jŒ9¦7Æ*´·qe#>MªÏe¼wQ™wM]kôòK/=­„ n»¦®âÛaµ{ÿKAž ±¼¤öófÞ/†f‡»e»u[èÁBI°6X‰å¡ÏøªïSÿÃé\¾À0Ó°Ðð n›eWnŸ^¨õ«yuÁŹ ‚,¬ësïÈ“*ƒõ|ƒn¢aŠ©Á76WÈÍ +õ¾ŠÜ EžÀËœYò9 !}nn®_ÈËU‹–ëW[o²ÝX°²p£m]áö ÷åîó:𽎻œþ¦0VÄ;|vÕçØÕ,OÄcÇŸ€Ù[.úš÷H@ufGî"í%èݦ"\Z„KŠpQޝTÁJ9¸¾iÝœz£'פN&zÿí ¯î¥,? úV»ÃHëíM)Õă(ý6¦‚ǘÇvÌákðÍÀQǼÔqËØAX·/—ägô$ß=‡ÅlC¾®ÉÝ ØÍð¥&ܹÐÒžÙ‡r“¤V§¯7sé+ªœ<šèñä¥ò.·–W3!qÈmÈÝnx ÷w¹ïäò¾\½eÝ(m×¢rjáö8ŠkpÚ Òò¹…j6œ~ÓwÚM˜mÅø$fV × 9m™a‡–«“‹ç°'YBI°«Ðµ½Ü¡B¿:u¨•½£r¨ˆ _“ã]±Ž™nô·É›ÜI7IßN/~´‡¾Ùli§ï8oHeSÌHUFS^E;<--šk——üƒ*é,5¦|ˆ€_í7Té­ú*šŒë«€C_vëª4÷ Óëýö–Œ€]3|+à° ÐBÏ?.å²ÙÀƒgéïÑè•Q)v[®Ÿ]eÀj›xæŠ5~úá;ù‰ïÌsš—•z³‚øÅhó©¯?Â%ái3ó³J¼6«¹q̬‡:ß³yø˜±»?Ç–µhbãú_þ%¦Ù“žäçä>îWp*¼¡x80ri”q¢1j\6ädì6ä°dX±ÃB¬ØÉH‚,è”á&äèrÄL+€~ãG-nÃTiö ýÈ Õ¨×I%r _iè êÊå;™ Ã2ÓVcÝiÝkeZ­Ö-Ö£Ö“VY«×Zje­.÷ê®sEc¬4ÅhÐ}ÈšìMùy§Zª•SšŸ7¨ýzšSÂ\žöóZ08uV«>}ijöW”WÌäæ~](+4Ñ9ï–Ën®ÒI·Ý†Ýlp 1ãöpV懅åSë‡?ˆßxû‰Ä&àÏÝ g¦³A°Q—››·rŒÄ»øjRmn$æD0QRͬΎd›\Xðcƒ6¢*Òh×,…”³û?X ’xÞDñI‹›Ú©Cæ?Y-©KŸ`^[º1f&:²ôš=—a—gZÍø ±kçÌyWíÙJºÎ…£§¬<Žû©céÿØÙ@§gª6.ß]hÄÓH¤8Çzj.×=*ò0‹yF'в^gÃ6baÜ’[ÎEźWuzØÝ'U{¶7"#NgE.]ê"h”n’RJiŸŒ z­/䈰I˜G2ª¡o{«ÂÚ‹€LÕ¢C2«“%‰ÌCZª¢÷‡ª3+?¢3x´7ù¬Ááp+r©Ã4©: ZDœ!Žç8°WEIÒ!®—\çË%z¡N1ì4 C‹I¹Ž[N¦.‡é«I-üI´;éE—k’ÒrZK¡’”~…ˆþt#Ü~îשԹ›-GUJÔŸ—½ Õ”ÀÔ¥Å9iio¿Ó¨k+‹éºêñÚÄ}øòÃ¯à‰‰íxSb×±‰Ÿ0‰p^Bz OHHýÆ Ìxý'®;™cªþVt‰Ú/ÿ_®Ïøçy(%¦òÛ¹·5]sîŸl…1‰Éhœ‚~ø!1U©ÿ/ÿqË塈T›´]a„åÜ«h+„¹Ü,ô ¿Ýéí|ŠÒ|ºî~v9ša&ûw4`-à9iú¢u›(²Ñ(»Â4›™l´êJ¡­òwCZýJéÿâFÀçôú?JªÉ#Ì+ì+ÜD.Î/àß>o¿‘ÎÈ«u‹t½úÉúu†« ï/3¾nªVÌmæã–{2^²>—æU.ú1h>âÀ'SP ‚½ÁOV–AÑZXÒ| ÿþBÍSkë›Ãµ7,{mñØe×.˜4#å'kO2„ÞÿÙ¿]äj¿ÔÁÌ@A”r4•¡rTF¢: GÐDtšŒ¦ &4MCÓa.³Ðå¨EÑltB¿E3˜‡‘ Só«ŸÙÞ£XËÔ^æ¡SF™Z«0¢&ŘI¨A˘ûÐZš7Æ‹‡—õÑDl,S ýfä…ÐA]c-¯B í7ƒ‰L»¿#n2kx¿ˆ—FR‰ÅYÖTkeV#Ì,d®G~äaÖÌ8`6ÀyÌdÐæ©ö˜”²¯š×06TÕµŒè÷0uŒejÍVÆ©qVÆó ËjefãÔš˜Š!^æñbT˜©Êlì‘tt~㊭ìs'# +´ê€Vé#£”’=’¡lK­ž™dζx`ŽíÔb•¹>ÁxõL˜kæ=À&'nóôbîךý’ö㉋åôŒeýµ3jcÌ=Àñ{´Ñ¶ôG–¡Ú ‹ S×Bj-/¦R°L°4°40‹Nú7PfÔl‚6%ÌͨY…¶@Ø iº´Åƒ}Z"/¿¬q1Nà„rx‡¡ÔÝ#éÌœqK†ÖÌÙ£7–Õa–£)L~EÃY¶ìS¨‘RÔã̤mqI¬s¤Öít Ž0YLŽÆ‰l±Zä121„Éëä(åy›¼K×—þÕNƒLÃ7ÒðÏ)˜ì'G{`µ—ü…ÂÚ,ò)}Á@>F;!EÈ!ò2ìùôÒYHªx ò ö,x0î{ÍÓKz{ÀÜwÄ vJ,y9.I'Ú£ 0Ú£MÃhŒ6ÀhŒ6 £M}%ŠÑ ­€Ñ ­F+`´F+`´jt¾­€Ñªa4F`4F“†ÑM€ÑMF`4F“†¡† *`¨† *`¨€¡j*`¨€¡j¥€Q ¥€Qªa”F)`”F©†Q ¥€Qªaxà ^Àðj^Àð†0¼†0¼€áÕ0ÀPC EÃPC 0 CÑÖg%Š1€1Æ` Æ` h€1dU7s´ö÷€rPŽÊQ å( ”£€rTC9 (Gåhšô3ˆÍk!t@ ¸ý€Û¸ý€Û¯áökâµÅF 0b€Ó0b€Œ`Ä4Œ`Ä#¦atF`tF—†Ñ]€Ñ]F—&¸+!PŒÿ½Pþ¯—†Ü†›E8\I.ÐàZô•× c¼ukðô”n×àͨRƒ«PPƒÐŸW ˆãžJS­TÀs ,ƒ°Â^/@´Ô›>$j.k¦;…½Â ·Wˆ‰ŸÂïä÷ò/ðÜ^~€'ÞÚLbÐô(¨t¯¯…økpˆ@\£¥jHÆ€ž­€O„DTó ÷ëBüf!~¡ï-Ä÷âZ‰\ŠYMÓyQ%‰ãfUã9¡2šéžý_9<ñàO/>œjàWº!<áv•Ê C@ðhe…оYÍMwyB‚‚—ìv0,fQí#üTÏï H¢ã„òïPt§aŒÂç=O6yv@_8°ßóg˜çžâ^Šï†yoÒ†ˆ{n÷ö’§Õ O‡§Ô³¢ø¸g¹g¢g®gš§%åqÏ•žÃtš(Š›ÉÓû=MÐá "÷\èÕ¦Øà¹É£zBž*ïaÊ_42ÕoeñaÊT–½ø[è¥2>³²›ÕBᤰE¸B+ŒüB®#d VÑ"*¢QÔ‹²(‚ëÍŠDD¢•zdaj`[yúKij4fµ´Bhœ²¿Áá XƱ ¦‘4N‹cýóQãb"†úº>b¤ ÚÜǶSý4ZζÕE¡Ùq­H³š¡ÐL‹¼´蓱´¬Qª]Сh'PPk” Z;ÓvÝǼõuÝ^¯Ö&€Ð1­Í±º  H àÖuƒZ+¿7ÓV¸ÙïÕ&V uäñ@“bÖƒ]§uäÁÚ`±’ŸšÒM*Î7©ÐÆbðOm<©6Öüsm¬ùÐ&üÿù,Æ=ÃW®y™þ#·Õ_¿BklóKœ±Žy^o÷š•é¿ê[çÍ_BáÜ…±•þ…u±5þ:o÷ð—¦úeZ=Ü_× nóŒæî—Õ…uñáêðzÿܺhOMusíEcm:?VsõÏtVM;k¦cÕÔþLu-­®¡cÕÒ±jéX5j6VýR*÷MÍÝ"we ö 2ܚ鋎µ+mc¨@÷ö9×ddÞtáhLï3@ Uŵŵ´ ö­2Ò¿]§«œkFû2âÝé*ŠÍþ±çï˜mDß»5Æ|Óg7SQ‰©s~Í–ÓG«v¢ú¥uð…ü -Àç–hùÏ>+~îY¹rår­ /G¨1V8½16‚¾ªµ. eÃΕ1ŒVÖ-Iõ½É~¨ Ã$ð :M…1ý%*ƒ×%.¾K ÔUXÑãÎ.[vNðµÀ#«â%š¿LVõä¨ÿ²¢§¤"Á?¥0îö•ÑkÊJ@¥0‚ª¹[[Š·TvºŠ»*éeæþ§ Ðó=Jã%O1hExù9F@rE¥~àã=ÏÊÖp8^ŽSÿíù/>Çô?±? µîWœ[Tùr”jœª ¯<‡´2¢U®ÔP´ÿô8àK endstream endobj 41 0 obj 13539 endobj 42 0 obj << /Type /FontDescriptor /Ascent 905 /CapHeight 722 /Descent -212 /Flags 32 /FontBBox [ -628 -377 2034 1011 ] /FontName /XQKAEX+Arial-BoldMT /ItalicAngle 0 /StemV 0 /Leading 33 /MaxWidth 2000 /XHeight 525 /FontFile2 40 0 R >> endobj 43 0 obj [ 278 750 750 750 750 750 750 750 333 333 750 750 750 333 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 750 722 722 750 667 750 750 750 750 750 750 750 833 722 778 667 750 722 750 750 722 750 750 750 750 750 750 750 750 750 750 750 556 750 556 611 556 333 611 750 278 750 556 278 889 611 611 611 750 389 556 333 611 556 778 556 ] endobj 6 0 obj << /Type /Font /Subtype /TrueType /BaseFont /XQKAEX+Arial-BoldMT /FontDescriptor 42 0 R /Widths 43 0 R /FirstChar 32 /LastChar 120 /Encoding /MacRomanEncoding >> endobj 44 0 obj << /Length 45 0 R /Length1 45436 /Filter /FlateDecode >> stream xÚ”¼ `TÕÙ?|ιÛìsg&³o÷ΞL’™dfB&rYÂŽ l š%‰ˆ,RâŠjwÀ*ŠJkØZVm­úŠ­µjk¥}Ñb5-í‹[!3ßsî„Å÷ýÞÿ÷ÿææž{î¹Û¹Ïò{–snFP7b²ðšùœŽ[-oÑu᪕ÒU~tBø„„×w,¹æï#ݶ!îÞ%Ë×,~§åò d:ÐÖî¥WÎ_ô•g=œ¿c%\_·lå†aìG–^³rµ/ižûÇàžeËW,œÿ³è»ß"´ó¿óšù«;ø›Ä§z¬ö¥kç_s¥0®l<ìo…ýŠŽ×­äB3ì¿û{:º®ì8Qïýd)Bf´aD߇¾úé=Ðåj Aç~ b§Öx$ Ò"ÒÃùFdBf$B»Y½W¬võLr"r#ò"ò£´áÞ2 ¡0ŠÀ^ÅP% V®^QqþyIX+QªF)”F5¨ePÚr¨ Cõ(ÐpÔˆF ‘¨ )hÆ ±ÜÝ@á)(«¹ž‹Š†èTDW .ô):ï1ý [á>ͨÞ>_üÊÉèŽâ8Kýû:Š—ãðNcÐR‰“ðä-Å~ S¢øvñØ{}Š#ŽhÔ>šÆÑô# ìÕè×ųTÐô¾TlG›Ù,ÛS\”8ˆ~‡'Cm*ZÃ} =ˆ–ÃUc'î/~Rü+z‘ÅèJ¸ÓÍèèñ>ÔOª™1ÜNàE (x šGס± ×0J1^]|ZŸBÿ"Iò:#@?’h"š‡îB5ÞG'ÐWXsøQü,,ïâ¿s@ß&£ëÑZЉGzO¡=è®Á5ÄIœ@-'pxÛ‚vÁó÷£cx2nÅýøef—.4ËŠöâ_‹E€èáô2<ã4NÃ9ð&ĬdìJ®vð&xÃEèt ½ ýøÐý+ô-®€åÏä‡dCqNqwñSè‹$­]Šæ¢hºý¸ú zýŸ!Z8óö5n-wªxÐ6²3Mƒ³gÀ½7—ö¡>XÞ‡·´` Þ¢_‚/ÃKð¼ ÷áñ‡„'2é$cz™7™?²uWl€;9@ƃ %sÐRàÀÚ÷ÀûîF¯¡7°Çp¼Ñûpý×d8 Ëãäò'æ6f {–»½p¼ðEáL±ôk,È] Pó Â?°úPޝÆ×áÿ„žo%#2a&ÇŒbf2­Ì̯̽˜ÿ`»ØgÙ¸‰Ü|îYa~áÚ»ÅÉÅ[Uíæ¡_qЧ,èδ¤iô¯–.t#º õ »A^îA;ѳðÞ/¡7ÐïÐÇèKàÂ2ôù*xú5 u·á»ayïÁ/ã×ðøÏøkº, RGšÈ2Ž,!·Ár/9FÞ''³ÙÀtò9Ä|È"–e‹\-,¸ÍÜSü›BB˜ ,мuv`°b°uðOTð./l+¼\økqvq ô?ª"Áh#ôòAÁ]°<’x½˜û{µ¯ÿÂs ñ.i¨®5áñx",Sñ¥°Ì‚ež Ë|¼/…eîÆ7ã[ð­ø.|Ÿº<ï¶ ?Ár…åwøüþþ!& Hs”ÄIŠäáMÇñd¹ –%d,¤‹¬=Eö“#ä}ÆÆD™*f>ÓÉ<ÈüŒy…yùŽ%l%›bÙÙìööö]öö äš¹¥ÜvîÞËgùYüÕüüsüIþ¬À Ó…ÂÂ{BQ´ú%¼÷Atñ/Å¿ƒ¯ãÊØÕäÐ ÓÁmij€b<™É,gîf~Ã-Ƨ „{˜«˜eÅÇ™qä[fžM^Â!&È50‹Ñ¨ˆŸ%&§É_Y;žI>Ç öGø0YÁŒ!<}÷[ÖÎÞ“ð{Ô@Öã~òs sKñç¨ÛŽ?á¶“w‘Ä'6ô hõFÖý¹ŠlF-l–;ƒ®º?Í­z$wà æ=v;ú” “ÿ§ð6@·ñ$6B~@òøY@ÜA@¸uàû‚ŸÇã>„ñnæ)<…€[½Äˆ‡z›‘ñ{ŒµÒ>â±ãéä™Å¼ÀcrJü­Å Nƒìœûе ÷’8`Z3 Éoq-X©ûïO^ ˆÍ}Àm9{Œ©D—íi#o‚­¹æSÐÉÛÁ¼¥ÉèÆb7^¸?ð“ >|5Ja= ¥ú¶ì…ƒ„ çÁS¿üÿ5 þdüwt–@³úQ‚¥Gîd›™Ú7òµÁÞ#èþ ÷[4 ;b¥Âvò?¢€ÍùOx¾ìÞÙc+¡× s'\ñHaØAzø&&h=ôy$èùtv ï¶âÕð†Wš6ñ tUñ~4xwYñ–âf4¯øXñ ´Í(îü]UÜ6v#×JfsI6 û~ìÑðfÀí è#À£(v¡¿Áò3èÿHîyÔÃþ°³©xgñw`û`ßœ™èu ú;ÐmÓ2…KÈÞâ8¦,Ô'èÒâSÅ Ö¡¥Å值/ ]ØÓÜ.]¤Œž5Si9¢qxC¾~X].›©­I§ª«*“å‰x, ‡d)ðû¼·Ëé(³Y-¢Ùd4èuZÀs,C0ªlk—zcí½l,-€ÞîK[JûZà݇”T²µ—´Ó#ýçŽØgÑ#Ý玜¿¼= r|@콚Øù?³è°5/mèÅŽÿÃá+KÇ'ÏO¾tn‹ÔÜÓ>DÛÉ3¿·W:^þØP —Á{Ù(PjbDï²¹-´þ¸è¸póUí@Õ ½¶1-Œ—´–jÄ˨·ù½âüéN‹Þ‹òªü/ê4 Àj –ÆõŠíJe«N–ÿ//ê+ž¢W©› — ½SoCòûûÿ·ÿ½îzè0#“gÎíéÑ}ïØ8«žžqai\O{Ïü¾b÷‚°$†{Ž0-LKOGsû9ö÷nööŽ»³^b)nÑ&h4UÆ13[.&³*»­UˆPÎq4 dÀGº—àçÉ‹4$/íCÛG^<À @+1rkxî%8NƒË‘/Ã?@®¤øuã`ã%â鯩ƒ¨ êâY(jÒ²E¶D¡À`5ÏJLÿY…CgÀ£èW£ÐÛÀSxb7#ؾG÷¹åþÆÀúŠßîG³ê¶*Å}Å“û+rYÔWü•⇊Û…§Šo X08 Dç»Í´¤Î–zæ~ñ˜`»¯ŒA}Lî€Ñ¨cMPQÓ¢»†ý…ódÁ–Û¼¾{å«×º’ɯÛ¿°Xó©Rš›hד¸³-©þpfâ±\¶.Së°— ŒÌ\´C”:©¯Næmù‚aPÉOÆ‘5nwSCCͬ……?àÄÚJ¥axMüî‡Ôo¿Ž{འèRÅ«3u–ÔééKèKõé¥ÿ@RÏèûæ“ÓéÑÒ—Qtƒö¦Û8ó Jñèí%bó•c?CMSiqtÖvqç¶×9³UUÃÕ%Ö%¡éèJ}˜Y˜Dn„¸Ú†”ð6ËSr»a“…èÐZÐ1"¤Óî6…¦ó˜ï.›ùúÀ¶ÁÆFø;Ð4PnÃöX‚k¿^·ýÙ3i}aEtÊâáž÷p.^[1ö˶×ޮ穇 ÕЇÙjòJ¤œ­ÐLàx¸:aÇP«ƒH|šWx†ï¶·<ñ?;Ûl9‡Óaµ‹HÈÕÕYsÙx5©~àÊ-ÞùfÝŽ©²{òÜ¢ŠÉ‹ï)Üð»Â¯ øÚhóxÙk¿ëíyò!5†º¶ð,~ý "ÙJ¼•´:_u0Zg»û˜›Ñb$°¬YcE‡¬ŠAÏ6˜íA{·±÷á E4Ï3³Ûõt $¿mê`ÏÀ k[¬Î<íî´A§ O±pHàáóœá¯]Ò©}ÔZVÓ0¹nô’-…g+C[¦ÛŒÚ2mC¦fÜuó–ìU_4w“ˆµÔ¤H„ëö/ªÛÀLP/à "âé`3¶âøæ!ˆÍDÝì̹”Rƒm”N©(ig’6Ù.Ï Üà⼿tïOàà—êQRñ!…×3ŠViÈi•¦Ü<-Þ¡}NK´·¨–ˆ_w‚pÑ÷«IGÕ7(½ F)eTuõ¨Q¯¨euJ¡÷eŠ'ÈHà+ƒ.S´ˆ{3¸¤ØÙÇÄ#aÊŽêèA¾ƒJ™Ä¤™v¦ƒÙÉgxæyüSò&Û‡WìýD•ñÓ”¨M¹êäzñUª–’‘ûtüw÷¿gsÏ K&O2‡¹¥HDttß| 8hü>޳ÓÑèéÃfŪõ ˜#J¬=¶3v<ÆÆ,´Ù4­·~ „ÉrGâwˆ§ `m_O·1k”)8Ž„"„'€^ˆú¼~oÀËð¶˜9ª¹ÜN7áeÖ²yÏ\f‚šÃµ–`¯ «h_€Ü:(Tt¡E…ºVTÜdËZ‡Œ8–24ŽÇ†‰NG¦¶nXĨ$HdÒ+ç¶?rãÃwüvÁ+7]ójs¾³ne :É—7ŒÍMÈ’í'ñ´ËFíx­ðÜ—…C÷}úò7…“{ï›ßµçO>|]Z1£ðˆÊÿSù<ÐÌîWÊW»k§ë¸‹E.ÅEVAÀAL£lø*< P~'øþŒZ×@= ‹Ìø*䀄ÿ¥˜°ÙL´©k5 £ø8}¢b5™ÌŠ%—6o0o5ï4³f·ó(‰àCäM6NNPe[¨âäÑWgñWɤŠ/m¶hÆRæp8írn$ÉQP œÂ“d[ãÒ^ïÐ QOt4ûËÇÎlìªh”økÖ’?Þ[!‚ô+ៅw à¥ÊÍ‚KŸwº|#². 7-̇£\h& O ¼"]ÎÎÕ\îœëZ¦YiYi}Dÿ¨éAËýÓÜÎ_¹>t~è:.}Ç~ç´Û±Ÿus^»Ûávú]‚Ö©wéýY÷x÷&çIp¹ qzÜ7odÜ„ã!˜<¶±Æ>è†V«”šºµXÛÇdƒÈy¶¸ñ÷snâ>Êd€pwíÇÄèÃw)FÄÿešmžm…mƒµõaA±)ðR$)R·Ä´K;%"¹ŸÇß®±¢”Í#+Ȳ…¼DÞ!Ÿ qâ»/Hô‰Æ’L·MÕ©r ¶u‚ÉëÜËSáð-~IûŽ– ¶ÎÖä e*g¬ù<K§Xï¾Ë Ç[MEný«&PKÜÙÕ1FIÌÈ9„rY`/„놌/A®­«Æ<;ïìqpn¥í×.Ú‹ºßyx×ÇéIO~7/X>gœs…3Q<?ðôMO^ßyäõ÷¶.Yò“ƒ…SõbMÅCÐóÙÀÏZ<åÒï3äµ}Å~¥Ñ¥mÖÓO±ïhqyy}¹’mϾ“=žýF' ,¥Ý^[ýLäHähõÕŸ„?‰þ¡úo¡Ï£†‰šò>|çþDBD}äÄþciœîc²Nt`GÞqЯ$SY³_4–'žÇKQÒ’ÿTôÓd«Êàäþ^6ôá­Ð^Õ]E¶Ví¬"UÐ~pž°Þ½|ªè”,Þ™íÏðfðÈÊí%±¹3rNžgʶÎÓ´8>€Or «i m€:(* ÕU§1™åCrXŽÈQ™å¹¨)Ó¼¤Øª8`†š¬/À:m5Ÿ^€ƒF?ű±8ÉŠ›à§êXê·¡NEà“Ce–>gôÑõÝ÷¾Ø´0%»=–ÕÎhÅâûÞ`rÛ%Ò´njx);iÓ}WO›{ïöšCëzoÚ=6î¯ÔpM¼~ûòi“ëý‰QÝn¶dÓ%—@_uàþ^I8ŒØŒšŠ™Q̸€í€.f´YƒÞˆXƒ‘å FÐ+Ÿb4e‚ Ñ0¬À4(hÄÆçñ#àÉêñÅÈa^«áy Ç ìóx"hŒ/VôZ­™Á;˜çÂôáonRÌŒÛ±Ž›3¯Xp›.Ò¢ÎF•G BPýL¤>oS>%‚¥ÄÁ®FKÞ¢ªÌÆê$ V‹VÍf3`Z8M]ض„-rg`ƒ™#‡v ¾B®¿vW!‚Oß]x/îfn>{'ylp^ÉN/™_ÃMA2(cž`±µ5pU`·ßà¿“½Ë/äHNžÅÌ’æÈË|«¸5¾¤ÇÓã{œÙ­Ý>6£06‹«ÍîpjÊÀ3”XIÓËJ²ÇëcËAëŽý’$ÛŽš¸›TÅAä/² ÎûQ<yñøƒÝÂN*Ëø+å0VÂía%ùîHvÊX¦7Q´’"î‰èÅ÷áÏUšh¨Û(}Tñ>Àu°ªªPòS¤Ù¨©Nr@0DwJ`£»pé’nÆ7“›%P‡‚ ` „dŠ~»Âº(ÐÁuø¹¶Vp¸Y`©óüEþÖƒüÆ1³æ’ÂÒV¬}ø¶9·^zÝšµ+ªÃžxjòÔë÷nß|Í ˜å¦ìx2öÓøO3}ì!Íçú¿>7}ÿ¼¶\0jã (ëk¹±dðÄYµªwÊsUtc3úGiå´ tMC]dQNÉ%מۙ;žcsáàòPò K;çV'ãtgâ¿)uXO« 6pâtÉg¥ÌÇ4†×&SÅÁjìQ™ ƒƒ*øàʲŠ¨Ú "Ä‚ÉP5é¨Z€R–ªÛ‡øNíU<øë)>Êg)PCähÝß©Øxº²xÓcmo=ýį–?Û›ŸòÑÞ——Ï^ƒkV+«/îÎÕÔ͘~×5ËoŽ'ÏÞºsö­/íëš²}Ù—,îÜòæšù×ÍÝûþòõÓ®ºaÕ´ìÒTá¯ãvµßôðÚ9òWƒ>^Z<Áì™p¢86(™uñ¹ß‡>Œ³KÙ5ÜzÍZí †ÕÆ5¶¤Íš[l:­fK9®áâ.9îâ˜@”Ew/D.¬ˆOœ-U´©èŠ(x’(@Ùcâ@_ï<àt"£‹j£›#«h•¬Œµ_ šY®”w—3Jy{ùÎòãål9¦ú,ÃiŠî%ѹß³ï%?XBÀ¦!EOÓôƒ¥¤¯ù¿*¼Å£¾X84Ê ßL Ô$}¢ !môbõ¤ŒRñÑIãáa%6dÜ h*¦ *qHUÓå7·üÑ [ÞZ¼îõ§n¸çO¯?ö"ÉXG¯™Úz{ë¨yÕ?ôEÉõ8òܕ޷ùéžgÏü¥°æ¦«É‘›/™ÿçÕ;·ÿö†Ù•ªÝî…Xr+Ó ±¤Þ˸ûpTñ—Ômuï„€HA‚àͬØ!ÄÌnµï´û 8 (úŒÔüQÛiÕŠê“ø¢ ÓvqÀ)Ó0ÖÊÔ¨ÑtËô–"ÏêQƒ¶Ñ¥Úhj3ãèyörö^°þÿuxƒÈÅ“!‹¢g‘FÀŠÖ˜ÅJ¥’*ŽûX0Œ¢êy®ŒgϑҾá2İóG¸33z#Pرò×ýæ%u T*|¡,Ý*ÿiwf3Š\ …;­U (¼þìØÈØè&χøýÈG™O£ÁQc­ÈØy¯§,àˆ8ötumsdRvnqÏo#‰ ³ðÜH{CGCwÃÎ'í©ŽQðD wŠå p¦eîˆ<ù0#H JÃô†…d!ÓεóíB{zç:oG`eäºøÚÄ­üíÞÛ[2Ý ¿N}”ú"òUczµrH zr8ä©D¹d0„Êë+3Lu(‘Ëiå §ÓAªTR¶‚ßMž!§nFÓM÷þ¦QYº»Ì8u«”Aû”y>¬ ¤}Ä7‹Më+kè±9gUØ,APg–6ꌖ,À¾Äb¶¿«D+y›Ìª4˜Í´4¡ ,›E2Ë,Ñ]óö|à ø]$£ùØ6/yÉéd²qêÈÎ`[g²­sLËTÃT}îU7­¬7R íP¬«ä0ÀªT¨‰g)ÐtæiÆ \†Q©l8á `Áãu{ ÏÇ"àÈdb W,ƒSBM‡± “Å5&î-Ïà4WAQ(ƒµL.ñ„ؘl¼È™(å hÅ]]]¨«ó¼Cˆhº§äúña9—©V§æçÂáœL³ÐuPÿ¢ä –¡@M 1ûî7¿û“O»3³¢N|j†Lzbá¶í7®‹ÎËßóãK^9ºhúÊ΃/Î~eËÈ/9}ÅmW™­ w1Ë(WF]‘Ã7,~Ì,M7O½a·ãÌ ïã«§Ý3“å¨m›Tü3g¬Ž`¢ŒÖR8ERL*¸Íü`àqóãÖCæÃV½&½‡pm}µã.¦Çñ(³Í³‡yžÑKü˜V†KiDKÄ‹ú0wx1>Šú˜É‡¤‡¸„Á}䓃–d¯ˆÅ>fÔÁ-ÆFbìcRJªLKö Œq­¸ç9 Zš,ÄâQ@µ’ ›]Aq©âáš]´Pu “m]j¦ùë®Npà;éTçé¶ÓŸ5 |y ‡úôo¨ì•ì^Þ D=1}Ìå½Ú*d°C¡qsUXç4VQ?_ìvAœf «D'ö2«šIvòlX¢Îº5B½Bʹaì»ÁàÈÏÛøÑúUÜúë5ÁÅ…SÏž;Òs7ýüÇ[*¬Þ2ž[VȼshSá½Oú ÿÚÚ¹»ìàî=û&žùü‡Í›.åoÂ`'i®Â0£´ê½zÿíâ}âïDn•¸ªl£ø€íAûÞ7üÅZæ0‚oôÜ ô"9$½F9ì”ÝÁ„Éd$î„Ã4¾ÆiV\r»ÓVÅÊYûŠ:D©h¦Ú8²)§„±Æašó`²SÕG§ªN•àÎÀDÐG^mä=´‘ßš?Īƒj zWòk•-”.NÉ|ž€Ù.FËb³o6öØ¡ð[‚³±×æž}Ž4HiëÌ|_5$Öj^ŽÝ %hF83;âðQHà4ñòž— ×ÿaÃ쓸¶ð§æ^&_Ç,ß UF{ /þ¶ðé‹ï-ðáq؉Ýx¬¿ä˃šgpÒ¤ä–ønð=œ~Úµ'ý|úxN3ÛÝÁw4´Ý|·°E³E«½~9 z“rX£P’hd“)¨õjJL™¶2!AÞ+øD/ÁaðAü´+YªDšÖ$¿sQ™¡Úå÷žôùüí†ßÓDsH…i÷úL™®ÞkUõžÊd°*—.÷ì‘À«ùÄËxgLÏu@pËä¨2KTù"ªÌCшʬˆÚQ™Ùž=~oTÊ(•[ 7m§ÛN ÃÚÕœ¶ø%XuØTópÙ8ØH}XqàK$~•ÄCÛ¡q†6l‘©d,a5É)Ó1‡Œ:ê2,ÔÀí ©>A ïÁ+ãY>5™¬—Í*¼/&ê?»nizä¨Äõg¾H§“’Ó™™fíæ¸=S›¸’#ƒ'ÃÕ+ ‰…¾p¢0jnÜ)¥F®/ì‰:Ee!ÓyS -ü~Ùt»¹ÄSxJç;Wኽ‰T(â‹ê´¬V×›bHM¾žüùmòsösÝöŒNÛÁuð€ËÝ\7¿¸¬tÚ "ÈCŽ)FWð½N9Ä[iK9çåMª ½19œ¬Lè4[€ÙÀg ÇPBLåu4‡SO&ö rŒÊÓôv@¬»•烞&à—Ôàù RL*/M*ÛL*/M¡€_å¥_mô«¼ôo¯þŠwô®|µN5:þý½í<ûÔðXŽ“Cü<·&vÒÄ*„)”iÀÆj[ ¾xËØ/²Nç8ÇñãßÌšfŒFq¼yì7FT™®<šžsuA æŸÆ°§ùÊ«m_L^QÈM›-Ì^"»­®h´FZË,/Õ ïÏkMP~M›ó Øœ,nSfêØqÕÄ÷$ˆèÝDªSêÚëVk:\îÕ[][ݽ®^·¾*µJ¿Qϸêª=Óë:êîdʯc Ìíúþ:f‚øâú¯•r-œU­Ð~Õ áýàNVÆÔAM)5Â|Ë/¿T œ¢†©ÿí$Ý~œì¯I'½JgÇøã?>žµßîSê¦C•€ÌéåP(èõÉ¡lÐ[-‡šƒÞ‘rˆ½:9l z½rŒG•ν#ä0P ‰xGŽ¡×ëHuU•ÏçÕXm!¢„ð'!,…Ò¡ŽÐÎбÐñê#’âÇ·ïÏHãñøæh(7=Ûž%ÙíãæÿÑ•œ*žî¢ÓˆÄÎ.Ô ECÑ,%08ç–rE4ðº Ýª €$üwõ—ÿw@ºï"« ’é4«8@Ae:=øBzFÌ=Ø£ª|~$ài"‚C÷{|ëÒ48ÅQ‹ÎÞw'𣅅¡Æ²‹N+ás$£ŒV¦7?‰'»”Cä®wôÛèè~¼Ï|¾À§ðWºS†]ŽŒ#›­MggâѽÆmµ÷eµC™59eÍcíÈž&¦4bâ.‡Ûëâ]šò˜7>M›J4)èõÈ¡jIÀ¶käp)§&«(BKšØw¹v»\BF¦Sei—3r¥p úîô¸ÝN¢ÕhJ§ã Múr°fîTuH’är¯L­Çq™—·+µ¸z £h–Ìš «QÍ p“Zû©4Š£•FK>U–)xÉèÓQ±ó“ÔÔ=­¸.ø`“:A‹ÕIÞ”XfhÂ¥BÌ»\–¼K´æ‘Æ•wötæé²|iª’º¶â6Ô&«ºù}ͤn%ÆÙ°‹cfÜàiotzºHCü^fš<wã/ñ Üšñ|tzj°?='ìüнþìªõÁŠh4+u1«æ&üñè™?°êîÙžózÎlÙ*~ZüÄSP¿¬Lî±b댉2-·…`«Ÿà8©²ÕÛVÛ Ÿ"l¡U¤^YH¦^Yˆ¡| —Q¾†­V &$d •Y­!ÐÑŸ(æø¬Ój1ñz4V-£òÃ`a±HbZTDFH;`æ@åô5‡Ššf·—«™Ð¦œRŽ¥rLG:I¹­ŒÞÂ.Ëéî«z¬jà¢!„Nõe݉ù?9§·€ç ¹ç3,ÐõÏÔ 4%^ lšÁ^^e±@'°¢6 Ñ ­Õm-ÇM(o†&Y硹ÖèjëZëÃøiü<>h}ÿ[ÿA0ZD„ G)îÞ°6šîD‡Àçä!*Å—§Õ}C¯º9ä΃WE«(fkÞê°æ‰h‡Õwýƒ}ú<ÜæXióíÁ²šO¤«çƯŠwTwWë_GØã+÷MöýÞý/·;ùÐùQäÃø‰/"¼O ûÓz9 Pk—ÃÈ/UVøMáia öŠ„Ãa'AcEÑ“ö(žç™X=”ËDÕX©î­&;ªû«U3Õ•X5’X5‡X5’8d6©ú6”iQm¤i{Uu¾a¿LS+ßó¦†4®m*eˆ•Fbt”¡”hQÇèüµdEiž3Rîô¹¢‰X¹3–ÁqwEG½÷^ÈsNœ¹F@áál( Vãw”,Mé‚нFjÿcÕñÇÐÜqa”@ÀOøbS³ƒÏƒ.ó‚Æÿ<ô›­øUMרÜeþ¥÷O¸uff:YW¸¾;6º>¸’YNk“÷­}ò˜i¼N÷XwËý“mçsÒK÷ ”%DÙqQ‚EU²m aëm±×¯U1#OUWÐY½8Âh±6‹ŽG-xYY‡×‘ë‚×I«B«£=x£ô@Õ³øÙèáØ Uň—nÅwFn?Ù…Ÿ OFž«z©êƒô?ªŠUF+r`±&€¿5 Õ éÅ‘«Rº ñù°=è5Ë!Mx„w&9ì ÑvX!•ÑH$Dp„v‘=D"BEù.5)ë¤ÝDaºÐ.0[ÕixȻǗíÃ?R̵ ¿ßGÌ&„1«:ÄÛRâmž–Còs2™™ÈÅ:¬ÔuÔ«cê²U¦4*4ªLiB»*SvµÑ®Ê”}{nþÕ=ÿ^®Nl£ñy2Iå)U’§Ô< +•¤^ºÛ#œóȱ5ïq ¹àIuqMÚE%®ª&F«Â© ® @QªÌ p$-Õf0:7yõ¦›pWilCÅö¨: üðSûÊò ê§—©` ÕSÅ|Z4<ã*ƒ©O&e«ÂöFúí¸öü<6[ZØVÈe$c@ôŦäT±T]Gü÷ÞÞòø³ØÕÞ³âì›OûÊk;niXHÖŒ «¾/œMO_¿¾/VXw{‹Ü‹wß¼a‡ú“ÝÅ?³àv=™£¸­÷Ub36=ƒÌl•sÉixÑZúð8åX]}‡ñ²ó\óÜó<ó¼•,Y=1‡&WÒpÓTŠ3Ïå?ÕZ;¡^š°I ¶DL_©Í r3…SBvuU† Ò*“qÀÕl*¯ˆZ`5)žÊ|)ªçæáÑù*m4^]¨_l\".LÒxº£ÎÒ´XƒÞeγis>“6«®I+VSâ¥9_Κ¯Wš oÉȹ ²‘عiß4mÊ<µ¶í¹béÉ‘Ÿ¿¸yò?^ž þÂãö Ѩ§åàòõ?Ö/<ñã)Ǻ|M½Ó#ëÀ'7îüÁ†KGf&¯_|ͽ—>ô‰–k ¤ð»÷ü¨ýÖ¹µ‹+¿XyçÌ{~›sS¥ÜÎH°Ë½ª]þ§Ò0Ï%sýsËð2²Ì¿, IÉMò4ùî~ïnîI¯@°?à 1eHKñ3,¸Â(HD³Fî#ýŠM‹“Hqšš¬f¸ÝtôbQI(VE:­ jZé´!§#˜ P„4Ñ+P@ Ì ì °£$Å/=ÅA‡Š€¸û~iQ[iØét…¼@¬>Go°OoΉ“'ÄÆ¡A ʤès°ž;ô™jfiâ‹oÐÑ\s”rÙ±ÒPÅEH¤¦„°}ÌÓÛ‚Kf¾þ`jðeê>>/‘$ÄDnJá•™‘†agNŸsYƒÉ¶ü <²DW}ñ8·èZo9‚ÒàöV¤²iuFPDÝ*3¾l‚oà§ðkÌl4׆kãÍáæø®¸PÏÇÉôôJý:óCñ—â߯øFS)  zÝr¨BÍBÚh"* ¡!Ø*Mµ#üó¥T>SµBiXN#Q«Õ(†¼F'S“Ö „Š¥¬ŒÚÕñj’¥4¥ÚÓ±M91;Ò;Ó½éãi6”TvJ*;%•RÈjÝ`Ã+lئÚ/›‰³è1›;uúBüÑv.s@çK«H²íB:A;=4ôNÐäK×ì¦õÉ …~kAxs4˜¤*$Zb†ò*¬×Éb´ %ôQêÓbUYKó&pè#ê¤j‹/dByÕöÄÀÞ|/AªêàbÞÅÇ3Ó“öKÞúÓgi©™NÈÎŒ¸ýS¶,½í7SÁêpñhtL°sð£·þüØC7·~E¬ë/‰Fs‘®Á½ÓÞêš´òà$ºAª9ðÿ,¬9È3ÒØÄ!-®/•Yú˜¿Ðð†Ä‰O›ö²z+Ñk4p曚ÄÁcðëÇ):Í­å‚A£Ó :]šÏ V“Ë–7Àê¥ò¤Ñf½t6 l}°UNB¥N›KMÒ¶²-Ú§´|ŒOj*õ C–ð”{+ñš:>ïɦÇóc…Éú Þ™|‹Ð¢iÕµZ<-é™5Wñ‹„åú¥ž¥Þe™Uì*~•°J·Z¿Î°Î³Ú»Þ·Zº>u{§¦ÇwGêŽô¦š{„õ?¶ýØõ çiûR÷¦wkžÑ>£ƳÛû´ïÿS©ýÂ~Ía]Ÿç@ú—éï4ßéÏú¿“&-M]™^Z³IËÖ{—V¯­b¯®Ô,Õ2“µS‚“Sl«wNêÒ43]˜®™«gXéÀÐù© _y°FÈëÏ%týÈ:¼Á›ÖúX½¥DY¯U#è±^“[i2·±‰B¿Fçç÷z•J­Ï§Ñju>°|€ñØ‹lž2¯-‘*÷&¬¸K<óÆó5õÞ|_±c¿W¯“úŠ+”²´F z}È g{=>_@«Ó©a¸× ¾”_£ ÑïâRMX±QÏ9ôí£a ( µŠe‰„þZHi(‚.«¾ %kÛZ±Œ!ø}aúi,~nL‘šLl‹Ó4­šª½ÐˆK&3œÖçFÊ’…Û…¾)\Se(kŽ¿våê+±þÏ üh›Ûm+'b¤>[…YL*ýŽØnJ4– ßzæyfáÙGÙÅ?tÆ¢Ñh:þá @6v]^³­šÊ3ƒä‹ÓN-£%|÷€Ý¤y" &¬ àåÜ›'[o®Çr“Ì·³›Œ‡µtž¦6Š/AÍøÝ"vÐn[Év ¶ÛÙ[„nÛÓèiÝ.ãK¨¿¤ë3–™EŽ8†á-O‡DBZ]ȨVÔè0‚Võ“EEÉhtú°Å‚è\ί+}¤½ƒgyOÊÖd›fcl–ZIÄâÝ·Õ¶F^Ö¦F£SO·ÑÏT>kS?ùœªÎЀÐೡO¦KL•R?¥–‹Le² xx‰šj§ž¾®¯øíÞR¯c™Nlbä–C%ÓùÐÙÛHe÷¦œ¬œée.Y>?cù¸)gøŽgùƒQöýTëZ<ƒÒ²øÂ8ÖZx1H:‚ýL™TǼ„?¬þW¥Ïð /rNf­g>fÃ…q3il9±8ÀlbžCµh3qh^°Ô¤Žà5)ÔLÙ½BuT£×Óˆ“¶F‘!Cscz«•ÌÊ8è)°ÿ'Õlf¨=´SÓ•QÏÍäu+T©‰I —TgP€-¯Lg ŠnjPü~ZZ࡯øž ' ìv©­.õ — •,J÷ zÕñ>5ro§) ½—|§`Gu1ûû?N&_ß{›ëy•z_O†XgÔa«Ìw7íÖÒ1Ö¤u=ZŸ¹mÖoÎñ~«£Alênbµ¾)ܾYjMiPš6ù5:“ ¡ÐD%`úAɘ‘c®-…]]Iú}N\ š‹oñÜ(Ö×m ]§O´‰MtÔ+iÉÓs’ÉTÉÌìc µµ–>ú>d|n¸/ÌÙ†Õ×Õ^«Ñi/‡¤ású¼„,~›Ymæ Ñ‡Cáá\Þ‡ê5Y ç²z«OôaSŠ¾Ñ‡Ôhž†C¾KEô‰»p'8/]S´ìk²RˆlK"U kàM«éø—¨n™òÃ$xwšC5ÐÍqE¯Ï»$}Þ «J»GŸ×+‡%èV[lµ°ÕžÏžûµÂ{FÏ}¿7¬®nX)çíβóßôÑQ4»:K‹ÎÛ²—Ây^úÞˆŒ¿+R7bÞº@ù›_ΙÑ‘T,šêݱö’á>«Îi öÆŽÅ5 øþÊicg×O¹õ‹ûæ«ÇÔŒ]=;²iq(TÙP]›­š½µ<8:y[á[†— ÆÆúmcŒÛÝ•íù êw™¤x¦x‚9ÂÝ(‚SÒý½Žê°Hµ™+3 —šw¨LUÝ@6©ªéz¾‘žo0¸œˆ%ZuÍ,eŠN+³#oT«—[‰ ÆM'K§ª©'ûÅ×AmÁKòFbp n×Ñk赎‹EsÊÏr*¿´;ß ûPùûaÚd0Ä¢@õûiíí¡ç½]úo^eÃOð‡øƒÂß‚,cl«“b×3«ØÛ™ì“̳a¼€4eqã([ l¬Ëi@¬×DŸïIMÛZúæ9Žá¾08rE Ñ8ÝØaÜjd»¡è52È(%cªýÆcFÁú¸1gl¾2yh¾,Pûlë*Eä]Mg^ýïªr$Ü£b°Gçò!·Koði`/ÈÊvë½>äç½ÒЧSC>ÿM7È«³ºZ[ñ…¯AºJIÉx4c±8.¤…x<ü¶‡îúÍO6?;}×l³äòU˜°­*sMþòG]”Ë%È×Gþùîéûº˜ƒLðˆáŽÁÄàk3¿z©÷çÞ2°ãã@†&ýñWû4,>gAˆç{SUU+À;¢f­Ð.wÈ„¦öÔ‰E²0ÿ€ "(¨üúµ)þ@<ÙÖôê€*(oÓ/IöZÕ™²×UTeQ˜rÏiœÃŸm&;ƒ›ÁÏZ¼->a ·ŠëFÝòïkÒ1é8ú”ÓÃãñl×,ß¼p»«Ý·ÊÕåë±ÞmÛjÙêz?Až ïÇ/ã_ ¿t®9áû›t»x2É:Ǻ9¸YêŸ  ¿P<Ž$XƒÈ(§A.Úån™ Y”%u²I‡¼õ¢QÃS²Q^ìÿČͿtDµ‚Ÿ½”åéF©·æá%õò[AžfØb †”¨Ž0·£´õ"úµ–6ôÌuž[°ñg5•Ã}8%!a›pbYÆ\±±ÂáXÈ"oH6„µ,È‚ÂzÉéàÝMØ„·6ë%!àÄ!„MÀ–ß_Õ3²½›÷½}ß÷dÿõWWUWSõ_õ×ßäiÙ<¤Èf“ײñ̉“„“Î4j»aàS³ŽcDö¢Q×+¬Þ§AX –=j°,ÓíMK{š9™° ™²T3-^SŸo|¦AçUžïFi“߈Y“Áhâ,z÷JÃ^泆{-Ÿï}…yJ:âü ósáUñ=æ¬Ó1jåÆàéöš¾cüžpÆÜÎhýÚÈL1ÀLéi1-c–›úåµÌZÓffœÙëÜë{ÄùUÓWùYîˆišÿ.ó+æ Ë{¼‹;iÄÈxÒÈl'˜¼;² 6 êûn =nr«NGÙ1âÞãžr¿îÖ¹Ý&;µÎŸ&¢#‚ª“ Ÿ©+eòޝ `ò‹ÄyR²àÁÛ<{<û<¬ç=—k‚8QNrL‘Ûǽα"§rð$Ü4÷gà¾asëÐ^2®Ø¬ê(ÚȾCÙD›bcÏØ°Ü‰ Þ¥mixiUzE`Õ¹íDtÙNÜÛNƒ´O·>“!•·ÃO÷67HÜJì§ÅP[ñ)[:xØ€0Ãl¢*]Ú§kaF¸š9Z¶¨¹²€#\'U6jˆP‰™€vÐêªG¼vÄkG&z¤ÚLe·è+û{ÙªPœ¹DVr¼Õ=Es.$´µ…WñÖ­÷n¼;'»ðÅ'ÞþýÑG_:w/þº^ômiYs³èG7ß¼å6×ÞÃøçocã¿Ñ>kS?2Q?BìúÏ¢ ÃUgw6βœ*GÃSáÂLØ‹{qfTàb}Úa7pF^„>‹WÚjï,óþ ®ÏÌbQµ¦ÒØ!ØÅÏ Ž‘Ázht´™âöv W*Ž5P¬z‚‘æI&C|Ä6f›³´l¾ì³¬5VÍ´A¹ê4±šÁºЛçÆéHGǹñŽÊ9Ðo U?G<éò$âîDÜ“ ¢¤+Äÿe¥‹–Hˆ™¬~Òáx8ñH ‹râ&æ–ú[Ö0¨Þ7¬þŒ¢«´öoÚÖº31¶‰Ä¹Ëû)i_éÓ‹ïêÞ×{Oÿ¼_éŸÕÓö–¾ßüýÞ¹M'7½±é̦€_q7‰%W‹¼Iÿ5®§¥@¶%Ò@¾¥â›œN—‰›ˆcGœX‰À‡âäçpY*«f‡¹2?!ÎÆgñãG3 pASÕJÚ:¦""/DØHõŠá”´U¥ÉÜCb‘õ¨PÔ“%S§gÀ…]³˜SÛ8¼‡ƒŒ,Ï” ,ÅKgÙÕâëá ><à›ð1¾ç™B˜\«PTñ£ï |E6+¬ú6[~†´ŒV±EU‹x[q_qªÈ%Â_‹2%Š¥ržX‹×’g³Âl…Ì‹.šùµÈ¬ÕÉ`"­Ë)œ¢cÐëoÞ—Âý©±Ô\êdJ—²‘–©š×d~«:ÁHíT67©›öÃ;×o"§Í–æM¶}-Ã˨-gYƒâÁ‚gÌó2ûÙóïªvºîg!‚‡Þ£g–y^u>RÁ•†";À2,&nS K^¥/ÔL1ôÊ’ËA™dž!ÏÈ^¿qÓ³ø6Ðíøƒ{‰M\sŸ?=~ŽfNgÆO‰™íÔ n{FÛæ»]%ˆUv»Èû¤˜i’ÇÓ<ø1~Š™×ñ„HÅs(Ë˹Ühn,§›ÈMæ˜é&[vçr'sºÜhë“{´0)tc‘@/Þ`uºÒa/—«8«ÌÙåê9C<ê}AläüÆaÏUk5“—Ä–aoÑvÜU½ì5^M=«4Oª’½ÚnڪΈWmûdçåc§/ªó‹Ýj#ÏÊ]ņzÜåeóí—E]’ ûÝvèï?·ùŽîõWªß˜ÿÖE ÆbÉ„x9îzèªBsÿ|𪼋9ù¶õìešþHtÅHŒ0_Ì¨Ž©®ÏC1`!ºñÑJ‡»5BmêqJ¬ 8¥å&âMFˆHýGfÏÿø(im²J5Š™_®N·7jÓí•#t¶)Ä âíl‹ì6\· æð¨¨$KõvÒ¡Îàið ê'†Å׆«6m=æL  ™fsa&X:"4%ýîí­f:;µŒêkm5¬S‰¹k¿!EH‰ÔäñÞWƒäL“)µÒù`eȰ·Òù@žL›™øtþ@É3ÚŠE/ššŽ ÷þÚ‰Ê mÉ¢:|“1<‹MÆöÇÎÄôJl ƨ$‰†ÙØØLq[»†sE Gã«yŸ¿&ˆ³§Îš;`Z$}J8ÒeñYœ“ð(e„ê,F§ƒŸ4aS™ðà™¥%‚T¡Rb?j±X}Ö˜¤fÊ]=jiož”ð€„G¥1iRÚ/‘ôÒLtæ+t:ÐàÆdë=­‰©ÀyÉ~ñ…p´‹‚¡®™†/Oµ0®[ZBÔ¸N×/ZT_ß±èN_CçüÒ¥ù€ÉöS6ìÒßO*:êëÍGÎ)ëË0ýëðÕ_È*>!6F×wíé,0n[Ùªt>ã§äÛGSÍíÅ®yk.0+”Ë’mÿ5$£f4"ß’Ì˸JÞé.Àˆü<¥ßy!øùÏ×è|žÌÒAžl¤®ýyÛe]‚÷úã)z!"r=Ô>J0Ö-”Ú·´¢„ÏbÑÖ:Ø_5Y¬tö°¿<ÈhHÓL• œËÌÍÍ]XÔ¨ÒÙ—`Ô€†"ª¹ÖÔcBY.3ƒˆáÿ¦/ð“æIËc£öÇÊSåC<_ö•ý#âˆ}D¾QÜfß&?ƘÞŸ–™ Ó'l/±/ o1o §í¿sp{EªÈmJ¥¼Lçw \©•¸’(”Ûp›ht‹ëðjq­¢‹ŠðáMñ¢~¥}…ü¢éEþßy½×äå,w3KƒÙ.8­~KHÛdÃvn~H\k_ë4ø„P(,¯atÕi[h‘¨Í‹,Ÿ,Á;ÚeÁ–Ãæ ¾¤Å—®r'jÔ‰äɺ9&B‡ù€ÎÃ|¾Üv/Q¶DøÑ ‹6@.Ôu¢€»Ãé}²?ìË«IÖñŒ)ÌN“Œ¶$ ¥pK* ³ScŠìR0£ÈÀÛ‹˜qaÌm_²ë’ŒÀ‹¢Ä·"äÅï¨}’åGf3o€ïóI¼¹h™°0g,ø¤å 3f™#vy¯wJÂ’_.ã2°&+P^ÌOS·vý@Oä'óL~´­<‹o;yòcÔO`û8ñÒéàrqœì "áíí&C;|䑉P tLê[l«í²iQDËRuk®ÆZ'RwÜh¤{ÿÆ·³ýxÕemGÚ~¦ äM9’3@H…—È–¹sÙL½,hȤ!²L}Ð^®zW-üdÕÔNdNâ+RЏ £ÑIeÒ¦Z\(\‹pÝØz[ÒÿV…‹$ðý«oê|ûíÍuŘoñüÒD 5ÿ+_~Õ|~YÔmlŠß]oÇ¢þþ³c?írX,®£(L~ÑÏçÿå㑂ŰÛémÂ×Οj“p,f7{#W°K¦–ìQÖ\¶\“(1ÙhûÏU>â¢úµ¢yíô§µ¯ë+Ö(~‘ü äç#%ª@~ãb†¶Ê4´.«µZVkEJÔiµ¬sy'm×IJ'(}.rµ¾Úy}5ÓWë2¨>Ò¶'Ýôeèézz¦•úÊ‚VŠ¢•ø¸PßÜÖ é¸•ª1¤i+CëénøV;íÃNû°Ç­¥X]ÃzQëC©§ë[³ç_Uͤ©ÂTëÏÂ%k^_¡±{á”åkש¤Maî_·mÝžuìºõ†å Rêò4¯še6×Ú#Íâ­wÓýV ž ïÍꔆ:.×¾ÒBã*ôÿ*ÊÂjþ hAçªi]u1‹`G1K$ˆmB-~±ÖJù< qQhÕ”®¿ zU¹ µ‹Þ td¡Øx‘Nv‰ìÚ„¶:r×5­ßå¾öþÞ•Û#+ßrÙ|‡sQÄËëÉõ¥ö1Œ»}Ù|C_Ù¬dû[Jkr¾†ÞùE•F?•s“ve˜w¶ ‰ú­#·õö®kß5ËzÅ*šWŒÚð§Çòji…93ßKõ6àK«¡¬A e[çÝ[±X`Ñ:|ÕÃÙÈ‚LlAˆýO eMÌ-+QZV¤2qƒ¶Ž(]g¯Œ4!'¤E:]jþŸL@>m/©õ%®D(@±4P-•&Kúœ«4?GÓ%Ãtéd‰™.áQ(˜+±!Γ šñ$Çzê¸tØÖ ¥ÃQÍxÒ¬ï,†º‚(ÚØDŸ8 ‚÷zbÆIOsXàÆ¸)îeNÇãI ÝŠÕËéô(‰l5‘žLO§Y”Ó Ýúl‚)ŸmÖ (™ÿ¹Å!ùXƒ.îc½A¬7Hzm"kaÉòᦪ»Ñ_´žð‰^špïß|¾÷FÅc37,™_äT›x]çª[o1ÛÈTt-käÚL<ýbïúŽ]ó·o}Ôn"ôã[woÿä|hØ‚¹¶|+^ûÄ ?™i íSì1˜g 1–êL ‚ ¨9©QNÓëDâÖjñëÈÜ!•$£:I¡Ž6ÓyãœYŒ#7j®HšI㹉ԓv~rr€Œ)¿ÎEGœË"RN¤œŽJ$«Ó…-m¡›2#2¸€¡ÚRZ·c¿æ9êùü}ÓñÐÏMǯx¼ÂÔíÙà¾Ö´WøyÀ(«%]àž’ñKîïûUÆ+¹ÚÝ8hÏ èý0uø$It£º1ݤnZgнCZWT˨9 k»ÄÓ×2½Ó©5½ÓWlJÇPãù³GÈ@läɘ¤ŽF<¿¨['¥‘NEãrS¿UT\S UÊ`K"ì³Á͘ÉÝ ¾–¢Fñ‚Çɪ G†Œê;ùEd´–Å•â&q¯]wO/ÊVõf7eo°ßÝÁÝn¿=û)î ã[ÜŸMÖâ¢Á¦¡æ›uê"\àØTÚáÁÊwOÄ«d%#ýÉ0êb™«Ë‹-˜Ü c$÷ä“l 2?É3£ü€gù·ÆI<Š2@Ü'"˜¸íi®zúÈh;q̤ê uè×|2 9$V4‘ˆ¶Z(ÓBÉhåâÍ K¢/\°BÒdjQpƒ9¯ü—P¦t-† or/|ª†ŽÃdM„iò\dWÖk“l§«Š: ö'–ïëÿô•ÛïûFOKªÑ[îW|­I§[Œ†¥8n6ÙnZ³uñWªƒÅBŒ-¿rûÕ7~ê'§Ûãróo]Õ&ÁqÌ [ÙÍCEɶgþۢ탗äØ?m¿\rP_»ù‚±Bü“êXö'(©L¸=t/5(Óáª6m#Z õ¯«îݧrˆX©C¢KPý³šò¬ŠÆA;¢qÉr˜6mÜÀ©\¬>ÏÑ« š¹@=!¡z2õd úx½Èâº)9cÔÜDî«©ý9]Ñ_ŒTêÛ2ý¢êW#ýõ+2ƒÂ€(<ÙX?’Ù&nöoŽl«ß%n÷ï oìÉÜíÿ\æKÂCþ/…Š|±þñÌ×=OúŸ >9æù6ÜÁ«™w2fê•ÜŽøŽÔ>ç÷]s9ã'®ãl C'«:t@Â2õ§1y¬h<$[ €dÙF†]Éx3£xÀ,æ¨Æÿv¢At¸™Ü/»çfÝt5×½4[ó€#ûvÏe†ÇµÐ‘ªbŸ®œ#ãÑQ‹ä*ÅRNoÌ›PPÊ IÜUpÒEáÈØÓ– ÉÎÚ¶ qëÌ\PÆ«A«>pˆJà­¬½öa²ŒÈ~Tjê™ot¶…\Ò¦ûVÞýØõ÷åÑD{é®äÖÊØþ¯ìXt%{àà 6ãqÑ\á÷ÆþwøŽ+J0v®€ÿøõ·¿sl®IÛïc…ö Œ­>Róx«§TÒ {íI*ž&%WÕù‹µ_¹&ÙÊ5™T&ôˆ®sËT9—©+S­—6Ä"+y|Ĥ+¡ <[r[rO’M¦Œ’…ru‚h¹§AÇýor)Y«/]´‹’îpî6Óc‚$Ü)%•vªÅ’{ü€’J™XȈ%ê5#Ëõé‹ìœâqê53¼ EÔm Â L£ 2ªðIQ­Ç#õX&tŽêŒ÷D“I¥3Nv!Þ\ow)"ÖIäókeÑ‚-C,‹Œ Ž°jÀ†¼\ë‘=&˲‚'”I…AŠZâœrRÑ+£é'vshzÞø©íãÕ㧇íÕý}袅ƒqð€uº[j¾5ÍË»°v‰Ù¯oÇí­+šcÑ n‡;WtZ—,žÏ,«óñzkÔ/'yìfüøÇK³É–nWúªù•}IßbªSmÙY*Km=Šù)Œ—]su¼$›èxiR‰|Æ`ºâ…éŠ~.i!åɈP#@a¥4‚[ƒ‘K #£Ç·ëñz¬0ÆõFß­a¼%ŒÃqÅGýc~Æï0£Êñáa‚ € [2D@ò;ñ“âO4^º0:#B’ÓÕ{ÂŽ¼ž©o0jÝø½züQýÇõŒ>^oì ã­á›ÃL8î0cr‡ïª~2Z¡©ÑÏÙ¨“t”L65Vyæq 'ÞÃÄãLJ+âqºƒ¦º§!mÊú²ŒÃ‘WÍålÊ\–\C–‰ÇÄczÞȧøôhÓXÓD“AhšÅŠz/ÌZh;;ÿ—è+±ŸgßÔ½}3öVÖì¨d‡³ËíÎîÃû˜}ì„›|‰h"¸7·/o%ÑxÖd1ùì÷ê¾催ÇåzB¾t ûˆéþ1åè1³#cMe{²ýM#M·¥oËÞcûzô@Ó¯Ù7ƒ–4×FÏ3a,ãýBf=ŸŸÅ~Õ^/…}ÏÂ~ÙE¿oŽTúž÷Ê:‡#µšuB’"}å õ ‘—ê¿Ó瓈+¾ËS /–ù‘cq(ùñb]ªyŒ|mL˜Xa·¨¾¤ß——9Ìe§’x49–œH²J²˜d’Ïb5bå`omr˜ T=:G|ÏGððP¹’åÌy Yú¡Ô÷èçohp¿‹‚)€\ʃ¦³š]V«¹ZaH‹­0<~ItÈV?l•WLÖf”Ñ>lL¥eE´Œ²=Ć4DäȘÒq´í‹ìÓÿÐø¾ø¾ýÔnxÓ ƒªo O1Sì”ùQë¤{Ò?˜ >R÷pt*g!‰G ñ´QÍ…h!ö™ìc±Ç²úá!"6ÛSНlJùÊXåË @@s«ôÓÕX¾œ‡¢,SÙ"†›B²¡1P¦ÈWŽiΩQ YH@*g9[Ým=ãÐúp \ÂQÎ*rÎU ™PfE+\ÇJ:8£:¬p+´ìþëv«Kÿ°¶ÿŠŒXøHwáO$Z¹½©¶ý%–¼8X3IÜzå²õŠ<òù>¿sí·×‰ßܽáêù_är}¼eU“]tXØóß{à†ž\[*_¾åË» ó~¼ü³÷_Qî¾j²½¼aû½‚Mæ:ÿ{¦C÷Àçj~ !Õ4,D½AÍj‚±¸Xï¤Y'edΚϋ“p>ª.w¡0sYÁãÒP„ ÀÉΈâL±:® 5†§ðËX‡©«“Ãç9ÎI'3É´“Õ¾¨ <v‰÷\*©‘X²Õo‡kŸt áÉ/ÈjÀ<Ä@P°‰ö€ "j¬£ß<ÎÔ–ã´.µ‘’›±©ŽO;Yçe·œ´Íÿ6wË®îUÛ³ÁÖ¸s¨’¹©·¼‘}ðÜO§è¾–'– }v?ÒÙÀñsM ´ô1ÆË[™8Y·ƒ1zƨÂ|§·Ã„üý”@`Ø_DÄ™âô;ïT À ìj o p&S]Î3»¨Øå4Ø©hwZ3\¡…ôs"sá¿æ2Zxí„H÷G©&Ç~PÚäc}4b©Žð¡«Ý%—Ïåšêøˆ]qÄ$ŧøÛMe¾ÝA˜¶û{¸•¦.¾[êö­ô_Ï}‰{Äô×þGSu‹¾Î=aú²ïËþ¯¾Í1åJÏøžõ?˜«û©ô>ÿ¾ô¡?7eÂuÔWh´™âLƒ†Ãi /_®ádRÃѨ†ívŠUÕlêv!òÑ1ý.åú»íûêLí\3ß,•/æ"?óïã÷J÷úØVÇ ‰qJ®°”0rðö0Ì‚{Ô¬ÉïS$Ÿ¯¨ÅBøý19ÎhÐëteNNÈà÷™¥Y j„Ç"ã§ø£üOx=¿Û ƒXT …ýÜ1îÇ0{w›|;ýd›»‚Lp¿‚£ÙTu&¦¾%‚ž±”i¦YüÂQ±OÔioZ|Tp6Giõ‰™ ‰•Nè…ÿœô¦Ƽôžÿ4Áã’öùtm¬úz¯&P]ˆ°ñlh!4¶×d:ô3˜¸ááµÄë×Ï6ÅÌĽê Sxâ^Ê;Ëœ‚ @Õ k»Dj13œNjŽ¡Q4ªÁ6ˆã~ÒŽ“i÷O_ñræºfœivEƒóÏ¥çyR²½‘}0žP¢Åycm ÙL‚9×ÙÃËÎþ–Õ·D§éÇçOéÃ|ɲ'ªó% ÛmL–˜úlÈ”8]*.è•J¡à-_å¦fÚKí¢~nAªVÐT¢ÆNK¥„I‡R´óÛ³8‹vÆqܼ3…Sf­÷l6‰äsUë4¹Ve¸BœúèÅ4Çú^4¬C°Rò$AÉ´Ç“J~$½i,ÿVü­ÔŸâJYHƒg‰¶û^@nŽäóé­-!ŸODżŽO„ÙD9±Îû5ïפ¯%8s¼5ÖšìG}x•q%·<¶,¹*µ*}ŸqBœ°.~_ê¾ôDþQñAÒ8þœx,~,õBþ{ñï¥~ÿyêd^FzÑàÖyMqcÒ”2¤KÞ¥âRû€~µq½´:½×¼O¼OÚëÛ½/~_b"ï½×t÷Þk5 á[Å[í:˜ð{Æã<6¼½ö°¨D#a¥³a$ð¶° ûÂaPíï9Ä¥’ÀNw«ª)œ‘3cé”+NÁxˆ'‹œÉÅq&P|îwñ|<‹%ŸK’|éDÔ ;Ì@~‡çð;0ÂøC2ìäHD6O€Š"(ñ bH!FYhÓTz߀âˆÃOªBJ…›ÅRfå¬p zÕÁÃsèšt”ìp«Â€ï÷áç}/û^º÷ùX&xàEˆc~ôªßü9,¢r÷¨|a$ÕÄù†~ç°iw²À= ‘ŠWP O¤Îoª÷‡SSûÔ¬:Æä«*bZI«ééô\údÚ˜Í-HN§ÉʲÏúÜ)P|¶Wg7ù¡ª¥S~§Ô>mç×|¤ˆ˜U 2¡åOkº‰½c«ÅHçj»¸ä{‡DÞÑ‚0ÓH-ãÔO’l‚>’ A˜‰rB¶ž8 ¥‘Ì ÈEЙo9N›t—ñÅ;̈Ï%4F8j¤¤zŒ£¬FI¬xññh–’ž|xEØÅüŽ+YÆ‘ éù§ÿcþñùWCm@Qtá œ=÷{üô½^³^1êrŸ{Ø¢8ÃL£1VŠ»J¥¸Å“L›,®¦& üö’ÉâmJÆ}æ¶BBâYK³±$qP†_¢'?0q»pæ¼.‡s¹p8Ä[@Ì<²Íƒ=ùø,¶R|ØG(«E,©¾iß¾3>) Ù÷Ó‚š_;SÊ'"BM¸é9æ;¨ŒÚ™U‡"'öja®Þ#¬Ã™í§ß«}Xr¸ÆqÉök‘ÊœÃD˜¢êM5`$we«¾Â’£¼» ½#ž&ïø}Ñä›ÃP"ÒCq×;3rb‡­ã^›Ø±ûøq‚ŽsÇ€8(Õ¾e@ƒWÔÜÍ0«xâ­ø§gLe/±5@þ×$¶›¨ª¦ ½bUbE"¥p@°êôÚ*z²¶i$²ZHŽ|$òÀé”@z;sT(Ç0ýŸÍdÓè€è'¬Pa¥%ÄF‘PØ¡ÌNÎ#±³‰ 0ãÐ]Ö²/ÀàUeQÊv€¬ê&· ]ðhÈA?]J, gT§»Ü¹˩¢«œ°s⇠yÊiÕà.7€+{ÉÕ9hþ÷?ôß-!UPBT3‡hh¨Ê0Fç‚÷&È6ÉK>ÚJd>ŽDÍžÎÞu ÜÒkX·ûÔÚåùœÏ©Þó@W.7ÿÓX ±qîïz®¸ HSÐ+5Šu×]·Åïa’êÆ¿6?{{‹¹l^ïðñã›ìR’‰Åô®Ð­çÏÞØªùÆÌ/cßÚÔ¸°Š 2j¦žE·%q2zµ÷ºi²Ó, x”¡Y†di¶q¶¦RdNgÞ•‰áѪҊ°)ƒB.;sG#nD Ñ;È5—« ¡æ¦Áçµáã Rê ™ê§ÅÞµƒÏ£Àù?!ßù3ÈÄž«î`O™Èþ.[æ iÆÙœ÷lm¹K·1™ôÎÇùM—?aŠ9bþD¦ ·8JåŽëL×ñ×û>â߸.{w;»ïVÿÍÛ²{ù½¾/¢/šö?”ylþCä’L&[_Ïc*¯ûˆŸm¬ ù NñùýÅzÞ ²™ ï3õpJ½ß¤ã¹,`H\´*è'éîh¸Ûd!Z Í^¯ßG$†À>¿ÎŸ!˦cüïx–ßM>"3bbM»A½µ©¡Ì+‚‚eJa”}#Y\ÈV²LÖ×Ôü·Ä…Œ¸ ¯:5¼ýÔ¹÷†ÉžïsU·±UçNeª?ªEœå.âÞ$ž2ñtþ¿3h¼‡ÌÿI §¹á¢KDŸmÅZä; ~ÊËE^?a7ru\OI&ßügZ\±¨¯µ)§øðòXçü3BÄ'z›`'CÉîùFüA:å0™­ ²K[åìÇ+[ßäM1‡ä|Ô"Zjßao„ñëÆ«œNÒM馬S¶¿ÕÍêŒS^lõî´6´  AaÀÍt^›S¸J·Zx]wR0VÇe ³^+06½¥W?^ýì¶¾h1t øfÛF(2<ªœBI“ _•+ƒŠ‹ÞÅNw˜¸bj£^˜›u6Aˆ±:ËêX3£°Åæµ’«èôX_´Z ∀…"fxá9f1²!³XͲ8?•°â¢UµŽYY«¿à­xû½¬×’7—ƒŸÇû7¹ü½í«Þ#±ñH\ý÷†O‰§ÈoèNi’Ô—t¸{w—ª_1¬"JþÑx”5JûmçOª& ôlêÌb…Œ ’£˜‡ø®ÿëQOY—r‘ìÏŽºÊº1ÉNu”u’›d}Ô Yf —NúÝŒjÀ=7ÑÖˆ›ákie¯4Ÿý3:ÿ“«;œ]ÊÀ¢sâ˯ïõŠfì›ÿUŒ­÷E{æãgÍ*×’ß~zˉcŸýŒ}Dèø#Lw"m¡¿ïvþ¾†ÏÿÇü2ãnýýph¢í5y #óÝhƒˆ>¼y~µØ¾PSûë6”q!Ýw¡»)^Á|­ÈCÙǯüWL™|ºõœÈ¬P6 ì¸ÚMëîBqúï"Q¿Õô@>ªûwT¯Û"_AŽ¡ï&ÀuPž6† ÝwÏÿ©ƒ6äœ(à ¨[ efãçPò~:ÿ;ösh%à/ƒkvú!€î¡°ðe% oè†sþLÚC[+B[¡ÞÇ i ×°¶ÐÌ3ÔÿfѸ߉ŒÏ2)f3s–ý˜n½~™þ¤á!ãZî*SéÓüçͯX¯³%lo?¿lßïø¶sÀmqÑó’÷”4îóÏú­üª2¡<^÷¥è·c¿M ¦V¤?y%÷±üPÃo›×¶p­‹Û¾Zþ§öß\Ö·ø¶Ê:7/}°û—Ë—¬Pé/ÖÞE,Ú†ôô+ë´!ý'”1ôWvTW’àgÚ8pÅêÎÌÚëoºfÇå×ܺzÛMWl`ͪµ4. ý;A[Ñ_úë&®Â#3² ®e‡¾È…Üȃ¼Ð»$ü !EH @Pê’(o¬ePåáÞŠ¨5‚TXB-¨µ¡vtZ‚º ïeh9ZV¢Ô‹úÐå¨  +Ðj´­Eëà™6 A4„6¢MèJ4ü,Z{~Žý·CÝÝê,àLžâ™Tºñ©˜ñŸgÿù&Ü€ ¯Ïx´æ3K–T3-mZæP}®ñõNžýúÃþ‚}nšžu(•o<Ói…ÌÞ‰à]2ÚϾ†¦¤²¯Š%§^`õ?`¿ïœöý«½:ü.û ¼™=Ê©Ö9d³7¢Î0Œ0šƒô$Àgthû5´`À • ý¤„}Š} îó 8_€´° `€­e¿å%)ûuöTç~–°ÀŸa ø«€ý€¿ åaÀÇOULê­–?ÇÀ_¬â‡¡<ø!8&ø Õã[Øô¼›«x?»c&,‹a¨WŠ,ä„܃ðê$‘| Åì]ìôJ7¾IÃðºvÏD¢ô7Ú}Èëkܯt7¼úÝðævÛÛM<Ù]µ6»´69v´ÙmvA›]ðVŠì¸Þ2¼!Þûxï¤|Ò9€“´üSNì'Gì­ðÓpW{ÙfR2 ²k•ÕÆÊsìGàU«ìGùBû.™x2ÛªX m¯¡µ×2YHé5‡ü! C«vÚØ-èã rAhèб[fbùYört‡T›¼‡ÙÃîÑíÑëŠ]ØñÛˆ€ÔËÈÁæP4HË#¸uÔ4fš0±äã3E“j0é·±{Ø},K>XSaûÙVOôc{ajË íM“æýæióœù¤Y?m˜3œ4¼a8cÐkÞ £†1ÄaÒ°ß`"‘T˜Qó˜yÂÌŠfÅ\4«æ³^6âýw³› ¡T˜ÐÁ;r…½ `~xWA9‚Á‘pòoÖÑíh'@©¥”"HIÍÀ(ÀXµÖ°PS;‡´?Cj’PkƒR¼Û7 =Cr=pd…#+Y¡ÕIæ,Ü¡©0ÀÒ²7`Ô@Z«+VëG ´þ mS«SɹÌYõêä\O“¯<áÉ4V;*j$‡c$:I<¡ÛÝß–Úö„®?ÚïOõ?¡«D+ñJªò„®-Ä ©Â:9*Çå”ü„n_ß¾ú^îÓômëÛÓǶ%{&Sl¤¸.N𑟿±Uè\Ä€Çt àuÉ*ÛtÌHeæi(}JŸFý#z8ãiB^ •«u¤|ŠÖ‘©g.©gáÁ¿9ÓÞÔßÙ$w` €…¾¿ õߤ­µÜZ> é´¼¿Ú~?-—!­ÃÛHÉÜF˜~Q`` @^f7 × gHe€1€:v#üÛÀn`ž†ßd¾ÉfUkƒ[Fð/‡;EÆcÀŠ¿NÓ/Òt/M+4©¶ëû=Öo÷Xïé±&!äP'T"„—< m|T>½V~:JkŸˆB-üÔS9ù±èFù‘8ÏÈŸÈ~‹Üº žx=TeË}OÉË⳪ո˜ÊËíÑq¹ Åm³x塧䆨,¹•"ôñÔQ¹®˜ˆÒ[Y×ú,SBF¼SÍo6n6®7^a\dl2挊1d ]œƒ9gáxŽã œŽc8ĹˆA(CdH—A$È #©ŽæE†ºhŠƒ9æÎ´“íez×,ÁÓŽ^Ô»vÉtk¦wÖx~õt[¦wšØ4xãû‡àhš¹o£µƒ0@IÑÝiù(Æ…»? x×ÝŸ½Ós[Pïfeúý5ðü§õÑ%òÜR‘*ŽÅöò²®¿ŒVÓ‹”-éË”š~¨wÍàô7BCÓ$s>4Ô;½|j³ÙÖÝuŒ#hhð¾ƒÙÞ½š”ã;º†š¡:f š¡‚H³C¨Ž4CuømÖG›Á0­ëî:XW§5z¯$`ø¼H]«õƒK@_A3&Œb´¯&Í`гl#í|guýmÚ‘ÁpûÄ~3Ivdn¦Q 1yÝ7ïÈdÐÍBŽá {Öÿ‹UïØ‰àUÀÑÒä´_hø¿»p¢ì endstream endobj 45 0 obj 32613 endobj 46 0 obj << /Type /FontDescriptor /Ascent 891 /CapHeight 670 /Descent -216 /Flags 32 /FontBBox [ -569 -307 2029 1007 ] /FontName /JZPQRA+TimesNewRomanPSMT /ItalicAngle 0 /StemV 0 /Leading 42 /MaxWidth 2000 /XHeight 454 /FontFile2 44 0 R >> endobj 47 0 obj [ 250 778 408 778 778 778 778 180 333 333 778 778 250 333 250 278 500 500 500 500 500 500 500 778 500 500 278 778 564 778 564 778 778 722 667 667 722 611 556 722 722 333 778 722 611 889 722 722 556 778 667 556 611 722 778 944 778 778 611 778 778 778 778 500 778 444 500 444 500 444 333 500 500 278 778 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 444 ] endobj 8 0 obj << /Type /Font /Subtype /TrueType /BaseFont /JZPQRA+TimesNewRomanPSMT /FontDescriptor 46 0 R /Widths 47 0 R /FirstChar 32 /LastChar 122 /Encoding /MacRomanEncoding >> endobj 48 0 obj << /Length 49 0 R /Length1 16216 /Filter /FlateDecode >> stream xÚÕ{y|”Õ½þ9ïûÎ’L’Y“I2ûúÎ’d2“,@v!ˆQ@@DQP)õ"UJ#ZÁâRD Ô*²¨DÔªqé­ÔzÁZZ½¥¿›*½Ms­¥b1L~Ïù΄­íçþ} g_Þsžó]Ïû㌱v“Yëõ‹çÜ&~ˆš÷þãú;–yOßwÛÆøSŒI-¸í†Åsì·MbL©F{× 7¯Xð“êg¢üSÆ*O,œ?gÞŸ–,±1–BV¿†Q²å_£\¸xÙ]¿XZ2唟½ùÖëçßôY+c5»PîX<ç®ÛôuҌբȼ·ÌY<ÿsÝÒÕ({Eù¶[—.SbZÌW‹1ì®ÛnŸÛ]ßz§å—Ëuœ‰ýˆiÙ;b »6Wsñ?)—Êì_ÿS4”ÓR¬CÐ_ОÇò)5äžxñ¿B„"#‚‰™™…Y™³fg¥¨+cåÌÁœÌÅÜ(y°Ró³ ² 3•EX”Åh¦-¬›]ÍÞcGÛÉò%‡4Ž­dw³(ocϲ·¥|¾™}ÄGò—ÙF¾Ž¿ÁçñuÔûFÛäž_ÀßPôRêžCÝ:¶–áÿ¥g¿eXû­ü[!DË ö¿Z…U-QlTÞ>ŒF¹™mæùü0?ÎË׳ü]ާËìKÌ·NÞ&¿ˆU®SÊØ—r,áI›ñŒ]4ê·ÈßÎ?åýìEfç øs¼€í’¶ ýN~†-Gÿu¼’=Ìæ#Ùl6Wy u«Yý}§la]üçØwÂò$ô»=ÂXÇv€/aód=_ÍX†Ÿ‘‹d»˜‹=½®eÙé^>†?,¹Øï.:⯔íÙ?qÀ­Ïìb>¥_üiŠØrÉ•ˆö.Ö¥µi§ów¥Jþ2HÏ“ìR_ÌÞ§Éç‰Qr>ú=,M–W±.ùC©ŒFy5[ÍW*Û¥Ò” °“ |‹t5Fm–šÙT¶RkSòý ¾;•ÆiŽh†k\Øófy߀–׸–•!]Éž7k׳;ù w·ÀŸ-jó”§°Ò[ñ·a¥à)¶Ø-d·Êzp±Z¬Ú¤òR˜c ò±•š%ì5¶Tú-¥x#ÐZÁV+ÂiÕ Ö´…}‡U·ê´É*¼¦½Rhü¼½­Wtxߛ髬¸¤è5é¼{Ù”½…+¼/NéPš™{5νrH¿W ~ÿ¯_Y1qJ‡÷e>º½-7mûì6T^Ù¬(¡õím•YN^Ù¬,Ðì/똽5OaZ®×H K¼ÿÉûIf:öþ±÷«­fŸ9ä3û(l`©ìøCf³®èë/o×FIù6ù °ÃîhÜ>"ÝÒ\W[UYyÜ.{‰ÉX¤×qV¬øË‡)éýcG¥[˜[Ó.š+5ÃEW%¥~švÑS±Š­¶ödqÔ6|¬éXoï'½½f{£ÅÞh¶d{#V6ð~ª'%ê«yh¯I•x¸›Û´:R#/â8Áu¹´Š×ÕÖä¡\Jcì…fž*qqé)®×)zƒ®L–MÆÌÉÃ:]¡aTA‘F[¤Ý´QgÔ)¦üÖB,òpæ¿Mf/Óèõ®wX“fùê%’b´M*0Êúyäo´FƘ—ÈÓäýµÁ ×'òDö7#åÂ<©X3Éf”¤¥ÜS`.ÀÂ’oüRŽóé‹¶Ö<ùXÞÑ­ƒ˜Žõa˧úªCµõX46‡ ñí‹g̼yqGÇÍ;&Ï›;eÊܹ8‹6Ö¥LW®… jm­ÐÛJm’Ëf5äs¯ŽÛ?Õ}⎳)Lo\d=×R®„Œn<"eoìLvŠçtÚ«;ó²pâI*«áºÚ†ú†,hd®JŸV„ž"¿gàŠöš«õŠìp„‹µâ²ë˜4Æ8ßp®Å*W°Î–¾K×I*“—ر8V§ëFmƒ¼äl¨*pCNÙ¡è¯îÈW°ÞÚRw \%­à“±N—ßP˜Ù()‘T2ªH™.Ét—G‹ f ç>mK¬šmjMM”fIRD>”Ïyþ+¿7ásÉÆžHIµl(22.¹=^_AEy¥ÉÊ­U¡J]EERPð©Î^‹ Ú–žê;Õgê¯C¦Ë˜ÄÛ0¯Œsoƒmcn#þЍú±Á—ëW­Ó˜úúúL}:‘èûf²Nî½ÐVk|yø¨ª™«>Ý%5| ßúñ†ïOÆgsWƒjâkÍõ‘pmæ‹IñDºsNF™>gTu||æï­±X‹Ub’ŧF=.u áFꉆ=ýýž°È©î¬ ™;8 ,F¬‚ÍlmʳrË=±bÖãî-tèJ\WšõÍÊý»ÕWô¯(ùFwi±Rbñ1ma°Æa©õ2cIªÒ4ЗJõ¦NõYˆ×qƉ¾¾Ô±>S¦åíê{«¯« üZ9·çfnΞs³œbf%±:¿Ó;ÒýÕ>;›H?Q Å[,¦–ÊâÓ¿óÈUWLüx·íº.YþäÏýÇ%ù›þ`PuËk¼‘P ózæÖôNŸoŠ¥ÆÆ‹ß1VTÄ*Š~fÝ\kΜÄY§K\¦†˜ß»£*YÈû¤ÛƒÞ€/ì¸ÝUDÀ&ל}#†©¤‘;¼¡ˆ—€}Ðö¼A! :r<£e\Û:œba.…´ì-Éë1†ýáà,Ý,ù&ÝMòJÝJYï)+1)v«1O/…½Ú¦) ¨ÌhwZíQÁ'½àS¿9§ý…DÌ‘úUg57çäõâ½_ÈD(üµWßöø¶’d6i÷ƒÄWéðþ:pæoÏ+–Lõ²åK— ¬ô#ÞØ"Ký‡_z©;óèdÃàQ¥Fy›foµ>mÛ¼®ì»Í›·–m2mK>QýdâÿGïl<4ú`swÙ¿9ñW†˜6_n.-kRÒžÊ?Öþhé‘O¦k{B'=ûÓÛJFNJ]“šošçžW7¯ñ&ëMöeîeuËWÚWZ—›Ö˜Ö[ïk¹Ï}_í¦äÊäú¤ldΦҲfRÛ‰kºhñ˜ ctÎ6€Ôw¬/ËOd5f•cï@oŸ ò#KWÄZ ¨PÎ"1a/±‰ÕÄy5š³¦Hù«aµ ´Å¶!ûJØQš ‹Ê…­å†À£7®þáõ×mú൳¯6|ë2Éé¯ð+E‘`«¨È÷íËW<ºdÙSÏí=óḕdÃIKudz¼d̤o]wùì"›ë©‡·þÒåq•”'?̨bÅ©ú»æLê0Ùì?zp×ÏýdmËtÉIЕ5µz JŒöÝ—%1ö–õ†ÌFfU¬á´.7”–éì͇ÂT„Ê»¯Ö\À%æ (D·Ëô»2õÄb^èò]»¾ö:\°Só°3ìƒt¼x #Zýb :†|‰•œ_…ò$-ÁjU°ŠX(f:’Ü*²§TÍ/ÜC”+­ÙåøÜ¼À‹y3§\þ€{—¢úœ._ØyæVg8àrzìϸ”ße6Â0·j9\mI1ëÖzO5/öÕ)¿ûƘÙxÇ‚×~®¬•@ÖÕ±{[g|K³^óÍcÅè~¬Ù¡ÛúqdOñÁüW<ÝæÂrWY]a2ÄÊ¢ò‰%¼d ïŒÉûµëDø´éhì›dÜÜdé¶ÈÉxU]ªPfUž2¦F§h#k½ ÂSg–,äBo÷ ôšú3ýB¦ÑÄÙ1 ¢³ !¢Ëjösåbó ‡|“Ûn¨ylß­ÓW×O}cÁ#/ýõ“¦;FܲlòO=®ð§Ïî=[‰<î jy·Å¼°£­c͸&LÞ¹æ‰çŒ&ÝÒ[¦%BÍS÷?ŸivCø½À¥m°_¹¢vÕñôUàíBv%³îO#=Œt?R-Ú+Xø‘/c¥Ì z<ÁŠYˆ3´h‘7²Ó(EiØ7è1‘i8›…tÒg˜ÁÊ"=ˆTÏÂ,о.Œ‘™#*YåÑü¨‰0 JLEzz^‰>SÑã –4 ôöö™˜CUÐÉÅþÞL¿°'² „vhÈ`à²àjVlcBa䀽Xµoi[×Þý÷¯á…Ÿ Ûµèg¼ óçwnÜ–²–¼¤†«ÚŠ­m©ˆºÅíX¿ïÁõö?ðÀiõ˜ ™¿¼÷v¦ÂÄ)ŽR¡ 惶bìz6h¯´WÁV¶^³Æ¹Á¸5ð¤ñE[-;*^1vTäÃÕâL6+—®3Üj˜ç\æ\exÒð¼a‡s¯;ßm?4˜O(±ÓÁ£•m–¶’i–i%»Ã»#Ýáîˆ¾ÈÆ’>Ý4[D.ìÆS=}ä^O_)ÓÓIbOPÜEözýÁŸÉzSJÀÏêjòòÆp$ê ‡ª³zÝÌmo½²qôŠz«7ò¨™vÏüŽ{=i«<[ñyª'v‡BžäW¾üýG^ … ÊêTÏåÏð’_þ’Û£dw`ÿÆ‚ ¡ÓÓAcFœ¤4¦a{@O#ùnä÷#¯”‚BL¬ ”'ÓZô¥cfÐZ)jO þ4ÊGQõ|ƒm, ²iH§!ÝšÞêéFÚTªb,ŽU¸™ž`ÁÌböbô‹ãi*êg å*Ðy„å³é‚ÊúNÉÞ¬æâi0uß%æ&¦`c)  ýBjʱp€gÙ(QÞXln9p㫃Üôóv4×ͨ‰ªGÜŽÊdEØ;°wߺû÷½°¾ë¹b÷Ô‰WòÂ÷>àÖñcù*OTÔ7[}Aèž7îßûR×ú/fï/€ñÕò‹X}€½šžÌÏ;vR(a»±¿Ýè÷"Ê:ìZp«ø×ű{À¿añ4Ýlr޶Óèuˆµ¡fÂNÈüÝàÛÝ8Ýqån”»QîF9Ÿn#Åͤ è:ºH桦5‚›§³à•f¡#Zíèìé$HA§BsÞµ@4K’ŒX5ä#ºå6ýþ,ç6—;«š÷ÑàxîÿãQ^’Xh<;_ZoܽrÍ‹|ûCßvºªíÉZ®;þ)· ²‡…ï½óá²÷5‡a£5k<,É6¤kpúA¬Ó¬|È@.ݪ¨ã¬„K¨¤;Ùo€U -– 0ȧÛÝ(F(äŸÚ1›ŠÔ žWQ££|x³)aÊ ôë¹Ð–¦L]°«0^àáüSK®9ÇÂYÛ0¸¸/×Ñ,?GÕ³·‹xÏŽhe,òÄ/>»í¦ª e]rÉ\>7¯gvnÂî"’®#×vðéT'RzÝ-PêÙdz~ìšÌeüø¦ý9=üc“ y¯Dz Ò›–"ÿm¤Ï"<üa¤Ý ½ýÈ ÿ7Îê†9î>õàÝ!|t è,BZÃÏ,\HúÓ,ãehMÜÞh@oAÃîåìžØƒSéFÚM¢¨Ö`¾äãxŠŠ’ô[ÀžG¦á¹ªÐOl ‚¾S„6çxØ>&.sî$„MÈÏ©äÚ0ò¢³ £2Ëàçõtý9DšpïÎ÷~çG?âÕNÿ°_wû5Çm®Mß¾iö+è¾lãD‡ëÑH$Õn‘õÛW¯zúéU«vœ­|`yÅ„Ë*ª= ã÷žY1vÔß_ÿéÙÆ¦qŶ@ âÅîç>WBn6²Ÿ¥ÇÖTq9Æq%öGŒŠ:•Aëi䇟Ùè­Ä7,E)Þ À©C¾ã*P+kfzô«'+Ñ{ ôk§\ IhE¯tž*Ú®DyúNE¯™¬ úb°¥×”óÍ/°®sÞ¬ðàú….>ïÕW7\$³·hæKœ6sVU_\]ÓomƒˆÜâpßpÙ£?I¤*"‘ÌW _´1°hþ ?´Ä|‰ÌWªšhëʪÞk¦¹-}xg¦Ù’÷D#.þÔò•÷/ÈÌ÷7BE3’hL™¢™ ZWÙ·Ò1Äà%s-Ëãæ¶Pe90ø†Þ½”ƒÎí@ß+ÎÄö‹x·t-ò­¨átN*úyÑ/žïèé<ÖwÞþËÔ—ÊÃ9_?ËØVßEûö]èÇIùjëˆH(ݪâi5H |‰Äb<ùV4‰ðã¾yX¢cz4‚5md#HÆ 8{Ak—CòaÕáYj˜¸Y.EŸ3¬ §ÇX è§ùÓÿ1Á…èù ü‡Æ´ƒ>q¾°ÍF!´°ùË´l$öÌÑ6‘ó*¡jA.ŒÜ7ÚÛ¬Š€ZŒ¡×õˆ¯A_/›ƒ&4Üuhm@錟ˆ:áyL}ª··/e×S¦þ^Ë5˜M²×’â¶!ÑB2/•¡ëÌ!‡ÏB÷W 5Aùyè·æ_èû¡;ûE‚’ÈW>^3b Ëð¨?°*îik®œèµÄüÕ¡D›Í2¦&Ùê+–¢×6™U»eìê;M#bÁÀŠHXªìºþžÛ2³]’‘Q.¾sòÄuµg ¹E\Òjo$°‡*bÃGŒlÙu8ë.V×ÉUðešÙé  Ã"È=N8=+Ó[òÎÓœÕJ8O3N³gQœÓG5d¡  ¼½ð¨ uâÔ 1O¨¤zzƒÅT˜ÓJY¯ïôžþâ„⤅V²A+ C{-é¥tÒ?SLÿ‹nº@3IÂIúGÀÿQ3Å¥,Ã| ÍK$fŸWM‰–O[ƒ±&h¦Û ™‚c^¬F¡™²!_‰µmH1©>wLuŸWL1·8ìújØóKå} N;ko­e'ŒÚŧGKÛtm†‰š‰|šnša–fßcÞc}ÆþLa·¹ÛzÐ~°Ð$G æåE,ÓKé¦%ë Š7-úÀ\x¿9»ZZðØÛïlÝúvô£Ì'<™ù„Ožä¡¥o=úèÛo?ºåM~õ¯2_pÓ¯~Å™/È>ûð^؇`þŸé°ƒ*ì@ìÀ ‚ ;Ðî߄ȱC:èPwµ Љ‡™@'vЉ6`ˆëPsç?>ÞDÈ€YHg!}6ùNÐÍA¤/"ÕCn¤0§sê!éŒ9Y(d^žêGNX>B»ø!/lhç¬v ]¦’Ýט½|ÏZ„½9¯Î”»§kšÍ™Yaä5‡Õ‹Ð÷E8JdÆF¢5íVk{M4²Åíh{溟ñ¢Aöî¢}-¼~ý¾ý÷ß¿÷ùA ªÞ ì=¥H0­xΘ1™/޼™8Fz~ý÷^Ø»îþ½‚ï‹÷ à»8»7Vvï$®cY Ég=Aø <‡°ÞÄv @Q+0ˆÙ€ 1‡Y'2 ®BØ+âµ ‰¶ÜÛ'¨âsˆÁ?ñý/°œ÷Qt’Â' Kåìíj$®mNµéu8¯ûÅ3oiðÙÇ'ÿ䯮ó¦Š'Ûöܹl\c¨qø­wa…ûÿ¨Ø±÷V>+ý‹“ƒ]Ì@:i$Æw o¾ƒ}|˜¬‡~\©}äÊwÑçq´o$}ä@p² }+Ú7¡}3Ú7C’lýýžF¿§ÑïiôÛMtWôªá{T±WоíûѾíÝh?Éu¶LØ…€°ÔçF?‰dÀܬOH²RÂÙ€óÆV¡çJœ•zoEÿQŠS¶£ì6&Þ¸)hIÃ>ªÅ Añ§4=–B{‚æ-ÆiÎgOâ©Ï#¼Nçëï$PËК¦q¸ÕæÆÜ1šÄmð@O__§¸º¸ð:\Ü5\z>ô:•|Ÿs7G܃ÛϽ'¿hŸ/-5Æv\¿èžînxÿW¾zÙSŠa„ÛïóÜ[Ý]W\»ôŽ·~ùÓcXH™¡qû*ÂÃüæúôô1c[\{ß÷ãj*µ¼.Q°$ãW¶Ž¬W4k»Ön/.³Û“ä³w ö+s•n òTº R![†pÂ&:«Bè¨\T…Ö×(PfdœA‹u‡P¦Û°×£ö(N1 = ¹ÅèŽ$”È _ÞˆzŽ4ë„i 1éÈ×ίYïý‚+Þ!ßÜ–pèBC 8ü<Ï zÑ'ß™¬ŒÅ27]uìŒÛ©&›ç>Þ¾üIÕfÞ ×^µ$¤Vøåy~Øò™};.Џ|I»œ8!0{ž‡Oøî#uñhjæÏÅ®Æ öAlîv¥=†°+”ŸÌY`nàPN÷@~ì[*Yä†HX!9ʱçJPx9ð1‚¶ÏÛQU$w äßkÉÓ™Öè%É’$m ú§w@hbóy{éœþ*õ_`"ånÇþÉÅYÖZÊ:ß6óÅ‹–.þÁ:5Ž}öT%ãäÎ^7é™gŠÛRjôÑ€ƒ/ù·e÷/äûá ¯õìToH°mž¿)$®³š¨ :ø©ò𠳦UÈ#üŸx4B÷ÝYÊp““‰hìL ´@Køàaúö®}MÀÖ>6’ÑùÂG‡ nÊy5&±k;,CqÉ#œ 3ÂUñb!ÆÛiÕ…qíôé^Xx/ô©ƒÞÔ73É:­¿×Ëã—¼è˽ Ý6* —°´1œâ ÷µ\Vnäu‘Hr”%óbY2O”ɤuÕô¨¥E£œÝÅ„Ýj23[êðD#î ?ì•ÎZE• ¶©zÎ`4¿þU½ø*d²éÐkÖÁ+Z ê»uP¨þÝTäüÐ ÂgO!m‚¯3é\„EÈ/@ë ¤ë¶"p¢£©§‰¬©j´{Ä6.î7Kq‚iÌY”³æÅI!%“¨ó¢ç(úºµ³„a±T²› Õ£ìD\Œ’‚´å)³dêÛöèì=ÕkúìÔg9ç?ûîßž:Ü*l¾¥üx 6„œà—Qx¸i’®„Ûo¤vÑ&FŒ"RðbCb¬åE0Ó¸¡¶Á_ô!ÑP”½5%Án¼ó’NÎqܹû?{CàRž¼ÄsPùzWjX².ÓçŽÔ7Ûx[æÍ¢¦ÊšqGê“ µú«¯®çŠGM583¿ç׿‡cÕ߯KUdž t…üAÄòóI¼ÎCNš?xô¨/ TO(ù(³'„vÐþJÐK#ìó.ÐK‚½–N /üi/¬/NÛD<돚ÉF<„Là´Ý¹3Žœ³Æ«Iš 8ôe±ûÞÄÄmV rZäò0[ Ò2¤a¤Q¤7 Õá4¬d™3c‚„õ —i©"ò\¡SÔ€Ï é†ÒGI Y*n!}ØCy=ø¦ 81"nÃAù6fy­§o@‰PÂ8«×‰‡0 baö0!*…Ö©&>¸ð›ª¡;1_qî«ó’wñ/¯¿vÔÙ§‡5•UI-™€¸9=N²[YÙU;½&ÙY©VU8ª«¤æš©HdOT­I¹ÆÇ³ß:2ëå}¨ðžt%$‰6‡;Ž‘’¤wLìIA^ØØÅ Yñ†Å¸˜ < X ùë%ÑPŠ9dv+æ1³[€²–v©°æzS§€…%ûeB¯ø&Q˜$C7;d—¸96\b§o*s[&œØ=þ†ÝÝÒ¡€FrÌ›RÑTXÚQÛ}ÿ¨Õªßé1:w>°;ZÙaΙœÂxºvnZ8¦H– ÆøÃ»N.[>§D‚¨—u7ïü|êo7ȼ`âÍ”}W%E3zi»6=XZu >Õ¦d¿†;Ô˜RtÅ mâôñ °K²ûà+VAö{éÆ_hqãê¤7Ÿfz÷)4z8Y b' ¹,–½‚œ~iPEøy ¿2 § G|ۑïó<€ÙÏorwcÕ\X»@Œ¾Í‘=ç<3mî4}W;‚¬aißü+*†–OÅv?°Ýcòº<^ƒmïý»ãñé}ºú ~ÄÕµsã¢ñÁÖ°ºçó;ßòk•¼€×ÑJŠÿe'w©jk$Æ,Þ´cíaÓÑòŽëŒ-ã<ûŒ·Ú­Jû2zåsm‚xgè×Hµú :k7göeÆi×üÃï@âʶ!|¨áÛ‘¶!ŒRŽ fÎE¸¡¡¡aúmËx3GØÚܘٹv1ßa„5óv",DèÎÍ)òWgŸÁ#ìˇEŸ>¤SsÏ|Ïq(G¤¨H±^?þÞc'y HòKÊNùß”ˆò}Í4ÍfÍo4_h¿­«Ò=§Ÿ­?“÷Ýü ù†ec ž(ÜT4®h³qŠñ¦cæ…fyÀ:Ù¶ ¸ ø½’)% J¾ TâÐïû$‘9Ó*~é¢;ÉïÈÝ rÐÏýzgÒØñ£¦ŽŽ¾uùí7ο}è—4™ìŽú+š8ýʦ´ç¡·³*½koëaa´B·A6acÙ86žM`Ù$6™];ã XOW²«`óÌ`°[¯f³Ø5¬“]Ë®c³ÓƒÒ=<-Þ¤Áß.@<‚e§¸IÜ_óFøý2F5 ”¯Çh™×ÁGy-Õ×P} ި̫©¦’â Dªá1*EÌ#ðÐe®R>LÏ QkâÍê園†{©NäeNïQ!]œØ†»¨ŸÈË8ÕIˆË)_F#J¹žk§R {ƒJ6*Yéù %s37Á#Öp3µˆ¼Ì”/ Ø@q>σ߫¡Xãü^© %ṳ̂AÚFïÌD ÅJ®ŸB%™b‰åB’€°6ˆú"PŒHEŸ³tœ!ûò,ÝÜù†Úϰ¿³»Ñ~†J"/³¯AW2;;‚ÿ¯Aš¡ÒO!Ù¾bcsP'ZdÄ÷ îoìæÓP‹Ìþ–í(¨£µR›Ly™}A7ÖÿCóõ³?CÖiŠ’Èˬ}PƒTÔý‰ý7õø•þ›zü‘lª“l'âÏY#âÏØ ‡54R¦¼ û<=»—FþÅÿOPû=åO ]f¿£üRü[ŠCox³_"Ç©îׄÈÇÔò+ªù@íQéÅG³g†Tœ€ÈËìCjù%ÅнÀ/h–#”ŸêÎþÆýœJÿNã~YbCÝϨî=ó.{‡êÞ¡ÒÛ‚ÒYàö{“ZÞ¢wo ŠSz3·ÿ7©÷4ÏkìUöê^Ë•D¿WÙap¯†ZdÄâ4cÖ0êD‹ŒXœ¥¨‘YwnßÝÐ`2¬#ËË4ÛK¿Hû:ˆóÏö;Hµ‰DÌö³}´†ýÔ²ŸÖ°½@kØGkØGkxí¥5¼@kxÖ°7·§½´‘—aNE·‰˜=GgúšùYŠLñ¢ˆ]”ÿÅ;)ÞÁž|J±Ì¶SüCÈ8™=Åžò©ÀWäeöyœm#ÊØF{ V(dÅ2ÛBñ#Ô² ò¸ -›h¾ôµÆ÷©ýaöÑôCDÍèmÞƒ¬ ’WƒTpŠÈËÀBô^Oñý¯cßCo Rñ„ïÑȵÔò]¢ì5D÷±{iM÷RËw(^µÈÀ­bÿÆÄêUÀE¦¼ [Œ¿‹æ½“FÜ?¸‰¾u¥å4~ åo¡x1»~Œi J"/ãé¢eËàüev#[H–õt*"/Ãú¾éh qŽ „tƒ­/ž:M£Þó讇]€Òõ4ã\Bo<[q 9‡,ÎÙôÛµX· üN¢òY¹ygѨ«IÞ̤|GnöBv´‡3¨m:=ÿª\«¨n­öJÊO….ç5•JWÐ S(?™¨ý2?‰â‰lâ Ô:^è-èM‘K2a ɬvªMRlTnîQÀ^ˆ¹[q®b­4~d®4’fA{Nq ÍÓLqÅÆ¥1ŒlÈ=¡Þ×ÍÕÒ\5Ô;Eq’âj‘ oF«¨†ô-Ê"ŽS£>QºÇäh> endobj 51 0 obj [ 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] endobj 17 0 obj << /Type /Font /Subtype /TrueType /BaseFont /LGIBRC+Courier /FontDescriptor 50 0 R /Widths 51 0 R /FirstChar 32 /LastChar 125 /Encoding /MacRomanEncoding >> endobj 52 0 obj << /Author (adamson) /Creator (Word) /CreationDate (D:20071024112329-04'00') /ModDate (D:20071024112329-04'00') /Producer (Mac OS X 10.4.10 Quartz PDFContext) /Title (Microsoft Word - npcUsage.doc) >> endobj xref 0 53 0000000000 00000 n 0000012012 00000 n 0000000022 00000 n 0000012117 00000 n 0000011991 00000 n 0000013080 00000 n 0000074414 00000 n 0000055121 00000 n 0000107948 00000 n 0000046688 00000 n 0000039078 00000 n 0000012251 00000 n 0000013060 00000 n 0000023005 00000 n 0000013116 00000 n 0000023113 00000 n 0000022984 00000 n 0000119380 00000 n 0000028717 00000 n 0000023249 00000 n 0000028825 00000 n 0000028696 00000 n 0000059972 00000 n 0000038822 00000 n 0000028974 00000 n 0000038930 00000 n 0000038801 00000 n 0000039183 00000 n 0000039234 00000 n 0000046320 00000 n 0000046341 00000 n 0000046604 00000 n 0000046877 00000 n 0000054490 00000 n 0000054511 00000 n 0000054761 00000 n 0000055304 00000 n 0000059690 00000 n 0000059711 00000 n 0000059948 00000 n 0000060144 00000 n 0000073774 00000 n 0000073796 00000 n 0000074038 00000 n 0000074591 00000 n 0000107295 00000 n 0000107317 00000 n 0000107564 00000 n 0000108130 00000 n 0000118740 00000 n 0000118762 00000 n 0000118984 00000 n 0000119553 00000 n trailer << /Size 53 /Root 27 0 R /Info 52 0 R /ID [ ] >> startxref 119770 %%EOF norm-1.5.8+dfsg2/examples/0000755000000000000000000000000013320270771012207 5ustar norm-1.5.8+dfsg2/examples/README.TXT0000644000000000000000000000506611433527621013556 0ustar ================= NORM API Examples ================= This directory contains some purposely simplified examples of NORM API usage. See comments in the source code files on how to build these on Unix platforms. Eventually, "Makefiles" (and hopefully "waf" configure/build scripts) will be provided as well as Visual C++ project files for Win32 builds. The following example programs are included: (These two programs use a hard-coded multicast address and port, but take a file name and directory name, respectively, as a command-line argument to determine the file sent and the directory to which receive files are stored.) normFileSend.cpp - simple file transmission program. Sends one file and exits. normFileRecv.cpp - simple file reception program. Receives one file and exits. normDataSend.cpp - simple NORM_OBJECT_DATA transmission program. Sends a series of data objects of random size. In this example, the NORM_INFO for the objects is set with some text with some "info" about the object. normDataRecv.cpp - simple NORM_OBJECT_DATA reception program. This receives the data objects that "normDataSend" transmits and validates their correctness, in part based on the "info" embedded in the NORM_INFO. java - There is a README.TXT in the java directory. It explains the java examples, how to build them, and how to run them. NOTES: Althought the normDataSend/Recv example use relatively small data object sizes, the _intended_ use of NORM_OBJECT_DATA is for bulkier content stored in application memory space. For "messaging" applications that use modestly small message sizes, the NORM_OBJECT_STREAM transport option in NORM is likely to provide more efficient service than NORM_OBJECT_DATA for small objects due to the packet level Forward Error Correction (FEC) based packet recovery mechanism that NORM uses. In the future, a similar "simple" example pair will be provided to illustrate the NORM_OBJECT_STREAM form of transport. Meanwhile, the "normTest.cpp" file in the "norm/src/common" directory provides an example of the NORM API calls related to this. Other examples will be added later including examples using the "NormGetDescriptor()" function to allow NORM API events to be multiplexed with other possible application events (e.g. other I/O or Windows messages, etc). Brian Adamson 20 August 2010 norm-1.5.8+dfsg2/examples/java/0000755000000000000000000000000013320270771013130 5ustar norm-1.5.8+dfsg2/examples/java/NormFileRecv.java0000644000000000000000000000325611316204003016320 0ustar import mil.navy.nrl.norm.NormEvent; import mil.navy.nrl.norm.NormFile; import mil.navy.nrl.norm.NormInstance; import mil.navy.nrl.norm.NormNode; import mil.navy.nrl.norm.NormObject; import mil.navy.nrl.norm.NormSession; import mil.navy.nrl.norm.enums.NormEventType; import mil.navy.nrl.norm.enums.NormObjectType; /** * Example code to receive a file from the NormFileSend example. * * @author Jason Rush */ public class NormFileRecv { public static void main(String[] args) throws Throwable { if (args.length != 1) { System.err.println("Usage: NormFileRecv "); return; } NormInstance instance = new NormInstance(); instance.setCacheDirectory(args[0]); NormSession session = instance.createSession("224.1.2.3", 6003, NormNode.NORM_NODE_ANY); session.startReceiver(1024 * 1024); NormEvent event; while ((event = instance.getNextEvent()) != null) { NormEventType eventType = event.getType(); NormObject normObject = event.getObject(); System.out.println(eventType); switch (eventType) { case NORM_RX_OBJECT_INFO: byte[] info = normObject.getInfo(); String infoStr = new String(info, "US-ASCII"); System.out.println("Info: " + infoStr); break; case NORM_RX_OBJECT_COMPLETED: if (normObject.getType() == NormObjectType.NORM_OBJECT_FILE) { NormFile normFile = (NormFile)normObject; String filename = normFile.getName(); System.out.println("NormFileObject: " + filename); } break; } } session.stopReceiver(); session.destroySession(); instance.destroyInstance(); } } norm-1.5.8+dfsg2/examples/java/NormFileSend.java0000644000000000000000000000224411406426466016331 0ustar import java.nio.ByteBuffer; import mil.navy.nrl.norm.NormEvent; import mil.navy.nrl.norm.NormInstance; import mil.navy.nrl.norm.NormNode; import mil.navy.nrl.norm.NormSession; import mil.navy.nrl.norm.enums.NormEventType; /** * Example code to send a file to the NormFileRecv example. * * @author Jason Rush */ public class NormFileSend { public static void main(String[] args) throws Throwable { if (args.length != 1) { System.err.println("Usage: NormFileSend "); return; } NormInstance instance = new NormInstance(); NormSession session = instance.createSession("224.1.2.3", 6003, NormNode.NORM_NODE_ANY); session.startSender(1, 1024 * 1024, 1400, (short)64, (short)16); // Enqueue some data ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024); session.dataEnqueue(byteBuffer, 0, 1024); // Enqueue a file session.fileEnqueue(args[0]); NormEvent event; while ((event = instance.getNextEvent()) != null) { NormEventType eventType = event.getType(); System.out.println(eventType); } session.stopSender(); session.destroySession(); instance.destroyInstance(); } } norm-1.5.8+dfsg2/examples/java/NormFileSendRecv.java0000644000000000000000000000573311406426466017157 0ustar import mil.navy.nrl.norm.*; import mil.navy.nrl.norm.enums.NormEventType; import mil.navy.nrl.norm.enums.NormObjectType; /** * The ... class ... *

* Created by scmijt * Date: Feb 14, 2010 * Time: 11:10:50 AM */ public class NormFileSendRecv extends Thread { NormInstance instance; NormSession session; String fileToSend; public NormFileSendRecv(String cacheDirectory, String fileToSend) throws Throwable { instance = new NormInstance(); instance.setCacheDirectory(cacheDirectory); session = instance.createSession("224.1.2.3", 6003, NormNode.NORM_NODE_ANY); session.setLoopback(true); this.fileToSend=fileToSend; start(); sendFile(); session.destroySession(); instance.destroyInstance(); } public void run() { try { receive(); } catch (Throwable throwable) { throwable.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } public void receive() throws Throwable { session.startReceiver(1024 * 1024); NormEvent event; while ((event = instance.getNextEvent()) != null) { NormEventType eventType = event.getType(); NormObject normObject = event.getObject(); System.out.println("NORM: Received something !!!!"); System.out.println(eventType); switch (eventType) { case NORM_RX_OBJECT_INFO: byte[] info = normObject.getInfo(); String infoStr = new String(info, "US-ASCII"); System.out.println("Info: " + infoStr); break; case NORM_RX_OBJECT_COMPLETED: if (normObject.getType() == NormObjectType.NORM_OBJECT_FILE) { NormFile normFile = (NormFile)normObject; String filename = normFile.getName(); System.out.println("NormFileObject: " + filename); } break; } } session.stopReceiver(); } public void sendFile() throws Throwable { session.startSender(1, 1024 * 1024, 1400, (short)64, (short)16); // Enqueue some data // byte buffer[] = "Hello to the other norm node!!!!!!".getBytes(); // session.dataEnqueue(buffer, 0, buffer.length); // Enqueue a file session.fileEnqueue(fileToSend); NormEvent event; while ((event = instance.getNextEvent()) != null) { NormEventType eventType = event.getType(); System.out.println(eventType); } session.stopSender(); } public static void main(String[] args) throws Throwable { if (args.length != 2) { System.err.println("Usage: NormFileSendRecv "); return; } new NormFileSendRecv(args[0], args[1]); } } norm-1.5.8+dfsg2/examples/java/NormMsgr.java0000644000000000000000000006776712767653525015606 0ustar // This is a Java implementation of the same // NORM "messenger" approach as normMsgr.cpp import java.util.concurrent.Semaphore; import java.nio.ByteBuffer; import java.util.Random; import java.util.HashMap; import java.util.LinkedList; import mil.navy.nrl.norm.NormEvent; import mil.navy.nrl.norm.NormInstance; import mil.navy.nrl.norm.NormNode; import mil.navy.nrl.norm.NormSession; import mil.navy.nrl.norm.NormObject; import mil.navy.nrl.norm.NormData; import mil.navy.nrl.norm.enums.NormEventType; import mil.navy.nrl.norm.enums.NormObjectType; import mil.navy.nrl.norm.enums.NormAckingStatus; import mil.navy.nrl.norm.enums.NormSyncPolicy; public class NormMsgr { static final int MSG_SIZE_MAX = 65536; static final int MSG_HDR_SIZE = 2; private static Random randGen = new Random(System.currentTimeMillis()); // These members track NORM's "tx ready" status private Semaphore normTxLock; // this acts as a mutex to manage "tx ready" status in a thread safe way private Semaphore normTxReady; // this blocks data enqueuing until tx ready private boolean norm_tx_vacancy; private int norm_tx_queue_count; private int norm_tx_queue_max; private boolean norm_tx_watermark_pending; public NormInstance normInstance; private NormSession normSession; private boolean norm_acking; // This HashMap is where we cache enqueued Messages until NORM_TX_OBJECT_PURGED // (In the C++ version we used the NormObjectSetUserData() which isn't available in NORM Java API) private HashMap input_msg_list = new HashMap(); // Messages received from NORM are enqueued here until // retrieved by the OutputWriter thread private MessageQueue output_msg_queue; private Semaphore normRxLock; // protects inter-thread access to output_msg_queue private Semaphore normRxReady; // blocks OutputWriter when output_msg_queue is empty // Porbably will build these congestion control modes into the NORM API public enum NormCCMode { NORM_FIXED, NORM_CC, NORM_CCE, NORM_CCL; } // Constructor public NormMsgr() throws java.io.IOException, InterruptedException { normTxLock = new Semaphore(1); normTxReady = new Semaphore(1); try { normInstance = new NormInstance(); normInstance.setDebugLevel(3); } catch (java.io.IOException ex) { System.err.println(ex); throw(ex); } // Default parameter values norm_tx_vacancy = true; norm_tx_queue_max = 2048; // this is set largish, since I'm testing with _small_ messages norm_tx_queue_count = 0; norm_tx_watermark_pending = false; norm_acking = false; normRxLock = new Semaphore(1); normRxReady = new Semaphore(1); output_msg_queue = new MessageQueue(); normRxReady.acquire(); // nothing received yet } public boolean openNormSession(String addr, short port, long nodeId) { try { normSession = normInstance.createSession(addr, port, nodeId); if (null == normSession) { System.err.println("normMsgr error: unable to create NORM session"); return false; } // Set some default parameters (maybe we should put parameter setting in Start()) normSession.setRxCacheLimit(2*norm_tx_queue_max); // we let the receiver track some extra objects normSession.setDefaultSyncPolicy(NormSyncPolicy.NORM_SYNC_ALL); normSession.setDefaultUnicastNack(true); normSession.setTxCacheBounds(10*1024*1024, norm_tx_queue_max, norm_tx_queue_max); normSession.setCongestionControl(true, true); //normSession.setMessageTrace(true); } catch (java.io.IOException ex) { System.err.println(ex); } return true; } // end NormMsgr::openNormSession() public void addAckingNode(long nodeId) { try { normSession.addAckingNode(nodeId); } catch (java.io.IOException ex) { System.err.println(ex); return; } norm_acking = true; } // end NormMsgr::addAckingNode() public boolean setNormMulticastInterface(String ifaceName) { try { normSession.setMulticastInterface(ifaceName); } catch (java.io.IOException ex) { System.err.println(ex); return false; } return true; } // end NormMsgr::setMulticastInterface() public void setNormCCMode(NormCCMode ccMode) { switch (ccMode) { case NORM_CC: // default TCP-friendly congestion control normSession.setEcnSupport(false, false, false); break; case NORM_CCE: // "wireless-ready" ECN-only congestion control normSession.setEcnSupport(true, true); break; case NORM_CCL: // "loss tolerant", non-ECN congestion control normSession.setEcnSupport(false, false, true); break; case NORM_FIXED: normSession.setEcnSupport(false, false, false); break; } if (NormCCMode.NORM_FIXED != ccMode) normSession.setCongestionControl(true); else normSession.setCongestionControl(false); } // end NormMsgr::setNormCCMode() public void setNormTxRate(double bitsPerSecond) { normSession.setTxRate(bitsPerSecond); } public void setNormDebugLevel(int level) {normInstance.setDebugLevel(level);} public void setNormMessageTrace(boolean state) {normSession.setMessageTrace(state);} public boolean start(boolean send, boolean recv) { // Start NORM sender and/or receiver operation boolean recvStarted = false; try { if (recv) { normSession.startReceiver(10*1024*1024); recvStarted = true; } if (send) { if (norm_acking) { // ack-based flow control enabled on command-line, // so disable timer-based flow control normSession.setFlowControl(0.0); } // Pick a random instance id for now int instanceId = randGen.nextInt(); normSession.startSender(instanceId, 10*1024*1024, 1400, (short)16, (short)4); } } catch (java.io.IOException ex) { System.err.println(ex); if (recvStarted) normSession.stopReceiver(); return false; } return true; } // end NormMsgr::start() public boolean sendMessage(Message msg) { // Future version will support NORM_OBJECT_STREAM as an option while (!enqueueMessageObject(msg)); // keep trying until success (we're blocked by "normTxReady" semaphore) return true; } // end NormMsgr::sendMessage() public boolean enqueueMessageObject(Message msg) { try { normTxReady.acquire(); // caller will be blocked if NORM is not "tx ready" normTxLock.acquire(); // this guarantees protected access to "tx ready" state variables } catch (InterruptedException ex) { System.err.println(ex); if (!normTxReady.tryAcquire()) normTxReady.release(); return false; } NormData obj = null; try { obj = normSession.dataEnqueue(msg.getBuffer(), 0, msg.getSize()); } catch (java.io.IOException ex) { //System.err.println(ex); obj = null; } if (null == obj) { // Note we don't call normTxReady.release() here, it's up to the // NormEventHandler to do that upon NORM_TX_QUEUE_EMPTY (or VACANCY for streams) //System.err.println("NormMsgr::SendMessage() warning: data enqueue was blocked."); norm_tx_vacancy = false; // there was no room at the inn normTxLock.release(); return false; } // System.err.println("caching msg for object " + obj + "\n"); // Cache the msg associated with the resultant tx object. We use the // input_msg_list HashMap so we can remove the msg upon NORM_TX_OBJECT_PURGED input_msg_list.put(obj, msg); if (norm_acking) { norm_tx_queue_count++; if (!norm_tx_watermark_pending && (norm_tx_queue_count >= (norm_tx_queue_max / 2))) { try { normSession.setWatermark(obj); norm_tx_watermark_pending = true; } catch (java.io.IOException ex) { System.err.println(ex); } } if (norm_tx_queue_count >= norm_tx_queue_max) { // We've filled our tx cache, so don't call normTxReady.release() // NormEventHandler will do this upon watermark completion normTxLock.release(); return true; } } normTxReady.release(); normTxLock.release(); return true; } public void onNormTxObjectPurged(NormObject normObject) { try { normTxLock.acquire(); } catch (InterruptedException ex) { System.err.println(ex); return; // Should kill program here (or maybe we should acquire uninterruptably)? } if (NormObjectType.NORM_OBJECT_DATA == normObject.getType()) { // removed "msg" will get garbage-collected //System.err.println("purging msg for object " + (NormData)normObject + "\n"); Message msg = input_msg_list.remove((NormData)normObject); if (null == msg) // Shouldn't happen (and it doesn't after adding normTxLock.acquire()) System.err.println("normMsgr warning: purged invalid object?!"); } normTxLock.release(); } // end NormMsgr::onNormTxObjectPurged() // These next two methods are used by the NormEventHandler to update the // NORM "tx ready" status variables in a thread-safe manner. Release of // the "normTxReady" semaphore will unblock the InputThread if it was blocked // due filling up the NORM tx queue. // (The "!wasTxReady" check in these avoids any race condition with the normTxReady semaphore public void onNormTxQueueVacancy() { try { normTxLock.acquire(); } catch (InterruptedException ex) { System.err.println(ex); return; // Should kill program here (maybe we should acquire uninterruptably) } boolean wasTxReady = norm_tx_vacancy && (norm_acking ? (norm_tx_queue_count < norm_tx_queue_max) : true); norm_tx_vacancy = true; boolean isTxReady = norm_acking ? (norm_tx_queue_count < norm_tx_queue_max) : true; if (!wasTxReady && isTxReady) { if (normTxReady.tryAcquire()) System.err.println("NormMsgr::setNormTxVacancy() warning: normTxReady wasn't locked?!"); normTxReady.release(); } normTxLock.release(); } // end NormMsgr::onNormTxQueueVacancy() public void onNormTxWatermarkCompleted() { try { normTxLock.acquire(); } catch (InterruptedException ex) { System.err.println(ex); return; // Should kill program here (or maybe we should acquire uninterruptably)? } boolean wasTxReady = norm_tx_vacancy && (norm_acking ? (norm_tx_queue_count < norm_tx_queue_max) : true); norm_tx_queue_count -= (norm_tx_queue_max / 2); norm_tx_watermark_pending = false; boolean isTxReady = norm_tx_vacancy && (norm_acking ? (norm_tx_queue_count < norm_tx_queue_max) : true); if (!wasTxReady && isTxReady) { if (normTxReady.tryAcquire()) System.err.println("NormMsgr::decrementNormTxQueueCount() warning: normTxReady wasn't locked?!"); normTxReady.release(); } normTxLock.release(); } // end NormMsgr::onNormTxQueueVacancy() public void onNormRxObjectCompleted(NormObject obj) { try { normRxLock.acquire(); } catch (InterruptedException ex) { System.err.println(ex); return; // Should kill program here (or maybe we should acquire uninterruptably)? } if (NormObjectType.NORM_OBJECT_DATA == obj.getType()) { // It's a message, so put it in the output_msg_queue for the OutputWriter thread boolean wasEmpty = output_msg_queue.isEmpty(); Message msg = new Message(((NormData)obj).getData(), (int)obj.getSize()); output_msg_queue.append(msg); if (wasEmpty) normRxReady.release(); // this will unblock the waiting OutputWriter } normRxLock.release(); } // end NormMsgr::onNormRxObjectCompleted() // Called by OutputWriter thread to fetch received messages public Message getRxMsg() { try { normRxReady.acquire(); // will block if output_msg_queue is empty normRxLock.acquire(); } catch (InterruptedException ex) { System.err.println(ex); return null; } Message msg = output_msg_queue.removeHead(); if (!output_msg_queue.isEmpty()) normRxReady.release(); normRxLock.release(); if (null == msg) // shouldn't happen System.err.println("NormMsgr warning: output_msg_queue unexpectedly empty?!"); return msg; } public void RunThreads() { InputReader inputReader = new InputReader(this); System.err.println("main thread starting input thread ..."); inputReader.start(); NormEventHandler normEventHandler = new NormEventHandler(this); System.err.println("main thread starting norm event handler thread ..."); normEventHandler.start(); OutputWriter outputWriter = new OutputWriter(this); System.err.println("main thread starting output thread ..."); outputWriter.start(); // For now, we put the "inputReader" thread in the driver's seat. // In the future, we'll be acquiring a semaphore shared among the // threads and determine what thread(s) are signaling the parent // and their status(es) System.err.println("main thread waiting on input thread ..."); inputReader.acquireLock(); // when acquired, indicates thread is done try { inputReader.join(); normInstance.stopInstance(); normInstance.destroyInstance(); normEventHandler.join(); } catch (InterruptedException ex) { System.err.println(ex); } System.err.println("main thread exiting ..."); } public class Message { private ByteBuffer msgBuffer; // Constructors public Message(int size) { msgBuffer = ByteBuffer.allocateDirect(size); } public Message(byte[] buffer, int size) { msgBuffer = ByteBuffer.wrap(buffer, 0, size); } public int getSize() {return msgBuffer.capacity();} public ByteBuffer getBuffer() {return msgBuffer;} } // end class NormMsgr::Message public class MessageQueue extends LinkedList { public void append(Message msg) {addLast(msg);} public void prepend(Message msg) {addFirst(msg);} public Message removeHead() {return removeFirst();} public Message removeTail() {return removeLast();} public boolean isEmpty() { if (null == peekFirst()) return true; else return false; } } // end class NormMsgr::MessageQueue private class InputReader extends Thread { private NormMsgr parentMsgr; private boolean inputDone; private Semaphore threadLock; public InputReader(NormMsgr parent) { parentMsgr = parent; inputDone = false; threadLock = new Semaphore(1); } public boolean acquireLock() { try { threadLock.acquire(); return true; } catch (InterruptedException ex) { System.err.println(ex); return false; } } @Override public void run() { System.err.println("input thread acquiring its lock ..."); try { threadLock.acquire(); } catch (InterruptedException ex) { System.err.println(ex); return; } System.err.println("input thread entering its main loop ..."); byte[] msgHeader = new byte[MSG_HDR_SIZE]; byte[] tmpBuffer = new byte[MSG_SIZE_MAX]; while (!inputDone) { // Read in one message at time. int want = MSG_HDR_SIZE; int got = 0; while (got < want) { try { int result = System.in.read(msgHeader, got, want - got); if (-1 == result) { System.err.println("normMsgr: input end-of-file!"); inputDone = true; threadLock.release(); System.err.println("input thread exiting 1 ..."); return; } //System.err.println("input thread read " + result + " bytes of msg header\n"); got += result; } catch (java.io.IOException ex) { System.err.println(ex); } } int msgSize = 256*msgHeader[0] + msgHeader[1]; //System.err.println("msg header is (256 * " + msgHeader[0] + ") + " + msgHeader[1] + " = " + msgSize); got = 0; msgSize -= 2; // already read header while (got < msgSize) { try { int result = System.in.read(tmpBuffer, got, msgSize - got); if (-1 == result) { System.err.println("normMsgr: input end-of-file!"); inputDone = true; threadLock.release(); System.err.println("input thread exiting 2 ..."); return; } //System.err.println("input thread read " + result + "bytes of message data\n"); got += result; } catch (java.io.IOException ex) { System.err.println(ex); } } int totalSize = msgSize + 2; //System.err.println("normMsgr: read a " + totalSize + " byte message ...\n"); Message msg = new Message(msgSize); msg.getBuffer().put(tmpBuffer, 0, msgSize); parentMsgr.sendMessage(msg); } System.err.println("input thread releasing its lock ..."); threadLock.release(); System.err.println("input thread exiting 3 ..."); } // end InputReader::run() } // end class NormMsgr::InputReader private class NormEventHandler extends Thread { private NormMsgr parentMsgr; public NormEventHandler(NormMsgr parent) { parentMsgr = parent; } @Override public void run() { try { System.err.println("entering NormEventHandler loop ..."); NormEvent event; while (null != (event = normInstance.getNextEvent())) { //System.err.println(event); NormSession session = event.getSession(); switch (event.getType()) { case NORM_TX_QUEUE_EMPTY: case NORM_TX_QUEUE_VACANCY: // This will unblock the InputThread if it was blocked parentMsgr.onNormTxQueueVacancy(); break; case NORM_TX_WATERMARK_COMPLETED: if (NormAckingStatus.NORM_ACK_SUCCESS == session.getAckingStatus(NormNode.NORM_NODE_ANY)) { // This will unblock the InputThread if it was blocked //System.err.println("sender tx watermark completed ..."); parentMsgr.onNormTxWatermarkCompleted(); } else { // TBD - we could see who didn't ACK and possibly remove them // from our acking list. For now, we are infinitely // persistent by resetting watermark ack request session.resetWatermark(); } break; case NORM_TX_OBJECT_PURGED: parentMsgr.onNormTxObjectPurged(event.getObject()); break; case NORM_RX_OBJECT_COMPLETED: parentMsgr.onNormRxObjectCompleted(event.getObject()); break; case NORM_REMOTE_SENDER_INACTIVE: // optionally free memory resources that were in // use by this remote sender break; default: break; } } System.err.println("NormEventHandler got null event ..."); } catch (java.io.IOException ex) { System.err.println("NormGetNextEvent IOException:"); System.err.println(ex); } System.err.println("exiting NormEventHandler ..."); } // end NormEventHandler::run() } // end class NormMsgr::NormEventHandler private class OutputWriter extends Thread { private NormMsgr parentMsgr; boolean outputDone = false; // Constructors public OutputWriter(NormMsgr parent) { parentMsgr = parent; } @Override public void run() { while (!outputDone) { Message msg = parentMsgr.getRxMsg(); // this will block if none available // Make and write 2-byte length header (adding to the length to account for header, too) int msgSize = msg.getSize() + MSG_HDR_SIZE; byte[] msgHeader = new byte[MSG_HDR_SIZE]; // This currently assumes 2-byte MSG_HDR_SIZE msgHeader[0] = (byte)((msgSize >> 8) & 0xff); msgHeader[1] = (byte)(msgSize & 0xff); System.out.write(msgHeader, 0, MSG_HDR_SIZE); // Write message content System.out.write(msg.getBuffer().array(), 0, msg.getSize()); } System.err.println("NormMsgr output thread exiting ..."); } } // end class NormMsgr::OutputWriter() public static void usage() { System.err.println("Usage: normMsgr id {send &| recv} [addr [/]][ack [,,...]\n" + " [cc|cce|ccl|rate ][interface ][debug ][trace]\n"); } public static void main(String[] args) throws Throwable { // Default parameters String sessionAddr = "224.1.2.3"; short sessionPort = 6003; long nodeId = 0; boolean send = false; boolean recv = false; String[] ackerList = null; String mcastIface = null; int debugLevel = 0; boolean normTrace = false; NormCCMode ccMode = NormCCMode.NORM_CC; double txRate = 1.0e+06; // only applies for NORM_FIXED ccMode int i = 0; while (i < args.length) { String cmd = args[i++]; if (cmd.equals("id")) { nodeId = Integer.parseInt(args[i++]); } else if (cmd.equals("send")) { send = true; } else if (cmd.equals("recv")) { recv = true; } else if (cmd.equals("addr")) { String[] items = args[i++].split("/"); sessionAddr = items[0]; if (items.length > 1) sessionPort = (short)Integer.parseInt(items[1]); } else if (cmd.equals("interface")) { mcastIface = args[i++]; } else if (cmd.equals("cce")) { ccMode = NormCCMode.NORM_CCE; } else if (cmd.equals("cce")) { ccMode = NormCCMode.NORM_CCL; } else if (cmd.equals("rate")) { ccMode = NormCCMode.NORM_FIXED; txRate = Double.parseDouble(args[i++]); } else if (cmd.equals("ack")) { ackerList = args[i++].split(","); } else if (cmd.equals("debug")) { debugLevel = Integer.parseInt(args[i++]); } else if (cmd.equals("trace")) { normTrace = true; } else { System.err.println("normMsgr error: invalid command '" + cmd + "'"); usage(); return; } } if (!send && !recv) { System.err.println("normMsgr error: not configured to send or recv!"); usage(); return; } if (0 == nodeId) { System.err.println("normMsgr error: no local 'id' provided!"); usage(); return; } NormMsgr msgr = new NormMsgr(); msgr.setNormDebugLevel(debugLevel); msgr.openNormSession(sessionAddr, sessionPort, nodeId); if (null != mcastIface) msgr.setNormMulticastInterface(mcastIface); if (null != ackerList) { for (i = 0; i < ackerList.length; i++) msgr.addAckingNode(Integer.parseInt(ackerList[i])); } msgr.setNormCCMode(ccMode); if (NormCCMode.NORM_FIXED == ccMode) msgr.setNormTxRate(txRate); msgr.setNormMessageTrace(normTrace); msgr.start(send, recv); msgr.RunThreads(); System.err.println("normMsgr: main() exiting ..."); } } // end class NormMsgr norm-1.5.8+dfsg2/examples/java/NormStreamRecv.java0000644000000000000000000000611011433527621016702 0ustar import java.io.IOException; import java.net.InetAddress; import mil.navy.nrl.norm.NormEvent; import mil.navy.nrl.norm.NormInstance; import mil.navy.nrl.norm.NormNode; import mil.navy.nrl.norm.NormObject; import mil.navy.nrl.norm.NormSession; import mil.navy.nrl.norm.NormStream; import mil.navy.nrl.norm.enums.NormEventType; public class NormStreamRecv { static final long SESSION_BUFFER_SIZE = 1024 * 1024; static final int SEGMENT_SIZE = 1400; static final int BLOCK_SIZE = 64; static final int PARITY_SEGMENTS = 16; static final String DEST_ADDRESS = "224.1.2.3"; static final int DEST_PORT = 6003; public static void main(String[] args) { NormInstance instance = null; NormSession session = null; String destAddress = DEST_ADDRESS; int destPort = DEST_PORT; try { int length = 0; int offset = 0; byte[] buf = new byte[65536]; boolean useUnicastNACKs = false; if (args.length > 0) { // dest addr is arg 1 InetAddress mcastAddr = InetAddress.getByName(args[0]); useUnicastNACKs = ! mcastAddr.isMulticastAddress(); destAddress = args[0]; if (useUnicastNACKs) System.err.println("Using unicast NACKs"); } if (args.length > 1) { // port is arg 2 destPort = Integer.parseInt(args[1]); } instance = new NormInstance(); session = instance.createSession(destAddress, destPort, NormNode.NORM_NODE_ANY); session.setDefaultUnicastNack(useUnicastNACKs); session.startReceiver(SESSION_BUFFER_SIZE); boolean streamIsAlive = true; NormEvent event; while ((null != (event = instance.getNextEvent())) && streamIsAlive) { NormEventType eventType = event.getType(); NormObject normObject = event.getObject(); //System.err.println(eventType); switch (eventType) { case NORM_RX_OBJECT_NEW: //System.err.println("New stream"); break; case NORM_RX_OBJECT_UPDATED: // Stream updated = data to read .... //System.err.println("An update!"); if (normObject instanceof NormStream) { int numRead = 0; NormStream normStreamobj; normStreamobj = (NormStream)normObject; // Read as much as possible, writing // everything to System.out. while (0 < (numRead = normStreamobj.read(buf, 0, buf.length))) { if (-1 != numRead) { System.out.write(buf, 0, numRead); } } } else { System.err.print("Expected NormStream. Got "); System.err.println(normObject); } break; case NORM_RX_OBJECT_COMPLETED: //System.err.println("Stream end"); streamIsAlive = false; break; } } } catch (IOException ex) { System.err.println(ex); } catch (NumberFormatException ex) { System.err.println("Usage: NormStreamRecv [host-name [port]]"); System.err.println("Default host-name: " + DEST_ADDRESS); System.err.println("Default port: " + DEST_PORT); } if (null != session) { session.stopReceiver(); session.destroySession(); } if (null != instance) { instance.destroyInstance(); } } }norm-1.5.8+dfsg2/examples/java/NormStreamSend.java0000644000000000000000000000570111433527621016701 0ustar import java.io.IOException; import mil.navy.nrl.norm.NormEvent; import mil.navy.nrl.norm.NormInstance; import mil.navy.nrl.norm.NormNode; import mil.navy.nrl.norm.NormSession; import mil.navy.nrl.norm.NormStream; import mil.navy.nrl.norm.enums.NormEventType; public class NormStreamSend { static final long REPAIR_WINDOW_SIZE = 1024 * 1024; static final long SESSION_BUFFER_SIZE = 1024 * 1024; static final int SEGMENT_SIZE = 1400; static final int BLOCK_SIZE = 64; static final int PARITY_SEGMENTS = 16; static final String DEST_ADDRESS = "224.1.2.3"; static final int DEST_PORT = 6003; public static void main(String[] args) { NormInstance instance = null; NormSession session = null; NormStream stream = null; String destAddress = DEST_ADDRESS; int destPort = DEST_PORT; try { int length = 0; int offset = 0; byte[] buf = new byte[65536]; if (args.length > 0) { destAddress = args[0]; } if (args.length > 1) { destPort = Integer.parseInt(args[1]); } instance = new NormInstance(); session = instance.createSession(destAddress, destPort, NormNode.NORM_NODE_ANY); String ccStr = System.getProperty("Norm.CC", "off"); if (ccStr.equalsIgnoreCase("on")) { session.setCongestionControl(true, true); System.out.println("Set Congestion Control to " + ccStr); } session.startSender(1, SESSION_BUFFER_SIZE, SEGMENT_SIZE, BLOCK_SIZE, PARITY_SEGMENTS); stream = session.streamOpen(REPAIR_WINDOW_SIZE); while (-1 != (length = System.in.read(buf, 0, buf.length))) { int numWritten = 0; offset = 0; while (length != (numWritten = stream.write(buf, offset, length))) { length -= numWritten; offset += numWritten; NormEvent event = instance.getNextEvent(); NormEventType eventType = event.getType(); while ((eventType != NormEventType.NORM_TX_QUEUE_EMPTY) && (eventType != NormEventType.NORM_TX_QUEUE_VACANCY)) { event = instance.getNextEvent(); eventType = event.getType(); } } stream.markEom(); //System.err.println("Wrote " + numWritten); //System.err.println("... Done!"); // TODO: Create a new buf each time I'm successful writing // all of it? } stream.flush(); System.err.println("End of file!"); } catch (IOException ex) { System.err.println(ex); } catch (NumberFormatException ex) { System.err.println("Usage: NormStreamSend [host-name [port]]"); System.err.println("Default host-name: " + DEST_ADDRESS); System.err.println("Default port: " + DEST_PORT); } if (null != stream) { System.err.println("Closing stream"); stream.close(true); } if (null != session) { System.err.println("Stopping sender"); session.stopSender(); System.err.println("Destroying session"); session.destroySession(); } if (null != instance) { System.err.println("Destroying instance"); instance.destroyInstance(); } System.err.println("That's all folks!"); } }norm-1.5.8+dfsg2/examples/java/README.TXT0000644000000000000000000000477011433527621014500 0ustar ================= NORM Java API Examples ================= This directory contains some purposely simplified examples of NORM Java API usage. See comments below on how to build and run these on Unix platforms. Eventually, "build.xml" will be provided. The following example programs are included: (These two programs use a hard-coded multicast address and port, but take a file name and directory name, respectively, as a command-line argument to determine the file sent and the directory to which receive files are stored.) NormFileSend.java - simple file transmission program. Sends one file. The address is 224.1.2.3:6003. NormFileRecv.java - simple file reception program. Receives one file. The address is 224.1.2.3:6003. NormFileSendRecv.java - One application that sends a file to itself. The address is 224.1.2.3:6003. NormStreamSend.java - This is an example of writing to a NORM stream. It reads from STDIN and writes to the stream. Specify the stream address on the command line or use the default address, 224.1.2.3:6003. Enable congestion control by setting the Java system property Norm.CC to "on" (i.e. -DNorm.CC=on). NormStreamRecv.java - This is an example of reading from a NORM stream. It writes to STDOUT and writes from the stream. Specify the stream address on the command line or use the default address, 224.1.2.3:6003. COMPILING THE Java API EXAMPLES After you build the JNI and the Norm Java jar file, you can compile the examples in this directory all at one go: javac -cp ../../lib/norm-1.0.0.jar *.java RUNNING THE Java API EXAMPLES You can use the shell scripts supplied to run the similarly named example programs. filesend.sh - Run NormFileSend filerecv.sh - Run NormFileRecv streamsend.sh - Run NormStreamSend streamrecv.sh - Run NormStreamRecv Alternatively, you can run any example program by invoking java. You must define the system property java.library.path and set the classpath so that java can find the norm jar file as well as the local classes. For example, to run NormStreamSend: java -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormStreamSend NOTE ABOUT NormStreamSend NormStreamSend supports NORM's TCP-friendly congestion control. Enable that by setting the system property Norm.CC to "on". You can do that in streamsend.sh or you can do that on the command line: java -DNorm.CC=on -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormStreamSend norm-1.5.8+dfsg2/examples/java/filerecv.sh0000755000000000000000000000013711433527621015271 0ustar #!/bin/bash java -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormFileRecv $@ norm-1.5.8+dfsg2/examples/java/filesend.sh0000755000000000000000000000013711433527621015263 0ustar #!/bin/bash java -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormFileSend $@ norm-1.5.8+dfsg2/examples/java/normMsgr.sh0000755000000000000000000000013312300160643015261 0ustar #!/bin/bash java -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormMsgr $@ norm-1.5.8+dfsg2/examples/java/streamrecv.sh0000755000000000000000000000014111433527621015640 0ustar #!/bin/bash java -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormStreamRecv $@ norm-1.5.8+dfsg2/examples/java/streamsend.sh0000755000000000000000000000023711433527621015640 0ustar #!/bin/bash # Enable TCP-friendly congestion control with: # -DNorm.CC=on java -Djava.library.path=../../lib -cp .:../../lib/norm-1.0.0.jar NormStreamSend $@ norm-1.5.8+dfsg2/examples/normClient.cpp0000644000000000000000000003503113224764576015045 0ustar #include "normSocket.h" #include #include #ifdef WIN32 #include "win32InputHandler.cpp" // brings in the entire implementation #else #include #include // for, well, fnctl() #include // obvious child #endif // if/else WIN32/UNIX // BUILD: (assumes "normApi.h" in "include" ... // g++ -I../include -o normClient normClient.cpp normSocket.cpp ../lib/libnorm.a ../protolib/lib/libprotokit.a -lresolv // NOTES: // 1) THIS IS A WORK IN PROGRESS AND NOT YET FUNCTIONAL! // 2) Some of the functions here may be added to the NORM API in the future. // Client initiates connection to "server". When the "client" gets a NORM_REMOTE_SENDER_NEW // from the "server", it knows its connection has been accepted. // To deny a connection, the "server" can send a stream close??? Which means the server will have // to establish state just to deny a client a connection (yuck!) void Usage() { fprintf(stderr, "Usage: normClient [connect [/][,]][debug ][trace]\n"); } const unsigned int MSG_LENGTH_MAX = 64; int main(int argc, char* argv[]) { char serverAddr[64]; strcpy(serverAddr, "127.0.0.1"); UINT16 serverPort = 5000; char groupAddr[64]; const char* groupAddrPtr = NULL; const char* mcastInterface = NULL; NormNodeId clientId = 2; bool trace = false; unsigned int debugLevel = 0; for (int i = 1; i < argc; i++) { const char* cmd = argv[i]; unsigned int len = strlen(cmd); if (0 == strncmp(cmd, "connect", len)) { // connect /[,] const char* val = argv[++i]; const char* portPtr = strchr(val, '/'); if (NULL == portPtr) { fprintf(stderr, "normClient error: missing number\n"); Usage(); return -1; } portPtr++; unsigned int addrTextLen = portPtr - val; if (addrTextLen > 0) { addrTextLen -= 1; strncpy(serverAddr, val, addrTextLen); serverAddr[addrTextLen] = '\0'; } else { fprintf(stderr, "normClient error: missing \n"); Usage(); return -1; } char portText[32]; const char* groupPtr = strchr(portPtr, ','); if (NULL == groupPtr) { strcpy(portText, portPtr); } else { groupPtr++; unsigned int portTextLen = groupPtr - portPtr - 1; strncpy(portText, portPtr, portTextLen); portText[portTextLen] = '\0'; } if (1 != sscanf(portText, "%hu", &serverPort)) { fprintf(stderr, "normClient error: invalid \n"); Usage(); return -1; } if (NULL != groupPtr) { strcpy(groupAddr, groupPtr); groupAddrPtr = groupAddr; } } else if (0 == strncmp(cmd, "interface", len)) { mcastInterface = argv[++i]; } else if (0 == strncmp(cmd, "trace", len)) { trace = true; } else if (0 == strncmp(cmd, "debug", len)) { if (1 != sscanf(argv[++i], "%u", &debugLevel)) { fprintf(stderr, "normClient error: invalid debug level\n"); Usage(); return -1; } } else if (0 == strncmp(cmd, "id", len)) { const char* val = argv[++i]; unsigned long id; if (1 != sscanf(val, "%lu", &id)) { fprintf(stderr, "normClient error: invalid 'id' value\n"); Usage(); return -1; } clientId = id; } else { fprintf(stderr, "normClient error: invalid command \"%s\"\n", cmd); Usage(); return -1; } } NormInstanceHandle instance = NormCreateInstance(); // Initate connection to server ... fprintf(stderr, "normClient: connecting to %s/%hu ...\n", serverAddr, serverPort); NormSocketHandle normSocket = NormOpen(instance); // setting 'localPort' param here to zero lets an ephemeral port be picked NormConnect(normSocket, serverAddr, serverPort, 0, groupAddrPtr, clientId); /* // Optional code to test NormWrite() immediately after NormConnect() call // (Note this is _not_ compatible with newer stale connection reject code) const char* helloStr = "Hello\n"; unsigned int helloLen = strlen(helloStr) + 1; NormWrite(normSocket, helloStr, helloLen); NormFlush(normSocket);*/ if (trace) { NormSetMessageTrace(NormGetSocketSession(normSocket), true); if (NULL != groupAddrPtr) NormSetMessageTrace(NormGetSocketMulticastSession(normSocket), true); } if (0 != debugLevel) NormSetDebugLevel(debugLevel); //NormSetDebugLevel(3); //NormSetMessageTrace(NormGetSocketSession(normSocket), true); #ifdef WIN32 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); Win32InputHandler inputHandler; inputHandler.Open(); HANDLE handleArray[2]; handleArray[0] = NormGetDescriptor(instance); handleArray[1] = inputHandler.GetEventHandle(); #else // On Unix, use a select() call to multiplex input reading and NormSocket handling fd_set fdset; FD_ZERO(&fdset); // Get our input (STDIN) descriptor and set non-blocking FILE* inputFile = stdin; int inputfd = fileno(inputFile); if (-1 == fcntl(inputfd, F_SETFL, fcntl(inputfd, F_GETFL, 0) | O_NONBLOCK)) perror("normClient: fcntl(inputfd, O_NONBLOCK) error"); // Get our NormInstance descriptor int normfd = NormGetDescriptor(instance); # endif // if/else WIN32 bool keepGoing = true; bool writeReady = false; int inputLength = 0; unsigned int bytesWritten = 0; const unsigned int BUFFER_LENGTH = 2048; char inputBuffer[BUFFER_LENGTH]; bool inputNeeded = false; // will be set to "true" upon CONNECT while (keepGoing) { bool normEventPending = false; bool inputEventPending = false; #ifdef WIN32 DWORD handleCount = inputNeeded ? 2 : 1; DWORD waitStatus = MsgWaitForMultipleObjectsEx(handleCount, // number of handles in array handleArray, // object-handle array INFINITE, // time-out interval QS_ALLINPUT, // input-event type 0); if ((WAIT_OBJECT_0 <= waitStatus) && (waitStatus < (WAIT_OBJECT_0 + handleCount))) { if (0 == (waitStatus - WAIT_OBJECT_0)) normEventPending = true; else inputEventPending = true; } else if (-1 == waitStatus) { perror("normClient: MsgWaitForMultipleObjectsEx() error"); break; } else { // TBD - any other status we should handle? // (e.g. WAIT_TIMEOUT, WAIT_ABANDONED or WAIT_IO_COMPLETION) continue; // ignore for now } #else FD_SET(normfd, &fdset); int maxfd = normfd; if (inputNeeded) { FD_SET(inputfd, &fdset); if (inputfd > maxfd) maxfd = inputfd; } else { FD_CLR(inputfd, &fdset); } int result = select(maxfd+1, &fdset, NULL, NULL, NULL); if (result <= 0) { perror("normClient: select() error"); break; } if (FD_ISSET(inputfd, &fdset)) inputEventPending = true; if (FD_ISSET(normfd, &fdset)) normEventPending = true; #endif // if/else WIN32/UNIX if (inputEventPending) { // Read input into our txBuffer #ifdef WIN32 inputLength = inputHandler.ReadData(inputBuffer, BUFFER_LENGTH); if (inputLength > 0) { // We got our input bytesWritten = 0; inputNeeded = false; } else if (inputLength < 0) { // Input stream has likely closed, initiate client shutown // TBD - initiate client shutdown if (NULL == groupAddrPtr) { fprintf(stderr, "normClient: CLOSING connection to server ...\n"); NormShutdown(normSocket); } inputNeeded = false; // TBD -should we also fclose(inputFile)??? inputHandler.Close(); } // else zero bytes read, still need input #else inputLength = fread(inputBuffer, 1, BUFFER_LENGTH, inputFile); if (inputLength > 0) { // We got our input bytesWritten = 0; inputNeeded = false; } else if (feof(inputFile)) { // TBD - initiate client shutdown if (NULL == groupAddrPtr) { fprintf(stderr, "normClient: CLOSING connection to server ...\n"); NormShutdown(normSocket); } inputNeeded = false; // TBD -should we also fclose(inputFile)??? if (stdin != inputFile) { fclose(inputFile); inputFile = NULL; } // else stick around to receive stuff from the server } else if (ferror(inputFile)) { switch (errno) { case EINTR: // interupted, try again break; case EAGAIN: // input starved, wait for next notification break; default: perror("normClient: error reading input?!"); break; } } #endif // if/else WIN32/UNIX } // end if inputEventPending if (normEventPending) { // There's a NORM event pending NormSocketEvent event; if (NormGetSocketEvent(instance, &event)) { switch (event.type) { case NORM_SOCKET_ACCEPT: // shouldn't happen break; case NORM_SOCKET_CONNECT: { char remoteAddr[16]; unsigned int addrLen = 16; UINT16 remotePort; NormGetPeerName(normSocket, remoteAddr, &addrLen, &remotePort); fprintf(stderr, "normClient: CONNECTED to server %s/%hu\n", serverAddr, remotePort); inputNeeded = true; writeReady = true; break; } case NORM_SOCKET_READ: { // This is a cue to try to read data from stream // For our test app here, the data is read and output to STDOUT bool rxReady = true; while (rxReady) { char buffer[1024]; ssize_t bytesRead = NormRead(event.socket, buffer, 1024); if (bytesRead < 0) { // This shouldn't happen with ack-based flow control used fprintf(stderr, "normClient: broken stream ...\n"); continue; } if (bytesRead > 0) { #ifdef WIN32 // Use Win32 WriteFile() so there is no buffer delay DWORD dwWritten; WriteFile(hStdout, buffer, bytesRead, &dwWritten, NULL); #else fwrite(buffer, sizeof(char), bytesRead, stdout); #endif // if/else WIN32 } // If less bytes read than request then need // to wait for next NORM_SOCKET_READ event if (bytesRead < 1024) rxReady = false; } break; } case NORM_SOCKET_WRITE: writeReady = true; break; case NORM_SOCKET_CLOSING: fprintf(stderr, "normClient: server CLOSING connection ...\n"); writeReady = false; inputNeeded = false; break; case NORM_SOCKET_CLOSE: { fprintf(stderr, "normClient: connection to server CLOSED.\n"); writeReady = false; inputNeeded = false; keepGoing = false; break; } case NORM_SOCKET_NONE: break; } // end switch(event.type) } else { fprintf(stderr, "normClient: NormGetSocketEvent() returned false\n"); } } // end if normEventPending // If we have data in our inputBuffer and the NormSocket is "writeReady", then send it if (writeReady && (inputLength > 0)) { bytesWritten += NormWrite(normSocket, inputBuffer + bytesWritten, inputLength - bytesWritten); if (bytesWritten < inputLength) { // Couldn't write whole inputBuffer, need to wait for NORM_SOCKET_WRITE event writeReady = false; } else { // inputBuffer has been completely written inputLength = 0; inputNeeded = true; NormFlush(normSocket); } } } // end while(keepGoing) NormClose(normSocket); #ifdef WIN32 inputHandler.Close(); #else if ((stdin != inputFile) && (NULL != inputFile)) { fclose(inputFile); inputFile = NULL; } #endif // if/else WIN32 fprintf(stderr, "normClient: Done.\n"); return 0; } norm-1.5.8+dfsg2/examples/normDataExample.cpp0000644000000000000000000000650411332613047015777 0ustar // This example uses the NORM API and demonstrates the use // of NORM_OBJECT_DATA transmission and reception. // The "data" sent and received are simple text messages // of randomly-varying length. XXXX - THIS CODE IS NOT YET COMPLETE !!!!! #include // We use some "protolib" functions for // cross-platform portability #include #include void Usage() { fprintf(stderr, "Usage: normDataExample [send][recv]\n"); } int main(int argc, char* argv[]) { bool send = false; bool recv = false; // Parse any command-line arguments int i = 1; while (i < argc) { if (!strcmp("send", argv[i])) { send = true; } else if (!strcmp("recv", argv[i])) { recv = true; } else { fprintf(stderr, "normDataExample error: invalid command-line option!\n"); Usage(); return -1; } return 0; } if (!send && !recv) { fprintf(stderr, "normDataExample error: not configured as sender or receiver!\n"); Usage(); return -1; } // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); if (NORM_INSTANCE_INVALID == instance) { fprintf(stderr, "normDataExample error: NormCreateInstance() failure!\n"); return -1; } // 2) Create a NormSession using default "automatic" local node id NormSessionHandle session = NormCreateSession(instance, "224.1.2.3", 6003, NORM_NODE_ANY); if (NORM_SESSION_INVALID == instance) { fprintf(stderr, "normDataExample error: NormCreateSession() failure!\n"); return -1; } // Enable some debugging output here //SetDebugLevel(2); // Uncomment to turn on debug NORM message tracing NormSetMessageTrace(session, true); // 3) Start receiver operation, if applicable if (recv) { // Start receiver w/ 1MByte buffer per sender if (!NormStartReceiver(session, 1024*1024)) { fprintf(stderr, "normDataExample error: NormStartReceiver() failure!\n"); return -1; } } // 4) Start receiver operation, if applicable if (send) { // a) Pick a random sender "sessionId" // (seed the random generation so we get a new one each time) struct timeval currentTime; ProtoSystemTime(currentTime); srand(currentTime.tv_sec); // seed random number generator NormSessionId sessionId = (NormSessionId)rand(); // b) Set sender rate or congestion control operation NormSetTxRate(session, 256.0e+03); // in bits/second } // Enter loop waiting for and handling NormEvents ... // (We illustrate usage of a NormDescriptor for this // with our WaitForNormEvent() routine.) // When set to "send" the "interval" is used to NormDescriptor normDescriptor = NormGetDescriptor(instance); bool keepGoing = true; while (keepGoing) { boolWaitForNormEvent(normDescriptor, timeDelay) } // end while (keepGoing) } // end main() norm-1.5.8+dfsg2/examples/normDataRecv.cpp0000644000000000000000000002366212276244627015323 0ustar /****************************************************************************** Simple NORM_OBJECT_DATA receiver example app using the NORM API USAGE: normDataRecv BUILD (Unix): g++ -o normDataRecv normDataRecv.cpp -D_FILE_OFFSET_BITS=64 -I../include/ \ ../lib/libnorm.a ../protolib/lib/libProtokit.a \ -lpthread (for MacOS/BSD, add "-lresolv") (for Solaris, add "-lnsl -lsocket -lresolv") ******************************************************************************/ // Notes: // 1) The program exits once a single file has been received ... // 2) The received file is written to the // 3) The program also will exit on from user // 4) "normDataRecv" should be started before "normFileSend" #include "normApi.h" // for NORM API #include "normMessage.h" #include "protoAddress.h" // for ProtoAddress for easy mcast test #include // for printf(), etc #include // for srand() #include // for strrchr() #include // for gettimeofday() // Usage: normDataRecv [addr /] #include "protoBitmask.h" void Usage() { fprintf(stderr, "Usage: normDataRecv [addr /]\n"); } int main(int argc, char* argv[]) { // Initialize default parameters. char sessionAddr[256]; strcpy(sessionAddr, "224.1.2.3"); UINT16 sessionPort = 6003; // Parse command-line for any parameters int i = 1; while (i < argc) { if (0 == strcmp("addr", argv[1])) { i++; if (i == argc) { fprintf(stderr, "normDataRecv error: missing \"addr\" arguments\n"); Usage(); return -1; } strcpy(sessionAddr, argv[i++]); char* ptr = strchr(sessionAddr, '/'); if (NULL != ptr) { *ptr = '\0'; sessionPort = atoi(ptr+1); } } else { fprintf(stderr, "normDataRecv error: invalid command \"%s\"\n", argv[i]); Usage(); return -1; } } // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); // 2) Create a NormSession using default "automatic" local node id fprintf(stderr, "joining session at addr/port %s/%hu\n", sessionAddr, sessionPort); NormSessionHandle session = NormCreateSession(instance, sessionAddr, sessionPort, 2);//NORM_NODE_ANY); // NOTE: These are debugging routines available // (not necessary for normal app use) NormSetDebugLevel(3); // Uncomment to turn on debug NORM message tracing //NormSetMessageTrace(session, true); // Uncomment to turn on some random packet loss for testing //NormSetRxLoss(session, 10.0); // 10% packet loss struct timeval currentTime; gettimeofday(¤tTime, NULL); // Uncomment to get different packet loss patterns from run to run srand(currentTime.tv_sec); // seed random number generator // Uncomment if unicast NACKing is desired // (We "cheat" here and use the Protolib "ProtoAddress" class // that NORM happens to use under the hood as well) ProtoAddress theAddr; theAddr.ResolveFromString(sessionAddr); if (!theAddr.IsMulticast()) { NormSetDefaultUnicastNack(session, true); // Set the tx port equal to session port so sender socket // and make it "connected" to the remote sender address (sessionAddr) and port (sessionPort+1) // (This assumes the remote sender address/port is known (sessionAddr/sessionPort+1 in this case) NormSetTxPort(session, sessionPort); NormSetRxPortReuse(session, true, NULL, sessionAddr, sessionPort+1); } else { // Uncomment to allow multiple NORM processes on same session port number //NormSetRxPortReuse(session, true, sessionAddr); // NormSetDefaultUnicastNack(session, true); } // Set a big rx cache for our current testing NormSetRxCacheLimit(session, 4096); // 3) Start the receiver with 1 Mbyte buffer per sender NormStartReceiver(session, 1024*1024); struct timeval startTime, endTime; // to measure object transfer time // 4) Enter NORM event loop bool keepGoing = true; while (keepGoing) { NormEvent theEvent; if (!NormGetNextEvent(instance, &theEvent)) continue; switch (theEvent.type) { case NORM_RX_OBJECT_NEW: gettimeofday(&startTime, NULL); //fprintf(stderr, "normDataRecv: NORM_RX_OBJECT_NEW event ...\n"); break; case NORM_RX_OBJECT_INFO: // Assume info contains '/' delimited string //fprintf(stderr, "normDataRecv: NORM_RX_OBJECT_INFO event ...\n"); if (NORM_OBJECT_DATA == NormObjectGetType(theEvent.object)) { char dataInfo[8192]; unsigned int nameLen = NormObjectGetInfo(theEvent.object, dataInfo, 8191); dataInfo[nameLen] = '\0'; //fprintf(stderr, "normDataRecv: info = \"%s\"\n", dataInfo); } break; case NORM_RX_OBJECT_UPDATED: { //fprintf(stderr, "normDataRecv: NORM_RX_OBJECT_UPDATE event ...\n"); // Uncomment this stuff to monitor file receive progress // (At high packet rates, you may want to be careful here and // only calculate/post updates occasionally rather than for // each and every RX_OBJECT_UPDATE event) //NormSize objectSize = NormObjectGetSize(theEvent.object); //NormSize completed = objectSize - NormObjectGetBytesPending(theEvent.object); //double percentComplete = 100.0 * ((double)completed/(double)objectSize); //fprintf(stderr, "normDataRecv: object>%p completion status %lu/%lu (%3.0lf%%)\n", // theEvent.object, (unsigned long)completed, (unsigned long)objectSize, percentComplete); break; } case NORM_RX_OBJECT_COMPLETED: { gettimeofday(&endTime, NULL); //fprintf(stderr, "normDataRecv: NORM_RX_OBJECT_COMPLETED event ...\n"); unsigned int objSize = NormObjectGetSize(theEvent.object); const char* dataPtr = NormDataAccessData(theEvent.object); // next 3 lines are temp for normMsgr testing // Validate that the data is complete/accurate // a) compare data size against the size embedded in the "INFO" char dataInfo[8192]; unsigned int nameLen = NormObjectGetInfo(theEvent.object, dataInfo, 8191); dataInfo[nameLen] = '\0'; unsigned int dataCount, dataLen; if (2 != sscanf(dataInfo, "NORM_OBJECT_DATA count>%u size>%u", &dataCount, &dataLen)) { fprintf(stderr, "normDataRecv error: received NORM_OBJECT_DATA with invalid INFO?!\n"); return -1; } if (objSize != dataLen) { fprintf(stderr, "normDataRecv error: received NORM_OBJECT_DATA with bad object size?!\n"); return -1; } // b) check the data content char data = *dataPtr; for (unsigned int i = 0; i < dataLen; i++) { if (dataPtr[i] != data) { fprintf(stderr, "normDataRecv error: received bad NORM_OBJECT_DATA!\n"); return -1; } } double transferTime = endTime.tv_sec - startTime.tv_sec; if (endTime.tv_usec > startTime.tv_usec) transferTime += 1.0e-06 * (double)(endTime.tv_usec - startTime.tv_usec); else transferTime -= 1.0e-06 * (double)(startTime.tv_usec - endTime.tv_usec); double transferRate = (8.0/1000.0) * (double)objSize / transferTime; fprintf(stderr, "normDataRecv: transfer duration %lf sec at %lf kbps\n", transferTime, transferRate); //fprintf(stderr, "normDataRecv: object>%p count>%d size>%u data>%.64s ...\n", // theEvent.object, dataCount, objSize, dataPtr); // NOTE: Since we did not "retain" or "detach data" from this // received data object, it (and its data) will be deleted upon // the next call to "NormGetNextEvent()". //keepGoing = false; break; } case NORM_RX_OBJECT_ABORTED: fprintf(stderr, "normDataRecv: NORM_RX_OBJECT_ABORTED event ...\n"); break; case NORM_REMOTE_SENDER_NEW: fprintf(stderr, "normDataRecv: NORM_REMOTE_SENDER_NEW event ...\n"); break; case NORM_REMOTE_SENDER_ACTIVE: fprintf(stderr, "normDataRecv: NORM_REMOTE_SENDER_ACTIVE event ...\n"); break; case NORM_REMOTE_SENDER_INACTIVE: fprintf(stderr, "normDataRecv: NORM_REMOTE_SENDER_INACTIVE event ...\n"); break; default: //fprintf(stderr, "normDataRecv: Got event type: %d\n", theEvent.type); break; } // end switch(theEvent.type) } NormStopReceiver(session); NormDestroySession(session); NormDestroyInstance(instance); fprintf(stderr, "normDataRecv: Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/normDataSend.cpp0000644000000000000000000002034012147201220015256 0ustar /****************************************************************************** Simple NORM_OBJECT_DATA sender example app using the NORM API USAGE: normSendData BUILD (Unix): g++ -o normDataSend normDataSend.cpp -D_FILE_OFFSET_BITS=64 -I../common/ \ -I../protolib/include ../lib/libnorm.a ../protolib/lib/libProtokit.a \ -lpthread (for MacOS/BSD, add "-lresolv") (for Solaris, add "-lnsl -lsocket -lresolv") ******************************************************************************/ // Notes: // 1) A single file is sent. // 2) The program exits upon NORM_TX_FLUSH_COMPLETED notification (or user ) // 3) NORM receiver should be started first (before sender starts) #include "normApi.h" // for NORM API #include "protoDefs.h" // for ProtoSystemTime() #include "protoDebug.h" // for SetDebugLevel(), etc #include "protoAddress.h" // for ProtoAddress for easy mcast test #include // for printf(), etc #include // for srand() #include // for strrchr() // Usage: normDataSend [addr /] void Usage() { fprintf(stderr, "Usage: normDataSend [addr /]\n"); } int main(int argc, char* argv[]) { // Initialize default parameters. char sessionAddr[256]; strcpy(sessionAddr, "224.1.2.3"); UINT16 sessionPort = 6003; // Parse command-line for any parameters int i = 1; while (i < argc) { if (0 == strcmp("addr", argv[1])) { i++; if (i == argc) { fprintf(stderr, "normDataSend error: missing \"addr\" arguments\n"); Usage(); return -1; } strcpy(sessionAddr, argv[i++]); char* ptr = strchr(sessionAddr, '/'); if (NULL != ptr) { *ptr = '\0'; sessionPort = atoi(ptr+1); } } else { fprintf(stderr, "normDataSend error: invalid command \"%s\"\n", argv[i]); Usage(); return -1; } } // Is the session an mcast addr? ProtoAddress theAddr; theAddr.ResolveFromString(sessionAddr); bool isMulticastSession = theAddr.IsMulticast(); // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); // 2) Create a NormSession using default "automatic" local node id NormSessionHandle session = NormCreateSession(instance, sessionAddr, sessionPort, NORM_NODE_ANY); // NOTE: These are some debugging routines available // (not necessary for normal app use) NormSetDebugLevel(3); // Uncomment to turn on debug NORM message tracing //NormSetMessageTrace(session, true); // Uncomment to turn on some random packet loss //NormSetTxLoss(session, 10.0); // 10% packet loss struct timeval currentTime; ProtoSystemTime(currentTime); // Uncomment to get different packet loss patterns from run to run // (and a different sender sessionId) srand(currentTime.tv_sec); // seed random number generator // 3) Set transmission rate NormSetTxRate(session, 2.0e+06); // in bits/second // Uncomment to enable TCP-friendly congestion control //NormSetCongestionControl(session, true); // Uncomment to use a _specific_ transmit port number // (Can be the same as session port (rx port), but this // is _not_ recommended for mcast sessions when unicast feedback may be // possible! - must be called _before_ NormStartSender()) if (!isMulticastSession) { NormSetTxPort(session, sessionPort+1, true); // Uncomment to set the session to only open // a single socket for transmission. // This also "connects" the sender to session (receiver) addr/port // (unicast nacking _and_ "txPort == rxPort" MUST be used by receivers) NormSetTxOnly(session, true, true); } // Uncomment to allow multiple NORM processes on same session port number // Note that port reuse only works well for mcast. // if (isMulticastSession) NormSetRxPortReuse(session, true); // 4) Start the sender using a random "sessionId" NormSessionId sessionId = (NormSessionId)rand(); TRACE("starting NORM sender ...\n"); NormStartSender(session, sessionId, 1024*1024, 1400, 64, 16); // Uncomment to set large tx socket buffer size // (might be needed for high rate sessions) //NormSetTxSocketBuffer(session, 512000); // 5) Enqueue the first data message // (we enqueue text strings of random length as object content) unsigned int MAX_COUNT = 1; // number of objects to send, zero means unlimited const int MIN_LENGTH = 460000; // min object size (in bytes) const int MAX_LENGTH = 460000; // max object size (in bytes) unsigned int dataCount = 0; int dataLen = MIN_LENGTH + rand() % (MAX_LENGTH - MIN_LENGTH + 1); char* dataMsg = new char[dataLen]; ASSERT(NULL != dataMsg); char data = 'a'; memset(dataMsg, data, dataLen); // set message content with 'dummy' data // Provide some "info" about this message char dataInfo[256]; sprintf(dataInfo, "NORM_OBJECT_DATA count>%d size>%d", dataCount, dataLen); // Enqueue the data object NormObjectHandle dataObj = NormDataEnqueue(session, dataMsg, dataLen, dataInfo, strlen(dataInfo)); ASSERT(NORM_OBJECT_INVALID != dataObj); dataCount++; // 6) Enter NORM event loop bool keepGoing = true; while (keepGoing) { NormEvent theEvent; if (!NormGetNextEvent(instance, &theEvent)) continue; switch (theEvent.type) { case NORM_TX_QUEUE_VACANCY: //fprintf(stderr, "normDataSend: NORM_TX_QUEUE_VACANCY event...\n"); break; case NORM_TX_QUEUE_EMPTY: { if ((0 == MAX_COUNT) || (dataCount < MAX_COUNT)) { // Enqueue another data object when norm tx queue goes empty //fprintf(stderr, "normDataSend: NORM_TX_QUEUE_EMPTY event...\n"); dataLen = MIN_LENGTH + rand() % (MAX_LENGTH - MIN_LENGTH + 1); dataMsg = new char[dataLen]; ASSERT(NULL != dataMsg); memset(dataMsg, data, dataLen); sprintf(dataInfo, "NORM_OBJECT_DATA count>%d size>%d data>%.64s ...", dataCount, dataLen, dataMsg); NormObjectHandle dataObj = NormDataEnqueue(session, dataMsg, dataLen, dataInfo, strlen(dataInfo)); // Note that flow control timer may have prevented NormDataEnqueue() // from succeeding even though we got a NORM_TX_QUEUE_EMPTY notification // (The underlying NORM code could be tightened up a bit here!) if (NORM_OBJECT_INVALID != dataObj) { dataCount++; if (++data > 'z') data = 'a'; } else { TRACE("normDataSend: FLOW CONTROL CONDITION?\n"); } } break; } case NORM_TX_OBJECT_PURGED: { //fprintf(stderr, "normDataSend: NORM_TX_OBJECT_PURGED event ...\n"); char* dataPtr = NormDataDetachData(theEvent.object); delete[] dataPtr; break; } case NORM_TX_FLUSH_COMPLETED: fprintf(stderr, "normDataSend: NORM_TX_FLUSH_COMPLETED event ...\n"); break; default: //TRACE("normDataSend: Got event type: %d\n", theEvent.type); break; } // end switch(theEvent.type) } // end while (NormGetNextEvent()) NormStopSender(session); NormDestroySession(session); NormDestroyInstance(instance); fprintf(stderr, "normDataSend: Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/normFileRecv.cpp0000644000000000000000000001525413046163431015314 0ustar /****************************************************************************** Simple NORM file receiver example app using the NORM API USAGE: normRecvFile BUILD (Unix): g++ -o normFileRecv normFileRecv.cpp -D_FILE_OFFSET_BITS=64 -I../common/ \ -I../protolib/include ../lib/libnorm.a ../protolib/lib/libProtokit.a \ -lpthread (for MacOS/BSD, add "-lresolv") (for Solaris, add "-lnsl -lsocket -lresolv") ******************************************************************************/ // Notes: // 1) The program exits once a single file has been received ... // 2) The received file is written to the // 3) The program also will exit on from user // 4) "normFileRecv" should be started before "normFileSend" #include "normApi.h" // for NORM API #include "protoDefs.h" // for ProtoSystemTime #include "protoDebug.h" // for SetDebugLevel(), etc #include // for printf(), etc #include // for srand() #include // for strrchr() #ifdef WIN32 const char DIR_DELIMITER = '\\'; #else const char DIR_DELIMITER = '/'; #endif // if/else WIN32/UNIX int main(int argc, char* argv[]) { // 0) The rxCachePath should be argv[1] ... if (argc != 2) { fprintf(stderr, "normFileRecv error: invalid argument(s)\n"); fprintf(stderr, "Usage: normRecvFile \n"); return -1; } const char* rxCachePath = argv[1]; // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); // 2) Create a NormSession using default "automatic" local node id NormSessionHandle session = NormCreateSession(instance, "224.1.2.3", 6003, NORM_NODE_ANY); NormSetRxPortReuse(session, true); NormSetMulticastLoopback(session, true); // NOTE: These are debugging routines available // (not necessary for normal app use) // (Need to include "protolib/common/protoDebug.h" for this //SetDebugLevel(2); // Uncomment to turn on debug NORM message tracing //NormSetMessageTrace(session, true); // Uncomment to turn on some random packet loss for testing NormSetRxLoss(session, 10.0); // 10% packet loss struct timeval currentTime; ProtoSystemTime(currentTime); // Uncomment to get different packet loss patterns from run to run srand(currentTime.tv_sec); // seed random number generator // 3) Set receiver file cache path (where received files are mstored) if (!NormSetCacheDirectory(instance, rxCachePath)) { fprintf(stderr, "normFileReceive: error setting cache directory\n"); return -1; } // 4) Start the receiver with 1 Mbyte buffer per sender NormStartReceiver(session, 1024*1024); // 5) Enter NORM event loop bool keepGoing = true; while (keepGoing) { NormEvent theEvent; if (!NormGetNextEvent(instance, &theEvent)) continue; switch (theEvent.type) { case NORM_RX_OBJECT_NEW: fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_NEW event ...\n"); break; case NORM_RX_OBJECT_INFO: // Assume info contains '/' delimited string fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_INFO event ...\n"); if (NORM_OBJECT_FILE == NormObjectGetType(theEvent.object)) { char fileName[PATH_MAX]; strcpy(fileName, rxCachePath); int pathLen = strlen(fileName); if (DIR_DELIMITER != fileName[pathLen-1]) { fileName[pathLen++] = DIR_DELIMITER; fileName[pathLen] = '\0'; } unsigned short nameLen = PATH_MAX - pathLen; nameLen = NormObjectGetInfo(theEvent.object, fileName+pathLen, nameLen); fileName[nameLen + pathLen] = '\0'; char* ptr = fileName + 5; while ('\0' != *ptr) { if ('/' == *ptr) *ptr = DIR_DELIMITER; ptr++; } if (!NormFileRename(theEvent.object, fileName)) fprintf(stderr, "normFileRecv: NormSetFileName(%s) error\n", fileName); } break; case NORM_RX_OBJECT_UPDATED: { //fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_UPDATE event ...\n"); // Uncomment this stuff to monitor file receive progress // (At high packet rates, you may want to be careful here and // only calculate/post updates occasionally rather than for // each and every RX_OBJECT_UPDATE event) NormSize objectSize = NormObjectGetSize(theEvent.object); fprintf(stderr, "sizeof(NormSize) = %d\n", (int)sizeof(NormSize)); NormSize completed = objectSize - NormObjectGetBytesPending(theEvent.object); double percentComplete = 100.0 * ((double)completed/(double)objectSize); fprintf(stderr, "normFileRecv: completion status %lu/%lu (%3.0lf%%)\n", (unsigned long)completed, (unsigned long)objectSize, percentComplete); break; } case NORM_RX_OBJECT_COMPLETED: fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_COMPLETED event ...\n"); keepGoing = false; break; case NORM_RX_OBJECT_ABORTED: fprintf(stderr, "normFileRecv: NORM_RX_OBJECT_ABORTED event ...\n"); break; case NORM_REMOTE_SENDER_NEW: fprintf(stderr, "normFileRecv: NORM_REMOTE_SENDER_NEW event ...\n"); break; case NORM_REMOTE_SENDER_ACTIVE: fprintf(stderr, "normFileRecv: NORM_REMOTE_SENDER_ACTIVE event ...\n"); break; case NORM_REMOTE_SENDER_INACTIVE: fprintf(stderr, "normFileRecv: NORM_REMOTE_SENDER_INACTIVE event ...\n"); break; default: fprintf(stderr, "normFileRecv: Got event type: %d\n", theEvent.type); } // end switch(theEvent.type) } NormStopReceiver(session); NormDestroySession(session); NormDestroyInstance(instance); fprintf(stderr, "normFileRecv: Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/normFileSend.cpp0000644000000000000000000001210313046163431015274 0ustar /****************************************************************************** Simple NORM file sender example app using the NORM API USAGE: normSendFile BUILD (Unix): g++ -o normFileSend normFileSend.cpp -D_FILE_OFFSET_BITS=64 -I../common/ \ -I../protolib/include ../lib/libnorm.a ../protolib/lib/libProtokit.a \ -lpthread (for MacOS/BSD, add "-lresolv") (for Solaris, add "-lnsl -lsocket -lresolv") ******************************************************************************/ // Notes: // 1) A single file is sent. // 2) The program exits upon NORM_TX_FLUSH_COMPLETED notification (or user ) // 3) NORM receiver should be started first (before sender starts) #include "normApi.h" // for NORM API #include "protoDefs.h" // for ProtoSystemTime() #include "protoDebug.h" // for SetDebugLevel(), etc #include // for printf(), etc #include // for srand() #include // for strrchr() #ifdef WIN32 const char DIR_DELIMITER = '\\'; #else const char DIR_DELIMITER = '/'; #endif // if/else WIN32/UNIX int main(int argc, char* argv[]) { // 0) The filePath should be argv[1] ... if (argc != 2) { fprintf(stderr, "normFileSend error: invalid argument(s)\n"); fprintf(stderr, "Usage: normFileSend \n"); return -1; } const char* filePath = argv[1]; // Here we determine the "name" portion of the filePath // (The file "name" is later used for NORM_INFO content) const char* fileName = strrchr(filePath, DIR_DELIMITER); if (fileName) fileName++; else fileName = filePath; // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); // 2) Create a NormSession using default "automatic" local node id NormSessionHandle session = NormCreateSession(instance, "224.1.2.3", 6003, 1); NormSetRxPortReuse(session, true); NormSetMulticastLoopback(session, true); // NOTE: These are some debugging routines available // (not necessary for normal app use) // (Need to include "protolib/common/protoDebug.h" for this //SetDebugLevel(2); // Uncomment to turn on debug NORM message tracing NormSetMessageTrace(session, true); // Uncomment to turn on some random packet loss //NormSetTxLoss(session, 10.0); // 10% packet loss struct timeval currentTime; ProtoSystemTime(currentTime); // Uncomment to get different packet loss patterns from run to run // (and a different sender sessionId) srand(currentTime.tv_sec); // seed random number generator // 3) Set transmission rate NormSetTxRate(session, 25600.0e+03); // in bits/second // Uncomment to use a _specific_ transmit port number // (Can be the same as session port (rx port), but this // is _not_ recommended when unicast feedback may be // possible! - must be called _before_ NormStartSender()) //NormSetTxPort(session, 6001); // Uncomment to enable TCP-friendly congestion control //NormSetCongestionControl(session, true); // 4) Start the sender using a random "sessionId" NormSessionId sessionId = (NormSessionId)rand(); NormStartSender(session, sessionId, 1024*1024, 1400, 64, 16); // Uncomment to set large tx socket buffer size // (might be needed for high rate sessions) //NormSetTxSocketBuffer(session, 512000); // 5) Enqueue the file for transmission // (We use the file _name_ for NORM_INFO) // NormObjectHandle txFile = NormFileEnqueue(session, filePath, fileName, strlen(fileName)); // 6) Enter NORM event loop bool keepGoing = true; while (keepGoing) { NormEvent theEvent; if (!NormGetNextEvent(instance, &theEvent)) continue; switch (theEvent.type) { case NORM_TX_QUEUE_VACANCY: fprintf(stderr, "normFileSend: NORM_TX_QUEUE_VACANCY event...\n"); break; case NORM_TX_QUEUE_EMPTY: fprintf(stderr, "normFileSend: NORM_TX_QUEUE_EMPTY event...\n"); break; case NORM_TX_OBJECT_PURGED: fprintf(stderr, "normFileSend: NORM_TX_OBJECT_PURGED event ...\n"); break; case NORM_TX_FLUSH_COMPLETED: fprintf(stderr, "normFileSend: NORM_TX_FLUSH_COMPLETED event ...\n"); keepGoing = false; // our file has been sent (we think) break; default: TRACE("normFileSend: Got event type: %d\n", theEvent.type); } // end switch(theEvent.type) } // end while (NormGetNextEvent()) NormStopSender(session); NormDestroySession(session); NormDestroyInstance(instance); fprintf(stderr, "normFileSend: Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/normMsgr.cpp0000644000000000000000000012620213277742622014534 0ustar #include "normApi.h" #include // for read() and write() #include // for printf(), etc #include // for srand() #include // for strrchr(), memset(), etc #include // for gettimeofday() #include // for htons() #include // for, well, fnctl() #include // obvious child #include // embarrassingly obvious #define SHOOT_NOW 1 #include "protoCheck.h" class NormMsgr { public: NormMsgr(); ~NormMsgr(); // some day build these directly into NORM API enum CCMode {NORM_FIXED, NORM_CC, NORM_CCE, NORM_CCL}; enum { MSG_SIZE_MAX = 65535, MSG_HEADER_SIZE = 2 }; // helper class and methods for message management class MessageQueue; class Message { friend class MessageQueue; public: Message(); Message(char* buffer, unsigned int size); ~Message(); bool Init(unsigned int size); void Destroy(); unsigned int GetSize() const {return msg_size;} const char* GetHeader() const {return msg_header;} char* AccessHeader() {return msg_header;} const char* GetBuffer() const {return msg_buffer;} char* AccessBuffer() {return msg_buffer;} void ResetIndex(unsigned int index = 0) {msg_index = index;} void IncrementIndex(unsigned int count) {msg_index += count;} unsigned int GetIndex() const {return msg_index;} bool IsComplete() const {return (msg_index == (MSG_HEADER_SIZE + msg_size));} private: unsigned int msg_size; unsigned int msg_index; char msg_header[MSG_HEADER_SIZE]; // this could be externalized to NormMsgr::input_msg_header / output_msg_header members char* msg_buffer; Message* prev; Message* next; }; // end class NormMsgr::Message class MessageQueue { public: MessageQueue(); ~MessageQueue(); bool IsEmpty() const {return (NULL == head);} void Prepend(Message& msg); void Append(Message& msg); void Remove(Message& msg); Message* RemoveHead(); Message* RemoveTail(); void Destroy(); unsigned int GetCount() const {return msg_count;} private: Message* head; Message* tail; unsigned int msg_count; }; // end class NormMsgr::MessageQueue Message* NewMessage(unsigned int size); void Destroy(); bool OpenNormSession(NormInstanceHandle instance, const char* addr, unsigned short port, NormNodeId nodeId); void CloseNormSession(); void SetNormCongestionControl(CCMode ccMode); void SetNormTxRate(double bitsPerSecond) { assert(NORM_SESSION_INVALID != norm_session); NormSetTxRate(norm_session, bitsPerSecond); } void SetNormMulticastInterface(const char* ifaceName) { assert(NORM_SESSION_INVALID != norm_session); NormSetMulticastInterface(norm_session, ifaceName); } void SetLoopback(bool state) { loopback = state; if (NORM_SESSION_INVALID != norm_session) NormSetMulticastLoopback(norm_session, state); } void SetNormMessageTrace(bool state) { assert(NORM_SESSION_INVALID != norm_session); NormSetMessageTrace(norm_session, state); } void AddAckingNode(NormNodeId ackId) { assert(NORM_SESSION_INVALID != norm_session); NormAddAckingNode(norm_session, ackId); norm_acking = true; // invoke ack-based flow control } void SetFlushing(bool state) {norm_flushing = state;} bool Start(bool sender, bool receiver); void Stop() {is_running = false;} bool IsRunning() const {return is_running;} unsigned long GetSentCount() {return sent_count;} void HandleNormEvent(const NormEvent& event); // Sender methods FILE* GetInputFile() const {return input_file;} int GetInputDescriptor() const {return input_fd;} bool InputReady() const {return input_ready;} void SetInputReady() {input_ready = true;} bool InputNeeded() const {return input_needed;} bool InputMessageReady() const {return ((NULL != input_msg) && !input_needed);} bool ReadInput(); bool TxReady() const; bool SendMessage(); bool EnqueueMessageObject(); // Receiver methods void SetOutputFile(FILE* filePtr) { output_file = filePtr; output_fd = fileno(filePtr); } FILE* GetOutputFile() const {return output_file;} int GetOutputDescriptor() const {return output_fd;} void SetOutputReady() {output_ready = true;} bool OutputReady() const {return output_ready;} bool OutputPending() const {return (NULL != output_msg);} bool RxNeeded() const {return rx_needed;} bool WriteOutput(); void OmitHeader(bool state) {omit_header = state;} // These can only be called post-OpenNormSession void SetSilentReceiver(bool state) {NormSetSilentReceiver(norm_session, true);} void SetTxLoss(double txloss) {NormSetTxLoss(norm_session, txloss);} private: bool is_running; FILE* input_file; // stdin by default int input_fd; bool input_ready; bool input_needed; // bool input_finished; Message* input_msg; // current input message being read/sent* MessageQueue input_msg_list; // list of enqueued messages (in norm sender cache) NormSessionHandle norm_session; bool is_multicast; bool loopback; unsigned int norm_tx_queue_max; // max number of objects that can be enqueued at once unsigned int norm_tx_queue_count; // count of unacknowledged enqueued objects (TBD - optionally track size too) bool norm_flow_control_pending; bool norm_tx_vacancy; bool norm_acking; bool norm_flushing; NormObjectHandle norm_flush_object; NormObjectHandle norm_last_object; unsigned long sent_count; bool rx_needed; FILE* output_file; int output_fd; bool output_ready; Message* output_msg; MessageQueue output_msg_queue; MessageQueue temp_msg_queue; // These are some options mainly for testing purposes bool omit_header; // if "true", receive message length header is _not_ written to output bool rx_silent; double tx_loss; }; // end class NormMsgr NormMsgr::NormMsgr() : input_file(stdin), input_fd(fileno(stdin)), input_ready(false), input_needed(false), input_finished(false), input_msg(NULL), norm_session(NORM_SESSION_INVALID), is_multicast(false), loopback(false), norm_tx_queue_max(8192), norm_tx_queue_count(0), norm_flow_control_pending(false), norm_tx_vacancy(true), norm_acking(false), norm_flushing(true), norm_flush_object(NORM_OBJECT_INVALID), norm_last_object(NORM_OBJECT_INVALID), sent_count(0), rx_needed(false), output_file(stdout), output_fd(fileno(stdout)), output_ready(true), output_msg(NULL), omit_header(false), rx_silent(false), tx_loss(0.0) { } NormMsgr::~NormMsgr() { Destroy(); } void NormMsgr::Destroy() { if (NULL != input_msg) { delete input_msg; input_msg = NULL; } input_msg_list.Destroy(); if (NULL != output_msg) { delete output_msg; delete output_msg; } output_msg_queue.Destroy(); } bool NormMsgr::OpenNormSession(NormInstanceHandle instance, const char* addr, unsigned short port, NormNodeId nodeId) { if (NormIsUnicastAddress(addr)) is_multicast = false; else is_multicast = true; norm_session = NormCreateSession(instance, addr, port, nodeId); if (NORM_SESSION_INVALID == norm_session) { fprintf(stderr, "normMsgr error: unable to create NORM session\n"); return false; } if (is_multicast) { NormSetRxPortReuse(norm_session, true); if (loopback) NormSetMulticastLoopback(norm_session, true); } // Set some default parameters (maybe we should put parameter setting in Start()) fprintf(stderr, "setting rx cache limit to %u\n", norm_tx_queue_max); if (norm_tx_queue_max > 65535/2) norm_tx_queue_max = 65535/2; NormSetRxCacheLimit(norm_session, norm_tx_queue_max); NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_ALL); if (!is_multicast) NormSetDefaultUnicastNack(norm_session, true); NormSetTxCacheBounds(norm_session, 10*1024*1024, norm_tx_queue_max, norm_tx_queue_max); //NormSetMessageTrace(norm_session, true); //NormSetTxRobustFactor(norm_session, 20); return true; } // end NormMsgr::OpenNormSession() void NormMsgr::CloseNormSession() { if (NORM_SESSION_INVALID == norm_session) return; NormDestroySession(norm_session); norm_session = NORM_SESSION_INVALID; } // end NormMsgr::CloseNormSession() void NormMsgr::SetNormCongestionControl(CCMode ccMode) { assert(NORM_SESSION_INVALID != norm_session); switch (ccMode) { case NORM_CC: // default TCP-friendly congestion control NormSetEcnSupport(norm_session, false, false, false); break; case NORM_CCE: // "wireless-ready" ECN-only congestion control NormSetEcnSupport(norm_session, true, true); break; case NORM_CCL: // "loss tolerant", non-ECN congestion control NormSetEcnSupport(norm_session, false, false, true); break; case NORM_FIXED: NormSetEcnSupport(norm_session, false, false, false); break; } if (NORM_FIXED != ccMode) NormSetCongestionControl(norm_session, true); else NormSetCongestionControl(norm_session, false); } // end NormMsgr::SetNormCongestionControl() bool NormMsgr::Start(bool sender, bool receiver) { fprintf(stderr, "enter NormMsgr::Start() ...\n"); // TBD - make these command-line accessible unsigned int bufferSize = 64*1024*1024; unsigned int segmentSize = 1400; unsigned int blockSize = 64; unsigned int numParity = 0; unsigned int txSockBufferSize = 4*1024*1024; unsigned int rxSockBufferSize = 6*1024*1024; if (receiver) { if (!NormStartReceiver(norm_session, bufferSize)) { fprintf(stderr, "normMsgr error: unable to start NORM receiver\n"); return false; } // Note: NormPreallocateRemoteSender() MUST be called AFTER NormStartReceiver() NormPreallocateRemoteSender(norm_session, bufferSize, segmentSize, blockSize, numParity, bufferSize); NormSetRxSocketBuffer(norm_session, rxSockBufferSize); rx_needed = true; fprintf(stderr, "normMsgr: receiver ready.\n"); } if (sender) { if (norm_acking) { // ack-based flow control enabled on command-line, // so disable timer-based flow control NormSetFlowControl(norm_session, 0.0); } NormSetGrttEstimate(norm_session, 0.001); //NormSetGrttMax(norm_session, 0.100); NormSetBackoffFactor(norm_session, 0); // Pick a random instance id for now struct timeval currentTime; gettimeofday(¤tTime, NULL); srand(currentTime.tv_usec); // seed random number generator NormSessionId instanceId = (NormSessionId)rand(); if (!NormStartSender(norm_session, instanceId, bufferSize, segmentSize, blockSize, numParity)) { fprintf(stderr, "normMsgr error: unable to start NORM sender\n"); if (receiver) NormStopReceiver(norm_session); return false; } //NormSetAutoParity(norm_session, 2); NormSetTxSocketBuffer(norm_session, txSockBufferSize); input_needed = true; } //ProtoCheckResetLogging(); is_running = true; return true; } // end NormMsgr::Start(); // Returns "true" when a complete message has been read bool NormMsgr::ReadInput() { assert(input_needed); while (input_needed) { size_t readLength; char* bufferPtr; if ((NULL == input_msg) || (input_msg->GetIndex() < MSG_HEADER_SIZE)) { if (NULL == input_msg) { // Allocate a new message/buffer for input if (NULL == (input_msg = new Message())) { perror("normMsgr new Message error"); Stop(); // fatal out of memory error return false; } } // need to read msg "length" header readLength = MSG_HEADER_SIZE - input_msg->GetIndex(); bufferPtr = input_msg->AccessHeader() + input_msg->GetIndex(); } else { unsigned int offset = input_msg->GetIndex() - MSG_HEADER_SIZE; readLength = input_msg->GetSize() - offset; bufferPtr = input_msg->AccessBuffer() + offset; } ssize_t result = read(input_fd, bufferPtr, readLength); if (result > 0) { input_msg->IncrementIndex(result); if ((size_t)result < readLength) { // Still need more input // (wait for next input notification to read more) return false; } else if (MSG_HEADER_SIZE == input_msg->GetIndex()) { // We have now read the message size header // TBD - support other message header formats? // (for now, assume 2-byte message length header) uint16_t msgSize ; memcpy(&msgSize, input_msg->GetHeader(), MSG_HEADER_SIZE); msgSize = ntohs(msgSize) - MSG_HEADER_SIZE; if (!input_msg->Init(msgSize)) { perror("normMsgr: input message initialization error"); Stop(); // fatal out of memory error return false; } } if (input_msg->IsComplete()) // have read complete header and message { // We have now read in the complete message input_needed = false; } } else if (0 == result) { // end-of-file reached, TBD - trigger final flushing and wrap-up fprintf(stderr, "normMsgr: input end-of-file detected (last:%p)...\n", norm_last_object); delete input_msg; input_msg = NULL; input_ready = false; input_needed = false; input_finished = true; if (norm_acking) { if (NORM_OBJECT_INVALID == norm_last_object) is_running = false; // everything sent and acked else if (!norm_flushing) NormSetWatermark(norm_session, norm_last_object, true); } } else // result < 0 { switch (errno) { case EINTR: continue; // interupted, try again case EAGAIN: // input starved, wait for next notification break; default: perror("normMsgr error reading input"); break; } input_ready = false; return false; } } return true; } // end NormMsgr::ReadInput() bool NormMsgr::WriteOutput() { while (NULL != output_msg) { size_t writeLength; const char* bufferPtr; if (output_msg->GetIndex() < MSG_HEADER_SIZE) { writeLength = MSG_HEADER_SIZE - output_msg->GetIndex(); bufferPtr = output_msg->GetHeader() + output_msg->GetIndex(); } else { unsigned int offset = output_msg->GetIndex() - MSG_HEADER_SIZE; writeLength = output_msg->GetSize() - offset; bufferPtr = output_msg->GetBuffer() + offset; } ssize_t result = write(output_fd, bufferPtr, writeLength); if (result >= 0) { output_msg->IncrementIndex(result); if ((size_t)result < writeLength) output_ready = false; // blocked, wait for output notification } else { switch (errno) { case EINTR: continue; // interupted, try again case EAGAIN: // input starved, wait for next notification output_ready = false; break; default: perror("normMsgr error writing output"); break; } return false; } if (output_msg->IsComplete()) { fflush(output_file); //delete output_msg; temp_msg_queue.Append(*output_msg); // cache for debugging purposes if (temp_msg_queue.GetCount() > 32) { //fprintf(stderr, "deleting cached recv'd message ...\n"); delete temp_msg_queue.RemoveHead(); } output_msg = output_msg_queue.RemoveHead(); if (NULL != output_msg) { if (omit_header) output_msg->ResetIndex(MSG_HEADER_SIZE); else output_msg->ResetIndex(); } else { rx_needed = true; } break; } } return true; } // end NormMsgr::WriteOutput() bool NormMsgr::TxReady() const { // This returns true if new tx data can be enqueued to NORM // This is based on the state with respect to prior successful data // data enqueuing (or stream writing) and NORM_TX_QUEUE_EMPTY or // NORM_TX_QUEUE_VACANCY notifications (tracked by the "norm_tx_vacancy" variable, // _and_ (if ack-based flow control is enabled) the norm_tx_queue_count or // norm_stream_buffer_count status. if (norm_tx_vacancy) { if (norm_tx_queue_count >= norm_tx_queue_max) return false; // still waiting for ACK return true; } else { return false; } } // end NormMsgr::NormTxReady() bool NormMsgr::SendMessage() { if (EnqueueMessageObject()) { // Our buffered message was sent, so reset input indices // and request next message from input input_msg_list.Append(*input_msg); input_msg = NULL; input_needed = true; sent_count++; return true; } // else will be prompted to retry by NORM event (queue vacancy, watermark completion) return false; } // end NormMsgr::SendMessage() bool NormMsgr::EnqueueMessageObject() { if (norm_acking) { assert(norm_tx_queue_count < norm_tx_queue_max); if (norm_tx_queue_count >= norm_tx_queue_max) return false; } // Enqueue the message data for transmission NormObjectHandle object = NormDataEnqueue(norm_session, input_msg->AccessBuffer(), input_msg->GetSize()); if (NORM_OBJECT_INVALID == object) { // This might happen if a non-acking receiver is present and // has nacked for the oldest object in the queue even if all // of our acking receivers have acknowledged it. fprintf(stderr, "NO VACANCY count:%u max:%u\n", norm_tx_queue_count, norm_tx_queue_max); norm_tx_vacancy = false; return false; } //NormObjectRetain(object); NormObjectSetUserData(object, input_msg); // so we can remove/delete upon purge if (norm_acking) { // ack-based flow control has been enabled norm_tx_queue_count++; if (!norm_flow_control_pending && (norm_tx_queue_count >= (norm_tx_queue_max / 2))) { NormSetWatermark(norm_session, object, true); // overrideFlush == true norm_last_object = object; norm_flow_control_pending = true; } else if (norm_flushing) // per-message acking { #ifdef SHOOT_FIRST NormSetWatermark(norm_session, object, true); norm_last_object = object; #else // ACK_LATER if (norm_flow_control_pending) { norm_flush_object = object; // will be used as watermark upon flow control ack } else { NormSetWatermark(norm_session, object, true); norm_last_object = object; } #endif // SHOOT_FIRST/ACK_LATER } else { //norm_last_object = object; } } return true; } // end NormMsgr::EnqueueMessageObject() void NormMsgr::HandleNormEvent(const NormEvent& event) { switch (event.type) { case NORM_TX_QUEUE_EMPTY: case NORM_TX_QUEUE_VACANCY: norm_tx_vacancy = true; break; case NORM_GRTT_UPDATED: //fprintf(stderr, "new GRTT = %lf\n", NormGetGrttEstimate(norm_session)); break; case NORM_TX_WATERMARK_COMPLETED: if (NORM_ACK_SUCCESS == NormGetAckingStatus(norm_session)) { //fprintf(stderr, "WATERMARK COMPLETED\n"); norm_last_object = NORM_OBJECT_INVALID; if (norm_flow_control_pending) { norm_tx_queue_count -= (norm_tx_queue_max / 2); norm_flow_control_pending = false; if (NORM_OBJECT_INVALID != norm_flush_object) { NormSetWatermark(norm_session, norm_flush_object, true); norm_last_object = norm_flush_object; norm_flush_object = NORM_OBJECT_INVALID; } } if (input_finished && (NORM_OBJECT_INVALID == norm_last_object)) is_running = false; } else { // TBD - we could see who did and how didn't ACK and possibly remove them // from our acking "membership". For now, we are infinitely // persistent by resetting watermark ack request without clearing // flow control if (NORM_OBJECT_INVALID == norm_flush_object) { NormResetWatermark(norm_session); } else // might as request ack for most recent enqueued object { NormSetWatermark(norm_session, norm_flush_object, true); norm_last_object = norm_flush_object; norm_flush_object = NORM_OBJECT_INVALID; } } break; case NORM_TX_OBJECT_PURGED: { NormDataDetachData(event.object); Message* msg = (Message*)NormObjectGetUserData(event.object); if(event.object == norm_flush_object) norm_flush_object = NORM_OBJECT_INVALID; if (NULL != msg) { input_msg_list.Remove(*msg); delete msg; } //NormObjectRelease(event.object); //fprintf(stderr, "normMsgr LOGGING ALLOCATIONS\n"); //ProtoCheckLogAllocations(stderr); break; } case NORM_REMOTE_SENDER_INACTIVE: //fprintf(stderr, "REMOTE SENDER INACTIVE node: %u\n", NormNodeGetId(event.sender)); //NormNodeDelete(event.sender); //logAllocs = true; break; case NORM_RX_OBJECT_ABORTED: //fprintf(stderr, "NORM_RX_OBJECT_ABORTED\n");// %hu\n", NormObjectGetTransportId(event.object)); break; case NORM_RX_OBJECT_COMPLETED: { sent_count++; char* data = NormDataDetachData(event.object); if (NULL != data) { Message* msg = new Message(data, NormObjectGetSize(event.object)); if (NULL == msg) { perror("normMsgr: new Message() error"); delete[] data; // TBD - may need to finally implement NormDelete() function! // TBD Stop() as a fatal out of memory error? break; } if (NULL == output_msg) { output_msg = msg; if (omit_header) output_msg->ResetIndex(MSG_HEADER_SIZE); else output_msg->ResetIndex(); } else { output_msg_queue.Append(*msg); } rx_needed = false; } // else TBD - "termination" info-only object? break; } default: break; } //NormReleasePreviousEvent(NormGetInstance(norm_session)); } // end NormMsgr::HandleNormEvent() void Usage() { fprintf(stderr, "Usage: normMsgr id {send &| recv} [addr [/]][ack [,,...]\n" " [cc|cce|ccl|rate ][interface ][debug ][trace]\n" " [flush {none|active}][omit][silent][txloss ]\n"); } int main(int argc, char* argv[]) { // REQUIRED parameters initiailization NormNodeId nodeId = NORM_NODE_NONE; bool send = false; bool recv = false; char sessionAddr[64]; strcpy(sessionAddr, "224.1.2.3"); unsigned int sessionPort = 6003; NormNodeId ackingNodeList[256]; unsigned int ackingNodeCount = 0; bool flushing = false; double txRate = 0.0; // used for non-default NORM_FIXED ccMode NormMsgr::CCMode ccMode = NormMsgr::NORM_CC; const char* mcastIface = NULL; int debugLevel = 0; const char* debugLog = NULL; // stderr by default bool trace = false; bool omitHeaderOnOutput = false; bool silentReceiver = false; double txloss = 0.0; bool loopback = false; NormMsgr normMsgr; // Parse command-line int i = 1; while (i < argc) { const char* cmd = argv[i++]; size_t len = strlen(cmd); if (0 == strncmp(cmd, "send", len)) { send = true; } else if (0 == strncmp(cmd, "recv", len)) { recv = true; } else if (0 == strncmp(cmd, "loopback", len)) { loopback = true; } else if (0 == strncmp(cmd, "addr", len)) { if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'addr[/port]' value!\n"); Usage(); return -1; } const char* addrPtr = argv[i++]; const char* portPtr = strchr(addrPtr, '/'); if (NULL == portPtr) { strncpy(sessionAddr, addrPtr, 63); sessionAddr[63] = '\0'; } else { size_t addrLen = portPtr - addrPtr; if (addrLen > 63) addrLen = 63; // should issue error message strncpy(sessionAddr, addrPtr, addrLen); sessionAddr[addrLen] = '\0'; portPtr++; sessionPort = atoi(portPtr); } } else if (0 == strncmp(cmd, "output", len)) { if (i >= argc) { fprintf(stderr, "normMsgr error: missing output 'device' name!\n"); Usage(); return -1; } FILE* outfile = fopen(argv[i++], "w+"); if (NULL == outfile) { perror("normMsgr output device fopen() error"); Usage(); return -1; } normMsgr.SetOutputFile(outfile); } else if (0 == strncmp(cmd, "id", len)) { if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'id' value!\n"); Usage(); return -1; } nodeId = atoi(argv[i++]); } else if (0 == strncmp(cmd, "ack", len)) { // comma-delimited acking node id list if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'id' value!\n"); Usage(); return -1; } const char* alist = argv[i++]; while ((NULL != alist) && (*alist != '\0')) { // TBD - Do we need to skip leading white space? int id; if (1 != sscanf(alist, "%d", &id)) { fprintf(stderr, "nodeMsgr error: invalid acking node list!\n"); Usage(); return -1; } ackingNodeList[ackingNodeCount] = NormNodeId(id); ackingNodeCount++; alist = strchr(alist, ','); if (NULL != alist) alist++; // point past comma } } else if (0 == strncmp(cmd, "flush", len)) { // "none", "passive", or "active" if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'flush' !\n"); Usage(); return -1; } const char* mode = argv[i++]; if (0 == strcmp(mode, "none")) { flushing = false; } else if (0 == strcmp(mode, "passive")) { flushing = false; } else if (0 == strcmp(mode, "active")) { flushing = true; } else { fprintf(stderr, "normMsgr error: invalid 'flush' mode \"%s\"\n", mode); return -1; } } else if (0 == strncmp(cmd, "rate", len)) { if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'rate' value!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lf", &txRate)) { fprintf(stderr, "nodeMsgr error: invalid transmit rate!\n"); Usage(); return -1; } // set fixed-rate operation ccMode = NormMsgr::NORM_FIXED; } else if (0 == strcmp(cmd, "cc")) { ccMode = NormMsgr::NORM_CC; } else if (0 == strcmp(cmd, "cce")) { ccMode = NormMsgr::NORM_CCE; } else if (0 == strcmp(cmd, "ccl")) { ccMode = NormMsgr::NORM_CCL; } else if (0 == strncmp(cmd, "interface", len)) { if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'interface' !\n"); Usage(); return -1; } mcastIface = argv[i++]; } else if (0 == strncmp(cmd, "omit", len)) { omitHeaderOnOutput = true; } else if (0 == strncmp(cmd, "silent", len)) { silentReceiver = true; } else if (0 == strncmp(cmd, "txloss", len)) { if (1 != sscanf(argv[i++], "%lf", &txloss)) { fprintf(stderr, "nodeMsgr error: invalid 'txloss' value!\n"); Usage(); return -1; } } else if (0 == strncmp(cmd, "debug", len)) { if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'debug' !\n"); Usage(); return -1; } debugLevel = atoi(argv[i++]); } else if (0 == strncmp(cmd, "log", len)) { if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'log' !\n"); Usage(); return -1; } debugLog = argv[i++]; } else if (0 == strncmp(cmd, "trace", len)) { trace = true; } else if (0 == strncmp(cmd, "help", len)) { Usage(); return 0; } else { fprintf(stderr, "nodeMsgr error: invalid command \"%s\"!\n", cmd); Usage(); return -1; } } if (!send && !recv) { fprintf(stderr, "normMsgr error: not configured to send or recv!\n"); Usage(); return -1; } if (NORM_NODE_NONE == nodeId) { fprintf(stderr, "normMsgr error: no local 'id' provided!\n"); Usage(); return -1; } // TBD - should provide more error checking of calls NormInstanceHandle normInstance = NormCreateInstance(); NormSetDebugLevel(debugLevel); if (NULL != debugLog) NormOpenDebugLog(normInstance, debugLog); normMsgr.SetLoopback(loopback); normMsgr.SetFlushing(flushing); if (omitHeaderOnOutput) normMsgr.OmitHeader(true); if (!normMsgr.OpenNormSession(normInstance, sessionAddr, sessionPort, (NormNodeId)nodeId)) { fprintf(stderr, "normMsgr error: unable to open NORM session\n"); NormDestroyInstance(normInstance); return false; } if (silentReceiver) normMsgr.SetSilentReceiver(true); if (txloss > 0.0) normMsgr.SetTxLoss(txloss); for (unsigned int i = 0; i < ackingNodeCount; i++) normMsgr.AddAckingNode(ackingNodeList[i]); normMsgr.SetNormCongestionControl(ccMode); if (NormMsgr::NORM_FIXED == ccMode) normMsgr.SetNormTxRate(txRate); if (NULL != mcastIface) normMsgr.SetNormMulticastInterface(mcastIface); if (trace) normMsgr.SetNormMessageTrace(true); // TBD - set NORM session parameters normMsgr.Start(send, recv); int normfd = NormGetDescriptor(normInstance); // Get input/output descriptors and set to non-blocking i/o int inputfd = normMsgr.GetInputDescriptor(); if (-1 == fcntl(inputfd, F_SETFL, fcntl(inputfd, F_GETFL, 0) | O_NONBLOCK)) perror("normMsgr: fcntl(inputfd, O_NONBLOCK) error"); int outputfd = normMsgr.GetOutputDescriptor(); if (-1 == fcntl(outputfd, F_SETFL, fcntl(outputfd, F_GETFL, 0) | O_NONBLOCK)) perror("normMsgr: fcntl(outputfd, O_NONBLOCK) error"); fd_set fdsetInput, fdsetOutput; FD_ZERO(&fdsetInput); FD_ZERO(&fdsetOutput); struct timeval lastTime; gettimeofday(&lastTime, NULL); while (normMsgr.IsRunning()) { int maxfd = -1; // Only wait on NORM if needed for tx readiness bool waitOnNorm = true; if (!(normMsgr.RxNeeded() || normMsgr.InputMessageReady())) waitOnNorm = false; // no need to wait else if (normMsgr.InputMessageReady() && normMsgr.TxReady()) waitOnNorm = false; // no need to wait if already tx ready if (waitOnNorm) { maxfd = normfd; FD_SET(normfd, &fdsetInput); } else { FD_CLR(normfd, &fdsetInput); } if (normMsgr.InputNeeded() && !normMsgr.InputReady()) { FD_SET(inputfd, &fdsetInput); if (inputfd > maxfd) maxfd = inputfd; } else { FD_CLR(inputfd, &fdsetInput); } if (normMsgr.OutputPending() && !normMsgr.OutputReady()) { FD_SET(outputfd, &fdsetOutput); if (outputfd > maxfd) maxfd = outputfd; } else { FD_CLR(outputfd, &fdsetOutput); } if (maxfd >= 0) { struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; int result = select(maxfd+1, &fdsetInput, &fdsetOutput, NULL, &timeout); switch (result) { case -1: switch (errno) { case EINTR: case EAGAIN: continue; default: perror("normMsgr select() error"); // TBD - stop NormMsgr break; } break; case 0: // shouldn't occur for now (no timeout) //fprintf(stderr, "normMsgr timeout ...\n"); continue; default: if (FD_ISSET(inputfd, &fdsetInput)) { normMsgr.SetInputReady(); } /*if (FD_ISSET(normfd, &fdsetInput)) { NormEvent event; while (NormGetNextEvent(normInstance, &event, false)) normMsgr.HandleNormEvent(event); }*/ if (FD_ISSET(outputfd, &fdsetOutput)) { normMsgr.SetOutputReady(); } break; } } NormSuspendInstance(normInstance); NormEvent event; while (NormGetNextEvent(normInstance, &event, false)) normMsgr.HandleNormEvent(event); // As a result of reading input or NORM notification events, // we may be ready to read input and/or send a message if it's been read const int LOOP_MAX = 100; int loopCount = 0; while (loopCount < LOOP_MAX) { loopCount++; if (normMsgr.InputNeeded() && normMsgr.InputReady()) normMsgr.ReadInput(); if (normMsgr.InputMessageReady() && normMsgr.TxReady()) normMsgr.SendMessage(); // and/or output a received message if we need if (normMsgr.OutputPending() && normMsgr.OutputReady()) normMsgr.WriteOutput(); } NormResumeInstance(normInstance); } // end while(normMsgr.IsRunning() NormCloseDebugLog(normInstance); fprintf(stderr, "destroying session ...\n"); normMsgr.CloseNormSession(); fprintf(stderr, "destroying instance ...\n"); NormDestroyInstance(normInstance); normMsgr.Destroy(); fprintf(stderr, "normMsgr exiting ...\n"); } // end main() NormMsgr::Message::Message() : msg_size(0), msg_index(0), msg_buffer(NULL), prev(NULL), next(NULL) { } NormMsgr::Message::Message(char* buffer, unsigned int size) : msg_size(size), msg_index(size+MSG_HEADER_SIZE), msg_buffer(buffer), prev(NULL), next(NULL) { assert(2 == MSG_HEADER_SIZE); uint16_t msgSize = size + MSG_HEADER_SIZE; msgSize = htons(msgSize); memcpy(msg_header, &msgSize, MSG_HEADER_SIZE); } NormMsgr::Message::~Message() { // in future we may need to use NormDelete() // to delete msg_buffer if it came from NORM if (NULL != msg_buffer) { //fprintf(stderr, "deleting msg_buffer ...\n"); delete[] msg_buffer; msg_buffer = NULL; } } bool NormMsgr::Message::Init(unsigned int size) { if ((NULL != msg_buffer) && (size != msg_size)) { delete[] msg_buffer; msg_buffer = NULL; } if (NULL == msg_buffer) msg_buffer = new char[size]; if (NULL != msg_buffer) { assert(2 == MSG_HEADER_SIZE); uint16_t msgSize = size + MSG_HEADER_SIZE; msgSize = htons(msgSize); memcpy(msg_header, &msgSize, MSG_HEADER_SIZE); msg_index = MSG_HEADER_SIZE; // empty message msg_size = size; return true; } else { msg_index = msg_size = 0; return false; } } // end NormMsgr::Message::Init() NormMsgr::MessageQueue::MessageQueue() : head(NULL), tail(NULL), msg_count(0) { } NormMsgr::MessageQueue::~MessageQueue() { } void NormMsgr::MessageQueue::Destroy() { while (NULL != head) { Message* msg = RemoveHead(); delete msg; } } // end NormMsgr::MessageQueue::Destroy() void NormMsgr::MessageQueue::Prepend(Message& msg) { msg.prev = NULL; if (NULL != head) head->prev = &msg; else tail = &msg; msg.next = head; head = &msg; msg_count++; } // end NormMsgr::MessageQueue::Prepend() void NormMsgr::MessageQueue::Append(Message& msg) { msg.next = NULL; if (NULL != tail) tail->next = &msg; else head = &msg; msg.prev = tail; tail = &msg; msg_count++; } // end NormMsgr::MessageQueue::Append() void NormMsgr::MessageQueue::Remove(Message& msg) { if (NULL == msg.prev) head = msg.next; else msg.prev->next = msg.next; if (NULL == msg.next) tail = msg.prev; else msg.next->prev = msg.prev; msg.prev = msg.next = NULL; msg_count--; } // end NormMsgr::MessageQueue::Remove() NormMsgr::Message* NormMsgr::MessageQueue::RemoveHead() { Message* msg = head; if (NULL != head) Remove(*head); return msg; } // end NormMsgr::MessageQueue::RemoveHead() NormMsgr::Message* NormMsgr::MessageQueue::RemoveTail() { Message* msg = tail; if (NULL != tail) Remove(*tail); return msg; } // end NormMsgr::MessageQueue::RemoveTail() norm-1.5.8+dfsg2/examples/normServer.cpp0000644000000000000000000006577413224764576015116 0ustar // This example NORM application acts as unicast "server". A NORM receive-only session "listens" // on a "serverPort". When new remote senders are detected, the sender is assigned to a // newly create "client" NormSession that is "connected" to the remote sender/client addr/port. // The NormSetRxPortReuse() call provides an option to "connect" the underlying NORM UDP socket // to the remote sender/client address/port. Note this is not yet supported for NORM-CCE (ECN) // congestion control operation. // By creating "client" NormSessions for each client connection, this enables multiple clients // from the same host (with the same NormNodeId to connect to the server at the same time. // Otherwise, clients with the same NormNodeId would "collide" at the server receive session. // Even the approach here is not perfect as a packet from a another client instance with the // same NormNodeId might change the given "remote sender" source addr/port before the // connected "client" session is created as a sort of race condition. // A potential enhancement to NORM would be to allow tracking of multiple remote senders // with the same NormNodeId but different instanceIds ... // BUILD: (assumes "normApi.h" in "include" ... // g++ -I../include -o normServer normServer.cpp normSocket.cpp ../lib/libnorm.a ../protolib/lib/libprotokit.a -lresolv // EXAMPLE NOTES: // // 0) THIS IS A WORK IN PROGRESS AND NOT YET FUNCTIONAL! // // 1) Some of the functions here may be added to the NORM API in the future. // // 2) The "main()" below is a single-threaded example with a single NormInstance and a // single NormGetNextEvent() main loop. Note that the NormAccept() call allows for a // new instance (and hence new NormDescriptor) for each accepted client, so multiple // threads or event thread-pooling versions of this could be implemented for // performance or application design purposes. A future version of the NORM API and // this could even provide for very "socket-like" API calls where each "client" // session has its own descriptor independent of threading (e.g. a "normSocket.h" API // that is implemented around the current low level NORM API). This sort of "NORM // socket" approach could be supported for unicast and SSM streams without too much // difficulty. #include // for fprintf() #include // for memcmp() #include // for std::map<> #include // more obvious #include "normSocket.h" #ifdef WIN32 #include "win32InputHandler.cpp" // to include full implementation #include // for inet_ntoa() #include // for inet_ntop() #else #include // for inet_ntoa #include #include // for, well, fnctl() #include // obvious child #endif // if/else WIN32/UNIX void Usage() { fprintf(stderr, "Usage: normServer [listen [/]][debug ][trace]\n"); } // Our "server" indexes clients by their source addr/port class ClientInfo { public: ClientInfo(UINT8 ipVersion = 0, const char* theAddr = NULL, UINT16 thePort = 0); bool operator < (const ClientInfo& a) const; int GetAddressFamily() const; const char* GetAddress() const {return client_addr;} UINT16 GetPort() const {return client_port;} const char* GetAddressString(); void Print(FILE* filePtr); private: UINT8 addr_version; // 4 or 6 char client_addr[16]; // big enough for IPv6 UINT16 client_port; }; // end class ClientInfo ClientInfo::ClientInfo(UINT8 addrVersion, const char* clientAddr, UINT16 clientPort) : addr_version(addrVersion), client_port(clientPort) { if (NULL == clientAddr) addrVersion = 0; // forces zero initialization switch (addrVersion) { case 4: memcpy(client_addr, clientAddr, 4); memset(client_addr+4, 0, 12); break; case 6: memcpy(client_addr, clientAddr, 16); break; default: memset(client_addr, 0, 16); break; } } // returns "true" if "this" less than "a" (used by C++ map) bool ClientInfo::operator <(const ClientInfo& a) const { if (addr_version != a.addr_version) return (addr_version < a.addr_version); else if (client_port != a.client_port) return (client_port < a.client_port); else if (4 == addr_version) return (0 > memcmp(client_addr, a.client_addr, 4)); else return (0 > memcmp(client_addr, a.client_addr, 16)); } // end ClientInfo::operator <() int ClientInfo::GetAddressFamily() const { if (4 == addr_version) return AF_INET; else return AF_INET6; } // end ClientInfo::GetAddressFamily() const char* ClientInfo::GetAddressString() { static char text[64]; text[63] = '\0'; int addrFamily; if (4 == addr_version) addrFamily = AF_INET; else addrFamily = AF_INET6; inet_ntop(addrFamily, client_addr, text, 63); return text; } // end ClientInfo::GetAddressString() void ClientInfo::Print(FILE* filePtr) { char text[64]; text[63] = '\0'; int addrFamily; if (4 == addr_version) addrFamily = AF_INET; else addrFamily = AF_INET6; inet_ntop(addrFamily, client_addr, text, 63); fprintf(filePtr, "%s/%hu", text, client_port); } // end ClientInfo::Print() class Client { public: Client(NormSocketHandle clientSocket); ~Client(); NormSocketHandle GetSocket() const {return client_socket;} bool GetWriteReady() const {return write_ready;} void SetWriteReady(bool state) {write_ready = state;} unsigned int GetBytesWritten() const {return bytes_written;} void SetBytesWritten(unsigned long numBytes) {bytes_written = numBytes;} private: NormSocketHandle client_socket; // These are state variables for unicast server -> client communication bool write_ready; unsigned int bytes_written; }; // end class Client Client::Client(NormSocketHandle clientSocket) : client_socket(clientSocket), write_ready(true), bytes_written(0) { } Client::~Client() { } // C++ map used to index client sessions by the client source addr/port typedef std::map ClientMap; ClientInfo NormGetClientInfo(NormNodeHandle client) { char addr[16]; // big enough for IPv6 unsigned int addrLen = 16; UINT16 port; NormNodeGetAddress(client, addr, &addrLen, &port); UINT8 version; if (4 == addrLen) version = 4; else version = 6; return ClientInfo(version, addr, port); } // end NormGetClientInfo(NormNodeHandle) ClientInfo NormGetSocketInfo(NormSocketHandle socket) { char addr[16]; // big enough for IPv6 unsigned int addrLen = 16; UINT16 port; NormGetPeerName(socket, addr, &addrLen, &port); UINT8 version; if (4 == addrLen) version = 4; else version = 6; return ClientInfo(version, addr, port); } // end NormGetSocketInfo(NormSocketHandle) Client* FindClient(ClientMap& clientMap, const ClientInfo& clientInfo) { ClientMap::iterator it = clientMap.find(clientInfo); if (clientMap.end() != it) return it->second; else return NULL; } // end FindClient() NormSocketHandle FindClientSocket(ClientMap& clientMap, const ClientInfo& clientInfo) { Client* client = FindClient(clientMap, clientInfo); if (NULL == client) return NORM_SOCKET_INVALID; else return client->GetSocket(); } // end FindClientSocket() int main(int argc, char* argv[]) { ClientMap clientMap; UINT16 serverPort = 5000; UINT16 serverInstanceId = 1; char groupAddr[64]; const char* groupAddrPtr = NULL; const char* mcastInterface = NULL; bool trace = false; unsigned int debugLevel = 0; for (int i = 1; i < argc; i++) { const char* cmd = argv[i]; unsigned int len = strlen(cmd); if (0 == strncmp(cmd, "listen", len)) { // listen [/] const char* val = argv[++i]; const char* portPtr = strchr(val, '/'); if (NULL != portPtr) portPtr++; else portPtr = val; unsigned int addrTextLen = portPtr - val; if (addrTextLen > 0) { addrTextLen -= 1; strncpy(groupAddr, val, addrTextLen); groupAddr[addrTextLen] = '\0'; groupAddrPtr = groupAddr; } if (1 != sscanf(portPtr, "%hu", &serverPort)) { fprintf(stderr, "normServer error: invalid \"%s\"\n", portPtr); Usage(); return -1; } } else if (0 == strncmp(cmd, "interface", len)) { // Note the NormSocket code does not yet expose mcast interface mcastInterface = argv[++i]; } else if (0 == strncmp(cmd, "trace", len)) { trace = true; } else if (0 == strncmp(cmd, "debug", len)) { if (1 != sscanf(argv[++i], "%u", &debugLevel)) { fprintf(stderr, "normServer error: invalid debug level\n"); Usage(); return -1; } } else { fprintf(stderr, "normServer error: invalid command \"%s\"\n", cmd); Usage(); return -1; } } NormInstanceHandle instance = NormCreateInstance(); NormSocketHandle serverSocket = NormOpen(instance); NormListen(serverSocket, serverPort, groupAddrPtr); if (trace) NormSetMessageTrace(NormGetSocketSession(serverSocket), true); if (0 != debugLevel) NormSetDebugLevel(debugLevel); //NormSetDebugLevel(8); //NormSetMessageTrace(NormGetSocketSession(serverSocket), true); #ifdef WIN32 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); Win32InputHandler inputHandler; inputHandler.Open(); HANDLE handleArray[2]; handleArray[0] = NormGetDescriptor(instance); handleArray[1] = inputHandler.GetEventHandle(); #else // We use a select() call to multiplex input reading and NormSocket handling fd_set fdset; FD_ZERO(&fdset); // Get our input (STDIN) descriptor and set non-blocking FILE* inputFile = stdin; int inputfd = fileno(inputFile); if (-1 == fcntl(inputfd, F_SETFL, fcntl(inputfd, F_GETFL, 0) | O_NONBLOCK)) perror("normClient: fcntl(inputfd, O_NONBLOCK) error"); // Get our NormInstance descriptor int normfd = NormGetDescriptor(instance); #endif // if/else WIN32/UNIX bool keepGoing = true; bool writeReady = false; int inputLength = 0; unsigned int bytesWritten = 0; const unsigned int BUFFER_LENGTH = 2048; char inputBuffer[BUFFER_LENGTH]; bool inputNeeded = false; // will be set to "true" upon CONNECT bool inputClosed = false; unsigned int clientCount = 0; while (keepGoing) { bool normEventPending = false; bool inputEventPending = false; #ifdef WIN32 DWORD handleCount = inputNeeded ? 2 : 1; DWORD waitStatus = MsgWaitForMultipleObjectsEx(handleCount, // number of handles in array handleArray, // object-handle array INFINITE, // time-out interval QS_ALLINPUT, // input-event type 0); if ((WAIT_OBJECT_0 <= waitStatus) && (waitStatus < (WAIT_OBJECT_0 + handleCount))) { if (0 == (waitStatus - WAIT_OBJECT_0)) normEventPending = true; else inputEventPending = true; } else if (-1 == waitStatus) { perror("normServer: MsgWaitForMultipleObjectsEx() error"); break; } else { // TBD - any other status we should handle? // (e.g. WAIT_TIMEOUT, WAIT_ABANDONED or WAIT_IO_COMPLETION) continue; // ignore for now } #else FD_SET(normfd, &fdset); int maxfd = normfd; if (inputNeeded) { FD_SET(inputfd, &fdset); if (inputfd > maxfd) maxfd = inputfd; } else { FD_CLR(inputfd, &fdset); } int result = select(maxfd+1, &fdset, NULL, NULL, NULL); if (result <= 0) { perror("normServer: select() error"); break; } if (FD_ISSET(inputfd, &fdset)) inputEventPending = true; if (FD_ISSET(normfd, &fdset)) normEventPending = true; #endif // if/else WIN32/UNIX if (inputEventPending) { // Read input into our txBuffer #ifdef WIN32 inputLength = inputHandler.ReadData(inputBuffer, BUFFER_LENGTH); if (inputLength > 0) { // We got our input bytesWritten = 0; inputNeeded = false; } else if (inputLength < 0) { inputHandler.Close(); inputClosed = true; } // else zero bytes read, still need input #else inputLength = fread(inputBuffer, 1, BUFFER_LENGTH, inputFile); if (inputLength > 0) { // We got our input bytesWritten = 0; inputNeeded = false; } else if (feof(inputFile)) { if (stdin != inputFile) { fclose(inputFile); inputFile = NULL; } inputClosed = true; } else if (ferror(inputFile)) { switch (errno) { case EINTR: // interupted, try again break; case EAGAIN: // input starved, wait for next notification break; default: perror("normServer: error reading input?!"); break; } } #endif // if/else WIN32/UNIX if (inputClosed) { inputNeeded = false; // Gracefully shutdown any connected clients // TBD - set state variable to indicate exit upon all closed? if (clientMap.empty()) { keepGoing = false; continue; } else { ClientMap::iterator it; for (it = clientMap.begin(); it != clientMap.end(); it++) { Client* client = it->second; NormSocketHandle clientSocket = client->GetSocket(); NormShutdown(clientSocket); } } } } // end if inputEventPending if (normEventPending) { // There's a NORM event pending NormSocketEvent event; if (NormGetSocketEvent(instance, &event)) { ClientInfo clientInfo; if (NORM_NODE_INVALID != event.sender) clientInfo = NormGetClientInfo(event.sender); else clientInfo = NormGetSocketInfo(event.socket); switch (event.type) { case NORM_SOCKET_ACCEPT: { if (event.socket == serverSocket) { // Possibly a new "client" connecting to our "server" // First confirm that this really is a new client. if (NORM_SOCKET_INVALID != FindClientSocket(clientMap, clientInfo)) { // We think we're already connected to this client fprintf(stderr, "normServer: duplicative %s from client %s/%hu...\n", (NORM_REMOTE_SENDER_NEW == event.event.type) ? "new" : "reset", clientInfo.GetAddressString(), clientInfo.GetPort()); continue; } NormSocketHandle clientSocket = NormAccept(serverSocket, event.sender); Client* client = new Client(clientSocket); if (NULL == client) { perror("normServer: new Client() error"); NormClose(clientSocket); continue; } // TBD - For multicast, if we are sending a tx_stream, we could flush it here to // bring the new receiver "up to date" ... probably would be best to // do this on some sort of timer-basis in the case of a bunch of receivers // joining in a short window of time ... if (trace) // note we're already tracing the mcast session NormSetMessageTrace(NormGetSocketSession(clientSocket), true); //NormSetMessageTrace(NormGetSocketSession(clientSocket), true); clientMap[clientInfo] = client; // ACCEPTED is good as CONNECTED, so enable writing right away client->SetWriteReady(true); if (0 == clientCount) { // We have at least one client, so lets serve up some juicy input inputNeeded = true; writeReady = true; } clientCount++; fprintf(stderr, "normServer: ACCEPTED connection from %s/%hu\n", clientInfo.GetAddressString(), clientInfo.GetPort()); // Note that an ACCEPTED socket is essentially CONNECTED, so we could // go ahead and set writeReady to true, etc here } else { // shouldn't happen } break; } case NORM_SOCKET_CONNECT: { fprintf(stderr, "normServer: CONNECTED to %s/%hu ...\n", clientInfo.GetAddressString(), clientInfo.GetPort()); Client* client = FindClient(clientMap, clientInfo); assert(NULL != client); break; } case NORM_SOCKET_READ: { // This is a cue to try to read data from stream // For our test app here, the data is read and output to STDOUT bool rxReady = true; while (rxReady) { char buffer[1024]; ssize_t bytesRead = NormRead(event.socket, buffer, 1024); if (bytesRead < 0) { // This shouldn't happen with ack-based flow control used fprintf(stderr, "normServer: broken stream ...\n"); continue; } if (bytesRead > 0) { #ifdef WIN32 // Use WriteFile() so there is no buffer delay DWORD dwWritten; WriteFile(hStdout, buffer, bytesRead, &dwWritten, NULL); #else fwrite(buffer, sizeof(char), bytesRead, stdout); #endif // if/else WIN32 } if (bytesRead < 1024) rxReady = false; } // Following lines are test code (to immediately close connection after first reaad) // (tests server stale connection "reject" command) //clientMap.erase(clientInfo); //NormClose(event.socket); break; } case NORM_SOCKET_WRITE: { if (NULL != groupAddrPtr) { // We are a multicast server writeReady = true; } else { Client* client = FindClient(clientMap, clientInfo); assert(NULL != client); client->SetWriteReady(true); } break; } case NORM_SOCKET_CLOSING: { fprintf(stderr, "normServer: client %s/%hu CLOSING connection ...\n", clientInfo.GetAddressString(), clientInfo.GetPort()); Client* client = FindClient(clientMap, clientInfo); assert(NULL != client); client->SetWriteReady(false); break; } case NORM_SOCKET_CLOSE: { fprintf(stderr, "normServer: connection to client %s/%hu CLOSED ...\n", clientInfo.GetAddressString(), clientInfo.GetPort()); clientMap.erase(clientInfo); NormClose(event.socket); if (inputClosed && clientMap.empty()) keepGoing = false; break; } case NORM_SOCKET_NONE: break; } // end switch(event.type) } else { fprintf(stderr, "normServer: NormGetNextSocketEvent() returned false\n"); } } // end if FD_ISSET(normfd) // If the normServer app has unsent data from STDIN, send it to the clients. // Note that a _multicast_ server multicasts to all clients at once while a // unicast server sends to each connected client individually if ((inputLength > 0) && !inputNeeded) { // There is inputBuffer data for the server to send to the client(s) if (NULL == groupAddrPtr) { // Unicast the data to each connected client individually by iterating // over the clientMap and sending data out to each pending client socket // (inputNeeded is reset to "true" when _all_ clients are non-pending) bool clientPending = false; ClientMap::iterator it; for (it = clientMap.begin(); it != clientMap.end(); it++) { Client* client = it->second; if (!client->GetWriteReady()) { clientPending = true; continue; } unsigned int numBytes = client->GetBytesWritten(); if (numBytes < inputLength) { NormSocketHandle clientSocket = client->GetSocket(); bytesWritten += NormWrite(clientSocket, inputBuffer + numBytes, inputLength - numBytes); client->SetBytesWritten(numBytes); if (bytesWritten < inputLength) { // Couldn't write whole inputBuffer, need to wait for NORM_SOCKET_WRITE event // for this client socket client->SetWriteReady(false); clientPending = true; } else { // inputBuffer has been completely written to this client NormFlush(clientSocket); } } } if (!clientPending) { // inputBuffer was sent to _all_ clients, so reset inputLength = 0; inputNeeded = true; // Reset all client "bytes_written" to zero for next chunk of data for (it = clientMap.begin(); it != clientMap.end(); it++) it->second->SetBytesWritten(0); } } else { // Multicast the data out the "serverSocket" to all clients // (Use the 'writeReady' and 'bytesWritten' state variables) NormSocketHandle sendSocket = serverSocket; if (NORM_SOCKET_INVALID != sendSocket) { if (writeReady && (inputLength > 0)) { // We have data in our inputBuffer and the NormSocket is "writeReady", so send it bytesWritten += NormWrite(sendSocket, inputBuffer + bytesWritten, inputLength - bytesWritten); if (bytesWritten < inputLength) { // Couldn't write whole inputBuffer, need to wait for NORM_SOCKET_WRITE event writeReady = false; } else { // inputBuffer has been completely written inputLength = 0; inputNeeded = true; NormFlush(sendSocket); } } } } } // end if ((inputLength > 0) && !inputNeeded) } // end while (keepGoing) #ifdef WIN32 inputHandler.Close(); #else if ((stdin != inputFile) && (NULL != inputFile)) { fclose(inputFile); inputFile = NULL; } #endif // if/else WIN32 NormClose(serverSocket); serverSocket = NORM_SOCKET_INVALID; } // end main() norm-1.5.8+dfsg2/examples/normSocket.cpp0000644000000000000000000016073613225002023015037 0ustar #include "normSocket.h" #include // for stderr #include // for assert() #include // for strlen() #ifdef WIN32 #include // for inet_ntoa() (TBD - change to use Protolib routines?) #include // for inet_ntop() #else #include // for inet_ntoa() (TBD - change to use Protolib routines?) #endif // if/else WIN32/UNIX // COMPILE: (assumes "normApi.h" in "include" ... // g++ -I../include -c normSocket.cpp #define TRACE(...) fprintf(stderr, __VA_ARGS__) // Extra, non-public NORM API functions used by NormSocket stuff extern void NormSetId(NormSessionHandle sesssionHandle, NormNodeId normId); // This "NormSocket" class is used to maintain tx/rx state for a NORM "socket" connection. // At the moment this "socket" connection represents a single, bi-directional NORM_OBJECT_STREAM // in either a unicast context or an asymmetric "server" multicast stream to possibly multiple "client" // nodes with individual unicast streams in return from those "client" nodes. (I.e., the server will need to // have a normSocket per client even for the server multicast case (maybe :-) ) const NormSocketHandle NORM_SOCKET_INVALID = (NormSocketHandle)0; const double NORM_DEFAULT_CONNECT_TIMEOUT = 60.0; // This is extra stuff defined for NormSocket API extension purposes. As the NormSocket // extension is finalized, these may be refined/relocated enum {NORM_SOCKET_VERSION = 1}; enum NormSocketCommand { NORM_SOCKET_CMD_NULL = 0, // reserved, invalid/null command NORM_SOCKET_CMD_REJECT, // sent by server-listener to reject invalid connection messages NORM_SOCKET_CMD_ALIVE // TBD - for NormSocket "keep-alive" option? }; // a 'helper' function we use for debugging const char* NormNodeGetAddressString(NormNodeHandle node) { char addr[16]; // big enough for IPv6 unsigned int addrLen = 16; UINT16 port; if (NormNodeGetAddress(node, addr, &addrLen, &port)) { static char text[64]; text[0] = text[31] = '\0'; int addrFamily; if (4 == addrLen) addrFamily = AF_INET; else addrFamily = AF_INET6; inet_ntop(addrFamily, addr, text, 31); sprintf(text + strlen(text), "/%hu", port); return text; } else { return "???"; } } // end NormNodeGetAddressString() class NormSocket { public: NormSocket(NormSessionHandle normSession = NORM_SESSION_INVALID); ~NormSocket(); // These methods identify the role of this socket with respect // to the client / server relationship (a "server socket" is // one for which NormListen() has been invoked). bool IsServerSocket() const {return (server_socket == this);} bool IsClientSocket() const {return (server_socket != this);} bool IsUnicastSocket() const {return (NORM_SESSION_INVALID == mcast_session);} bool IsMulticastSocket() const {return !IsUnicastSocket();} bool IsMulticastServer() const {return (IsMulticastSocket() && IsServerSocket());} bool IsMulticastClient() const {return (IsMulticastSocket() && IsClientSocket());} bool IsServerSide() const {return (NULL != server_socket);} bool IsClientSide() const {return (NULL == server_socket);} NormInstanceHandle GetInstance() const {return NormGetInstance(norm_session);} NormSessionHandle GetSession() const {return norm_session;} NormSessionHandle GetMulticastSession() const {return mcast_session;} void InitRxStream(NormObjectHandle rxStream) {rx_stream = rxStream;} NormObjectHandle GetRxStream() const {return rx_stream;} void InitTxStream(NormObjectHandle txStream, unsigned int bufferSize, UINT16 segmentSize, UINT16 blockSize) { tx_stream = txStream; tx_segment_size = segmentSize; tx_stream_buffer_max = NormGetStreamBufferSegmentCount(bufferSize, segmentSize, blockSize); tx_stream_buffer_max -= blockSize; // a little safety margin (perhaps not necessary) tx_stream_buffer_count = 0; tx_stream_bytes_remain = 0; tx_watermark_pending = false; tx_ready = true; } bool Open(NormInstanceHandle instance = NORM_INSTANCE_INVALID); bool Listen(UINT16 serverPort, const char* groupAddr, const char* serverAddr); NormSocket* Accept(NormNodeHandle client, NormInstanceHandle instance = NORM_INSTANCE_INVALID); bool Connect(const char* serverAddr, UINT16 serverPort, UINT16 localPort, const char* groupAddr, NormNodeId clientId); // Write to tx stream (with flow control) unsigned int Write(const char* buffer, unsigned int numBytes); void Flush(bool eom = false, NormFlushMode flushMode = NORM_FLUSH_ACTIVE); // Read from rx_stream bool Read(char* buffer, unsigned int& numBytes); // "graceful" shutdown (stream is flushed and stream end, etc) void Shutdown(); // hard, immediate closure void Close(); void SetUserData(const void* userData) {user_data = userData;} const void* GetUserData() const {return user_data;} void SetTrace(bool state); void GetSocketEvent(const NormEvent& event, NormSocketEvent& socketEvent); typedef enum State { CLOSED, OPEN, LISTENING, CONNECTING, ACCEPTING, CONNECTED, CLOSING } State; bool AddAckingNode(NormNodeId nodeId) { if (NormAddAckingNode(norm_session, nodeId)) { client_count++; return true; } else { return false; } } void RemoveAckingNode(NormNodeId nodeId) {NormRemoveAckingNode(norm_session, nodeId);} void GetPeerName(char* addr, unsigned int* addrLen, UINT16* port) { if (NULL == addrLen) return; switch (remote_version) { case 4: if ((*addrLen >= 4) && (NULL != addr)) memcpy(addr, remote_addr, 4); *addrLen = 4; break; case 6: if ((*addrLen >= 16) && (NULL != addr)) memcpy(addr, remote_addr, 16); *addrLen = 16; break; default: *addrLen = 0; return; } if (NULL != port) *port = remote_port; } private: void UpdateRemoteAddress() { unsigned int addrLen = 16; NormNodeGetAddress(remote_node, remote_addr, &addrLen, &remote_port); if (4 == addrLen) remote_version = 4; else remote_version = 6; } State socket_state; NormSessionHandle norm_session; NormSessionHandle mcast_session; // equals norm_session for a multicast server NormSocket* server_socket; // only applies to server-side sockets unsigned int client_count; // only applies to mcast server sockets NormNodeId client_id; // only applies to mcast client socket NormNodeHandle remote_node; // client socket peer info UINT8 remote_version; // 4 or 6 char remote_addr[16]; // big enough for IPv6 UINT16 remote_port; // Send stream and associated flow control state variables NormObjectHandle tx_stream; bool tx_ready; UINT16 tx_segment_size; unsigned int tx_stream_buffer_max; unsigned int tx_stream_buffer_count; unsigned int tx_stream_bytes_remain; bool tx_watermark_pending; // Receive stream state NormObjectHandle rx_stream; const void* user_data; // for use by user application }; // end class NormSocket NormSocket::NormSocket(NormSessionHandle normSession) : socket_state(CLOSED), norm_session(normSession), mcast_session(NORM_SESSION_INVALID), server_socket(NULL), client_count(0), client_id(NORM_NODE_NONE), remote_node(NORM_NODE_INVALID), remote_version(0), remote_port(0), tx_stream(NORM_OBJECT_INVALID), tx_ready(false), tx_segment_size(0), tx_stream_buffer_max(0), tx_stream_buffer_count(0), tx_stream_bytes_remain(0), tx_watermark_pending(false), rx_stream(NORM_OBJECT_INVALID), user_data(NULL) { // For now we use the NormSession "user data" option to associate // the session with a "socket". In the future we may add a // dedicated NormSetSocket(NormSessionHandle session, NormSocketHandle normSocket) API // to keep the "user data" feature available for other purposes if (NORM_SESSION_INVALID != normSession) // this should always be true NormSetUserData(normSession, this); } NormSocket::~NormSocket() { Close(); if (NORM_SESSION_INVALID != norm_session) { NormDestroySession(norm_session); norm_session = NORM_SESSION_INVALID; } } bool NormSocket::Open(NormInstanceHandle instance) { if (CLOSED != socket_state) { fprintf(stderr, "NormSocket::Open() error: socket already open?!\n"); return false; } // A proper NormNodeId will be set upon NormBind(), NormConnect(), or NormListen() if (NORM_SESSION_INVALID == (norm_session = NormCreateSession(instance, "127.0.0.1", 0, NORM_NODE_ANY))) { perror("NormSocket::Open() error"); return false; } NormSetUserData(norm_session, this); socket_state = OPEN; return true; } // end NormSocket::Open() bool NormSocket::Listen(UINT16 serverPort, const char* groupAddr, const char* serverAddr) { if (OPEN != socket_state) { fprintf(stderr, "NormSocket::Listen() error: socket not open?!\n"); return false; } // THe code below will be cleaned/tightened up somewhat once all is working // Note that port reuse here lets us manage our "client" rx-only unicast connections the // way we need, but does allow a second multicast server to be started on this group which leads // to undefined behavior. TBD - see if we can prevent via binding wizardry // (How is it done for TCP servers? - probably because the accept() call is in the network stack // instead of user-space) Perhaps we could have a semaphore lock to block a second "server" if (NULL != groupAddr) { // TBD - validate that "groupAddr" is indeed a multicast address NormChangeDestination(norm_session, groupAddr, serverPort); NormSetId(norm_session, 1); // server always uses NormNodeId '1' // TBD - we _could_ let the server have an independent, ephemeral tx_port // by _not_ calling NormSetTxPort() here to enable multiple multicast // servers on same group/port on same host if server instance use unique NormNodeIds? NormSetTxPort(norm_session, serverPort); // can't do this and distinguish unicast feedback NormSetMulticastInterface(norm_session, serverAddr); NormSetRxPortReuse(norm_session, true); mcast_session = norm_session; NormSetMulticastLoopback(norm_session, true); // for testing } else { // For unicast , the "server" has a NormNodeId of '1' and the "clients" are '2' // to obviate need for explicit id management and will allow NAT to work, etc NormChangeDestination(norm_session, "127.0.0.1", serverPort); NormSetId(norm_session, 1); // server always uses NormNodeId '1' NormSetTxPort(norm_session, serverPort); #ifdef WIN32 // UDP socket bind/connect does not work properly on WIN32, so no port reuse // (so a little different strategy is used for Win32 connections) NormSetRxPortReuse(norm_session, false, serverAddr); #else NormSetRxPortReuse(norm_session, true, serverAddr); #endif // if/else WIN32 } // TBD - the next four calls could be combined into a "NormStartListener()" function // Set session to track incoming clients by their addr/port // (instead of NormNodeId as usual) NormSetServerListener(norm_session, true); // Our listener is a "silent" receiver since all actual reception // (unicast) is handed off to a separate "client" session NormSetSilentReceiver(norm_session, true); // So that the listener can construct (unsent) ACKs without failure NormSetDefaultUnicastNack(norm_session, true); // Note we use a small buffer size here since a "listening" socket isn't // going to be receiving data (TBD - implement a mechanism to handoff remote // sender (i.e. "client") from parent if (!NormStartReceiver(norm_session, 2048)) { fprintf(stderr, "NormSocket::Listen() error: NormStartReceiver() failure (perhaps port already in use)\n"); //NormDestroySession(norm_session); //norm_session = NORM_SESSION_INVALID; return false; } server_socket = this; socket_state = LISTENING; return true; } // end NormSocket::Listen() NormSocket* NormSocket::Accept(NormNodeHandle client, NormInstanceHandle instance) { if (!IsServerSocket()) return NULL; char clientAddr[64]; clientAddr[63] = '\0'; char addr[16]; // big enough for IPv6 unsigned int addrLen = 16; UINT16 clientPort; NormNodeGetAddress(client, addr, &addrLen, &clientPort); int addrFamily; UINT8 version; if (4 == addrLen) { addrFamily = AF_INET; version = 4; } else { addrFamily = AF_INET6; version = 6; } inet_ntop(addrFamily, addr, clientAddr, 63); UINT16 serverPort = NormGetRxPort(norm_session); if (NORM_INSTANCE_INVALID == instance) instance = NormGetInstance(norm_session); #ifdef WIN32 NormSessionHandle clientSession = NormCreateSession(instance, clientAddr, 0, 1); #else NormSessionHandle clientSession = NormCreateSession(instance, clientAddr, serverPort, 1); NormSetTxPort(clientSession, serverPort, true); #endif // if/else WIN32/UNIX // NORM_SYNC_STREAM tries to get everything the sender has cached/buffered NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_STREAM); //NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_ALL); // This next API call will cause NORM to tightly bind the remote client src addr/port to // our server port so the "clientSession" captures the client packets instead of the "server" session // Any new packets will come to our new connected clientSession instead // However, note that even though we've "connected" this sender, // there is a chance that additional packets in the "serverSession" // rx socket buffer may look like a new sender if deleted now, so // we wait for NORM_REMOTE_SENDER_INACTIVE to delete #ifndef WIN32 // Enable rx port reuse since it's the server port, and connect // this socket to client addr/port for unique, tight binding // TBD - support option to bind to specific server address //fprintf(stderr, "accepting connection from %s/%d on port %d ...\n", clientAddr, clientPort, serverPort); NormSetRxPortReuse(clientSession, true, NULL, clientAddr, clientPort); #endif // WIN32 NormSetDefaultUnicastNack(clientSession, true); NormStartReceiver(clientSession, 2*1024*1024); // This call immediately inserts the "client" remote sender state // into the newly-created clientSession by injecting a NORM_CMD(CC) // message (and, as a result, a NORM_ACK is sent back to the client // for a quick initial RTT estimate) NormTransferSender(clientSession, client); NormSocket* clientSocket = new NormSocket(clientSession); clientSocket->server_socket = this; // this is a server-side socket clientSocket->remote_node = client; clientSocket->UpdateRemoteAddress(); NormNodeSetUserData(client, clientSocket); NormNodeId clientId = NormNodeGetId(client); if (IsUnicastSocket()) { NormChangeDestination(clientSession, clientAddr, clientPort, false); // point unicast session dest to client port // The clientSession is bi-directional so we need to NormStartSender(), etc NormAddAckingNode(clientSession, 2); //clientId); NormSetFlowControl(clientSession, 0); // disable timer-based flow control since we do explicit, ACK-based flow control NormStartSender(clientSession, NormGetRandomSessionId(), 2*1024*1024, 1400, 16, 4); } else // if IsMulticastSocket() { // TBD - should we make sure this not a NormNodeId we already have? // TBD - should we wait to add the client as acking node until CONNECT // (probably for heavyweight; for lightweight we know the client // has already started his multicast receiver) AddAckingNode(clientId); // TBD - check result NormNodeHandle node = NormGetAckingNodeHandle(mcast_session, clientId); NormNodeSetUserData(node, clientSocket); // a way to track mcast client sockets clientSocket->mcast_session = mcast_session; clientSocket->client_id = clientId; if (LISTENING == socket_state) { NormSetFlowControl(norm_session, 0); // disable timer-based flow control since we do explicit, ACK-based flow control NormStartSender(norm_session, NormGetRandomSessionId(), 2*1024*1024, 1400, 16, 4); socket_state = CONNECTED; if (NORM_OBJECT_INVALID == tx_stream) { tx_stream = NormStreamOpen(norm_session, 2*1024*1024); InitTxStream(tx_stream, 2*1024*1024, 1400, 16); } } /* The code below would be invoked for "heavyweight" mcast client admission (for the moment we go with a "lightweight" model - this might be invokable upon as an optional behavior later) // Here, we start the clientSession (w/ a minimal buffer size) and create a temporary sender // stream that is immediately flushed/closed to inform the "client" that his connection // has been accepted. The sender function is terminated upon client acknowledgement NormAddAckingNode(clientSession, clientId); NormSetFlowControl(clientSession, 0); // disable timer-based flow control since we do explicit, ACK-based flow control NormStartSender(clientSession, NormGetRandomSessionId(), 1024, 512, 1, 0); NormObjectHandle tempStream = NormStreamOpen(clientSession, 1024); NormStreamClose(tempStream, true); // Note our "trick" here to do a graceful close, _then_ watermark to get ack NormSetWatermark(clientSession, tempStream, true); // future NORM API will add "bool watermark" option to graceful close */ } // Note that for this lightweight connection mode, ACCEPTING is essentially CONNECTED so // app can treat this as a CONNECTED socket until otherwise notified // Should we start the time clientSocket timer and timeout if not connected in a timely fashion? clientSocket->socket_state = ACCEPTING; // will transition to CONNECTED when client is detected on new clientSession return clientSocket; } // end NormSocket::Accept() // TBD - provide options for binding to a specific local address, interface, etc bool NormSocket::Connect(const char* serverAddr, UINT16 serverPort, UINT16 localPort, const char* groupAddr, NormNodeId clientId) { // For unicast connections, the "client" manages a single NormSession for send and receive // (For multicast connections, there are two sessions: The same unicast session that will // be set to txOnly upon CONNECT and a separate NormSession for multicast reception) // Setting the session port to zero here causes an ephemeral port to be assigned _and_ // it is also a single socket (tx_socket == rx_socket) session for client->server unicast NormSetId(norm_session, clientId); // NORM_SYNC_STREAM tries to get everything the sender has cached/buffered NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_STREAM); //NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_ALL); #ifndef WIN32 // We don't set reuse for the ephemeral port, but do want to 'connect' to // the server addr/port for this unicast client->server socket NormSetRxPortReuse(norm_session, false, NULL, serverAddr, serverPort); #endif // WIN32 if (0 != localPort) { // Set client session up to use a user-specified (non-ephemeral) port number NormChangeDestination(norm_session, NULL, localPort, false); NormSetTxPort(norm_session, localPort); } // TBD - for a multicast connection, the unicast receiver could be started with minimal buffer // (not that it matters since the buffers aren't activated until a sender starts sending _data_) if (!NormStartReceiver(norm_session, 2*1024*1024)) // to get ephemeral port assigned { fprintf(stderr, "NormSocket::Connect() error: unicast NormStartReceiver() failure\n"); return false; } NormSetSynStatus(norm_session, true); // Point our unicast socket at the unicast server addr/port NormChangeDestination(norm_session, serverAddr, serverPort, false); NormSessionId sessionId = NormGetRandomSessionId(); // TBD - use ephemeral port as session/instance id? //NormAddAckingNode(norm_session, 1); // servers always have NormNodeId '1' for unicast sessions NormSetAutoAckingNodes(norm_session, NORM_TRACK_RECEIVERS); // this way we get informed upon first ACK NormSetFlowControl(norm_session, 0); // since we do explicit, ACK-based flow control if (!NormStartSender(norm_session, sessionId, 2*1024*1024, 1400, 16, 4)) { fprintf(stderr, "NormSocket::Connect() error: NormStartSender() failure\n"); return false; } if (NULL != groupAddr) { // Create the "mcast_session" for multicast reception mcast_session = NormCreateSession(NormGetInstance(norm_session), groupAddr, serverPort, clientId); //NormSetTxPort(mcast_session, serverPort); // TBD - not sure this is a good idea if multiple clients on a machine? NormSetUserData(mcast_session, this); // NORM_SYNC_STREAM tries to get everything the sender has cached/buffered NormSetDefaultSyncPolicy(mcast_session, NORM_SYNC_STREAM); //NormSetDefaultSyncPolicy(mcast_session, NORM_SYNC_ALL); NormSetDefaultUnicastNack(mcast_session, true); // we could optionally allow multicast NACKing, too NormSetMulticastLoopback(mcast_session, true); // for testing client_id = clientId; // TBD - make this SSM??? ... this would allow for multiple servers using the same groupAddr/port // Note we 'connect' to server addr/port to make this associated with single, specific mcast server // TBD - Once we add code to set multicast interface, we can set the port reuse // here to 'connect' to the specified server addr/port for tighter binding NormSetRxPortReuse(mcast_session, true, groupAddr);//, serverAddr, serverPort); // For a "lightweight" client->server connection establishment, we go ahead and // stop our unicast receiver and start multicast receiver, assuming the server // will admit us into the group. // (TBD - provide a "heavier weight" connection acceptance confirmation/denial signal from server // via unicast from server -> client here (i.e. keep the unicast receiver open) if (!NormStartReceiver(mcast_session, 2*1024*1024)) // to get ephemeral port assigned { fprintf(stderr, "NormSocket::Connect() error: multicast NormStartReceiver() failure\n"); return false; } } else { // Set timeout for connect attempt (for "heavyweight" mcast connect, this would also be done) NormSetUserTimer(norm_session, NORM_DEFAULT_CONNECT_TIMEOUT); } server_socket = NULL; // this is a client-side socket if (NORM_OBJECT_INVALID == tx_stream) { tx_stream = NormStreamOpen(norm_session, 2*1024*1024); InitTxStream(tx_stream, 2*1024*1024, 1400, 16); } socket_state = CONNECTING; return true; } // end NormSocket::Connect() unsigned int NormSocket::Write(const char* buffer, unsigned int numBytes) { // Make sure the socket is CONNECTED first // (TBD - an option for allowing NormWrite() to start sending // data prior to connection confirmation is being considered // to accelerate data transfer (most useful for short-lived // or 'urgent' connections such as transactions) if (CONNECTED != socket_state) return 0; if (IsMulticastClient() && IsServerSide()) { // This is multicast server rxonly client socket, so we redirect // the write() to the associated txonly multicast socket return server_socket->Write(buffer, numBytes); } // TBD - if tx_stream not yet open, open it!!! if (NORM_OBJECT_INVALID == tx_stream) { tx_stream = NormStreamOpen(norm_session, 2*1024*1024); InitTxStream(tx_stream, 2*1024*1024, 1400, 16); } // This method uses NormStreamWrite(), but limits writes by explicit ACK-based flow control status if (tx_stream_buffer_count < tx_stream_buffer_max) { // 1) How many buffer bytes are available? unsigned int bytesAvailable = tx_segment_size * (tx_stream_buffer_max - tx_stream_buffer_count); bytesAvailable -= tx_stream_bytes_remain; // unflushed segment portiomn if (numBytes <= bytesAvailable) { unsigned int totalBytes = numBytes + tx_stream_bytes_remain; unsigned int numSegments = totalBytes / tx_segment_size; tx_stream_bytes_remain = totalBytes % tx_segment_size; tx_stream_buffer_count += numSegments; } else { numBytes = bytesAvailable; tx_stream_buffer_count = tx_stream_buffer_max; } // 2) Write to the stream unsigned int bytesWritten = NormStreamWrite(tx_stream, buffer, numBytes); //assert(bytesWritten == numBytes); // this could happen if timer-based flow control is left enabled // 3) Check if we need to issue a watermark ACK request? if (!tx_watermark_pending && (tx_stream_buffer_count >= (tx_stream_buffer_max / 2))) { //fprintf(stderr, "tx_engine_t::WriteToNormStream() initiating watermark ACK request (buffer count:%lu max:%lu usage:%u)...\n", // tx_stream_buffer_count, tx_stream_buffer_max, NormStreamGetBufferUsage(tx_stream)); NormSetWatermark(norm_session, tx_stream); tx_watermark_pending = true; } // TBD - set "tx_ready" to false if tx_stream_buffer_count == tx_stream_buffer_max here ??? return bytesWritten; } else { tx_ready = false; return 0; } } // end NormSocket::Write() void NormSocket::Flush(bool eom, NormFlushMode flushMode) { // TBD - make sure the socket is CONNECTED first if (IsMulticastClient() && IsServerSide()) { // This is multicast server rx-only client socket, so we redirect // the flush() to the associated tx-only multicast socket return server_socket->Flush(eom, flushMode); } // NormStreamFlush always will transmit pending runt segments, if applicable // (thus we need to manage our buffer counting accordingly if pending bytes remain) if (tx_watermark_pending) { NormStreamFlush(tx_stream, eom, flushMode); } else if (NORM_FLUSH_ACTIVE == flushMode) { // we flush passive, because watermark forces active ack request NormStreamFlush(tx_stream, eom, NORM_FLUSH_PASSIVE); NormSetWatermark(norm_session, tx_stream, true); } else { NormStreamFlush(tx_stream, eom, flushMode); } if (0 != tx_stream_bytes_remain) { // The flush forces the runt segment out, so we increment our buffer usage count tx_stream_buffer_count++; tx_stream_bytes_remain = 0; if (!tx_watermark_pending && (tx_stream_buffer_count >= (tx_stream_buffer_max >> 1))) { //fprintf(stderr, "tx_engine_t::stream_flush() initiating watermark ACK request (buffer count:%lu max:%lu usage:%u)...\n", // tx_stream_buffer_count, tx_stream_buffer_max); NormSetWatermark(norm_session, tx_stream, true); tx_watermark_pending = true; } } } // end NormSocket::Flush() bool NormSocket::Read(char* buffer, unsigned int& numBytes) { // TBD - make sure rx_stream is valid! // TBD - make sure this is not a tx only client socket ... if (NORM_OBJECT_INVALID != rx_stream) { return NormStreamRead(rx_stream, buffer, &numBytes); } else { numBytes = 0; return true; } } // end NormSocket::Read() void NormSocket::Shutdown() { // TBD - should we call NormStopReceiver(norm_session) here // or have SHUT_RD, SHUT_WR, and SHUT_RDWR flags // like the sockets "shutdown()" call??? // For now, we do a "graceful" SHUT_RDWR behavior if (CONNECTED == socket_state) { NormStopReceiver(norm_session); rx_stream = NULL; if ((IsServerSide() && IsMulticastClient()) || (NORM_OBJECT_INVALID == tx_stream)) { // Use a zero-timeout to immediately post NORM_SOCKET_CLOSE notification NormSetUserTimer(norm_session, 0.0); } else if (NORM_OBJECT_INVALID != tx_stream) { // It controls a tx_stream, so shutdown the tx_stream gracefully NormStreamClose(tx_stream, true); // Note our "trick" here to do a graceful close, _then_ watermark to get ack NormSetWatermark(norm_session, tx_stream, true); // future NORM API will add "bool watermark" option to graceful close } socket_state = CLOSING; } } // end NormSocket::Shutdown() void NormSocket::Close() { if (IsMulticastSocket()) { if (IsServerSide()) { if (IsServerSocket()) { // IsMulticastSocket() guarantees the mcast_session is valid // Dissociate remaining clients from this session and set their // timers so that NORM_SOCKET_CLOSE events are dispatched for them NormNodeId nodeId = NORM_NODE_NONE; while (NormGetNextAckingNode(mcast_session, &nodeId)) { NormNodeHandle node = NormGetAckingNodeHandle(mcast_session, nodeId); assert(NORM_NODE_INVALID != node); NormSocket* clientSocket = (NormSocket*)NormNodeGetUserData(node); NormSetUserTimer(clientSocket->norm_session, 0.0); } // for mcast server mcast_session == norm_session so it's destroyed below } else { // "IsServerSide()" guarantees the "server_socket" is non-NULL // server-side multicast client socket closing, so we // need to remove this "client" NormNodeId from the mcast // session's acking node list server_socket->RemoveAckingNode(client_id); } } else // client-side multicast socket, so we need to destroy mcast_session { NormDestroySession(mcast_session); } mcast_session = NORM_SESSION_INVALID; } if (NORM_SESSION_INVALID != norm_session) { NormStopSender(norm_session); NormStopReceiver(norm_session); } server_socket = NULL; remote_node = NORM_NODE_INVALID; tx_stream = NORM_OBJECT_INVALID; tx_segment_size = 0; tx_stream_buffer_max = tx_stream_buffer_count = tx_stream_bytes_remain = 0; tx_watermark_pending = false; rx_stream = NORM_OBJECT_INVALID; socket_state = CLOSED; } // end NormSocket::Close() void NormSocket::GetSocketEvent(const NormEvent& event, NormSocketEvent& socketEvent) { socketEvent.socket = (NormSocketHandle)this; socketEvent.type = NORM_SOCKET_NONE; // default socket event type if no socket-specific state change occurs socketEvent.event = event; //fprintf(stderr, "NormSocket::GetSocketEvent() norm event type:%d session:%p\n", event.type, event.session); switch (event.type) { case NORM_TX_QUEUE_EMPTY: case NORM_TX_QUEUE_VACANCY: { // The socket may be tx ready, so issue a NORM_SOCKET_WRITE event if (CONNECTED == socket_state) { if (!tx_ready) { tx_ready = true; socketEvent.type = NORM_SOCKET_WRITE; } } break; } case NORM_TX_WATERMARK_COMPLETED: { switch (socket_state) { /* case ACCEPTING: { // This only comes into play for the "confirmed connection" // model for multicast sockets (not yet implemented) assert(0); assert(IsServerSide() && IsMulticastClient()); if (NORM_ACK_SUCCESS == NormGetAckingStatus(norm_session)) { // Client has acknowledged our acceptance socketEvent.type = NORM_SOCKET_CONNECT; NormStopSender(norm_session); // the mcast_session is our tx channel break; } else { // Client didn't acknowledge, so we cull him from our server socketEvent.type = NORM_SOCKET_CLOSE; } break; } */ case CLOSING: { // Socket that was shutdown has either been acknowledged or timed out // TBD - should we issue a different event if ACK_FAILURE??? Close(); socketEvent.type = NORM_SOCKET_CLOSE; break; } default: { // TBD - implement option for more persistence bool success = false; if (NORM_ACK_SUCCESS == NormGetAckingStatus(norm_session)) { success = true; } else { // At least one receiver didn't acknowledge if (IsUnicastSocket() || IsMulticastClient()) { // We could be infinitely persistent w/ NormResetWatermark() // (TBD - provide a NormSocket "keep alive" option NormResetWatermark(event.session); // Or just declare the connection broken/closed //socketEvent.type = NORM_SOCKET_CLOSE; } else { // Multicast server, so determine who failed to acknowledge // and cull them from our acking node list ... and shutdown // their associated unicast sockets ... ugh!!! NormNodeId nodeId = NORM_NODE_NONE; NormAckingStatus ackingStatus; while (NormGetNextAckingNode(mcast_session, &nodeId, &ackingStatus)) { if (NORM_ACK_SUCCESS == ackingStatus) { success = true; // there was at least one success } else { NormNodeHandle node = NormGetAckingNodeHandle(mcast_session, nodeId); assert(NORM_NODE_INVALID != node); NormSocket* clientSocket = (NormSocket*)NormNodeGetUserData(node); assert(NULL != clientSocket); // We use the session timer to dispatch a NORM_SOCKET_CLOSE per failed client // (This will also remove the client from this server's acking list) clientSocket->socket_state = CLOSING; NormSetUserTimer(clientSocket->norm_session, 0.0); } } // TBD - what do we if all clients failed ... issue a NORM_SOCKET_DISCONNECT event, // probably stop sending data and resume when a new client appears ??? } } if (tx_watermark_pending && success) { // flow control acknowledgement tx_watermark_pending = false; tx_stream_buffer_count -= (tx_stream_buffer_max >> 1); if (!tx_ready) { tx_ready = true; socketEvent.type = NORM_SOCKET_WRITE; } } break; } } break; } case NORM_ACKING_NODE_NEW: // This means we have received an ACK from the server case NORM_REMOTE_SENDER_RESET: case NORM_REMOTE_SENDER_NEW: { switch (socket_state) { case LISTENING: socketEvent.type = NORM_SOCKET_ACCEPT; break; case ACCEPTING: if (IsServerSide() && IsClientSocket() && (NORM_NODE_INVALID != remote_node)) { NormNodeDelete(remote_node); } case CONNECTING: // TBD - We should validate that it's the right remote sender // (i.e., by source address and/or nodeId) NormCancelUserTimer(norm_session); socketEvent.type = NORM_SOCKET_CONNECT; NormSetSynStatus(norm_session, false); socket_state = CONNECTED; // Since UDP connect/bind doesn't really work properly on // Windows, the Windows NormSocket server farms out client connections // to new ephemeral port numbers, so we need to update // the destination port upon connection (Yuck!) remote_node = event.sender; UpdateRemoteAddress(); NormChangeDestination(norm_session, NULL, remote_port); if (NORM_OBJECT_INVALID == tx_stream) { tx_stream = NormStreamOpen(norm_session, 2*1024*1024); InitTxStream(tx_stream, 2*1024*1024, 1400, 16); } break; case CONNECTED: if (IsMulticastSocket()) { if (IsServerSocket()) { // New client showing up at our multicast party socketEvent.type = NORM_SOCKET_ACCEPT; } else { // TBD - validate if this same server or not (e.g. by source addr/port) // Different sender showing up in multicast group!? if (event.sender != remote_node) { char senderAddr[16]; unsigned int addrLen = 16; UINT16 senderPort; NormNodeGetAddress(event.sender, senderAddr, &addrLen, &senderPort); unsigned int senderVersion = (4 == addrLen) ? 4 : 6; if ((senderVersion != remote_version) || (senderPort != remote_port) || (0 != memcmp(senderAddr, remote_addr, addrLen))) { //fprintf(stderr, "NormSocket warning: multicast sender %s reset?!\n", NormNodeGetAddressString(event.sender)); } } // TBD - should Close() the socket and issue a NORM_SOCKET_CLOSE event // and leave it up to the application to reconnect? Or should we // provides some sort of NORM_SOCKET_DISCONNECT event //socketEvent.type = NORM_SOCKET_CLOSE; } } else // unicast { // Eemote sender reset? How do we tell? // TBD - validate if this same server or not (e.g. by source addr/port) if (event.sender != remote_node) { char senderAddr[16]; unsigned int addrLen = 16; UINT16 senderPort; NormNodeGetAddress(event.sender, senderAddr, &addrLen, &senderPort); unsigned int senderVersion = (4 == addrLen) ? 4 : 6; if ((senderVersion != remote_version) || (senderPort != remote_port) || (0 != memcmp(senderAddr, remote_addr, addrLen))) { fprintf(stderr, "NormSocket warning: unicast sender %s reset?!\n", NormNodeGetAddressString(event.sender)); } } // Close(); //socketEvent.type = NORM_SOCKET_CLOSE; } break; default: // CLOSING, CLOSE // shouldn't happen break; } break; } case NORM_SEND_ERROR: { switch (socket_state) { case CONNECTING: case ACCEPTING: case CONNECTED: case CLOSING: if (IsMulticastServer()) fprintf(stderr, "SEND_ERROR on a multicast server socket?!\n"); /*else fprintf(stderr, "SEND_ERROR session:%p sender:%p remote_node:%p (%s)\n", event.session, event.sender, remote_node, NormNodeGetAddressString(remote_node));*/ Close(); socketEvent.type = NORM_SOCKET_CLOSE; break; default: // shouldn't happen break; } break; } case NORM_USER_TIMEOUT: { switch (socket_state) { case CONNECTING: // client connection attempt timed out case ACCEPTING: // accepted client didn't follow through case CONNECTED: // multicast client ack failure case CLOSING: Close(); socketEvent.type = NORM_SOCKET_CLOSE; break; default: // shouldn't happen assert(0); break; } break; } case NORM_RX_CMD_NEW: { char buffer[4096]; unsigned int buflen = 4096; if (NormNodeGetCommand(event.sender, buffer, &buflen)) { if ((buflen < 2) || (NORM_SOCKET_VERSION == buffer[0])) { if (NORM_SOCKET_CMD_REJECT == buffer[1]) { Close(); socketEvent.type = NORM_SOCKET_CLOSE; } else { fprintf(stderr, "NormSocket warning: received unknown command\n"); } } else { fprintf(stderr, "NormSocket warning: received command with invalid version\n"); } } else { fprintf(stderr, "NormSocket warning: unable to get received command\n"); } break; } case NORM_REMOTE_SENDER_INACTIVE: { switch (socket_state) { case LISTENING: { // delete state for remote sender that has been accepted (or not) // TBD - do something a little more tidy here NormSocket* clientSocket = (NormSocket*)NormNodeGetUserData(event.sender); if ((NULL != clientSocket) && (clientSocket->remote_node == event.sender)) clientSocket->remote_node = NORM_NODE_INVALID; NormNodeDelete(event.sender); break; } case CONNECTED: { if (IsServerSocket()) { NormSocket* clientSocket = (NormSocket*)NormNodeGetUserData(event.sender); if ((NULL != clientSocket) && (clientSocket->remote_node == event.sender)) clientSocket->remote_node = NORM_NODE_INVALID; NormNodeDelete(event.sender); } // TBD - should we do something here (perhaps issue a NORM_SOCKET_IDLE event or something // that could be used as a clue that our "connection" may have broken or timed out??? // (Meanwhile, applications will have to figure that our for themselves) break; } default: // CONNECTING, ACCEPTING, CLOSING, CLOSED { // shouldn't happen break; } } break; } case NORM_RX_OBJECT_NEW: { switch (socket_state) { case LISTENING: // TBD - shouldn't happen, delete sender right away? break; case CONNECTED: // TBD - make sure the sender is who we expect it to be??? if (IsServerSocket()) break; if (NORM_OBJECT_INVALID == rx_stream) { // We're expecting this, new stream ready for reading ... InitRxStream(event.object); socketEvent.type = NORM_SOCKET_READ; } else { // Stream reset fprintf(stderr, "NormSocket::GetSocketEvent(NORM_RX_OBJECT_NEW) warning: client stream reset?!\n"); } break; default: // CONNECTING, ACCEPTING, CLOSING, CLOSED // shouldn't happen break; } break; } case NORM_RX_OBJECT_UPDATED: { switch (socket_state) { case CONNECTED: // TBD - use an rx_ready indication to filter this event a little more if (IsServerSocket()) break; // we don't receive data on server socket if (event.object == rx_stream) socketEvent.type = NORM_SOCKET_READ; else fprintf(stderr, "NormSocket::GetSocketEvent(NORM_RX_OBJECT_UPDATED) warning: non-matching rx object\n"); break; default: // shouldn't happen break; } break; } case NORM_RX_OBJECT_ABORTED: case NORM_RX_OBJECT_COMPLETED: { if (event.object != rx_stream) break; // not our stream, so ignore rx_stream = NORM_OBJECT_INVALID; switch (socket_state) { case CONNECTED: // Initiate graceful closure of our tx_stream to allow at least some time to // acknowledge the remote before closing everything down if (NORM_OBJECT_INVALID != tx_stream) { NormStreamClose(tx_stream, true); // Note our "trick" here to do a graceful close, _then_ watermark to get ack NormSetWatermark(norm_session, tx_stream, true); // future NORM API will add "bool watermark" option to graceful close socket_state = CLOSING; } else { // This still allows at least a chance of an ACK to be sent upon completion NormSetUserTimer(norm_session, 0.0); } socketEvent.type = NORM_SOCKET_CLOSING; break; case CLOSING: // We're already closing, so just let that complete. This helps make sure we allow // at least some time to acknowledge the remote before closing everything down break; default: // shouldn't happen break; } break; } default: break; } //fprintf(stderr, "NormSocket::GetSocketEvent() returning NormSocket event type:%d session:%p\n", socketEvent.type, event.session); } // end NormSocket::GetSocketEvent() void NormSocket::SetTrace(bool state) { if (NORM_SESSION_INVALID != norm_session) NormSetMessageTrace(norm_session, state); if (NORM_SESSION_INVALID != mcast_session) NormSetMessageTrace(mcast_session, state); } // end NormSocket::SetTrace() /////////////////////////////////////////////////////////////////////////////////// // NormSocket API implementation NormSocketHandle NormOpen(NormInstanceHandle instance) { NormSocket* normSocket = new NormSocket(); if (NULL == normSocket) { perror("NormOpen() new NormSocket() error"); return NORM_SOCKET_INVALID; } else if (normSocket->Open(instance)) { return (NormSocketHandle)normSocket; } else { perror("NormOpen() error"); delete normSocket; return NORM_SOCKET_INVALID; } } // end NormOpen() // TBD - provide options for binding to a specific local address, interface, etc bool NormListen(NormSocketHandle normSocket, UINT16 serverPort, const char* groupAddr, const char* serverAddr) { // TBD - make sure normSocket is valid NormSocket* s = (NormSocket*)normSocket; return s->Listen(serverPort, groupAddr, serverAddr); } // end NormListen() NormSocketHandle NormAccept(NormSocketHandle serverSocket, NormNodeHandle client, NormInstanceHandle instance) { // TBD - if another instance handle is provided use that instead // TBD - VALIDATE PARAMETERS AND ERROR CHECK ALL THE API CALLS MADE HERE !!!!! NormSocket* s = (NormSocket*)serverSocket; NormInstanceHandle serverInstance = s->GetInstance(); NormSuspendInstance(serverInstance); NormSocketHandle clientSocket = s->Accept(client, instance); NormResumeInstance(serverInstance); return clientSocket; } // end NormAccept() // TBD - provide options for binding to a specific local address, interface, etc bool NormConnect(NormSocketHandle normSocket, const char* serverAddr, UINT16 serverPort, UINT16 localPort, const char* groupAddr, NormNodeId clientId) { // TBD - make sure normSocket is valid NormSocket* s = (NormSocket*)normSocket; NormInstanceHandle instance = s->GetInstance(); NormSuspendInstance(instance); bool result = s->Connect(serverAddr, serverPort, localPort, groupAddr, clientId); NormResumeInstance(instance); return result; } // end NormConnect() ssize_t NormWrite(NormSocketHandle normSocket, const void *buf, size_t nbyte) { // TBD - we could make write() and read() optionally blocking or non-blocking // by using GetSocketEvent() as appropriate (incl. returning error conditions, etc) NormSocket* s = (NormSocket*)normSocket; NormInstanceHandle instance = s->GetInstance(); NormSuspendInstance(instance); ssize_t result = (ssize_t)s->Write((const char*)buf, nbyte); NormResumeInstance(instance); return result; } // end NormWrite() int NormFlush(NormSocketHandle normSocket) { NormSocket* s = (NormSocket*)normSocket; NormInstanceHandle instance = s->GetInstance(); NormSuspendInstance(instance); s->Flush(); NormResumeInstance(instance); return 0; } // end NormFlush() ssize_t NormRead(NormSocketHandle normSocket, void *buf, size_t nbyte) { // TBD - we could make write() and read() optionally blocking or non-blocking // by using GetSocketEvent() as appropriate (incl. returning error conditions, etc) NormSocket* s = (NormSocket*)normSocket; NormInstanceHandle instance = s->GetInstance(); NormSuspendInstance(instance); // TBD - make sure s->rx_stream is valid unsigned int numBytes = nbyte; ssize_t result; if (s->Read((char*)buf, numBytes)) result = numBytes; else result = -1; // broken stream error (TBD - enumerate socket error values) NormResumeInstance(instance); return result; } // end NormWrite() void NormShutdown(NormSocketHandle normSocket) { NormSocket* s = (NormSocket*)normSocket; NormInstanceHandle instance = s->GetInstance(); NormSuspendInstance(instance); s->Shutdown(); NormResumeInstance(instance); } // end NormShutdown() void NormClose(NormSocketHandle normSocket) { NormSocket* s = (NormSocket*)normSocket; NormInstanceHandle instance = s->GetInstance(); NormSuspendInstance(instance); s->Close(); NormResumeInstance(instance); delete s; } // end NormClose() void NormSetSocketUserData(NormSocketHandle normSocket, const void* userData) { if (NORM_SOCKET_INVALID != normSocket) ((NormSocket*)normSocket)->SetUserData(userData); } // end NormSetSocketUserData() const void* NormGetSocketUserData(NormSocketHandle normSocket) { NormSocket* s = (NormSocket*)normSocket; return s->GetUserData(); } // end NormGetSocketUserData() // This gets and translates low level NORM API events to NormSocket events // given the "normSocket" state bool NormGetSocketEvent(NormInstanceHandle instance, NormSocketEvent* socketEvent, bool waitForEvent) { if (NULL == socketEvent) return false; NormEvent event; if (NormGetNextEvent(instance, &event, waitForEvent)) { NormSuspendInstance(instance); NormSocket* normSocket = NULL; if (NORM_SESSION_INVALID != event.session) normSocket = (NormSocket*)NormGetUserData(event.session); if (NULL == normSocket) { socketEvent->type = NORM_SOCKET_NONE; socketEvent->socket = NORM_SOCKET_INVALID; socketEvent->event = event; } else { normSocket->GetSocketEvent(event, *socketEvent); } NormResumeInstance(instance); return true; } else { return false; } } // end NormGetSocketEvent() // Other helper functions void NormGetPeerName(NormSocketHandle normSocket, char* addr, unsigned int* addrLen, UINT16* port) { NormSocket* s = (NormSocket*)normSocket; s->GetPeerName(addr, addrLen, port); } // end NormGetPeerName() NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket) { NormSocket* s = (NormSocket*)normSocket; return s->GetSession(); } // end NormGetSocketSession() NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket) { NormSocket* s = (NormSocket*)normSocket; return s->GetMulticastSession(); } // end NormGetSocketMulticastSession() void NormSetSocketTrace(NormSocketHandle normSocket, bool enable) { NormSocket* s = (NormSocket*)normSocket; s->SetTrace(enable); } norm-1.5.8+dfsg2/examples/normSocket.h0000644000000000000000000001324213274125525014512 0ustar #ifndef _NORM_SOCKET #define _NORM_SOCKET // IMPORTANT NOTE: THIS IS A WORK IN PROGRESS. This code, if/when fully developed, will be // "promoted" from the 'examples' directory to a standard part of the NORM // library if appropriate. // This provides a higher level API that facilitates a socket-like programming interface // to use NORM for a specific usage pattern. The usage pattern uses NORM_OBJECT_STREAM // (as a byte-stream initially with eventual support for NORM's message-stream capability, too) // where "clients" explicitly connect to a "server" and bi-directional stream communication is // established. This enables ACK-based flow control to/from the server and client(s). This // is supported for NORM unicast and also (as this is completed) an asymmetric model where the // server can multicast to the clients while the clients unicast back to the server. // TODO: // // 0) Make "NormInstanceHandle" optional for Listen/Connect/Accept // (for eventual blocking usage, it wouldn't be needed) // 1) Support asymmetric server->multicast, client->unicast model (DONE) // 2) Provide non-blocking option for read/write calls // 3) leverage ICMP (e.g., port unreachable) feedback to detect connect() failure (DONE) // 4) provide means for connect() to time out??? (DONE) // 5) Separate socket open (i.e. session creation) from connect/accept to allow // opportunity for application to set NORM parameters prior to sender/receiver start // 6) Extend to include message stream, and data/file object sockets // 7) Option to associate NORM_INFO w/ stream (or objects eventually) // Here is a list of NORM parameters that need to be set _before_ sender or receiver // startup. These will need to be "NormSocket" parameters that can be set after // NormOpen() but before NormListen(), NormAccept(), or NormConnect(): // // a) SSM source address (perhaps incorporate into NormListen() and NormConnect()?) // b) TTL (could be set _after_ connect/accept, but may be something convenient to preset? // c) TOS (same as for TTL) // d) Fragmentation (not one to worry much about initially?) // e) FEC parameters (block size, parity count, segment size, "auto" parity) // f) Buffer size (sender, stream, receiver) // g) cache bounds / limits #ifdef WIN32 #include // for SSIZE_T typedef SSIZE_T ssize_t; #endif // WIN32 #include "normApi.h" typedef const void* NormSocketHandle; extern const NormSocketHandle NORM_SOCKET_INVALID; extern const double NORM_DEFAULT_CONNECT_TIMEOUT; #ifndef NULL #define NULL 0 #endif // !NULL // Main NormSocket API Functions NormSocketHandle NormOpen(NormInstanceHandle instance); bool NormListen(NormSocketHandle normSocket, UINT16 serverPort, const char* groupAddr = NULL, const char* serverAddr = NULL); bool NormConnect(NormSocketHandle normSocket, const char* serverAddr, UINT16 serverPort, UINT16 localPort = 0, const char* groupAddr = NULL, NormNodeId clientId = NORM_NODE_ANY); NormSocketHandle NormAccept(NormSocketHandle serverSocket, NormNodeHandle clientNode, NormInstanceHandle instance = NORM_INSTANCE_INVALID); void NormShutdown(NormSocketHandle normSocket); void NormClose(NormSocketHandle normSocket); ssize_t NormRead(NormSocketHandle normSocket, void* buf, size_t nbyte); ssize_t NormWrite(NormSocketHandle normSocket, const void* buf, size_t nbyte); int NormFlush(NormSocketHandle normSocket); // NormSocket helper functions void NormSetSocketUserData(NormSocketHandle normSocket, const void* userData); const void* NormGetSocketUserData(NormSocketHandle normSocket); NormInstanceHandle NormGetSocketInstance(NormSocketHandle normSocket); NormSessionHandle NormGetSocketSession(NormSocketHandle normSocket); NormSessionHandle NormGetSocketMulticastSession(NormSocketHandle normSocket); void NormGetPeerName(NormSocketHandle normSocket, char* addr, unsigned int* addrLen, UINT16* port); void NormSetSocketTrace(NormSocketHandle normSocket, bool enable); typedef enum NormSocketEventType { NORM_SOCKET_NONE = 0, // applications should generally ignore these NORM_SOCKET_ACCEPT, // only issued for listening server sockets NORM_SOCKET_CONNECT, // notification confirming connection to server NORM_SOCKET_READ, // edge-triggered notification that socket is ready for reading NORM_SOCKET_WRITE, // edge-triggered notification that socket is ready for writing NORM_SOCKET_CLOSING, // indicates remote endpoint is closing socket (only read data at this point) NORM_SOCKET_CLOSE // indicates socket is now closed (invalid for further operations) } NormSocketEventType; typedef struct { NormSocketEventType type; NormSocketHandle socket; // The underlying NormEvent is embedded. The union // here lets us access the NormEvent fields directly. // (E.g., *.sender, *.object, etc. as needed) union { NormEvent event; // underlying NormEvent that evoked this socketEvent struct { NormEventType etype; // underlying NormEventType NormSessionHandle session; // NormEvent session NormNodeHandle sender; // NormEvent sender NormObjectHandle object; // NormEvent object }; }; } NormSocketEvent; bool NormGetSocketEvent(NormInstanceHandle normInstance, NormSocketEvent* event, bool waitForEvent = true); #endif // !_NORM_SOCKET norm-1.5.8+dfsg2/examples/normSocketNotes.txt0000644000000000000000000001564713142742165016125 0ustar NormSocket API Extension Notes The NormSocket API (currently defined in examples/normSocket.h) is an in-development extension to the base (low-level) NORM API (defined in include/normApi.h) that provides a more familiar (socket-like), easier-to-use API for some specific NORM use patterns. The use patterns supported here are those of a client-server paradigm where "clients" have individual, reliable connections to the server and the "server" can have either a one-to-many multicast connection or individual unicast connections to the set of clients. The paradigm follows a connection-oriented socket model where the server "listens" for incoming connections initiated by clients. The low-level NORM API is used to establish multiple NORM sessions as needed to support the necessary data exhange relationships. Since this is a connection-oriented model, explicit ACK-based flow control used for both client-to-server and server-to-client(s) data transfers. This is a more controlled model of NORM use as compared to the looser "connection-free" model of operation NORM use has typically observed. The NormSocket API code makes careful use of operating system socket-binding to enable port reuse and simpler session establishment where clients can "connect" to the server listening on a well-known port as compared to typical base NORM API use where participants can exchange data on a a priori known common port number (and group address if multicast). However, the clients do need to know the unicast address of the server and the paradigm is somewhat that of Single-Source Multicast (SSM). Client application can, of course, using multiple NormSocket instances connect to multiple multicast (or unicast) servers.. THere A server application can use the NormListen() call to establish a session that listens for incoming connection requests, Client applications can use the NormConnect() call to initiate a connection to a listening server. In response, the server application can use NormAccept() to establish connections with the clients. At the moment a NormGetSocketEvent() (analogous to the NormGetNextEvent() call in the base NORM API) can be used to provide cues to changes in NormSocket state (notification of incoming connections, connection establishment, read/write readiness, etc.). A descriptor is provided for asynchronous I/O notification of pending events. At the moment, the default behavior is a single NormInstance, and hence a single descriptor, can be used for multiple NormSockets, but it is possible to call NormCreateInstance() and associate a separate NormInstance (and hence separate descriptor) with each NormSocket that is listending, connected or accepted if desired. As the NormSocket API extension matures, more examples and documentation will be provided as well as incorporating it (possibly directly) into the "normApi.h" header file and NORM library. At the moment, "examples/normClient.cpp" and "examples/normServer.cpp" illustrate (and test) basic usage of the API. The "normServer" can be run as a unicast server using the syntax: ./normServer listen or a multicast server using the syntax: ./normServer listen / Corresponding "normClient" instances can connect to unicast server using the syntax: ./normClient connect / or to a multicast server using the syntax: ./normClient connect /, There are some additional command-line options shared by these examples such as "trace" to enable NORM's message trace output and "debug " to invoke different levels of debug output. Note that an option to specify the multicast interface is planned but not yet implemented in these examples. Similarly, an option to set a specific unicast server binding will also be provided. TODO (not in priority order): 1) When client initiates connection and server-listener receives NORM_CMD(CC), add code to directly "inject" the NORM_CMD(CC) into the newly created server-side client session such that NORM_ACK is immediately sent. This will give client a more immediate RTT measurement, etc. 2) Add options to set transmit rate, congestion control, etc options via NormSocketHandle (current code works at default tx rate of 64 kbps) 3) The server-listener session should be modified so NORM_DATA messages are ignored. Also, NormSetServerListener() could also set the session a silent receiver, too? 4) Add support for additional transport modes in addition to current byte stream: ` 1) Message stream 2) NORM_OBJECT_DATA (w/ data copy option?) 3) NORM_OBJECT_FILE 5) Add option to specify multicast "interface" and use in examples. 6) Enable setting a specific unicast server binding address. =========================================================================== MISC. DEVELOPMENT NOTES // Notional program outline // (optional mcastAddr iff asymm multicast/unicast (i.e. SSM)) normSocket = NormListen(port, [mcastAddr]) _or_ normSocket = NormConnect(addr, port, [mcastAddr]) while NormGetSocketEvent(normSocket) { switch (event.GetType()) NORM_ACCEPT: clientSocket = NormAccept(normSocket, client, [instance]); // rx-only for asymm mcast case NORM_CONNECTED: // in response to NormConnect when "server" is detected (NEW_REMOTE_SENDER) NORM_TX_READY: upon QUEUE_VACANCY, etc ... socket _might_ be write() ready NORM_RX_READY: upon RX_OBJECT_NEW, RX_OBJECT_UPDATE ... socket _might_ be read() ready NORM_CLOSING: ??? upon stream end received from remote sender NORM_CLOSED: ??? upon stream end _and_ ack to our stream end } *** Server listen on a port (optional mcast address): - Create NormSession that receive-only on given port (if it's asymm mcast, then sender enabled, too) - For each client (detected via NEW_REMOTE_SENDER yielding a NormSocket::NORM_ACCEPT event) Create tightly binded session for rx (and tx if unicast) ... this will fail if binding already exists *** Client connect - Create single socket (common ephemeral tx/rx port) NormSession for server destination addr/port. - Call NormStartSender() to initiate probing of server - NORM_CONNECTED upon NEW_REMOTE_SENDER (from server) ??? QUESTIONS: 1) How does a server reject a connection request? (for now, just ignore) 2) How is a "connection" gracefully terminated? (NormShutdown() vs. NormClose()?) NormClose(graceful = false) ... a) stop sender/receiver, destroy everything NormShutdown(graceful = true) ... a) close stream (gracefully, w/ ack request) b) upon ack receipt (or timeout) _and_ rx stream end, destroy everything Upon receipt of rx stream end, close tx stream gracefully ... initiator -> stream end; upon ack set tx_stream = NULL and wait for rx_stream end receptor -> upon rx_stream end, initiate tx_stream shutdown and wait for ack norm-1.5.8+dfsg2/examples/normStreamRecv.cpp0000644000000000000000000002371712304404061015664 0ustar /****************************************************************************** Simple NORM_OBJECT_STREAM receiver example app using the NORM API (expects NORM message stream of text messages with 2-byte length header (network byte order)) USAGE: normStreamRecv BUILD (Unix): g++ -o normStreamRecv normStreamRecv.cpp -D_FILE_OFFSET_BITS=64 -I../include/ \ ./lib/libnorm.a ../protolib/lib/libProtokit.a -lpthread (for MacOS/BSD, add "-lresolv") (for Solaris, add "-lnsl -lsocket -lresolv") ******************************************************************************/ // Notes: // 1) The program also will exit on from user // 2) "normStreamRecv" should be started before "normStreamSend" but can join stream in progress. // 3) This example is designed to receive a single stream from a single sender (could be modified // to support multiple streams and/or senders) #include "normApi.h" // for NORM API #include // for printf(), etc #include // for srand() #include // for strrchr() #include // for gettimeofday() #include // for ntohs() int main(int argc, char* argv[]) { // 0) Some default params const unsigned int MSG_LENGTH_MAX = 5000; // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); // 2) Create a NormSession using default "automatic" local node id NormSessionHandle session = NormCreateSession(instance, "224.1.2.3", 6003, NORM_NODE_ANY); // NOTE: These are debugging routines available // (not necessary for normal app use) // (Need to include "protolib/common/protoDebug.h" for this NormSetDebugLevel(3); // Uncomment to turn on debug NORM message tracing NormSetMessageTrace(session, true); // Uncomment to write debug output to file "normLog.txt" //NormOpenDebugLog(instance, "normLog.txt"); // Uncomment to turn on some random packet loss for testing //NormSetRxLoss(session, 10.0); // 10% packet loss struct timeval currentTime; gettimeofday(¤tTime, NULL); // Uncomment to get different packet loss patterns from run to run srand(currentTime.tv_sec); // seed random number generator // Uncomment to enable rx port reuse (this plus unique NormNodeId's enables same-machine send/recv) NormSetRxPortReuse(session, true); // 3) Start the receiver with 1 Mbyte buffer per sender NormStartReceiver(session, 8*1024*1024); NormSetSilentReceiver(session, true); if (!NormSetRxSocketBuffer(session, 8*1024*1024)) perror("normStreamRecv error: unable to set requested socket buffer size"); // We use these variables to keep track of our recv stream // and to buffer reading from the recv stream NormObjectHandle stream = NORM_OBJECT_INVALID; // we use this to make sure we're handling the correct (only) stream bool msgSync = false; char msgBuffer[MSG_LENGTH_MAX]; UINT16 msgLen = 0; UINT16 msgIndex = 0; // 4) Enter NORM event loop bool keepGoing = true; while (keepGoing) { NormEvent theEvent; if (!NormGetNextEvent(instance, &theEvent)) continue; switch (theEvent.type) { case NORM_RX_OBJECT_NEW: fprintf(stderr, "normStreamRecv: NORM_RX_OBJECT_NEW event ...\n"); if (NORM_OBJECT_INVALID == stream) { if (NORM_OBJECT_STREAM == NormObjectGetType(theEvent.object)) { stream = theEvent.object; msgLen = msgIndex = 0; // init stream reading state msgSync = false; } else { fprintf(stderr, "normStreamRecv error: received NORM_RX_OBJECT_NEW for non-stream object?!\n"); } } else { fprintf(stderr, "normStreamRecv error: received NORM_RX_OBJECT_NEW while already receiving stream?!\n"); } break; case NORM_RX_OBJECT_INFO: { // Assume info contains NULL-terminated string //fprintf(stderr, "normStreamRecv: NORM_RX_OBJECT_INFO event ...\n"); if (theEvent.object != stream) { fprintf(stderr, "normStreamRecv error: received NORM_RX_OBJECT_UPDATED for unhandled object?!\n"); break; } char streamInfo[8192]; unsigned int infoLen = NormObjectGetInfo(theEvent.object, streamInfo, 8191); streamInfo[infoLen] = '\0'; fprintf(stderr, "normStreamRecv: NORM_RX_OBJECT_INFO event, info = \"%s\"\n", streamInfo); break; } case NORM_RX_OBJECT_UPDATED: { //fprintf(stderr, "normStreamRecv: NORM_RX_OBJECT_UPDATED event ...\n"); if (theEvent.object != stream) { fprintf(stderr, "normStreamRecv error: received NORM_RX_OBJECT_UPDATED for unhandled object?!\n"); break; } while (1) { // If we're not "in sync", seek message start if (!msgSync) { msgSync = NormStreamSeekMsgStart(stream); if (!msgSync) break; // wait for next NORM_RX_OBJECT_UPDATED to re-sync } if (msgIndex < 2) { // We still need to read the 2-byte message header for the next message unsigned int numBytes = 2 - msgIndex; if (!NormStreamRead(stream, msgBuffer+msgIndex, &numBytes)) { fprintf(stderr, "normStreamRecv error: broken stream detected, re-syncing ...\n"); msgLen = msgIndex = 0; msgSync = false; continue; // try to re-sync and read again } msgIndex += numBytes; if (msgIndex < 2) break; // wait for next NORM_RX_OBJECT_UPDATED to read more memcpy(&msgLen, msgBuffer, 2); msgLen = ntohs(msgLen); if ((msgLen < 2) || (msgLen > MSG_LENGTH_MAX)) { fprintf(stderr, "normStreamRecv error: message received with invalid length?!\n"); msgLen = msgIndex = 0; msgSync = false; continue; // try to re-sync and read again } } // Read "content" portion of message (note "msgIndex" accounts for length "header" unsigned int numBytes = msgLen - msgIndex; if (!NormStreamRead(stream, msgBuffer+msgIndex, &numBytes)) { fprintf(stderr, "normStreamRecv error: broken stream detected, re-syncing ...\n"); msgLen = msgIndex = 0; msgSync = false; continue; // try to re-sync and read again } fprintf(stderr, "read %u bytes from stream ...\n", numBytes); msgIndex += numBytes; if (msgIndex == msgLen) { // Complete message read fprintf(stderr, "normStreamRecv msg: %s\n", msgBuffer+2); msgLen = msgIndex = 0; // reset state variables for next message } else { break; // wait for next NORM_RX_OBJECT_UPDATED to read more } } // end while(1) (NormStreamRead() loop) break; } case NORM_RX_OBJECT_COMPLETED: { fprintf(stderr, "normStreamRecv: NORM_RX_OBJECT_COMPLETED event ...\n"); if (stream == theEvent.object) { fprintf(stderr, "normStreamRecv: current stream completed ...\n"); stream = NORM_OBJECT_INVALID; } break; } case NORM_RX_OBJECT_ABORTED: fprintf(stderr, "normStreamRecv: NORM_RX_OBJECT_ABORTED event ...\n"); if (stream == theEvent.object) { fprintf(stderr, "normStreamRecv error: current stream aborted ...\n"); stream = NORM_OBJECT_INVALID; } break; case NORM_REMOTE_SENDER_NEW: fprintf(stderr, "normStreamRecv: NORM_REMOTE_SENDER_NEW event ...\n"); break; case NORM_REMOTE_SENDER_ACTIVE: fprintf(stderr, "normStreamRecv: NORM_REMOTE_SENDER_ACTIVE event ...\n"); break; case NORM_REMOTE_SENDER_INACTIVE: fprintf(stderr, "normStreamRecv: NORM_REMOTE_SENDER_INACTIVE event ...\n"); break; case NORM_GRTT_UPDATED: fprintf(stderr, "normStreamRecv: NORM_GRTT_UPDATED event ...\n"); break; default: fprintf(stderr, "normStreamRecv: Got event type: %d\n", theEvent.type); } // end switch(theEvent.type) } NormStopReceiver(session); NormDestroySession(session); NormDestroyInstance(instance); fprintf(stderr, "normStreamRecv: Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/normStreamSend.cpp0000644000000000000000000003006212240477051015655 0ustar /****************************************************************************** Simple NORM_OBJECT_STREAM sender example app using the NORM API USAGE: normSendStream BUILD (Unix): g++ -o normStreamSend normStreamSend.cpp -D_FILE_OFFSET_BITS=64 -I../include/ \ ../lib/libnorm.a ../protolib/lib/libProtokit.a -lpthread (for MacOS/BSD, add "-lresolv") (for Solaris, add "-lnsl -lsocket -lresolv") ******************************************************************************/ // Notes: // 1) A series of text messages are sent over a stream #include "normApi.h" // for NORM API #include // for printf(), etc #include // for srand() #include // for strrchr() #include // for gettimeofday() #include // for htons() int main(int argc, char* argv[]) { // 0) Default parameter values const int MSG_COUNT_MAX = 10; const unsigned int MSG_LENGTH_MIN = 40; const unsigned int MSG_LENGTH_MAX = 40; UINT32 streamBufferSize = 4*1024*1024; // 1 Mbyte stream buffer size double normRate = 1.0e+07; // 10 Mbps default NORM tx rate for fixed rate operation (bits/sec units here) double msgRate = -1.0; //1e+06; // 32 kbits/sec default message rate // 1) Create a NORM API "NormInstance" NormInstanceHandle instance = NormCreateInstance(); // 2) Create a NormSession using default "automatic" local node id (based on IP addr) // TBD - add an option to set a specific NormNodeId NormSessionHandle session = NormCreateSession(instance, "224.1.2.3", 6003, 1);//NORM_NODE_ANY); // NOTE: These are some debugging routines available // (not necessary for normal app use) NormSetDebugLevel(3); // Uncomment to turn on debug NORM message tracing NormSetMessageTrace(session, true); // Uncomment to turn on some random packet loss //NormSetTxLoss(session, 25.0); // 25% packet loss for testing purposes struct timeval currentTime; gettimeofday(¤tTime, NULL); // Uncomment to get different packet loss patterns from run to run // (and a different sender sessionId) srand(currentTime.tv_sec); // seed random number generator // 3) Set transmission rate NormSetTxRate(session, normRate); // in bits/second //NormSetFlowControl(session, 0.0); // Init GRTT to low value (3 msec) //NormSetGrttEstimate(session, 1.0e-03); // Disable receiver backoffs (for lower latency, high speed performance) // (For large group sizes, the default backoff factor is RECOMMENDED) NormSetBackoffFactor(session, 2.0); // Uncomment to use a _specific_ transmit port number // (Can be the same as session port (rx port), but this // is _not_ recommended when unicast feedback may be // possible! - must be called _before_ NormStartSender()) //NormSetTxPort(session, 6001); // Uncomment to enable TCP-friendly congestion control //NormSetCongestionControl(session, true); // Uncomment to enable rx port reuse (this plus unique NormNodeId's enables same-machine send/recv) NormSetRxPortReuse(session, true); // 4) Start the sender using a random "sessionId" NormSessionId sessionId = (NormSessionId)rand(); NormStartSender(session, sessionId, 4*1024*1024, 1300, 64, 16); // Uncomment to set large tx socket buffer size // (may be needed to achieve very high packet output rates) //NormSetTxSocketBuffer(session, 512000); // 5) Enqueue the NORM_OBJECT_STREAM object // Provide some "info" about this stream (the info is OPTIONAL) char dataInfo[256]; sprintf(dataInfo, "NORM_OBJECT_STREAM message stream ..."); NormObjectHandle stream = NormStreamOpen(session, streamBufferSize, dataInfo, strlen(dataInfo) + 1); if (NORM_OBJECT_INVALID == stream) { fprintf(stderr, "normStreamSend NormStreamOpen() error!\n"); return -1; } // 6) Write the first stream message // (we enqueue text strings of random length as messages) // ( a 2-byte network byte order length "header" is in each message) unsigned int msgCount = 0; char data = 'a'; char msgData[MSG_LENGTH_MAX]; UINT16 msgLen = MSG_LENGTH_MIN + (rand() % (MSG_LENGTH_MAX - MSG_LENGTH_MIN + 1)); // set 2 byte message header (length in network byte order) UINT16 msgHeader = htons(msgLen); memcpy(msgData, &msgHeader, 2); // 2-byte message length "header" memset(msgData + 2, data, msgLen - 3); // n-byte message content msgData[msgLen - 1] = '\0'; // 1-byte NULL-termination // Write the message (as much as stream buffer will accept) unsigned int bytesWritten = NormStreamWrite(stream, msgData, msgLen); bool vacancy = (bytesWritten == msgLen); // Initialize the "delayTime" used in "select()" loop below // based on whether message was competely written to stream // (i.e. wait according to "msgRate" (configured bytes per second)) double delayTime; if (vacancy) { // Complete message was written, wait msg interval time NormStreamMarkEom(stream); msgCount++; delayTime = (msgRate > 0.0) ? ((double)msgLen / msgRate) : 0.0; } else { // wait indefinitely for NORM_TX_QUEUE_VACANCY event // to finish writing current message to stream delayTime = -1.0; } // 6) We keep a running "timeAccumulator" value to maintain the proper // _average_ message transmission rate. (TBD - impose "max" accumulation limit) double timeAccumulator = 0.0; struct timeval lastTime; gettimeofday(&lastTime, NULL); // 7) We use a "select()" call to wait for NORM events or message interval timeout int normfd = NormGetDescriptor(instance); fd_set fdset; struct timeval timeout; // 6) Enter NORM event loop bool keepGoing = true; while (keepGoing) { FD_SET(normfd, &fdset); struct timeval* timeoutPtr; if (delayTime < 0.0) { timeoutPtr = NULL; // wait indefinitely (i.e. for queue vacancy) } else { if (delayTime > timeAccumulator) delayTime -= timeAccumulator; else delayTime = 0.0; timeout.tv_sec = (unsigned long)delayTime; timeout.tv_usec = (unsigned long)(1.0e+06 * (delayTime - (double)timeout.tv_sec)); timeoutPtr = &timeout; } int result = select(normfd+1, &fdset, NULL, NULL, timeoutPtr); bool keepSending = true; if ((MSG_COUNT_MAX > 0) && (msgCount >= (unsigned int)MSG_COUNT_MAX)) keepSending = false; if (result > 0) { // Get and handle NORM API event NormEvent theEvent; if (NormGetNextEvent(instance, &theEvent)) { switch (theEvent.type) { case NORM_TX_QUEUE_EMPTY: case NORM_TX_QUEUE_VACANCY: { /* if (NORM_TX_QUEUE_VACANCY == theEvent.type) fprintf(stderr, "normStreamSend: NORM_TX_QUEUE_VACANCY event ...\n"); else fprintf(stderr, "normStreamSend: NORM_TX_QUEUE_EMPTY event ...\n"); */ if (keepSending && (bytesWritten < msgLen)) { // Finish writing remaining pending message content (as much as can be written) bytesWritten += NormStreamWrite(stream, msgData + bytesWritten, msgLen - bytesWritten); if (bytesWritten == msgLen) { // Complete message was written, wait msg interval time NormStreamMarkEom(stream); msgCount++; delayTime = (msgRate > 0.0) ? ((double)msgLen / msgRate) : 0.0; vacancy = true; } } break; } case NORM_TX_OBJECT_PURGED: fprintf(stderr, "normStreamSend: NORM_TX_OBJECT_PURGED event ...\n"); break; case NORM_TX_FLUSH_COMPLETED: fprintf(stderr, "normStreamSend: NORM_TX_FLUSH_COMPLETED event ...\n"); break; case NORM_GRTT_UPDATED: fprintf(stderr, "normStreamSend: NORM_GRTT_UPDATED event ...\n"); break; default: fprintf(stderr, "normStreamSend: Got event type: %d\n", theEvent.type); } // end switch(theEvent.type) } // end if (NormGetNextEvent()) } else if (result < 0) { // select() error perror("normStreamSend: select() error"); break; } // This code writes _new_ message(s) to the stream _if_ there is "vacancy" // and it is time based on "msgRate" and how much time has passed since "lastTime" struct timeval currentTime; gettimeofday(¤tTime, NULL); double timeDelta = (double)(currentTime.tv_sec - lastTime.tv_sec); if (currentTime.tv_usec > lastTime.tv_usec) timeDelta += 1.0e-06 * (currentTime.tv_usec - lastTime.tv_usec); else timeDelta -= 1.0e-06 * (lastTime.tv_usec - currentTime.tv_usec); timeAccumulator += timeDelta; while (keepSending && vacancy && (timeAccumulator > delayTime)) { timeAccumulator -= delayTime; // subtract last message tx duration from accumulator // Fill buffer with new message "data" text character (a-z) if (++data > 'z') data = 'a'; msgLen = MSG_LENGTH_MIN + (rand() % (MSG_LENGTH_MAX - MSG_LENGTH_MIN + 1)); // set 2 byte message header (length in network byte order) msgHeader = htons(msgLen); memcpy(msgData, &msgHeader, 2); // 2-byte message length "header" memset(msgData+2, data, msgLen-3); // n-byte message content msgData[msgLen - 1] = '\0'; // 1-byte NULL-termination bytesWritten = NormStreamWrite(stream, msgData, msgLen); if (bytesWritten < msgLen) { // wait indefinitely for NORM_TX_QUEUE_VACANCY event // to finish writing current message to stream vacancy = false; delayTime = -1.0; //fprintf(stderr, "norm tx stream buffer full, time accumulator = %lf\n", timeAccumulator); } else { // Complete message was written, wait msg interval time NormStreamMarkEom(stream); msgCount++; delayTime = (msgRate > 0.0) ? ((double)msgLen / msgRate) : 0.0; if ((MSG_COUNT_MAX > 0) && ((unsigned int)msgCount >= MSG_COUNT_MAX)) { fprintf(stderr, "closing stream after %u messages ...\n", msgCount); NormStreamClose(stream, true); // gracefully close stream keepSending = false; } } } if (timeAccumulator <= delayTime) { delayTime -= timeAccumulator; timeAccumulator = 0.0; } lastTime = currentTime; } // end while (keepGoing) NormStopSender(session); NormDestroySession(session); NormDestroyInstance(instance); fprintf(stderr, "normDataSend: Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/normStreamer.cpp0000644000000000000000000023563613275210135015405 0ustar #include "normApi.h" #include "protoSocket.h" #include // for printf(), etc #include // for srand() #include // for strrchr(), memset(), etc #include // for gettimeofday() #include // for htons() #include // for, well, fnctl() #include // obvious child #include // embarrassingly obvious #include // Memory Lock. #include // Adjust scheduler (linux) #include // for setpriority() stuff #ifdef LINUX #include #endif // LINUX const unsigned int LOOP_MAX = 100; // Setting SHOOT_FIRST to non-zero means that an ACK request // will be used to advance the acking "watermark" point // with each message fully written to the transmit stream. // The alternative "ack later" behavior waits to send a new // ACK request until any pending flow control ACK requeset // has completed. This latter approach favors throughput // over timeliness of message delivery. I.e., lower data // rate applications that are concerned with low-latency message // delivery can potentially benefit from the "shoot first" // behavior while very high throughput applications that want // to "keep the pipe full as possible" can benefit from the // "ack later" behavior. The difference between these behaviors, // since ACK requests are cued for all messages when flow // control is _not_ pending, is somewhat subtle and developers // may want to assess both behaviors for their application. // Additionally, limiting ACK request to flow control only is // another possible approach as well as dynamically updating // something like the "tx_stream_buffer_count" with each // message ACK request initiated could be possible. The caution // with the SHOOT_FIRST type strategies and high throughput is // the application may end up "chasing" the ACK request until // flow control buffer limits are reached and end up with // "dead air" time. There are always tradeoffs! #define SHOOT_FIRST 0 class NormStreamer { public: NormStreamer(); ~NormStreamer(); // some day build these directly into NORM API enum CCMode {NORM_FIXED, NORM_CC, NORM_CCE, NORM_CCL}; enum { MSG_HEADER_SIZE = 2, // Big Endian message length header size MSG_SIZE_MAX = 65535 // (including length header) }; void SetOutputFile(FILE* filePtr) { output_file = filePtr; output_fd = fileno(filePtr); } void SetLoopback(bool state) { loopback = state; if (NORM_SESSION_INVALID != norm_session) NormSetMulticastLoopback(norm_session, state); } bool EnableUdpRelay(const char* relayAddr, unsigned short relayPort); bool EnableUdpListener(unsigned short thePort, const char* groupAddr, const char * interfaceName); bool UdpListenerEnabled() const {return input_socket.IsOpen();} bool UdpRelayEnabled() const {return output_socket.IsOpen();} int GetInputDescriptor() const {return (input_socket.IsOpen() ? input_socket.GetHandle() : fileno(input_file));} int GetOutputDescriptor() const {return (output_socket.IsOpen() ? output_socket.GetHandle() : fileno(output_file));} bool OpenNormSession(NormInstanceHandle instance, const char* addr, unsigned short port, NormNodeId nodeId); void CloseNormSession(); void SetNormCongestionControl(CCMode ccMode); void SetFlushMode(NormFlushMode flushMode) {flush_mode = flushMode;} void SetNormTxRate(double bitsPerSecond) { assert(NORM_SESSION_INVALID != norm_session); NormSetTxRate(norm_session, bitsPerSecond); } void SetNormMulticastInterface(const char* ifaceName) { assert(NORM_SESSION_INVALID != norm_session); NormSetMulticastInterface(norm_session, ifaceName); } void SetNormMessageTrace(bool state) { assert(NORM_SESSION_INVALID != norm_session); NormSetMessageTrace(norm_session, state); } void AddAckingNode(NormNodeId ackId) { assert(NORM_SESSION_INVALID != norm_session); NormAddAckingNode(norm_session, ackId); norm_acking = true; // invoke ack-based flow control } bool Start(bool sender, bool receiver); void Stop() {is_running = false;} bool IsRunning() const {return is_running;} void HandleNormEvent(const NormEvent& event); // Sender methods int GetInputFile() const {return input_fd;} void SetInputReady() {input_ready = true;} bool InputReady() const {return input_ready;} bool InputNeeded() const {return input_needed;} void ReadInput(); void ReadInputSocket(); bool TxPending() const {return (!input_needed && (input_index < input_msg_length));} bool TxReady() const {return (tx_ready && (!norm_acking || (tx_stream_buffer_count < tx_stream_buffer_max)));} void SendData(); unsigned int WriteToStream(const char* buffer, unsigned int numBytes); void FlushStream(bool eom, NormFlushMode flushMode); // Receiver methods bool RxNeeded() const {return rx_needed;} bool RxReady() const {return rx_ready;} void RecvData(); int GetOutputFile() const {return output_fd;} void SetOutputReady() {output_ready = true;} bool OutputReady() const {return output_ready;} bool OutputPending() const {return (!rx_needed && (output_index < output_msg_length));} void SetOutputBucketRate(double bitsPerSecond) { output_bucket_rate = bitsPerSecond / 8.0; // convert to bytes per second output_bucket_interval = 1.0 / output_bucket_rate; } void SetOutputBucketDepth(unsigned int numBytes) {output_bucket_depth = numBytes;} unsigned int GetOutputBucketDepth() const {return output_bucket_depth;} double GetOutputBucketTimeout() const { if (0 != output_bucket_depth) { if (OutputPending()) { unsigned int pendingBytes = output_msg_length - output_index; if (pendingBytes > output_bucket_count) { return ((double)(pendingBytes - output_bucket_count)) * output_bucket_interval; } else { return 0.0; } } else { return -1.0; } } else { return 0.0; } } double GetOutputBucketFillTime() const { return (output_bucket_count < output_bucket_depth) ? ((double)(output_bucket_depth - output_bucket_count)) * output_bucket_interval : 0.0; } bool OutputBucketReady() const { if (0 != output_bucket_depth) { unsigned int pendingBytes = output_msg_length - output_index; return (output_bucket_count >= pendingBytes); } else { return true; } } void CreditOutputBucket(double interval) { if (0 != output_bucket_depth) { output_bucket_count += interval * output_bucket_rate; if (output_bucket_count > output_bucket_depth) output_bucket_count = output_bucket_depth; } } void WriteOutput(); void WriteOutputSocket(); void OmitHeader(bool state) {omit_header = state;} unsigned long GetInputByteCount() const {return input_byte_count;} unsigned long GetTxByteCount() const {return tx_byte_count;} // These can only be called post-OpenNormSession() void SetSilentReceiver(bool state) {NormSetSilentReceiver(norm_session, true);} void SetTxLoss(double txloss) {NormSetTxLoss(norm_session, txloss);} // Set the scheduler for running the app and norm threads. static bool BoostPriority(); void SetSegmentSize(unsigned short segmentSize) {segment_size = segmentSize;} void SetBlockSize(unsigned short blockSize) {block_size = blockSize;} void SetNumParity(unsigned short numParity) {num_parity = numParity;} void SetAutoParity(unsigned short autoParity) {auto_parity = autoParity;} void SetStreamBufferSize(unsigned int value) {stream_buffer_size = value;} void SetTxSocketBufferSize(unsigned int value) {tx_socket_buffer_size = value;} void SetRxSocketBufferSize(unsigned int value) {rx_socket_buffer_size = value;} void SetInputSocketBufferSize(unsigned int value) {input_socket_buffer_size = value;} void SetOutputSocketBufferSize(unsigned int value) {output_socket_buffer_size = value;} // Check that sequence numbers increase by one each time. // Assumes that sequence number is 8- or 4-byte network-order first 8 bytes of buffer. void CheckSequenceNumber(const char* buffer, const char* source); void CheckSequenceNumber64(const char* buffer, const char* source); void CheckSequenceNumber32(const char* buffer, const char* source); void SetCheckSequence(unsigned int value) // 64 or 32 {check_sequence = value;} private: NormSessionHandle norm_session; bool is_multicast; bool loopback; bool is_running; // State variables for reading input messages for transmission ProtoSocket input_socket; // optional UDP socket to "listen" FILE* input_file; int input_fd; // stdin by default bool input_ready; bool input_needed; char input_buffer[MSG_SIZE_MAX]; unsigned int input_msg_length; unsigned int input_index; NormObjectHandle tx_stream; bool tx_ready; unsigned int tx_stream_buffer_max; unsigned int tx_stream_buffer_threshold; // flow control threshold unsigned int tx_stream_buffer_count; unsigned int tx_stream_bytes_remain; bool tx_watermark_pending; bool norm_acking; bool tx_ack_pending; NormFlushMode flush_mode; // TBD - allow for "none", "passive", "active" options // Receive stream and state variables for writing received messages to output NormObjectHandle rx_stream; bool rx_ready; bool rx_needed; bool msg_sync; double output_bucket_rate; // bytes per second double output_bucket_interval; // seconds per byte unsigned int output_bucket_depth; // bytes unsigned int output_bucket_count; // bytes ProtoSocket output_socket; // optional UDP socket for recv msg output ProtoAddress relay_addr; // dest addr for recv msg relay FILE* output_file; int output_fd; // stdout by default bool output_ready; char output_buffer[MSG_SIZE_MAX]; unsigned int output_msg_length; unsigned int output_index; // These are some options mainly for testing purposes bool omit_header; // if "true", receive message length header is _not_ written to output //bool rx_silent; //double tx_loss; unsigned long input_byte_count; unsigned long tx_byte_count; unsigned short segment_size; unsigned short block_size; unsigned short num_parity; unsigned short auto_parity; unsigned long stream_buffer_size; unsigned int tx_socket_buffer_size; unsigned int rx_socket_buffer_size; unsigned int input_socket_buffer_size; unsigned int output_socket_buffer_size; unsigned int check_sequence; uint64_t sequence_prev; }; // end class NormStreamer NormStreamer::NormStreamer() : norm_session(NORM_SESSION_INVALID), is_multicast(false), loopback(false), is_running(false), input_socket(ProtoSocket::UDP), input_file(stdin), input_fd(fileno(stdin)), input_ready(true), input_needed(false), input_msg_length(0), input_index(0), tx_stream (NORM_OBJECT_INVALID), tx_ready(true), tx_stream_buffer_max(0), tx_stream_buffer_count(0), tx_stream_bytes_remain(0), tx_watermark_pending(false), norm_acking(false), tx_ack_pending(false), flush_mode(NORM_FLUSH_ACTIVE), rx_stream(NORM_OBJECT_INVALID), rx_ready(false), rx_needed(false), msg_sync(false), output_bucket_rate(0.0), output_bucket_interval(0.0), output_bucket_depth(0), output_bucket_count(0), output_socket(ProtoSocket::UDP), output_file(stdout), output_fd(fileno(stdout)), output_ready(true), output_msg_length(0), output_index(0), omit_header(false), input_byte_count(0), tx_byte_count(0), segment_size(1398), block_size(64), num_parity(0), auto_parity(0), stream_buffer_size(2*1024*1024), tx_socket_buffer_size(0), rx_socket_buffer_size(0), input_socket_buffer_size(0), output_socket_buffer_size(0), check_sequence(0), sequence_prev(0) { } NormStreamer::~NormStreamer() { } bool NormStreamer::BoostPriority() { #ifdef LINUX pid_t this_process = getpid() ; int policy = SCHED_FIFO ; int max_priority = sched_get_priority_max(policy) ; struct sched_param schedule_parameters ; memset((void*)&schedule_parameters, 0, sizeof(schedule_parameters)) ; schedule_parameters.sched_priority = max_priority ; int status = sched_setscheduler(this_process, policy, &schedule_parameters) ; if (0 != status) { fprintf(stderr, "%s:=>sched_setscheduler failed (%d), %s\n", __PRETTY_FUNCTION__, errno, strerror(errno) ) ; return false ; } else { fprintf(stderr, "%s:=>sched_setscheduler set priority to %d for process %u \n", __PRETTY_FUNCTION__, max_priority, this_process ) ; } #else // (TBD) Do something differently if "pthread sched param"? if (0 != setpriority(PRIO_PROCESS, getpid(), -20)) { PLOG(PL_ERROR, "NormStreamer::BoostPriority() error: setpriority() error: %s\n", GetErrorString()); return false; } #endif // if/else LINUX return true; } #ifndef ntohll //Convert net-order to host-order. uint64_t ntohll(uint64_t value) { static const int betest = 1 ; union MyUnion { uint64_t i64; uint32_t i32[2]; }; uint64_t rval = value; bool host_is_little_endian = ( 1 == (int)(*(char*)&betest) ) ; if ( host_is_little_endian ) { MyUnion u; u.i64 = value; uint32_t temp = u.i32[0]; u.i32[0] = ntohl(u.i32[1]); u.i32[1] = ntohl(temp); rval = u.i64; } return rval ; } #endif // !nothll void NormStreamer::CheckSequenceNumber64(const char* buffer, const char* source) { uint64_t temp; memcpy((void*)&temp, (void*)buffer, sizeof(temp)); uint64_t sequence = ntohll(temp); if (0 != sequence_prev) { int64_t delta = (int64_t)(sequence - sequence_prev); if (1 != delta) { fprintf(stderr, "normStreamer: %s dropped %lu packets seq:%lu seq_prev:%lu\n", source, (unsigned long)delta, (unsigned long)sequence, (unsigned long)sequence_prev); } } sequence_prev = sequence; } // end NormStreamer::CheckSequenceNumber64() void NormStreamer::CheckSequenceNumber32(const char* buffer, const char* source) { uint32_t temp; memcpy((void*)&temp, (void*)buffer, sizeof(temp)); uint32_t sequence = ntohll(temp); if (0 != sequence_prev) { int32_t delta = (int32_t)(sequence - sequence_prev); if (1 != delta) { fprintf(stderr, "normStreamer: %s dropped %lu packets seq:%lu seq_prev:%lu\n", source, (unsigned long)delta, (unsigned long)sequence, (unsigned long)sequence_prev); } } sequence_prev = sequence; } // end NormStreamer::CheckSequenceNumber32() void NormStreamer::CheckSequenceNumber(const char* buffer, const char* source) { switch (check_sequence) { case 32: CheckSequenceNumber32(buffer, source); break; case 64: CheckSequenceNumber64(buffer, source) ; break; default: break; } } // end NormStreamer::CheckSequenceNumber() bool NormStreamer::EnableUdpRelay(const char* relayAddr, unsigned short relayPort) { if (!output_socket.Open()) { fprintf(stderr, "normStreamer error: unable to open 'relay' socket\n"); return false ; } if (!output_socket.SetTxBufferSize(output_socket_buffer_size)) { fprintf(stderr, "normStreamer warning: unable to set desired 'relay' socket buffer size (retrieved value:%u)\n", output_socket.GetTxBufferSize()); } if (!relay_addr.ResolveFromString(relayAddr)) { fprintf(stderr, "normStreamer error: invalid relay address\n"); output_socket.Close(); return false; } relay_addr.SetPort(relayPort); // TBD - validate port number?? return true; } // end bool EnableUdpRelay() bool NormStreamer::EnableUdpListener(unsigned short thePort, const char* groupAddr, const char * interfaceName) { if (!input_socket.Open(thePort)) { fprintf(stderr, "normStreamer error: unable to open 'listen' socket on port %hu\n", thePort); return false; } if (!input_socket.SetRxBufferSize(input_socket_buffer_size)) { fprintf(stderr, "normStreamer error: unable to set desired 'listen' socket buffer size\n"); return false; } if (NULL != groupAddr) { ProtoAddress addr; if (!addr.ResolveFromString(groupAddr) || (!addr.IsMulticast())) { fprintf(stderr, "normStreamer error: invalid 'listen' group address\n"); input_socket.Close(); return false ; } if (!input_socket.JoinGroup(addr, interfaceName)) { fprintf(stderr, "normStreamer error: unable to join 'listen' group address\n"); input_socket.Close(); return false; } } return true; } // end NormStreamer::EnableUdpListener() bool NormStreamer::OpenNormSession(NormInstanceHandle instance, const char* addr, unsigned short port, NormNodeId nodeId) { if (NormIsUnicastAddress(addr)) is_multicast = false; else is_multicast = true; norm_session = NormCreateSession(instance, addr, port, nodeId); if (NORM_SESSION_INVALID == norm_session) { fprintf(stderr, "normStreamer error: unable to create NORM session\n"); return false; } if (is_multicast) { NormSetRxPortReuse(norm_session, true); if (loopback) NormSetMulticastLoopback(norm_session, true); } // Set some default parameters (maybe we should put parameter setting in Start()) NormSetDefaultSyncPolicy(norm_session, NORM_SYNC_STREAM); NormSetDefaultUnicastNack(norm_session, true); NormSetTxRobustFactor(norm_session, 20); return true; } // end NormStreamer::OpenNormSession() void NormStreamer::CloseNormSession() { if (NORM_SESSION_INVALID == norm_session) return; NormDestroySession(norm_session); norm_session = NORM_SESSION_INVALID; } // end NormStreamer::CloseNormSession() void NormStreamer::SetNormCongestionControl(CCMode ccMode) { assert(NORM_SESSION_INVALID != norm_session); switch (ccMode) { case NORM_CC: // default TCP-friendly congestion control NormSetEcnSupport(norm_session, false, false, false); break; case NORM_CCE: // "wireless-ready" ECN-only congestion control NormSetEcnSupport(norm_session, true, true); break; case NORM_CCL: // "loss tolerant", non-ECN congestion control NormSetEcnSupport(norm_session, false, false, true); break; case NORM_FIXED: // "fixed" constant data rate NormSetEcnSupport(norm_session, false, false, false); break; } if (NORM_FIXED != ccMode) NormSetCongestionControl(norm_session, true); else NormSetCongestionControl(norm_session, false); } // end NormStreamer::SetNormCongestionControl() bool NormStreamer::Start(bool sender, bool receiver) { // Note the session NORM buffer size is set the same s stream_buffer_size unsigned int bufferSize = stream_buffer_size; if (receiver) { if (!NormPreallocateRemoteSender(norm_session, bufferSize, segment_size, block_size, num_parity, stream_buffer_size)) fprintf(stderr, "normStreamer warning: unable to preallocate remote sender\n"); fprintf(stderr, "normStreamer: receiver ready.\n"); if (!NormStartReceiver(norm_session, bufferSize)) { fprintf(stderr, "normStreamer error: unable to start NORM receiver\n"); return false; } if (0 != mlockall(MCL_CURRENT | MCL_FUTURE)) fprintf(stderr, "normStreamer error: failed to lock memory for receiver.\n"); if (0 != rx_socket_buffer_size) NormSetRxSocketBuffer(norm_session, rx_socket_buffer_size); rx_needed = true; rx_ready = false; } if (sender) { NormSetGrttEstimate(norm_session, 0.001); //NormSetGrttMax(norm_session, 0.100); NormSetBackoffFactor(norm_session, 0); if (norm_acking) { // ack-based flow control enabled on command-line, // so disable timer-based flow control NormSetFlowControl(norm_session, 0.0); } // Pick a random instance id for now struct timeval currentTime; gettimeofday(¤tTime, NULL); srand(currentTime.tv_usec); // seed random number generator NormSessionId instanceId = (NormSessionId)rand(); if (!NormStartSender(norm_session, instanceId, bufferSize, segment_size, block_size, num_parity)) { fprintf(stderr, "normStreamer error: unable to start NORM sender\n"); if (receiver) NormStopReceiver(norm_session); return false; } if (auto_parity > 0) NormSetAutoParity(norm_session, auto_parity < num_parity ? auto_parity : num_parity); if (0 != tx_socket_buffer_size) NormSetTxSocketBuffer(norm_session, tx_socket_buffer_size); if (NORM_OBJECT_INVALID == (tx_stream = NormStreamOpen(norm_session, stream_buffer_size))) { fprintf(stderr, "normStreamer error: unable to open NORM tx stream\n"); NormStopSender(norm_session); if (receiver) NormStopReceiver(norm_session); return false; } else { if (0 != mlockall(MCL_CURRENT|MCL_FUTURE)) fprintf(stderr, "normStreamer warning: failed to lock memory for sender.\n"); } tx_stream_buffer_max = NormGetStreamBufferSegmentCount(bufferSize, segment_size, block_size); tx_stream_buffer_max -= block_size; // a little safety margin (perhaps not necessary) tx_stream_buffer_threshold = tx_stream_buffer_max / 8; tx_stream_buffer_count = 0; tx_stream_bytes_remain = 0; tx_watermark_pending = false; tx_ack_pending = false; tx_ready = true; input_index = input_msg_length = 0; input_needed = true; input_ready = true; } is_running = true; return true; } // end NormStreamer::Start(); void NormStreamer::ReadInputSocket() { unsigned int loopCount = 0; NormSuspendInstance(NormGetInstance(norm_session)); while (input_needed && input_ready && (loopCount < LOOP_MAX)) { loopCount++; unsigned int numBytes = MSG_SIZE_MAX - MSG_HEADER_SIZE; ProtoAddress srcAddr; if (input_socket.RecvFrom(input_buffer+MSG_HEADER_SIZE, numBytes, srcAddr)) { if (0 == numBytes) { input_ready = false; break; } input_index = 0; input_msg_length = numBytes + MSG_HEADER_SIZE; input_byte_count += input_msg_length; unsigned short msgSize = input_msg_length;; msgSize = htons(msgSize); memcpy(input_buffer, &msgSize, MSG_HEADER_SIZE); input_needed = false; if (TxReady()) SendData(); } else { // TBD - handle error? input_ready = false; } } NormResumeInstance(NormGetInstance(norm_session)); } // end NormStreamer::ReadInputSocket() void NormStreamer::ReadInput() { if (UdpListenerEnabled()) return ReadInputSocket(); // The loop count makes sure we don't spend too much time here // before going back to the main loop to handle NORM events, etc unsigned int loopCount = 0; NormSuspendInstance(NormGetInstance(norm_session)); while (input_needed && input_ready && (loopCount < LOOP_MAX)) { loopCount++; //if (100 == loopCount) // fprintf(stderr, "normStreamer ReadInput() loop count max reached\n"); unsigned int numBytes; if (input_index < MSG_HEADER_SIZE) { // Reading message length header for next message to send numBytes = MSG_HEADER_SIZE - input_index; } else { // Reading message body assert(input_index < input_msg_length); numBytes = input_msg_length - input_index; } ssize_t result = read(input_fd, input_buffer + input_index, numBytes); if (result > 0) { input_index += result; input_byte_count += result; if (MSG_HEADER_SIZE == input_index) { // We have now read the message size header // TBD - support other message header formats? // (for now, assume 2-byte message length header) uint16_t msgSize ; memcpy(&msgSize, input_buffer, MSG_HEADER_SIZE); msgSize = ntohs(msgSize); input_msg_length = msgSize; } else if (input_index == input_msg_length) { // Message input complete input_index = 0; // reset index for transmission phase input_needed = false; if (TxReady()) SendData(); } else { // Still need more input // (wait for next input notification to read more) input_ready = false; } } else if (0 == result) { // end-of-file reached, TBD - trigger final flushing and wrap-up fprintf(stderr, "normStreamer: input end-of-file detected ...\n"); NormStreamClose(tx_stream, true); if (norm_acking) { NormSetWatermark(norm_session, tx_stream, true); tx_ack_pending = false; } input_needed = false; } else { switch (errno) { case EINTR: continue; // interrupted, try again case EAGAIN: // input starved, wait for next notification input_ready = false; break; default: // TBD - handle this better perror("normStreamer error reading input"); break; } break; } } // end while (input_needed && input_ready) NormResumeInstance(NormGetInstance(norm_session)); } // end NormStreamer::ReadInput() void NormStreamer::SendData() { while (TxReady() && !input_needed) { // Note WriteToStream() or FlushStream() will set "tx_ready" to // false upon flow control thus negating TxReady() status assert(input_index < input_msg_length); assert(input_msg_length); if ((0 != check_sequence) && (0 == input_index)) CheckSequenceNumber(input_buffer+MSG_HEADER_SIZE, __func__); input_index += WriteToStream(input_buffer + input_index, input_msg_length - input_index); if (input_index == input_msg_length) { // Complete message was sent, so set eom and optionally flush if (NORM_FLUSH_NONE != flush_mode) FlushStream(true, flush_mode); else NormStreamMarkEom(tx_stream); input_index = input_msg_length = 0; input_needed = true; } else { //fprintf(stderr, "SendData() impeded by flow control\n"); } } // end while (TxReady() && !input_needed) } // end NormStreamer::SendData() unsigned int NormStreamer::WriteToStream(const char* buffer, unsigned int numBytes) { unsigned int bytesWritten; if (norm_acking) { // This method uses NormStreamWrite(), but limits writes by explicit ACK-based flow control status if (tx_stream_buffer_count < tx_stream_buffer_max) { // 1) How many buffer bytes are available? unsigned int bytesAvailable = segment_size * (tx_stream_buffer_max - tx_stream_buffer_count); bytesAvailable -= tx_stream_bytes_remain; // unflushed segment portion if (bytesAvailable < numBytes) numBytes = bytesAvailable; assert(numBytes); // 2) Write to the stream bytesWritten = NormStreamWrite(tx_stream, buffer, numBytes); tx_byte_count += bytesWritten; // 3) Update "tx_stream_buffer_count" accordingly unsigned int totalBytes = bytesWritten + tx_stream_bytes_remain; unsigned int numSegments = totalBytes / segment_size; tx_stream_bytes_remain = totalBytes % segment_size; tx_stream_buffer_count += numSegments; //assert(bytesWritten == numBytes); // this could fail if timer-based flow control is left enabled // 3) Check if we need to issue a watermark ACK request? if (!tx_watermark_pending && (tx_stream_buffer_count >= tx_stream_buffer_threshold)) { // Initiate flow control ACK request //fprintf(stderr, "write-initiated flow control ACK REQUEST\n"); NormSetWatermark(norm_session, tx_stream); tx_watermark_pending = true; tx_ack_pending = false; } } else { fprintf(stderr, "normStreamer: sender flow control limited\n"); return 0; } } else { bytesWritten = NormStreamWrite(tx_stream, buffer, numBytes); tx_byte_count += bytesWritten; } if (bytesWritten != numBytes) //NormStreamWrite() was (at least partially) blocked { //fprintf(stderr, "NormStreamWrite() blocked by flow control ...\n"); tx_ready = false; } return bytesWritten; } // end NormStreamer::WriteToStream() void NormStreamer::FlushStream(bool eom, NormFlushMode flushMode) { if (norm_acking) { bool setWatermark = false; if (0 != tx_stream_bytes_remain) { // The flush will force the runt segment out, so we increment our buffer usage count // (and initiate flow control watermark ack request if buffer mid-point threshold exceeded tx_stream_buffer_count++; tx_stream_bytes_remain = 0; if (!tx_watermark_pending && (tx_stream_buffer_count >= tx_stream_buffer_threshold)) { setWatermark = true; tx_watermark_pending = true; //fprintf(stderr, "flush-initiated flow control ACK REQUEST\n"); } } // The check for "tx_watermark_pending" here prevents a new watermark // ack request from being set until the pending flow control ack is // received. This favors avoiding dead air time over saving "chattiness" if (setWatermark) { // Flush passive since watermark will invoke active request // (TBD - do non-acking nodes NACK to watermark when not ack target?) NormStreamFlush(tx_stream, eom, NORM_FLUSH_PASSIVE); } else if (tx_watermark_pending) { // Pre-existing pending flow control watermark ack request #if SHOOT_FIRST // Go ahead and set a fresh watermark // TBD - not sure this mode works properly ... may need to // keep track of unacknowledged byte count and decrement accordingly // when ack arrives NormStreamFlush(tx_stream, eom, NORM_FLUSH_PASSIVE); setWatermark = true; #else // ACK_LATER // Wait until flow control ACK is received before issuing another ACK request NormStreamFlush(tx_stream, eom, flushMode); tx_ack_pending = true; // will call NormSetWatermark() upon flow control ack completion #endif } else { // Since we're acking, use active ack request in lieu of active flush NormStreamFlush(tx_stream, eom, NORM_FLUSH_PASSIVE); setWatermark = true; } if (setWatermark) { NormSetWatermark(norm_session, tx_stream, true); tx_ack_pending = false; } } else { NormStreamFlush(tx_stream, eom, flushMode); } } // end NormStreamer::FlushStream() void NormStreamer::RecvData() { // The loop count makes sure we don't spend too much time here // before going back to the main loop to handle NORM events, etc unsigned int loopCount = 0; // Reads data from rx_stream to available output_buffer NormSuspendInstance(NormGetInstance(norm_session)); while (rx_needed && rx_ready && (loopCount < LOOP_MAX)) { loopCount++; //if (100 == loopCount) // fprintf(stderr, "normStreamer RecvData() loop count max reached.\n"); // Make sure we have msg_sync (TBD - skip this for byte streaming) if (!msg_sync) { msg_sync = NormStreamSeekMsgStart(rx_stream); if (!msg_sync) { rx_ready = false; break; // wait for next NORM_RX_OBJECT_UPDATED to re-sync } } unsigned int bytesWanted; if (output_index < MSG_HEADER_SIZE) { // Receiving message header bytesWanted = MSG_HEADER_SIZE - output_index; } else { // Receiving message body assert(output_index < output_msg_length); bytesWanted = output_msg_length - output_index; } unsigned bytesRead = bytesWanted; if (!NormStreamRead(rx_stream, output_buffer + output_index, &bytesRead)) { // Stream broken (should _not_ happen if norm_acking flow control) //fprintf(stderr, "normStreamer error: BROKEN stream detected, re-syncing ...\n"); msg_sync = false; output_index = output_msg_length = 0; continue; } output_index += bytesRead; /*if (0 == bytesRead) { rx_ready = false; } else*/ if (bytesRead != bytesWanted) { //continue; rx_ready = false; // didn't get all we need } else if (MSG_HEADER_SIZE == output_index) { // We have now read the message size header // TBD - support other message header formats? // (for now, assume 2-byte message length header) uint16_t msgSize ; memcpy(&msgSize, output_buffer, MSG_HEADER_SIZE); output_msg_length = ntohs(msgSize); } else if (output_index == output_msg_length) { // Received full message rx_needed = false; output_index = 0; // reset for writing to output if (output_ready && OutputBucketReady()) WriteOutput(); } } NormResumeInstance(NormGetInstance(norm_session)); } // end NormStreamer::RecvData() void NormStreamer::WriteOutputSocket() { if (output_ready && !rx_needed) { assert(output_index < output_msg_length); unsigned int payloadSize = output_msg_length - MSG_HEADER_SIZE; unsigned int numBytes = payloadSize; if ((0 != check_sequence)) CheckSequenceNumber(output_buffer+MSG_HEADER_SIZE, __func__); if (output_socket.SendTo(output_buffer+MSG_HEADER_SIZE, numBytes, relay_addr)) { if (numBytes != payloadSize) { // sendto() was blocked output_ready = false; return; } if (0 != output_bucket_depth) { // Debit output token bucket since it's active ASSERT(output_bucket_count >= payloadSize); output_bucket_count -= payloadSize; } rx_needed = true; output_index = output_msg_length = 0; } else { output_ready = false; } } } // end NormStreamer::WriteOutputSocket() void NormStreamer::WriteOutput() { if (UdpRelayEnabled()) { WriteOutputSocket(); return; } while (output_ready && !rx_needed) { assert(output_index < output_msg_length); if ((0 != check_sequence) && (0 == output_index)) CheckSequenceNumber(output_buffer+MSG_HEADER_SIZE,__func__); ssize_t result = write(output_fd, output_buffer + output_index, output_msg_length - output_index); if (result >= 0) { if (0 != output_bucket_depth) { // Debit output token bucket since it's active if (result > output_bucket_count) TRACE("result:%d output_bucket_count:%u\n", (int)result, output_bucket_count); ASSERT(output_bucket_count >= result); output_bucket_count -= result; } output_index += result; if (output_index == output_msg_length) { // Complete message written rx_needed = true; output_index = output_msg_length = 0; if ((NORM_OBJECT_INVALID == tx_stream) && (NORM_OBJECT_INVALID == rx_stream)) Stop(); // receive stream was terminated by sender } else { output_ready = false; } } else { switch (errno) { case EINTR: perror("normStreamer output EINTR"); continue; // interupted, try again case EAGAIN: // output blocked, wait for next notification //perror("normStreamer output blocked"); output_ready = false; break; default: perror("normStreamer error writing output"); break; } break; } } } // end NormStreamer::WriteOutput() void NormStreamer::HandleNormEvent(const NormEvent& event) { switch (event.type) { case NORM_TX_QUEUE_EMPTY: //TRACE("normStreamer: flow control empty ...\n"); tx_ready = true; break; case NORM_TX_QUEUE_VACANCY: //TRACE("normStreamer: flow control relieved ...\n"); tx_ready = true; break; case NORM_GRTT_UPDATED: //fprintf(stderr, "new GRTT = %lf\n", NormGetGrttEstimate(norm_session)); break; case NORM_TX_WATERMARK_COMPLETED: if (NORM_ACK_SUCCESS == NormGetAckingStatus(norm_session)) { //fprintf(stderr, "WATERMARK COMPLETED\n"); if (tx_watermark_pending) { // Flow control ack request was pending. tx_watermark_pending = false; tx_stream_buffer_count -= tx_stream_buffer_threshold; //fprintf(stderr, "flow control ACK completed\n"); if (tx_ack_pending) { NormSetWatermark(norm_session, tx_stream, true); tx_ack_pending = false; } } } else { // TBD - we could see who didn't ACK and possibly remove them // from our acking list. For now, we are infinitely // persistent by always resetting the watermark ack request // For example, an application could make a decision at this // point, depending upon some count of ACK request failures // to choose to remove a previously included receiver. fprintf(stderr, "flow control watermark reset\n"); if (tx_ack_pending) { // May as well advance the ack request point NormSetWatermark(norm_session, tx_stream, true); tx_ack_pending = false; } else { NormResetWatermark(norm_session); } } break; case NORM_TX_OBJECT_PURGED: // tx_stream graceful close completed NormStopSender(norm_session); tx_stream = NORM_OBJECT_INVALID; if (NORM_OBJECT_INVALID == rx_stream) Stop(); break; case NORM_REMOTE_SENDER_INACTIVE: //fprintf(stderr, "REMOTE SENDER INACTIVE node: %u\n", NormNodeGetId(event.sender)); //NormNodeDelete(event.sender); break; case NORM_RX_OBJECT_NEW: if ((NORM_OBJECT_INVALID == rx_stream) && (NORM_OBJECT_STREAM == NormObjectGetType(event.object))) { rx_stream = event.object; rx_ready = true; // By setting initial "msg_sync" to true, we can detect when // stream beginning was missed (for NORM_SYNC_STREAM only) msg_sync = false; rx_needed = true; output_index = output_msg_length = 0; } else { fprintf(stderr, "normStreamer warning: NORM_RX_OBJECT_NEW while already receiving?!\n"); } case NORM_RX_OBJECT_UPDATED: rx_ready = true; break; case NORM_RX_OBJECT_ABORTED: //fprintf(stderr, "NORM_RX_OBJECT_ABORTED\n");// %hu\n", NormObjectGetTransportId(event.object)); rx_stream = NORM_OBJECT_INVALID; rx_needed = false; rx_ready = false; break; case NORM_RX_OBJECT_COMPLETED: // Rx stream has closed // TBD - set state variables so any pending output is // written out and things shutdown if not sender, too fprintf(stderr, "normStreamer: rx_stream completed.\n"); // if rx_needed is true, all output has been written if (rx_needed && (NORM_OBJECT_INVALID == tx_stream)) { NormNodeHandle sender = NormObjectGetSender(rx_stream); // Wait a couple of GRTT's to ACK sender double exitTime = 20.0 * NormNodeGetGrtt(sender); if (exitTime < 1.0) exitTime = 1.0; fprintf(stderr, "normStreamer reception completed, exiting in %f seconds ...\n", (float)exitTime); sleep(exitTime); // TBD - use our user-defined NormSession timeout instead? (retaining rx_stream) if (rx_needed && (NORM_OBJECT_INVALID == tx_stream)) Stop(); } rx_stream = NORM_OBJECT_INVALID; rx_ready = false; rx_needed = false; break; default: break; } //NormReleasePreviousEvent(NormGetInstance(norm_session)); } // end NormStreamer::HandleNormEvent() void Usage() { fprintf(stderr, "Usage: normStreamer id {send|recv} [addr [/]][interface ][loopback]\n" " [cc|cce|ccl|rate ][ack [,,...][flush {none|passive|active}]\n" " [listen [/]][linterface ]\n" " [relay /][limit [/]][output ]\n" " [boost][debug ][trace][log ]\n" " [segment ][block ][parity ][auto ]\n" " [insockbuffer ][outsockbuffer ]\n" " [txsockbuffer ][rxsockbuffer ]\n" " [streambuffer ]\n" " [check64 | check32]\n"); //" [omit][silent][txloss ]\n"); } // end Usage() void PrintHelp() { fprintf(stderr, "\nHelp for normStreamer:\n\n") ; fprintf(stderr, "The 'normStreamer' application sends messages from STDIN (or a listening UDP socket) to one or more\n" "receiving nodes using the NORM protocol. Received messages are output to STDOUT (or relayed to\n" "to a UDP destination address/port). Key command line options are:\n\n" " id -- Specifies the node id for the local NORM instance (required)\n" " send | recv -- Specifies whether this node will be a sender and/or receiver (must choose at least one)\n" " addr [/] -- specifies the network address over which to send/receive NORM protocol\n" " interface -- Specifies the name of the network interface on which to conduct NORM protocol\n" " (e.g., 'eth0')\n" " loopback -- Enables 'loopback' sessions on the same host machine. Required for multicast loopback.\n" " rate -- sets fixed sender rate (and receiver token bucket rate if 'limit' option is used)\n" " [cc|cce|ccl] -- Enables optional NORM congestion control mode (overrides 'rate')\n" " ack [] -- Instructs sender to request positive acknowledgement from listed receiver nodes\n" " flush [] -- Choose 'none', 'passive', or 'active' message stream flushing mode. If 'none',\n" " NORM_DATA packets will always be packed with message content up to the full\n" " segment size. If 'passive', short NORM_DATA packets will be sent to transmit\n" " any messages as soon as possible. If 'active', NORM stream will be flushed\n" " on a per-message basis as with 'passive' mode, but positive acknowledgment will\n" " _also_ be requested if a list of acking receiver node ids has beeen provided.\n" " listen [/] -- Specifies the port and optional multicast address which the sender uses to listen\n" " for UDP packets to transmit to the receiver(s) via the NORM protocol\n" " linterface -- Specifies the name of the network interface on which to listen for UDP packet\n" " payloads to send to the receiver(s) via NORM protocol\n" " relay / -- Specifies the address/port for which to relay (as UDP datagrams) received messages\n" " limit [/] -- Token bucket rate/depth for optional receiver output limiter (smooths bursty output\n" " upon NORM loss recovery). When UDP 'relay' is used, this option is useful to avoid\n" " overly bursty UDP output. The is in units of bits/second and the is\n" " in units of bytes. If not specified here, the value set by 'rate' command is used\n" " as the token bucket rate.\n" " check64 | check32 -- Enables checking that packet sequence numbers in the first 4/8 bytes of received\n" " packets increment properly (optional)\n" " insockbuffer -- Specifies the size of the 'listen' UDP socket buffer (optional).\n" " outsockbuffer -- Specifies the size of the 'relay' UDP socket buffer (optional).\n" " txsockbuffer -- Specifies the size of the NORM/UDP transmit socket buffer (optional).\n" " rxsockbuffer -- Specifies the size of the NORM/UDP receive socket buffer (optional).\n" " streambuffer -- Specifies the size of the NORM stream buffer (optional).\n\n"); Usage(); } // end PrintHelp() int main(int argc, char* argv[]) { // REQUIRED parameters initiailization NormNodeId nodeId = NORM_NODE_NONE; bool send = false; bool recv = false; char sessionAddr[64]; strcpy(sessionAddr, "224.1.2.3"); unsigned int sessionPort = 6003; char listenAddr[64]; // UDP :listen" multicast addr listenAddr[0] = '\0'; unsigned int listenPort = 0; // UDP "listen" port for UDP "listen" const char* listenIface = NULL; // UDP "listen" interface char relayAddr[64]; relayAddr[0] = '\0'; unsigned int relayPort = 0; double txRate = 0.0; // used for non-default NORM_FIXED ccMode NormStreamer::CCMode ccMode = NormStreamer::NORM_CC; const char* mcastIface = NULL; NormNodeId ackingNodeList[256]; unsigned int ackingNodeCount = 0; bool loopback = false; int debugLevel = 0; bool trace = false; const char* logFile = NULL; bool omitHeaderOnOutput = false; bool silentReceiver = false; double txloss = 0.0; bool boostPriority = false; unsigned int checkSequence = 0; // can set to 64 or 32 // TBD - set these defaults to reasonable values or just use NormStreamer constructor defaults unsigned long inputSocketBufferSize = 256*1024*1024; unsigned long outputSocketBufferSize = 256*1024*1024; unsigned long txSocketBufferSize = 6*1024*1024; unsigned long rxSocketBufferSize = 6*1024*1024; unsigned long streamBufferSize = 256*1024*1024; // Instantiate a NormStreamer and set default params NormStreamer normStreamer; normStreamer.SetFlushMode(NORM_FLUSH_NONE); // Parse command-line int i = 1; while (i < argc) { const char* cmd = argv[i++]; size_t len = strlen(cmd); if (0 == strncmp(cmd, "help", len)) { PrintHelp() ; exit(0); } else if (0 == strncmp(cmd, "send", len)) { send = true; } else if (0 == strncmp(cmd, "recv", len)) { recv = true; } else if (0 == strncmp(cmd, "loopback", len)) { loopback = true; } else if (0 == strncmp(cmd, "addr", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'addr[/port]' value!\n"); Usage(); return -1; } const char* addrPtr = argv[i++]; const char* portPtr = strchr(addrPtr, '/'); if (NULL == portPtr) { strncpy(sessionAddr, addrPtr, 63); sessionAddr[63] = '\0'; } else { size_t addrLen = portPtr - addrPtr; if (addrLen > 63) addrLen = 63; // should issue error message strncpy(sessionAddr, addrPtr, addrLen); sessionAddr[addrLen] = '\0'; portPtr++; sessionPort = atoi(portPtr); } } else if (0 == strncmp(cmd, "listen", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing '[mcastAddr/]port]' value!\n"); Usage(); return -1; } const char* addrPtr = argv[i++]; const char* portPtr = strchr(addrPtr, '/'); if (NULL != portPtr) { size_t addrLen = portPtr - addrPtr; if (addrLen > 63) addrLen = 63; // should issue error message strncpy(listenAddr, addrPtr, addrLen); listenAddr[addrLen] = '\0'; portPtr++; listenPort = atoi(portPtr); } else { // no address, just port listenPort = atoi(addrPtr); addrPtr = NULL; } } else if (0 == strncmp(cmd, "relay", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing relay 'dstAddr/port' value!\n"); Usage(); return -1; } const char* addrPtr = argv[i++]; const char* portPtr = strchr(addrPtr, '/'); if (NULL == portPtr) { fprintf(stderr, "normStreamer error: missing relay 'port' value!\n"); Usage(); return -1; } if (NULL != portPtr) { size_t addrLen = portPtr - addrPtr; if (addrLen > 63) addrLen = 63; // should issue error message strncpy(relayAddr, addrPtr, addrLen); relayAddr[addrLen] = '\0'; portPtr++; relayPort = atoi(portPtr); } } else if (0 == strncmp(cmd, "output", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing output 'device' name!\n"); Usage(); return -1; } FILE* outfile = fopen(argv[i++], "w+"); if (NULL == outfile) { fprintf(stderr, "normStreamer output device fopen() error: %s\n", GetErrorString()); Usage(); return -1; } normStreamer.SetOutputFile(outfile); } else if (0 == strncmp(cmd, "id", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'id' value!\n"); Usage(); return -1; } nodeId = atoi(argv[i++]); } else if (0 == strncmp(cmd, "ack", len)) { // comma-delimited acking node id list if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'id' value!\n"); Usage(); return -1; } const char* alist = argv[i++]; while ((NULL != alist) && (*alist != '\0')) { // TBD - Do we need to skip leading white space? int id; if (1 != sscanf(alist, "%d", &id)) { fprintf(stderr, "normStreamer error: invalid acking node list!\n"); Usage(); return -1; } ackingNodeList[ackingNodeCount] = NormNodeId(id); ackingNodeCount++; alist = strchr(alist, ','); if (NULL != alist) alist++; // point past comma } } else if (0 == strncmp(cmd, "flush", len)) { // "none", "passive", or "active" if (i >= argc) { fprintf(stderr, "nodeMsgr error: missing 'flush' !\n"); Usage(); return -1; } const char* mode = argv[i++]; if (0 == strcmp(mode, "none")) { normStreamer.SetFlushMode(NORM_FLUSH_NONE); } else if (0 == strcmp(mode, "passive")) { normStreamer.SetFlushMode(NORM_FLUSH_PASSIVE); } else if (0 == strcmp(mode, "active")) { normStreamer.SetFlushMode(NORM_FLUSH_ACTIVE); } else { fprintf(stderr, "normMsgr error: invalid 'flush' mode \"%s\"\n", mode); return -1; } } else if (0 == strncmp(cmd, "rate", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'rate' value!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lf", &txRate)) { fprintf(stderr, "normStreamer error: invalid transmit rate!\n"); Usage(); return -1; } // set fixed-rate operation ccMode = NormStreamer::NORM_FIXED; normStreamer.SetOutputBucketRate(txRate); } else if (0 == strcmp(cmd, "cc")) { ccMode = NormStreamer::NORM_CC; } else if (0 == strcmp(cmd, "cce")) { ccMode = NormStreamer::NORM_CCE; } else if (0 == strcmp(cmd, "ccl")) { ccMode = NormStreamer::NORM_CCL; } else if (0 == strncmp(cmd, "interface", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'interface' !\n"); Usage(); return -1; } mcastIface = argv[i++]; } else if (0 == strncmp(cmd, "linterface", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'linterface' !\n"); Usage(); return -1; } listenIface = argv[i++]; } else if (0 == strncmp(cmd, "insockbuffer", len)) { unsigned long value = 0 ; if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'insockbuffer' size!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lu", &value)) { fprintf(stderr, "normStreamer error: invalid 'insockbuffer' size\n"); Usage(); return -1; } inputSocketBufferSize = value; } else if (0 == strncmp(cmd, "outsockbuffer", len)) { unsigned long value = 0 ; if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'outsockbuffer' size!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lu", &value)) { fprintf(stderr, "normStreamer error: invalid 'outsockbuffer' size!\n"); Usage(); return -1; } outputSocketBufferSize = value; } else if (0 == strncmp(cmd, "limit", len)) { // format: limit [/] with 'rate' in bps and 'size' in bytes if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'limit' size!\n"); Usage(); return -1; } const char* ratePtr = argv[i++]; const char* sizePtr = strchr(ratePtr, '/'); unsigned int rateLen = 0; if (NULL != sizePtr) rateLen = sizePtr++ - ratePtr; else sizePtr = ratePtr; if (0 != rateLen) { if (rateLen > 63) { fprintf(stderr, "normStreamer error: out-of-bounds 'limit' rate\n"); Usage(); return -1; } char rateText[64]; strncpy(rateText, ratePtr, rateLen); rateText[rateLen] = '\0'; double value; if (1 != sscanf(rateText, "%lf", &value)) { fprintf(stderr, "normStreamer error: invalid 'limit' rate\n"); Usage(); return -1; } normStreamer.SetOutputBucketRate(value); } unsigned long value; if (1 != sscanf(sizePtr, "%lu", &value)) { fprintf(stderr, "normStreamer error: invalid 'limit' size\n"); Usage(); return -1; } normStreamer.SetOutputBucketDepth(value); } else if (0 == strncmp(cmd, "txsockbuffer", len)) { unsigned long value = 0 ; if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'txsockbuffer' size!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lu", &value)) { fprintf(stderr, "normStreamer error: invalid 'txsockbuffer' size!\n"); Usage(); return -1; } txSocketBufferSize = value; } else if (0 == strncmp(cmd, "rxsockbuffer", len)) { unsigned long value = 0 ; if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'rxsockbuffer' size!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lu", &value)) { fprintf(stderr, "normStreamer error: invalid 'rxsockbuffer' size!\n"); Usage(); return -1; } rxSocketBufferSize = value; } else if (0 == strncmp(cmd, "segment", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'segment' size!\n"); Usage(); return -1; } unsigned short value; if (1 != sscanf(argv[i++], "%hu", &value)) { fprintf(stderr, "normStreamer error: invalid 'segment' size!\n"); Usage(); return -1; } normStreamer.SetSegmentSize(value); } else if (0 == strncmp(cmd, "block", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'block' size!\n"); Usage(); return -1; } unsigned short value; if (1 != sscanf(argv[i++], "%hu", &value)) { fprintf(stderr, "normStreamer error: invalid 'block' size!\n"); Usage(); return -1; } normStreamer.SetBlockSize(value); } else if (0 == strncmp(cmd, "parity", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'parity' count!\n"); Usage(); return -1; } unsigned short value; if (1 != sscanf(argv[i++], "%hu", &value)) { fprintf(stderr, "normStreamer error: invalid 'parity' count!\n"); Usage(); return -1; } normStreamer.SetNumParity(value); } else if (0 == strncmp(cmd, "auto", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'auto' parity count!\n"); Usage(); return -1; } unsigned short value; if (1 != sscanf(argv[i++], "%hu", &value)) { fprintf(stderr, "normStreamer error: invalid 'auto' parity count!\n"); Usage(); return -1; } normStreamer.SetAutoParity(value); } else if (0 == strncmp(cmd, "streambuffer", len)) { unsigned long value = 0 ; if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'streambuffer' size!\n"); Usage(); return -1; } if (1 != sscanf(argv[i++], "%lu", &value)) { fprintf(stderr, "normStreamer error: invalid 'streambuffer' size!\n"); Usage(); return -1; } streamBufferSize = value; } else if ( 0 == strncmp(cmd,"chkseq", len) ) { checkSequence = 64; // same as "check64" for "historical" reasons } else if ( 0 == strncmp(cmd,"check64", len) ) { checkSequence = 64; } else if ( 0 == strncmp(cmd,"check32", len) ) { checkSequence = 32; } else if (0 == strncmp(cmd, "omit", len)) { omitHeaderOnOutput = true; } else if (0 == strncmp(cmd, "silent", len)) { silentReceiver = true; } else if (0 == strncmp(cmd, "boost", len)) { boostPriority = true; } else if (0 == strncmp(cmd, "txloss", len)) { if (1 != sscanf(argv[i++], "%lf", &txloss)) { fprintf(stderr, "normStreamer error: invalid 'txloss' value!\n"); Usage(); return -1; } } else if (0 == strncmp(cmd, "debug", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'debug' !\n"); Usage(); return -1; } debugLevel = atoi(argv[i++]); } else if (0 == strncmp(cmd, "trace", len)) { trace = true; } else if (0 == strncmp(cmd, "log", len)) { if (i >= argc) { fprintf(stderr, "normStreamer error: missing 'log' !\n"); Usage(); return -1; } logFile = argv[i++]; } else if (0 == strncmp(cmd, "help", len)) { Usage(); return 0; } else { fprintf(stderr, "normStreamer error: invalid command \"%s\"!\n", cmd); Usage(); return -1; } } if (!send && !recv) { fprintf(stderr, "normStreamer error: not configured to send or recv!\n"); Usage(); return -1; } if (NORM_NODE_NONE == nodeId) { fprintf(stderr, "normStreamer error: no local 'id' provided!\n"); Usage(); return -1; } if (boostPriority) { if (!normStreamer.BoostPriority()) { fprintf(stderr, "normStreamer error: setting scheduler/ priority boost failed (requires 'sudo').\n"); return -1; } } if (0 != listenPort) { normStreamer.SetInputSocketBufferSize(inputSocketBufferSize); if (!normStreamer.EnableUdpListener(listenPort, listenAddr, listenIface)) { fprintf(stderr, "normStreamer error: Failed to enable UDP listener\n") ; return -1; } } if (0 != relayPort) { // TBD - check addr/port validity? normStreamer.SetOutputSocketBufferSize(outputSocketBufferSize); if (! normStreamer.EnableUdpRelay(relayAddr, relayPort)) { fprintf(stderr, "normStreamer error: Failed to open UDP relay socket\n") ; return -1; } } // TBD - should provide more error checking of NORM API calls NormInstanceHandle normInstance = NormCreateInstance(boostPriority); NormSetDebugLevel(debugLevel); if ((NULL != logFile) && !NormOpenDebugLog(normInstance, logFile)) { perror("normStreamer error: unable to open log file"); Usage(); return -1; } normStreamer.SetCheckSequence(checkSequence); normStreamer.SetTxSocketBufferSize(txSocketBufferSize); normStreamer.SetRxSocketBufferSize(rxSocketBufferSize); normStreamer.SetStreamBufferSize(streamBufferSize); normStreamer.SetLoopback(loopback); if (omitHeaderOnOutput) normStreamer.OmitHeader(true); if (!normStreamer.OpenNormSession(normInstance, sessionAddr, sessionPort, (NormNodeId)nodeId)) { fprintf(stderr, "normStreamer error: unable to open NORM session\n"); NormDestroyInstance(normInstance); return -1; } if (silentReceiver) normStreamer.SetSilentReceiver(true); if (txloss > 0.0) normStreamer.SetTxLoss(txloss); for (unsigned int i = 0; i < ackingNodeCount; i++) normStreamer.AddAckingNode(ackingNodeList[i]); normStreamer.SetNormCongestionControl(ccMode); if (NormStreamer::NORM_FIXED == ccMode) normStreamer.SetNormTxRate(txRate); if (NULL != mcastIface) normStreamer.SetNormMulticastInterface(mcastIface); if (trace) normStreamer.SetNormMessageTrace(true); // TBD - set NORM session parameters normStreamer.Start(send, recv); // TBD - add WIN32 support using win32InputHandler code // and MsgWaitForMultipleObjectsEx() instead of select() int normfd = NormGetDescriptor(normInstance); // Get input/output descriptors and set to non-blocking i/o int inputfd = normStreamer.GetInputDescriptor(); int outputfd = normStreamer.GetOutputDescriptor(); if (-1 == fcntl(inputfd, F_SETFL, fcntl(inputfd, F_GETFL, 0) | O_NONBLOCK)) perror("normStreamer: fcntl(inputfd, O_NONBLOCK) error"); //if (!normStreamer.UdpRelayEnabled()) if (-1 == fcntl(outputfd, F_SETFL, fcntl(outputfd, F_GETFL, 0) | O_NONBLOCK)) perror("normStreamer: fcntl(outputfd, O_NONBLOCK) error"); fd_set fdsetInput, fdsetOutput; FD_ZERO(&fdsetInput); FD_ZERO(&fdsetOutput); #ifdef LINUX // We user timerfd on Linux for more precise timeouts int timerfd = timerfd_create(CLOCK_MONOTONIC, 0); if (timerfd < 0) { perror("normStreamer: timerfd_create() error"); return -1; } #endif // LINUX struct timeval lastTime; gettimeofday(&lastTime, NULL); struct timeval bucketTime = lastTime; while (normStreamer.IsRunning()) { int maxfd = -1; int fdMask = 0; bool waitOnNorm = false; double timeoutInterval = -1.0; if (send) { if (normStreamer.InputNeeded()) { if (normStreamer.InputReady()) { FD_CLR(inputfd, &fdsetInput); timeoutInterval = 0.0; } else { FD_SET(inputfd, &fdsetInput); if (inputfd > maxfd) maxfd = inputfd; fdMask |= 0x01; } } else { FD_CLR(inputfd, &fdsetInput); } if (normStreamer.TxPending()) { if (normStreamer.TxReady()) timeoutInterval = 0.0; else waitOnNorm = true; } } if (recv) { if (normStreamer.RxNeeded()) { if (normStreamer.RxReady()) timeoutInterval = 0.0; else waitOnNorm = true; } if (normStreamer.OutputPending()) { if (normStreamer.OutputReady()) { FD_CLR(outputfd, &fdsetOutput); if (timeoutInterval < 0.0) timeoutInterval = normStreamer.GetOutputBucketTimeout(); } else { FD_SET(outputfd, &fdsetOutput); if (outputfd > maxfd) maxfd = outputfd; fdMask |= 0x02; } } else { FD_CLR(outputfd, &fdsetOutput); } } if (waitOnNorm) { // we need to wait until NORM is tx_ready or rx_ready FD_SET(normfd, &fdsetInput); if (normfd > maxfd) maxfd = normfd; fdMask |= 0x04; } else { FD_CLR(normfd, &fdsetInput); } // Set timeout for select() ... TBD - it may be a slight // performance enhancement to skip the select() call when // the timeout needed is zero??? struct timeval timeout; struct timeval* timeoutPtr = &timeout; #ifdef LINUX if (timeoutInterval > 0.0) { // On Linux, we use the timerfd with our select() call to get // more precise timeouts than select() does alone on Linux struct timespec timeoutSpec; timeoutSpec.tv_sec = (unsigned int)timeoutInterval; timeoutSpec.tv_nsec = 1.0e+09*(timeoutInterval - (double)timeoutSpec.tv_sec); struct itimerspec timerSpec; timerSpec.it_interval.tv_sec = timerSpec.it_interval.tv_nsec = 0; timerSpec.it_value = timeoutSpec; if (0 == timerfd_settime(timerfd, 0, &timerSpec, 0)) { timeoutPtr = NULL; FD_SET(timerfd, &fdsetInput); if (outputfd > maxfd) maxfd = timerfd; fdMask |= 0x08; } else { FD_CLR(timerfd, &fdsetInput); timeout.tv_sec = (unsigned int)timeoutInterval; timeout.tv_usec = 1.0e+06*(timeoutInterval - (double)timeout.tv_sec); perror("normStreamer: timerfd_settime() error"); } } else { // No precision timing needed FD_CLR(timerfd, &fdsetInput); if (timeoutInterval < 0.0) { // We wait one second maximum for debugging purposes timeout.tv_sec = 1; timeout.tv_usec = 0; } else // if (0.0 == timeoutInterval) { timeout.tv_sec = timeout.tv_usec = 0; } } #else // non-LINUX if (timeoutInterval > 0.0) { timeout.tv_sec = (unsigned int)timeoutInterval; timeout.tv_usec = 1.0e+06*(timeoutInterval - (double)timeout.tv_sec); } else if (timeoutInterval < 0.0) { // We wait one second maximum for debugging purposes timeout.tv_sec = 1; timeout.tv_usec = 0; } else // if (0.0 == timeoutInterval) { timeout.tv_sec = timeout.tv_usec = 0; } #endif // if/else LINUX int result = select(maxfd+1, &fdsetInput, &fdsetOutput, NULL, timeoutPtr); switch (result) { case -1: switch (errno) { case EINTR: case EAGAIN: continue; default: perror("normStreamer select() error"); // TBD - stop NormStreamer break; } break; case 0: // timeout break; default: if (FD_ISSET(inputfd, &fdsetInput)) normStreamer.SetInputReady(); if (FD_ISSET(outputfd, &fdsetOutput)) normStreamer.SetOutputReady(); #ifdef LINUX if (FD_ISSET(timerfd, &fdsetInput)) { // clear the timerfd status by reading from it uint64_t expirations = 0; if (read(timerfd, &expirations, sizeof(expirations)) < 0) perror("normStreamer read(timerfd) error"); } #endif // LINUX break; } // We always clear out/handle pending NORM API events // (to keep event queue from building up) NormEvent event; while (NormGetNextEvent(normInstance, &event, false)) normStreamer.HandleNormEvent(event); struct timeval thisTime; gettimeofday(&thisTime, NULL); if (0 != normStreamer.GetOutputBucketDepth()) { // Credit output token bucket for time that has passed double interval = (double)(thisTime.tv_sec - bucketTime.tv_sec); if (thisTime.tv_usec > bucketTime.tv_usec) interval += 1.0e-06 * (thisTime.tv_usec - bucketTime.tv_usec); else interval -= 1.0e-06 * (bucketTime.tv_usec - thisTime.tv_usec); normStreamer.CreditOutputBucket(interval); bucketTime = thisTime; } // for debugging to see if anything gets "stuck" if ((thisTime.tv_sec - lastTime.tv_sec) >= 1) { if (send) fprintf(stderr, "normStreamer: inputNeeded:%d inputReady:%d txPending:%d txReady:%d inputCount:%lu txCount:%lu fdMask:%d\n", normStreamer.InputNeeded(), normStreamer.InputReady(), normStreamer.TxPending(), normStreamer.TxReady(), normStreamer.GetInputByteCount(), normStreamer.GetTxByteCount(), fdMask); if (recv) fprintf(stderr, "normStreamer: rxNeeded:%d rxReady:%d outputPending:%d outputReady:%d fdMask:%d\n", normStreamer.RxNeeded(), normStreamer.RxReady(), normStreamer.OutputPending(), normStreamer.OutputReady(), fdMask); lastTime = thisTime; } // As a result of input/output ready or NORM notification events: // 1) Recv from rx_stream if needed and ready if (normStreamer.RxNeeded() && normStreamer.RxReady()) normStreamer.RecvData(); // 2) Write any pending data to output if output is ready if (normStreamer.OutputPending() && normStreamer.OutputReady()) { if (normStreamer.OutputBucketReady()) normStreamer.WriteOutput(); } // 3) Read from input if needed and ready if (normStreamer.InputNeeded() && normStreamer.InputReady()) normStreamer.ReadInput(); // 4) Send any pending tx message if (normStreamer.TxPending() && normStreamer.TxReady()) normStreamer.SendData(); } // end while(normStreamer.IsRunning() #ifdef LINUX close(timerfd); #endif // LINUX fflush(stderr); close(normStreamer.GetOutputDescriptor()); // TBD - do this in the destructor? NormDestroyInstance(normInstance); fprintf(stderr, "normStreamer exiting ...\n"); return 0; } // end main() norm-1.5.8+dfsg2/examples/python/0000755000000000000000000000000013320270771013530 5ustar norm-1.5.8+dfsg2/examples/python/debugStats.py0000755000000000000000000000260711157545067016230 0ustar #!/usr/bin/env python ''' Example of live plotting of pipe logging data. This has some problems still... ''' import sys import Queue from optparse import OptionParser import Gnuplot # Include the local pynorm in the module search path sys.path.insert(0, "../") from pynorm.extra.pipeparser import PipeParser USAGE = 'usage: %s [options]' % sys.argv[0] DEFAULT_PIPE = 'normtest' def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(pipe=DEFAULT_PIPE) parser.add_option('-p', '--pipe', help='The pipe to connect to (default %s)' % DEFAULT_PIPE) return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 1: print USAGE return 1 pipep = PipeParser(opts.pipe) pipep.start() g = Gnuplot.Gnuplot() g('set data style lines') g.title('FEC Buffer Usage') g.xlabel('Time (s)') g.ylabel('FEC Usage') ydata = [] while True: try: report = pipep.reports.get(False) except Queue.Empty: continue try: ydata.append(report['remote'][0]['fec_cur']) g.plot(list(enumerate(ydata))) except IndexError: continue pipep.reports.task_done() print "Exiting..." # g.reset() # g.close() # del g return 0 if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/fecBufferStats.py0000755000000000000000000000177311157545067017034 0ustar #!/usr/bin/env python ''' Example showing reading debug info from a pipe. ''' import sys import Queue from optparse import OptionParser from pynorm.extra.pipeparser import PipeParser USAGE = 'usage: %s [options]' % sys.argv[0] DEFAULT_PIPE = 'normtest' def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(pipe=DEFAULT_PIPE) parser.add_option('-p', '--pipe', help='The pipe to connect to (default %s)' % DEFAULT_PIPE) return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 1: print USAGE return 1 pipep = PipeParser(opts.pipe) pipep.start() while True: try: report = pipep.reports.get(True, 3) except Queue.Empty: continue try: print report['time'], report['remote'][0]['fec_cur'] except IndexError: pass pipep.reports.task_done() if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/fileRecvManager.py0000755000000000000000000000543111157545067017153 0ustar #!/usr/bin/env python ''' Simple NORM file receiver example app using Python NORM API Shows the usage of the event manager. ''' import sys import os.path from optparse import OptionParser sys.path.insert(0, '../') import pynorm from pynorm.extra.manager import Manager, StopManager USAGE = 'usage: %s [options] ' % sys.argv[0] DEFAULT_ADDR = '224.1.2.3' DEFAULT_PORT = 6003 DEFAULT_PIPE = 'normtest' def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(address=DEFAULT_ADDR, port=DEFAULT_PORT, debug=0, pipe=DEFAULT_PIPE) parser.add_option('-a', '--address', help='The IP address to bind to (default %s)' % DEFAULT_ADDR) parser.add_option('-p', '--port', type=int, help='The port number to listen on (default %i)' % DEFAULT_PORT) parser.add_option('-i', '--iface', help='The inteface to transmit multicast on.') parser.add_option('-d', '--debug', type=int, help='Debug level') parser.add_option('-e', '--pipe', help='Pipe name for logging.') return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 2: print get_option_parser().get_usage() return 1 path = os.path.abspath(args[1]) instance = pynorm.Instance() instance.setCacheDirectory(path) try: instance.openDebugPipe(opts.pipe) except pynorm.NormError: print 'Could not connect to pipe, disabling...' pynorm.setDebugLevel(opts.debug) manager = Manager(instance) manager.register(pynorm.NORM_RX_OBJECT_INFO, newObject, path) # manager.register(pynorm.NORM_RX_OBJECT_UPDATED, updatedObject) manager.register(pynorm.NORM_RX_OBJECT_COMPLETED, complete) manager.register(pynorm.NORM_RX_OBJECT_ABORTED, abort) manager.start() session = instance.createSession(opts.address, opts.port) if opts.iface: session.setMulticastInterface(opts.iface) session.startReceiver(1024*1024) print 'Starting listener on %s:%i' % (opts.address, opts.port) try: while True: manager.join(2) except KeyboardInterrupt: pass print 'Exiting...' instance.stop() manager.join() return 0 def newObject(event, path): print 'Filename = %s' % event.object.getInfo() event.object.filename = os.path.join(path, event.object.getInfo()) print 'Downloading file %s' % event.object.filename def updatedObject(event): print 'File %s - %i bytes left to download' % (event.object.filename, event.object.bytesPending) def complete(event): print 'File %s completed' % event.object.filename raise StopManager() def abort(event): print 'File %s aborted' % event.object.filename raise StopManager() if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/normFileFeedback.py0000755000000000000000000001031711213302212017250 0ustar #!/usr/bin/env python ''' Simple NORM file sender example app using Python NORM API ''' import sys import os.path import pickle from optparse import OptionParser from random import randint import pynorm import pynorm.constants as c DEFAULT_ADDR = '224.1.2.3' DEFAULT_PORT = 6003 def get_option_parser(): parser = OptionParser() parser.set_defaults(address=DEFAULT_ADDR, port=DEFAULT_PORT) parser.add_option('-s', '--send', help='The file to send.') parser.add_option('-r', '--receive', help='The directory to cache recieved files.') parser.add_option('-a', '--address', help='The IP address to bind to (default %s)' % DEFAULT_ADDR) parser.add_option('-p', '--port', type=int, help='The port number to listen on (default %i)' % DEFAULT_PORT) parser.add_option('-i', '--iface', help='The inteface to transmit multicast on.') return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 1: print 'Error: Invalid arguments' print get_option_parser().format_help() return 1 if opts.send is None and opts.receive is None: print 'No operation specified!' print 'Must provide a --send or --receive flag!' print get_option_parser().format_help() return 1 instance = pynorm.Instance() session = instance.createSession(opts.address, opts.port) if opts.iface: session.setMulticastInterface(opts.iface) session.setTxRate(256e10) session.startReceiver(1024*1024) session.startSender(randint(0, 1000), 1024**2, 1400, 64, 16) if opts.receive is not None: path = os.path.abspath(opts.receive) instance.setCacheDirectory(path) print 'Setting cache directory to %s' % path if opts.send is not None: filepath = os.path.abspath(opts.send) filename = opts.send[opts.send.rfind('/')+1:] print 'Sending file %s' % filename session.fileEnqueue(filepath, filename) try: for event in instance: if event.type == c.NORM_TX_FLUSH_COMPLETED: if event.object.type == c.NORM_OBJECT_FILE: print 'Flush completed for file %s' % event.object.filename elif event.type == c.NORM_RX_OBJECT_INFO: if event.object.type == c.NORM_OBJECT_FILE: event.object.filename = os.path.join(path, event.object.info) print 'Downloading file %s' % event.object.filename elif event.object.type == c.NORM_OBJECT_DATA: # I put the sender node ID in the info field # If it doesn't match ours, we dont care about it if int(event.object.info) != session.nodeId: event.object.cancel() elif event.type == c.NORM_RX_OBJECT_UPDATED: if event.object.type == c.NORM_OBJECT_FILE: print 'File %s - %i bytes left to download' % ( event.object.filename, event.object.bytesPending) # Let the sender know how much we have done data = pickle.dumps((event.object.filename, event.object.bytesPending), -1) session.dataEnqueue(data, str(event.object.sender.id)) elif event == 'NORM_RX_OBJECT_COMPLETED': if event.object.type == c.NORM_OBJECT_FILE: print 'File %s completed' % event.object.filename elif event.object.type == c.NORM_OBJECT_DATA: try: # This fails sometimes, not sure why yet, so ignore errors filename, pending = pickle.loads(event.object.accessData()) except KeyError: continue print 'Node %i - File: %s - Pending: %i' % (event.object.sender.id, filename, pending) elif event == 'NORM_RX_OBJECT_ABORTED': if event.object.type == c.NORM_OBJECT_FILE: print 'File %s aborted' % event.object.filename except KeyboardInterrupt: pass print 'Exiting.' return 0 # end main if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/normFileRecv.py0000755000000000000000000000404211157545067016511 0ustar #!/usr/bin/env python ''' Simple NORM file receiver example app using Python NORM API ''' import sys, os.path from optparse import OptionParser import pynorm USAGE = 'usage: %s [options] ' % sys.argv[0] DEFAULT_ADDR = '224.1.2.3' DEFAULT_PORT = 6003 def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(address=DEFAULT_ADDR, port=DEFAULT_PORT) parser.add_option('-a', '--address', help='The IP address to bind to (default %s)' % DEFAULT_ADDR) parser.add_option('-p', '--port', type=int, help='The port number to listen on (default %i)' % DEFAULT_PORT) parser.add_option('-i', '--iface', help='The inteface to transmit multicast on.') return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 2: print get_option_parser().get_usage() return 1 path = os.path.abspath(args[1]) instance = pynorm.Instance() instance.setCacheDirectory(path) session = instance.createSession(opts.address, opts.port) if opts.iface: session.setMulticastInterface(opts.iface) session.startReceiver(1024*1024) try: for event in instance: if event == 'NORM_RX_OBJECT_INFO': event.object.filename = os.path.join(path, event.object.info) print 'Downloading file %s' % event.object.filename elif event == 'NORM_RX_OBJECT_UPDATED': print 'File %s - %i bytes left to download' % ( event.object.filename, event.object.bytesPending) elif event == 'NORM_RX_OBJECT_COMPLETED': print 'File %s completed' % event.object.filename return 0 elif event == 'NORM_RX_OBJECT_ABORTED': print 'File %s aborted' % event.object.filename return 1 else: print event except KeyboardInterrupt: pass print 'Exiting.' return 0 if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/normFileSend.py0000755000000000000000000000327211213302212016457 0ustar #!/usr/bin/env python ''' Simple NORM file sender example app using Python NORM API ''' import sys, os.path from optparse import OptionParser from random import randint import pynorm USAGE = 'usage: %s [options] ' % sys.argv[0] DEFAULT_ADDR = '224.1.2.3' DEFAULT_PORT = 6003 def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(address=DEFAULT_ADDR, port=DEFAULT_PORT) parser.add_option('-a', '--address', help='The IP address to bind to (default %s)' % DEFAULT_ADDR) parser.add_option('-p', '--port', type=int, help='The port number to listen on (default %i)' % DEFAULT_PORT) parser.add_option('-i', '--iface', help='The inteface to transmit multicast on.') return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 2: print get_option_parser().get_usage() return 1 filepath = os.path.abspath(args[1]) filename = args[1][args[1].rfind('/')+1:] instance = pynorm.Instance() session = instance.createSession(opts.address, opts.port) if opts.iface: session.setMulticastInterface(opts.iface) session.setTxRate(256e10) session.startSender(randint(0, 1000), 1024**2, 1400, 64, 16) print 'Sending file %s' % filename session.fileEnqueue(filepath, filename) try: for event in instance: if event == 'NORM_TX_FLUSH_COMPLETED': print 'Flush completed, exiting.' return 0 else: print event except KeyboardInterrupt: pass print 'Exiting.' return 0 # end main if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/normMsgr.py0000644000000000000000000003547612307753352015732 0ustar from threading import Thread, Lock import sys import random import pynorm import signal import time from collections import deque MSG_HDR_SIZE = 2 class InputThread(Thread): """This thread reads 'messages" from STDIN and send them""" def __init__(self, parent, *args, **kwargs): super(InputThread, self).__init__(*args, **kwargs) self.setDaemon(True) ;# this is "child" daemon thread self.msgr = parent def run(self): while True: try: msgHdr = bytearray(sys.stdin.read(MSG_HDR_SIZE)) except: sys.stderr.write("normMsgr: input thread end-of-file 1 ...\n") return try: msgSize = 256*int(msgHdr[0]) + int(msgHdr[1]) msgBuffer = sys.stdin.read(msgSize - 2) except: sys.stderr.write("normMsgr: input thread end-of-file 2 ...\n") return msgr.sendMessage(msgBuffer) ;# will block if NORM not "tx ready" class OutputThread(Thread): """This thread writes received 'messages" to STDOUT.""" def __init__(self, parent, *args, **kwargs): super(OutputThread, self).__init__(*args, **kwargs) self.setDaemon(True) ;# this is "child" daemon thread self.msgr = parent def run(self): while True: msg = msgr.getRxMsg() ;# will block if none ready msgLen = len(msg) + MSG_HDR_SIZE msgHeader = bytearray(MSG_HDR_SIZE) msgHeader[0] = (msgLen >> 8) & 0x00ff msgHeader[1] = msgLen & 0x00ff sys.stdout.write(msgHeader) sys.stdout.write(msg) del msg class NormMsgr: """This class keeps state for NORM tx/rx operations""" def __init__(self): self.normInstance = pynorm.Instance() self.normSession = None # Sender state members self.normTxLock = Lock() ;# for thread-safe access to NORM tx state variables self.normTxReady = Lock() self.norm_tx_vacancy = True self.norm_tx_queue_count = 0 self.norm_tx_queue_max = 2048 self.norm_tx_watermark_pending = False self.norm_acking = False self.tx_msg_cache = {} # Receiver state members self.normRxLock = Lock() self.normRxReady = Lock() self.normRxReady.acquire() ;# no rx messages yet self.output_msg_queue = deque() random.seed(None) ;# seeds with current time def openNormSession(self, addr, port, nodeId): # Create a NormSession and set some default parameters self.normSession = self.normInstance.createSession(addr, port, nodeId) self.normSession.setRxCacheLimit(2*self.norm_tx_queue_max) ;# we let the receiver track some extra objects self.normSession.setDefaultSyncPolicy(pynorm.NORM_SYNC_ALL); self.normSession.setDefaultUnicastNack(True); self.normSession.setTxCacheBounds(10*1024*1024, self.norm_tx_queue_max, self.norm_tx_queue_max); self.normSession.setCongestionControl(True, True); return self.normSession def addAckingNode(self, nodeId): self.normSession.addAckingNode(nodeId); self.norm_acking = True def setNormMulticastInterface(self, ifaceName): self.normSession.setMulticastInterface(ifaceName) def setNormCCMode(self, ccMode): if ccMode == "cc": self.normSession.setEcnSupport(False, False, False) elif ccMode == "cce": self.normSession.setEcnSupport(True, True) elif ccMode == "ccl": self.normSession.setEcnSupport(False, False, True) elif ccMode == "fixed": self.normSession.setEcnSupport(False, False, False) else: raise Exception("normMsgr: invalid ccMode \"%s\"" % ccMode) if ccMode != "fixed": self.normSession.setCongestionControl(True) else: self.normSession.setCongetstionControl(False) def setNormTxRate(self, bitsPerSecond): self.normSession.setTxRate(bitsPerSecond) def setNormDebugLevel(self, level): self.normInstance.setDebugLevel(level) def setNormMessageTrace(self, state): self.normSession.setMessageTrace(state) def start(self, send, recv): if (recv): self.normSession.startReceiver(10*1024*1024) if (send): if (self.norm_acking): self.normSession.setFlowControl(0.0) # We use a random sender instanceId in case of stop/restart instanceId = random.randint(0, 0xffff) self.normSession.startSender(instanceId, 10*1024*1024, 1400, 16, 4); def stop(self): del self.normInstance self.normInstance = None def sendMessage(self, msgBuf): # caller will be blocked if NORM is (or becomes) not "tx ready" while not self.enqueueMessageObject(msgBuf): #sys.stderr.write("enqueue message was blocked\n") continue def enqueueMessageObject(self, msgBuf): self.normTxReady.acquire() ;# this blocks until NORM is "tx ready" with self.normTxLock: #sys.stderr.write("normMsgr: sending %d byte message payload ...\n" % len(msgBuf)) obj = self.normSession.dataEnqueue(msgBuf) if obj is None: self.norm_tx_vacancy = False ;# will be cleared by NORM_TX_QUEUE_EMPTY, etc return False # cache the sent msgBuf until NORM_TX_OBJECT_PURGED self.tx_msg_cache[obj] = msgBuf if (self.norm_acking): # Manage ack-based flow control state self.norm_tx_queue_count += 1 if not self.norm_tx_watermark_pending: if self.norm_tx_queue_count >= self.norm_tx_queue_max/2: #sys.stderr.write("setting watermark ...\n") self.normSession.setWatermark(obj) #sys.stderr.write("watermark set.\n"); self.norm_tx_watermark_pending = True if self.norm_tx_queue_count >= self.norm_tx_queue_max: # Don't release "normTxReady" since cache is filled # (Will be released upon NORM_TX_WATERMARK_COMPLETED) return True self.normTxReady.release() return True def onNormTxObjectPurged(self, obj): with self.normTxLock: if pynorm.NORM_OBJECT_DATA == obj.getType(): del self.tx_msg_cache[obj] def onNormTxQueueVacancy(self): with self.normTxLock: wasTxReady = self.norm_tx_vacancy if wasTxReady and self.norm_acking: wasTxReady = self.norm_tx_queue_count < self.norm_tx_queue_max self.norm_tx_vacancy = True if self.norm_acking: isTxReady = self.norm_tx_queue_count < self.norm_tx_queue_max else: isTxReady = False if isTxReady and not wasTxReady: if self.normTxReady.acquire(False): sys.stderr.write("normMsgr onNormTxQueueVacancy() warning: normTxReady wasn't locked?!\n") #sys.stderr.write("tx vacancy releasing norm tx ready ...\n"); self.normTxReady.release() def onNormTxWatermarkCompleted(self): with self.normTxLock: wasTxReady = self.norm_tx_vacancy if wasTxReady and self.norm_acking: wasTxReady = self.norm_tx_queue_count < self.norm_tx_queue_max self.norm_tx_watermark_pending = False self.norm_tx_queue_count -= self.norm_tx_queue_max / 2 isTxReady = self.norm_tx_vacancy if isTxReady and self.norm_acking: isTxReady = self.norm_tx_queue_count < self.norm_tx_queue_max else: isTxReady = False if isTxReady and not wasTxReady: if self.normTxReady.acquire(False): sys.stderr.write("normMsgr onNormTxWatermarkCompleted() warning: normTxReady wasn't locked?!\n") #sys.stderr.write("watermark completion releasing norm tx ready ...\n") self.normTxReady.release() def onNormRxObjectCompleted(self, obj): with self.normRxLock: if pynorm.NORM_OBJECT_DATA == obj.getType(): if 0 != len(self.output_msg_queue): wasEmpty = False else: wasEmpty = True msg = obj.getData() self.output_msg_queue.append(msg) if wasEmpty: #sys.stderr.write("releasing normRxReady ...\n") self.normRxReady.release() ;# unblocks waiting OutputThread def getRxMsg(self): self.normRxReady.acquire() ;# blocks if output_msg_queue is empty with self.normRxLock: msg = self.output_msg_queue.popleft() if 0 != len(self.output_msg_queue): self.normRxReady.release() ;# not empty yet return msg def getNextNormEvent(self): if self.normInstance is None: return None else: return self.normInstance.getNextEvent() class NormEventHandler(Thread): """This thread calls normInstance.getNextEvent() and handles the events""" def __init__(self, parentMsgr, *args, **kwargs): super(NormEventHandler, self).__init__(*args, **kwargs) self.setDaemon(True) ;# this is "child" daemon thread self.lock = Lock() self.msgr = parentMsgr def run(self): self.lock.acquire() while True: try: event = self.msgr.getNextNormEvent() except: sys.stderr.write("get next event exception\n"); self.lock.release() return if event is None: break if pynorm.NORM_EVENT_INVALID == event.type: continue elif pynorm.NORM_TX_QUEUE_EMPTY == event.type or pynorm.NORM_TX_QUEUE_VACANCY == event.type: msgr.onNormTxQueueVacancy() elif pynorm.NORM_TX_WATERMARK_COMPLETED == event.type: if pynorm.NORM_ACK_SUCCESS == event.session.getAckingStatus(): # All receivers acknowledged msgr.onNormTxWatermarkCompleted() else: # TBD - we could see who didn't ACK and possibly remove them # from our acking list. For now, we are infinitely # persistent by resetting watermark ack request event.session.resetWatermark() elif pynorm.NORM_TX_OBJECT_PURGED == event.type: msgr.onNormTxObjectPurged(event.object) elif pynorm.NORM_RX_OBJECT_COMPLETED == event.type: msgr.onNormRxObjectCompleted(event.object) #else: # sys.stderr.write("normMsgr: NormEventHandler warning: unhandled event: %s\n" % str(event)) sys.stderr.write("normMsgr: NormEventHandler thread exiting ...\n"); self.lock.release() def usage(): sys.stderr.write("Usage: normMsgr.py id {send &| recv} [addr [/]][ack [,,...]\n" + " [cc|cce|ccl|rate ][interface ][debug ][trace]\n") # Default parameters nodeId = None sessionAddr = "224.1.2.3" sessionPort = 6003 send = False recv = False ccMode = "cc" txRate = None ackerList = [] debugLevel = 3 normTrace = False mcastIface = None # Parse command-line cmd = None val = None try: i = 1 while i < len(sys.argv): cmd = sys.argv[i] i += 1 if "id" == cmd: val = sys.argv[i] nodeId = int(val) i += 1 elif "addr" == cmd: val = sys.argv[i] i += 1 if "/" in val: field = val.split('/') sessionAddr = field[0] sessionPort = int(field[1]) else: sessionAddr = val elif "send" == cmd: send = True elif "recv" == cmd: recv = True elif "cc" == cmd: ccMode = "cc" elif "cce" == cmd: ccMode = "cce" elif "ccl" == cmd: ccMode = "ccl" elif "rate" == cmd: val = sys.argv[i] rxRate = float(val) ccMode = "fixed" i += 1 elif "ack" == cmd: alist = sys.argv[i].split(',') for val in alist: ackerList.append(int(val)) elif "debug" == cmd: val = sys.argv[i] debugLevel = int(val) i += 1 elif "trace" == cmd: normTrace = True else: sys.stderr.write("normMsgr error: invalid command \"%s\"\n" % cmd) except Exception as e: sys.stderr.write("normMsgr \"" + cmd + " " + val + "\" argument error: " + e.__str__() + "\n") usage() sys.exit(-1) if not send and not recv: sys.stderr.write("normMsgr error: not configured to send or recv!\n") usage() sys.exit(-1) if nodeId is None: sys.stderr.write("normMsgr error: no local 'id' provided!\n") usage() sys.exit(-1) # Instantiate a NormMsgr and set its parameters msgr = NormMsgr() msgr.setNormDebugLevel(debugLevel) sys.stderr.write("normMsgr: opening norm session ...\n") msgr.openNormSession(sessionAddr, sessionPort, nodeId) if mcastIface: msgr.setNormMulticastInterface(mcastIface) for node in ackerList: msgr.addAckingNode(node) msgr.setNormCCMode(ccMode); if "fixed" == ccMode: msgr.setNormTxRate(txRate) msgr.setNormMessageTrace(normTrace) msgr.start(send, recv) sys.stderr.write("normMsgr: starting NormEventHandler ...\n") normEventHandler = NormEventHandler(msgr) normEventHandler.start() if send: sys.stderr.write("normMsgr: starting input thread ...\n") inputThread = InputThread(msgr) inputThread.start() if recv: sys.stderr.write("normMsgr: starting output thread ...\n") outputThread = OutputThread(msgr) outputThread.start() # The main thread just sits on a loop that sleeps and wakes up # once in a while. We could have made any of the other threads # the main loop if we had wanted. Since all the other threads # were child "daemons", they will get killed when this main exits # TBD - provide for a graceful/clean sender/receiver termination try: sys.stderr.write("normMsgr: running (use Crtl-C to exit) ...\n") while True: time.sleep(5) #sys.stderr.write("woke up ...\n") except KeyboardInterrupt: #sys.stderr.write("exception while waiting on input thread ..\n"); pass sys.stderr.write("normMsgr: Done.\n") norm-1.5.8+dfsg2/examples/python/rawRecv.py0000755000000000000000000000666511157545067015544 0ustar #!/usr/bin/env python ''' Example of using the NORM library directly. You really shouldn't need to do this. Use the pretty API instead. But its here if you need it. ''' import sys import os.path import ctypes from optparse import OptionParser from pynorm.core import libnorm, NormEventStruct import pynorm.constants as c USAGE = 'usage: %s [options] ' % sys.argv[0] DEFAULT_ADDR = '224.1.2.3' DEFAULT_PORT = 6003 def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(address=DEFAULT_ADDR, port=DEFAULT_PORT) parser.add_option('-a', '--address' help='The IP address to bind to (default %s)' % DEFAULT_ADDR) parser.add_option('-p', '--port', type=int, help='The port number to listen on (default %i)' % DEFAULT_PORT) parser.add_option('-i', '--iface', help='The inteface to transmit multicast on.') return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 2: print get_option_parser().get_usage() return 1 path = os.path.abspath(args[1]) instance = libnorm.NormCreateInstance(False) session = libnorm.NormCreateSession(instance, opts.address, opts.port, c.NORM_NODE_ANY) if opts.iface: libnorm.NormSetMulticastInterface(session, opts.iface) libnorm.NormSetCacheDirectory(instance, path) libnorm.NormStartReceiver(session, 1024*1024) theEvent = NormEventStruct() try: while libnorm.NormGetNextEvent(instance, ctypes.byref(theEvent)): if theEvent.type == c.NORM_RX_OBJECT_NEW: print 'rawRecv.py: NORM_RX_OBJECT_NEW event ...' elif theEvent.type == c.NORM_RX_OBJECT_INFO: print 'rafRecv.py: NORM_RX_OBJECT_INFO event ...' if c.NORM_OBJECT_FILE == libnorm.NormObjectGetType(theEvent.object): length = libnorm.NormObjectGetInfoLength(theEvent.object) buffer = ctypes.create_string_buffer(length) recv = libnorm.NormObjectGetInfo(theEvent.object, buffer, length) if recv == 0: print 'Error' filename = os.path.join(path, buffer.value) print 'Filename - %s' % filename libnorm.NormFileRename(theEvent.object, filename) elif theEvent.type == c.NORM_RX_OBJECT_UPDATED: size = libnorm.NormObjectGetSize(theEvent.object) completed = size - libnorm.NormObjectGetBytesPending(theEvent.object) percent = 100.0 * (float(completed) / float(size)) print '%.1f completed' % percent elif theEvent.type == c.NORM_RX_OBJECT_COMPLETED: print 'Complete' return 0 elif theEvent.type == c.NORM_RX_OBJECT_ABORTED: print 'Aborted' return 0 elif theEvent.type == c.NORM_REMOTE_SENDER_NEW: print 'New sender' elif theEvent.type == c.NORM_REMOTE_SENDER_ACTIVE: print 'Sender active' elif theEvent.type == c.NORM_REMOTE_SENDER_INACTIVE: print 'Sender inactive' except KeyboardInterrupt: pass libnorm.NormStopReceiver(session) libnorm.NormDestroySession(session) libnorm.NormDestroyInstance(instance) print 'Exiting.' return 0 if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/python/streamChat.py0000755000000000000000000000557011157545067016220 0ustar #!/usr/bin/env python ''' Simple NORM file receiver example app using Python NORM API Shows off streaming with a super simple chat app. ''' import sys import os.path import curses import curses.textpad from threading import Thread from optparse import OptionParser from random import randint import pynorm from pynorm.extra.manager import Manager, StopManager USAGE = 'usage: %s [options] name' % sys.argv[0] DEFAULT_ADDR = '224.1.2.3' DEFAULT_PORT = 6003 def get_option_parser(): parser = OptionParser(usage=USAGE) parser.set_defaults(address=DEFAULT_ADDR, port=DEFAULT_PORT) parser.add_option('-a', '--address', help='The IP address to bind to (default %s)' % DEFAULT_ADDR) parser.add_option('-p', '--port', type=int, help='The port number to listen on (default %i)' % DEFAULT_PORT) parser.add_option('-i', '--iface', help='The inteface to transmit multicast on.') return parser def main(argv): (opts, args) = get_option_parser().parse_args(argv) if len(args) != 2: print get_option_parser().get_usage() return 1 instance = pynorm.Instance() session = instance.createSession(opts.address, opts.port) if opts.iface: session.setMulticastInterface(opts.iface) session.startReceiver(1024*1024) session.startSender(randint(0, 1000), 1024**2, 1400, 64, 16) stream = session.streamOpen(1024*1024) gui = Gui(stream, args[1]) manager = Manager(instance) manager.register(pynorm.NORM_RX_OBJECT_UPDATED, lambda e: gui.showText(e.object.streamRead(1024)[1])) # manager.register(pynorm.NORM_RX_OBJECT_INFO, # lambda e: gui.showText('%s joined the chat' % e.object.info)) manager.start() try: curses.wrapper(gui) except KeyboardInterrupt: pass print 'Exiting...' stream.streamClose(True) instance.stop() manager.join() return 0 class Gui(object): def __init__(self, stream, name): self.stream = stream self.name = name self.curline = 0 def __call__(self, stdscr): self.stdscr = stdscr maxy, maxx = stdscr.getmaxyx() self.chatwin = curses.newwin(maxy - 2, maxx, 0, 0) self.chatwin.scrollok(True) typewin = curses.newwin(1, maxx, maxy-1, 0) textbox = curses.textpad.Textbox(typewin) while True: self.send(textbox.edit()) typewin.erase() def send(self, text): msg = '%s: %s' % (self.name, text) self.stream.streamWrite(msg) self.stream.streamFlush(True) self.showText(msg) def showText(self, msg): maxy, maxx = self.stdscr.getmaxyx() if self.curline >= maxy: self.curline = maxy - 1 self.chatwin.addstr(self.curline, 0, msg) self.curline += 1 self.chatwin.refresh() if __name__ == '__main__': sys.exit(main(sys.argv)) norm-1.5.8+dfsg2/examples/win32InputHandler.cpp0000644000000000000000000001551313201671016016173 0ustar #include #include // for perror() #include // for memset() #include // for _beginthreadex(), _endthreadex() // This class creates a child thread to read STDIN into a buffer. // An event is set that can be monitored by the parent to know // when input is available. Mutexes are used to regulate the // thread's reading (i.e., flow control). class Win32InputHandler { public: Win32InputHandler(); ~Win32InputHandler(); bool Open(int buflen = 4096); void Close(); // The event handle returned here can be used in // a call like WaitForSignalObject() to get notified // when there is data to be read. HANDLE GetEventHandle() const {return input_event;} // This does not block and the input_event // handle is a cue for when to call it // Returns number of bytes copied into "buffer" // (-1 is returned upon input error (input closed)) int ReadData(char* buffer, int numBytes); private: static unsigned int __stdcall DoThreadOpen(void* param); unsigned int Run(); HANDLE input_handle; HANDLE input_event; HANDLE thread_handle; bool input_ready; char* input_buffer; int input_buflen; int input_index; int input_outdex; CONDITION_VARIABLE buffer_vacancy; CRITICAL_SECTION buffer_lock; bool is_running; int input_length; bool input_error; }; // end class Win32InputHandler Win32InputHandler::Win32InputHandler() : input_handle(NULL), input_event(NULL), thread_handle(NULL), input_ready(false), input_buffer(NULL), input_buflen(0), input_index(0), input_outdex(0), is_running(false), input_length(0), input_error(false) { } Win32InputHandler::~Win32InputHandler() { if (is_running) Close(); } bool Win32InputHandler::Open(int buflen) { if (is_running) Close(); if (NULL != input_buffer) { input_buffer = NULL; delete[] input_buffer; } input_buflen = input_index = input_outdex = input_length = 0; input_error = false; if (NULL != input_event) CloseHandle(input_event); // Get the STDIN handle whatever it may be input_handle = GetStdHandle(STD_INPUT_HANDLE); /*if (FILE_TYPE_CHAR == GetFileType(input_handle)) { // The STDIN is a console DWORD consoleMode; bool result = GetConsoleMode(input_handle, &consoleMode); consoleMode &= ~(ENABLE_LINE_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT); SetConsoleMode(input_handle, consoleMode); }*/ // Create an event handle, non-signaled initially input_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (NULL == input_event) { perror("Win32InputHandler::Open() CreateEvent() error"); return false; } if (NULL == (input_buffer = new char[buflen])) { perror("Win32InputHandler::Open() new input_buffer error"); CloseHandle(input_event); input_event = NULL; return false; } input_buflen = buflen; InitializeConditionVariable(&buffer_vacancy); InitializeCriticalSection(&buffer_lock); is_running = true; if (0 == (thread_handle = (HANDLE)_beginthreadex(NULL, 0, DoThreadOpen, this, 0, NULL))) { perror("Win32InputHandler::Open() _beginthreadex() error"); DeleteCriticalSection(&buffer_lock); delete[] input_buffer; input_buffer = NULL; CloseHandle(input_event); input_event = NULL; return false; } return true; } // end Win32InputHandler::Open() void Win32InputHandler::Close() { EnterCriticalSection(&buffer_lock); is_running = false; WakeConditionVariable(&buffer_vacancy); // in case it was full LeaveCriticalSection(&buffer_lock); WaitForSingleObject(thread_handle, INFINITE); DeleteCriticalSection(&buffer_lock); delete[] input_buffer; input_buffer = NULL; CloseHandle(input_event); input_event = NULL; } // end Win32InputHandler::Close() unsigned int __stdcall Win32InputHandler::DoThreadOpen(void* param) { Win32InputHandler* inputHandler = reinterpret_cast(param); unsigned int exitStatus = inputHandler->Run(); _endthreadex(exitStatus); return exitStatus; } // end Win32InputHandler::DoThreadOpen() unsigned int Win32InputHandler::Run() { // This loop is for the child thread to read input one byte at a time // (Since consoles/anonymous pipes don't support async i/o) // The input bytes are copied to a circularly-managed "input_buffer" // that can be accessed via the "ReadData()" method by the parent while (is_running) { // Read input one byte at a time and buffer DWORD dwRead = 0; BOOL result = ReadFile(input_handle, input_buffer+input_index, 1, &dwRead, NULL); EnterCriticalSection(&buffer_lock); if (result) { if (0 != dwRead) { input_length++; input_index++; if (input_index >= input_buflen) input_index = 0; } else { LeaveCriticalSection(&buffer_lock); continue; } } else { // What do we do on error?! input_error = true; is_running = false; } // Signals the parent of data ready (or error) if (!input_ready) { SetEvent(input_event); input_ready = true; } // If the buffer has been filled, this blocks this child // loop until buffer space is available or it is stopped. while ((input_index == input_outdex) && (0 != input_length) && is_running) SleepConditionVariableCS(&buffer_vacancy, &buffer_lock, INFINITE); LeaveCriticalSection(&buffer_lock); } // end while(is_running) return (input_error ? 1 : 0); } // end Win32InputHandler::Run() // Called by parent to gobble up data (non-blocking read) // Returns number of bytes read or -1 on error (e.g., STDIN pipe closed) int Win32InputHandler::ReadData(char* buffer, int numBytes) { EnterCriticalSection(&buffer_lock); if ((0 != input_length) && (0 != numBytes)) { if (numBytes > input_length) numBytes = input_length; input_length -= numBytes; if (0 == input_length) { // On error condition, the event is left triggered // after the input_buffer is emptied so parent gets // all data buffered before the error (e.g., eof) // occurred. if (input_ready && !input_error) { input_ready = false; ResetEvent(input_event); } } // Copy "numBytes" of available data to caller's "buffer" // (two-step process when input_buffer wraps) unsigned int offset = input_outdex; input_outdex += numBytes; if (input_outdex >= input_buflen) { input_outdex -= input_buflen; unsigned int count = numBytes - input_outdex; memcpy(buffer, input_buffer+offset, count); if (0 != input_outdex) memcpy(buffer+count, input_buffer, input_outdex); } else { memcpy(buffer, input_buffer + offset, numBytes); } } else { // Doing the error check if (input_error && (0 != numBytes)) numBytes = -1; // to indicate an error has occurred and child is dead else numBytes = 0; } // This wakes up the child if it is sleeping because the buffer was full if (numBytes > 0) WakeConditionVariable(&buffer_vacancy); LeaveCriticalSection(&buffer_lock); return numBytes; } // end Win32InputHandler::ReadData() norm-1.5.8+dfsg2/examples/wintest.cpp0000644000000000000000000000212513147421107014406 0ustar #include "win32InputHandler.cpp" // for class Win32InputHandler #include #include #include #define BUFSIZE 4096 int main(int argc, char** argv) { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (argc > 1) { // Generate random output const char* text = "This is some text to output\n"; int textlen = strlen(text); while (true) { int count = rand() % 100; while (count > 0) { printf(text); DWORD dwWritten; BOOL fSuccess = WriteFile(hStdout, text, textlen, &dwWritten, NULL); count -= textlen; } int delay = (rand() % 1000); Sleep(1000); } return 0; } Win32InputHandler inputHandler; inputHandler.Start(); while (true) { char buffer[BUFSIZE]; WaitForSingleObject(inputHandler.GetEventHandle(), INFINITE); int numBytes = inputHandler.ReadData(buffer, 1024); if (numBytes < 0) break; DWORD dwWritten; BOOL fSuccess = WriteFile(hStdout, buffer, numBytes, &dwWritten, NULL); } inputHandler.Stop(); return 0; } // end main() norm-1.5.8+dfsg2/include/0000755000000000000000000000000013320270770012013 5ustar norm-1.5.8+dfsg2/include/galois.h0000644000000000000000000000350307723433227013453 0ustar /********************************************************************* * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution, and * * (3) all advertising materials mentioning features or use of this * software display the following acknowledgment: * * "This product includes software written and developed * by Brian Adamson and Joe Macker of the Naval Research * Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ********************************************************************/ #ifndef _NORM_GALOIS #define _NORM_GALOIS namespace Norm { extern const unsigned char GINV[256]; extern const unsigned char GEXP[512]; extern const unsigned char GMULT[256][256]; } inline unsigned char gexp(unsigned int x) {return Norm::GEXP[x];} inline unsigned char gmult(unsigned int x, unsigned int y) {return Norm::GMULT[x][y];} inline unsigned char ginv(unsigned int x) {return Norm::GINV[x];} #endif // _NORM_GALOIS norm-1.5.8+dfsg2/include/normApi.h0000644000000000000000000006411513320171766013605 0ustar #ifndef _NORM_API #define _NORM_API /******************************************************************************* * NOTE: To use NORM as a DLL on Win32 platforms, the macro "NORM_USE_DLL" must be * defined. Otherwise, the static library "NormLib.lib" is built and should * be used for your code compilation and linking. ********************************************************************************/ #ifdef WIN32 #include #include #include // for UINT32/INT32, etc types #ifdef NORM_USE_DLL #ifdef _NORM_API_BUILD #define NORM_API_LINKAGE __declspec(dllexport) // to support building of "Norm.dll" #else #define NORM_API_LINKAGE __declspec(dllimport) // to let apps use "Norm.dll" functions #endif // if/else _NORM_API_BUILD #else #define NORM_API_LINKAGE #endif // if/else NORM_USE_DLL #else #include // for "off_t" #include // for proper uint32_t, etc definitions typedef int8_t INT8; typedef int16_t INT16; #ifdef _USING_X11 typedef long int INT32; #else typedef int32_t INT32; #endif // if/else _USING_X11 typedef uint8_t UINT8; typedef uint16_t UINT16; typedef uint32_t UINT32; #if (defined __GNUC__ && __GNUC__ >= 4) #define NORM_API_LINKAGE __attribute__ ((visibility ("default"))) #else #define NORM_API_LINKAGE #endif #endif // if/else WIN32/UNIX //////////////////////////////////////////////////////////// // IMPORTANT NOTICE // The NORM API is _very_ much in a developmental phase // right now. So, although this code is available in // source code distribution, it is very much subject // to change in future revisions. The goal of the NORM // API _will_ be to provide a stable base of function calls // for applications to use, even as the underlying NORM // C++ code continues to evolve. But, until this notice // is removed, the API shouldn't be considered final. #ifndef __cplusplus # include # define DEFAULT(arg) #else # define DEFAULT(arg) = arg #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define NORM_VERSION_MAJOR 1 #define NORM_VERSION_MINOR 5 #define NORM_VERSION_PATCH 7 /** NORM API Types */ typedef const void* NormInstanceHandle; extern NORM_API_LINKAGE const NormInstanceHandle NORM_INSTANCE_INVALID; typedef const void* NormSessionHandle; extern NORM_API_LINKAGE const NormSessionHandle NORM_SESSION_INVALID; typedef UINT16 NormSessionId; typedef const void* NormNodeHandle; extern NORM_API_LINKAGE const NormNodeHandle NORM_NODE_INVALID; typedef UINT32 NormNodeId; extern NORM_API_LINKAGE const NormNodeId NORM_NODE_NONE; extern NORM_API_LINKAGE const NormNodeId NORM_NODE_ANY; typedef const void* NormObjectHandle; extern NORM_API_LINKAGE const NormObjectHandle NORM_OBJECT_INVALID; typedef UINT16 NormObjectTransportId; #ifdef WIN32 typedef __int64 NormSize; #else typedef off_t NormSize; #endif // WIN32 NORM_API_LINKAGE typedef enum NormObjectType { NORM_OBJECT_NONE, NORM_OBJECT_DATA, NORM_OBJECT_FILE, NORM_OBJECT_STREAM } NormObjectType; NORM_API_LINKAGE typedef enum NormFlushMode { NORM_FLUSH_NONE, NORM_FLUSH_PASSIVE, NORM_FLUSH_ACTIVE } NormFlushMode; NORM_API_LINKAGE typedef enum NormNackingMode { NORM_NACK_NONE, NORM_NACK_INFO_ONLY, NORM_NACK_NORMAL } NormNackingMode; NORM_API_LINKAGE typedef enum NormAckingStatus { NORM_ACK_INVALID, NORM_ACK_FAILURE, NORM_ACK_PENDING, NORM_ACK_SUCCESS } NormAckingStatus; NORM_API_LINKAGE typedef enum NormTrackingStatus { NORM_TRACK_NONE, NORM_TRACK_RECEIVERS, NORM_TRACK_SENDERS, NORM_TRACK_ALL } NormTrackingStatus; NORM_API_LINKAGE typedef enum NormProbingMode { NORM_PROBE_NONE, NORM_PROBE_PASSIVE, NORM_PROBE_ACTIVE } NormProbingMode; NORM_API_LINKAGE typedef enum NormSyncPolicy { NORM_SYNC_CURRENT, // attempt to receiver current/new objects only, join mid-stream NORM_SYNC_STREAM, // sync to current stream, but to beginning of stream NORM_SYNC_ALL // attempt to receive old and new objects } NormSyncPolicy; NORM_API_LINKAGE typedef enum NormRepairBoundary { NORM_BOUNDARY_BLOCK, NORM_BOUNDARY_OBJECT } NormRepairBoundary; NORM_API_LINKAGE typedef enum NormEventType { NORM_EVENT_INVALID = 0, NORM_TX_QUEUE_VACANCY, NORM_TX_QUEUE_EMPTY, NORM_TX_FLUSH_COMPLETED, NORM_TX_WATERMARK_COMPLETED, NORM_TX_CMD_SENT, NORM_TX_OBJECT_SENT, NORM_TX_OBJECT_PURGED, NORM_TX_RATE_CHANGED, NORM_LOCAL_SENDER_CLOSED, NORM_REMOTE_SENDER_NEW, NORM_REMOTE_SENDER_RESET, // remote sender instanceId or FEC params changed NORM_REMOTE_SENDER_ADDRESS, // remote sender src addr and/or port changed NORM_REMOTE_SENDER_ACTIVE, NORM_REMOTE_SENDER_INACTIVE, NORM_REMOTE_SENDER_PURGED, // not yet implemented NORM_RX_CMD_NEW, NORM_RX_OBJECT_NEW, NORM_RX_OBJECT_INFO, NORM_RX_OBJECT_UPDATED, NORM_RX_OBJECT_COMPLETED, NORM_RX_OBJECT_ABORTED, NORM_GRTT_UPDATED, NORM_CC_ACTIVE, NORM_CC_INACTIVE, NORM_ACKING_NODE_NEW, // whe NormSetAutoAcking NORM_SEND_ERROR, // ICMP error (e.g. destination unreachable) NORM_USER_TIMEOUT // issues when timeout set by NormSetUserTimer() expires } NormEventType; typedef struct { NormEventType type; NormSessionHandle session; NormNodeHandle sender; NormObjectHandle object; } NormEvent; // For setting custom NORM_OBJECT_DATA alloc/free functions typedef char* (*NormAllocFunctionHandle)(size_t); typedef void (*NormFreeFunctionHandle)(char*); /** NORM API General Initialization and Operation Functions */ NORM_API_LINKAGE int NormGetVersion(int* major DEFAULT((int*)0), int* minor DEFAULT((int*)0), int* patch DEFAULT((int*)0)); NORM_API_LINKAGE NormInstanceHandle NormCreateInstance(bool priorityBoost DEFAULT(false)); NORM_API_LINKAGE void NormDestroyInstance(NormInstanceHandle instanceHandle); NORM_API_LINKAGE void NormStopInstance(NormInstanceHandle instanceHandle); NORM_API_LINKAGE bool NormRestartInstance(NormInstanceHandle instanceHandle); NORM_API_LINKAGE bool NormSuspendInstance(NormInstanceHandle instanceHandle); NORM_API_LINKAGE void NormResumeInstance(NormInstanceHandle instanceHandle); // This MUST be set to enable NORM_OBJECT_FILE reception! // (otherwise received files are ignored) NORM_API_LINKAGE bool NormSetCacheDirectory(NormInstanceHandle instanceHandle, const char* cachePath); // This call blocks until the next NormEvent is ready unless asynchronous // notification is used (see below) NORM_API_LINKAGE bool NormGetNextEvent(NormInstanceHandle instanceHandle, NormEvent* theEvent, bool waitForEvent DEFAULT(true)); // The "NormGetDescriptor()" function returns a HANDLE (WIN32) or // a file descriptor (UNIX) which can be used for async notification // of pending NORM events. On WIN32, the returned HANDLE can be used // with system calls like "WaitForSingleEvent()", and on Unix the // returned descriptor can be used in a "select()" call. If this type // of asynchronous notification is used, calls to "NormGetNextEvent()" will // not block when the notification is posted. #ifdef WIN32 typedef HANDLE NormDescriptor; #else typedef int NormDescriptor; #endif // if/else WIN32/UNIX extern NORM_API_LINKAGE const NormDescriptor NORM_DESCRIPTOR_INVALID; NORM_API_LINKAGE NormDescriptor NormGetDescriptor(NormInstanceHandle instanceHandle); NORM_API_LINKAGE void NormSetAllocationFunctions(NormInstanceHandle instance, NormAllocFunctionHandle allocFunc, NormFreeFunctionHandle freeFunc); /** NORM Session Creation and Control Functions */ NORM_API_LINKAGE NormSessionHandle NormCreateSession(NormInstanceHandle instanceHandle, const char* sessionAddress, UINT16 sessionPort, NormNodeId localNodeId); NORM_API_LINKAGE void NormDestroySession(NormSessionHandle sessionHandle); NORM_API_LINKAGE NormInstanceHandle NormGetInstance(NormSessionHandle sessionHandle); NORM_API_LINKAGE bool NormIsUnicastAddress(const char* address); NORM_API_LINKAGE void NormSetUserData(NormSessionHandle sessionHandle, const void* userData); NORM_API_LINKAGE const void* NormGetUserData(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormSetUserTimer(NormSessionHandle sessionHandle, double seconds); NORM_API_LINKAGE void NormCancelUserTimer(NormSessionHandle sessionHandle); NORM_API_LINKAGE NormNodeId NormGetLocalNodeId(NormSessionHandle sessionHandle); NORM_API_LINKAGE bool NormGetAddress(NormSessionHandle sessionHandle, char* addrBuffer, unsigned int* bufferLen, UINT16* port DEFAULT((UINT16*)0)); NORM_API_LINKAGE UINT16 NormGetRxPort(NormSessionHandle sessionHandle); NORM_API_LINKAGE bool NormSetTxPort(NormSessionHandle sessionHandle, UINT16 txPortNumber, bool enableReuse DEFAULT(false), const char* txBindAddress DEFAULT((const char*)0)); // if non-NULL, bind() to / NORM_API_LINKAGE UINT16 NormGetTxPort(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormSetTxOnly(NormSessionHandle sessionHandle, bool txOnly, bool connectToSessionAddress DEFAULT(false)); NORM_API_LINKAGE void NormSetId(NormSessionHandle sessionHandle, NormNodeId normId); // This does not affect the rx_socket binding if already bound (sender or receiver already started) // (i.e., just affects where NORM packets are sent) NORM_API_LINKAGE bool NormChangeDestination(NormSessionHandle sessionHandle, const char* sessionAddress, UINT16 sessionPort, bool connectToSessionAddress DEFAULT(false)); NORM_API_LINKAGE void NormSetServerListener(NormSessionHandle sessionHandle, bool state); NORM_API_LINKAGE bool NormTransferSender(NormSessionHandle sessionHandle, NormNodeHandle sender); NORM_API_LINKAGE void NormSetRxPortReuse(NormSessionHandle sessionHandle, bool enableReuse, const char* rxBindAddress DEFAULT((const char*)0), // if non-NULL, bind() to / const char* senderAddress DEFAULT((const char*)0), // if non-NULL, connect() to / UINT16 senderPort DEFAULT(0)); NORM_API_LINKAGE UINT16 NormGetRxPort(NormSessionHandle sessionHandle); // TBD - We should probably have a "NormSetCCMode(NormCCMode ccMode)" function for users NORM_API_LINKAGE void NormSetEcnSupport(NormSessionHandle sessionHandle, bool ecnEnable, // enables NORM ECN (congestion control) support bool ignoreLoss DEFAULT(false), // With "ecnEnable", use ECN-only, ignoring packet loss bool tolerateLoss DEFAULT(false)); // loss-tolerant congestion control, ecnEnable or not, ignoreLoss = false NORM_API_LINKAGE bool NormSetMulticastInterface(NormSessionHandle sessionHandle, const char* interfaceName); NORM_API_LINKAGE bool NormSetSSM(NormSessionHandle sessionHandle, const char* sourceAddress); NORM_API_LINKAGE bool NormSetTTL(NormSessionHandle sessionHandle, unsigned char ttl); NORM_API_LINKAGE bool NormSetTOS(NormSessionHandle sessionHandle, unsigned char tos); NORM_API_LINKAGE bool NormSetLoopback(NormSessionHandle sessionHandle, bool loopback); NORM_API_LINKAGE bool NormSetMulticastLoopback(NormSessionHandle sessionHandle, bool loopback); NORM_API_LINKAGE bool NormSetFragmentation(NormSessionHandle sessionHandle, bool fragmentation); // Special functions for debug support NORM_API_LINKAGE void NormSetMessageTrace(NormSessionHandle sessionHandle, bool state); NORM_API_LINKAGE void NormSetTxLoss(NormSessionHandle sessionHandle, double percent); NORM_API_LINKAGE void NormSetRxLoss(NormSessionHandle sessionHandle, double percent); NORM_API_LINKAGE bool NormOpenDebugLog(NormInstanceHandle instanceHandle, const char *path); NORM_API_LINKAGE void NormCloseDebugLog(NormInstanceHandle instanceHandle); NORM_API_LINKAGE bool NormOpenDebugPipe(NormInstanceHandle instanceHandle, const char *pipeName); NORM_API_LINKAGE void NormCloseDebugPipe(NormInstanceHandle instanceHandle); NORM_API_LINKAGE void NormSetDebugLevel(unsigned int level); NORM_API_LINKAGE unsigned int NormGetDebugLevel(); NORM_API_LINKAGE void NormSetReportInterval(NormSessionHandle sessionHandle, double interval); NORM_API_LINKAGE double NormGetReportInterval(NormSessionHandle sessionHandle); /** NORM Sender Functions */ NORM_API_LINKAGE NormSessionId NormGetRandomSessionId(); // This function has been updated so that 16-bit Reed-Solomon // codecs can be accessed. This may cause an issue for linking // to older versions of the NORM library NORM_API_LINKAGE bool NormStartSender(NormSessionHandle sessionHandle, NormSessionId instanceId, UINT32 bufferSpace, UINT16 segmentSize, UINT16 numData, UINT16 numParity, UINT8 fecId DEFAULT(0)); NORM_API_LINKAGE void NormStopSender(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormSetTxRate(NormSessionHandle sessionHandle, double bitsPerSecond); NORM_API_LINKAGE double NormGetTxRate(NormSessionHandle sessionHandle); NORM_API_LINKAGE bool NormSetTxSocketBuffer(NormSessionHandle sessionHandle, unsigned int bufferSize); NORM_API_LINKAGE void NormSetFlowControl(NormSessionHandle sessionHandle, double flowControlFactor); NORM_API_LINKAGE void NormSetCongestionControl(NormSessionHandle sessionHandle, bool enable, bool adjustRate DEFAULT(true)); NORM_API_LINKAGE void NormSetTxRateBounds(NormSessionHandle sessionHandle, double rateMin, double rateMax); NORM_API_LINKAGE void NormSetTxCacheBounds(NormSessionHandle sessionHandle, NormSize sizeMax, UINT32 countMin, UINT32 countMax); NORM_API_LINKAGE void NormSetAutoParity(NormSessionHandle sessionHandle, unsigned char autoParity); NORM_API_LINKAGE void NormSetGrttEstimate(NormSessionHandle sessionHandle, double grttEstimate); NORM_API_LINKAGE double NormGetGrttEstimate(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormSetGrttMax(NormSessionHandle sessionHandle, double grttMax); NORM_API_LINKAGE void NormSetGrttProbingMode(NormSessionHandle sessionHandle, NormProbingMode probingMode); NORM_API_LINKAGE void NormSetGrttProbingInterval(NormSessionHandle sessionHandle, double intervalMin, double intervalMax); NORM_API_LINKAGE void NormSetBackoffFactor(NormSessionHandle sessionHandle, double backoffFactor); NORM_API_LINKAGE void NormSetGroupSize(NormSessionHandle sessionHandle, unsigned int groupSize); NORM_API_LINKAGE void NormSetTxRobustFactor(NormSessionHandle sessionHandle, int robustFactor); NORM_API_LINKAGE NormObjectHandle NormFileEnqueue(NormSessionHandle sessionHandle, const char* fileName, const char* infoPtr DEFAULT((const char*)0), unsigned int infoLen DEFAULT(0)); NORM_API_LINKAGE NormObjectHandle NormDataEnqueue(NormSessionHandle sessionHandle, const char* dataPtr, UINT32 dataLen, const char* infoPtr DEFAULT((const char*)0), unsigned int infoLen DEFAULT(0)); NORM_API_LINKAGE bool NormRequeueObject(NormSessionHandle sessionHandle, NormObjectHandle objectHandle); NORM_API_LINKAGE NormObjectHandle NormStreamOpen(NormSessionHandle sessionHandle, UINT32 bufferSize, const char* infoPtr DEFAULT((const char*)0), unsigned int infoLen DEFAULT(0)); NORM_API_LINKAGE void NormObjectSetUserData(NormObjectHandle objectHandle, const void* userData); NORM_API_LINKAGE const void* NormObjectGetUserData(NormObjectHandle objectHandle); // TBD - we should add a "bool watermark" option to "graceful" stream closure??? NORM_API_LINKAGE void NormStreamClose(NormObjectHandle streamHandle, bool graceful DEFAULT(false)); NORM_API_LINKAGE unsigned int NormGetStreamBufferSegmentCount(unsigned int bufferBytes, UINT16 segmentSize, UINT16 blockSize); NORM_API_LINKAGE unsigned int NormStreamWrite(NormObjectHandle streamHandle, const char* buffer, unsigned int numBytes); NORM_API_LINKAGE void NormStreamFlush(NormObjectHandle streamHandle, bool eom DEFAULT(false), NormFlushMode flushMode DEFAULT(NORM_FLUSH_PASSIVE)); NORM_API_LINKAGE void NormStreamSetAutoFlush(NormObjectHandle streamHandle, NormFlushMode flushMode); NORM_API_LINKAGE void NormStreamSetPushEnable(NormObjectHandle streamHandle, bool pushEnable); NORM_API_LINKAGE bool NormStreamHasVacancy(NormObjectHandle streamHandle); NORM_API_LINKAGE void NormStreamMarkEom(NormObjectHandle streamHandle); NORM_API_LINKAGE bool NormSetWatermark(NormSessionHandle sessionHandle, NormObjectHandle objectHandle, bool overrideFlush DEFAULT(false)); NORM_API_LINKAGE bool NormResetWatermark(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormCancelWatermark(NormSessionHandle sessionHandle); NORM_API_LINKAGE bool NormAddAckingNode(NormSessionHandle sessionHandle, NormNodeId nodeId); NORM_API_LINKAGE void NormRemoveAckingNode(NormSessionHandle sessionHandle, NormNodeId nodeId); NORM_API_LINKAGE NormNodeHandle NormGetAckingNodeHandle(NormSessionHandle sessionHandle, NormNodeId nodeId); NORM_API_LINKAGE void NormSetAutoAckingNodes(NormSessionHandle sessionHandle, NormTrackingStatus trackingStatus); NORM_API_LINKAGE NormAckingStatus NormGetAckingStatus(NormSessionHandle sessionHandle, NormNodeId nodeId DEFAULT(NORM_NODE_ANY)); NORM_API_LINKAGE bool NormGetNextAckingNode(NormSessionHandle sessionHandle, NormNodeId* nodeId, NormAckingStatus* ackingStatus DEFAULT(0)); NORM_API_LINKAGE bool NormSendCommand(NormSessionHandle sessionHandle, const char* cmdBuffer, unsigned int cmdLength, bool robust DEFAULT(false)); NORM_API_LINKAGE void NormCancelCommand(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormSetSynStatus(NormSessionHandle sessionHandle, bool state); /* NORM Receiver Functions */ NORM_API_LINKAGE bool NormStartReceiver(NormSessionHandle sessionHandle, UINT32 bufferSpace); NORM_API_LINKAGE void NormStopReceiver(NormSessionHandle sessionHandle); NORM_API_LINKAGE void NormSetRxCacheLimit(NormSessionHandle sessionHandle, unsigned short countMax); NORM_API_LINKAGE bool NormSetRxSocketBuffer(NormSessionHandle sessionHandle, unsigned int bufferSize); NORM_API_LINKAGE void NormSetSilentReceiver(NormSessionHandle sessionHandle, bool silent, int maxDelay DEFAULT(-1)); NORM_API_LINKAGE void NormSetDefaultUnicastNack(NormSessionHandle sessionHandle, bool unicastNacks); NORM_API_LINKAGE void NormNodeSetUnicastNack(NormNodeHandle remoteSender, bool unicastNacks); NORM_API_LINKAGE void NormSetDefaultSyncPolicy(NormSessionHandle sessionHandle, NormSyncPolicy syncPolicy); NORM_API_LINKAGE void NormSetDefaultNackingMode(NormSessionHandle sessionHandle, NormNackingMode nackingMode); NORM_API_LINKAGE void NormNodeSetNackingMode(NormNodeHandle remoteSender, NormNackingMode nackingMode); NORM_API_LINKAGE void NormObjectSetNackingMode(NormObjectHandle objectHandle, NormNackingMode nackingMode); NORM_API_LINKAGE void NormSetDefaultRepairBoundary(NormSessionHandle sessionHandle, NormRepairBoundary repairBoundary); NORM_API_LINKAGE void NormNodeSetRepairBoundary(NormNodeHandle remoteSender, NormRepairBoundary repairBoundary); NORM_API_LINKAGE void NormSetDefaultRxRobustFactor(NormSessionHandle sessionHandle, int robustFactor); NORM_API_LINKAGE void NormNodeSetRxRobustFactor(NormNodeHandle remoteSender, int robustFactor); NORM_API_LINKAGE bool NormPreallocateRemoteSender(NormSessionHandle sessionHandle, unsigned long bufferSize, UINT16 segmentSize, UINT16 numData, UINT16 numParity, unsigned int streamBufferSize DEFAULT(0)); NORM_API_LINKAGE bool NormStreamRead(NormObjectHandle streamHandle, char* buffer, unsigned int* numBytes); NORM_API_LINKAGE bool NormStreamSeekMsgStart(NormObjectHandle streamHandle); NORM_API_LINKAGE UINT32 NormStreamGetReadOffset(NormObjectHandle streamHandle); NORM_API_LINKAGE UINT32 NormStreamGetBufferUsage(NormObjectHandle streamHandle); /** NORM Object Functions */ NORM_API_LINKAGE NormObjectType NormObjectGetType(NormObjectHandle objectHandle); NORM_API_LINKAGE bool NormObjectHasInfo(NormObjectHandle objectHandle); NORM_API_LINKAGE UINT16 NormObjectGetInfoLength(NormObjectHandle objectHandle); NORM_API_LINKAGE UINT16 NormObjectGetInfo(NormObjectHandle objectHandle, char* buffer, UINT16 bufferLen); NORM_API_LINKAGE NormSize NormObjectGetSize(NormObjectHandle objectHandle); NORM_API_LINKAGE NormSize NormObjectGetBytesPending(NormObjectHandle objectHandle); NORM_API_LINKAGE void NormObjectCancel(NormObjectHandle objectHandle); NORM_API_LINKAGE void NormObjectRetain(NormObjectHandle objectHandle); NORM_API_LINKAGE void NormObjectRelease(NormObjectHandle objectHandle); NORM_API_LINKAGE bool NormFileGetName(NormObjectHandle fileHandle, char* nameBuffer, unsigned int bufferLen); NORM_API_LINKAGE bool NormFileRename(NormObjectHandle fileHandle, const char* fileName); NORM_API_LINKAGE const char* NormDataAccessData(NormObjectHandle objectHandle); NORM_API_LINKAGE char* NormDataDetachData(NormObjectHandle objectHandle); NORM_API_LINKAGE char* NormAlloc(size_t numBytes); NORM_API_LINKAGE void NormFree(char* dataPtr); NORM_API_LINKAGE NormNodeHandle NormObjectGetSender(NormObjectHandle objectHandle); /** NORM Node Functions */ NORM_API_LINKAGE NormNodeId NormNodeGetId(NormNodeHandle nodeHandle); NORM_API_LINKAGE bool NormNodeGetAddress(NormNodeHandle nodeHandle, char* addrBuffer, unsigned int* bufferLen, UINT16* port DEFAULT((UINT16*)0)); NORM_API_LINKAGE void NormNodeSetUserData(NormNodeHandle nodeHandle, const void* userData); NORM_API_LINKAGE const void* NormNodeGetUserData(NormNodeHandle nodeHandle); NORM_API_LINKAGE double NormNodeGetGrtt(NormNodeHandle remoteSender); NORM_API_LINKAGE bool NormNodeGetCommand(NormNodeHandle remoteSender, char* buffer, unsigned int* buflen); NORM_API_LINKAGE void NormNodeFreeBuffers(NormNodeHandle remoteSender); NORM_API_LINKAGE void NormNodeDelete(NormNodeHandle remoteSender); NORM_API_LINKAGE void NormNodeRetain(NormNodeHandle nodeHandle); NORM_API_LINKAGE void NormNodeRelease(NormNodeHandle nodeHandle); /** Some experimental functions */ NORM_API_LINKAGE void NormReleasePreviousEvent(NormInstanceHandle instanceHandle); NORM_API_LINKAGE UINT32 NormCountCompletedObjects(NormSessionHandle sessionHandle); // The next functions have _not_ yet been implemented // (work in progress) NORM_API_LINKAGE void NormNodeSetAutoDelete(NormNodeHandle remoteSender, bool autoDelete); NORM_API_LINKAGE bool NormNodeAllowSender(NormNodeId senderId); NORM_API_LINKAGE bool NormNodeDenySender(NormNodeId senderId); #ifdef __cplusplus } // end extern "C" #endif /* __cplusplus */ #endif // _NORM_API norm-1.5.8+dfsg2/include/normEncoder.h0000644000000000000000000000426411247552534014454 0ustar /********************************************************************* * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution, and * * (3) all advertising materials mentioning features or use of this * software display the following acknowledgment: * * "This product includes software written and developed * by Brian Adamson and Joe Macker of the Naval Research * Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ********************************************************************/ #ifndef _NORM_ENCODER #define _NORM_ENCODER #include "protokit.h" // protolib stuff class NormEncoder { public: virtual ~NormEncoder(); virtual bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize) = 0; virtual void Destroy() = 0; virtual void Encode(unsigned int segmentId, const char *dataVector, char **parityVectorList) = 0; }; // end class NormEncoder class NormDecoder { public: virtual ~NormDecoder(); virtual bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize) = 0; virtual void Destroy() = 0; virtual int Decode(char** vectorList, unsigned int numData, unsigned int erasureCount, unsigned int* erasureLocs) = 0; }; // end class NormDecoder #endif // _NORM_ENCODER norm-1.5.8+dfsg2/include/normEncoderMDP.h0000644000000000000000000000631211247552534015011 0ustar /********************************************************************* * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution, and * * (3) all advertising materials mentioning features or use of this * software display the following acknowledgment: * * "This product includes software written and developed * by Brian Adamson and Joe Macker of the Naval Research * Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ********************************************************************/ #ifndef _NORM_ENCODER_MDP #define _NORM_ENCODER_MDP #include "normEncoder.h" class NormEncoderMDP : public NormEncoder { // Methods public: NormEncoderMDP(); ~NormEncoderMDP(); bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize); void Destroy(); bool IsReady(){return (bool)(gen_poly != NULL);} // "Encode" MUST be called in order of source vector0, vector1, vector2, etc void Encode(unsigned int segmentId, const char *dataVector, char **parityVectorList); private: bool CreateGeneratorPolynomial(); // Members unsigned int npar; // No. of parity packets (n-k) UINT16 vector_size; // Size of biggest vector to encode unsigned char* gen_poly; // Ptr to generator polynomial unsigned char* scratch; // scratch space for encoding }; // end class NormEncoderMDP class NormDecoderMDP : public NormDecoder { // Methods public: NormDecoderMDP(); ~NormDecoderMDP(); bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize); int Decode(char** vectorList, unsigned int numData, unsigned int erasureCount, unsigned int* erasureLocs); int NumParity() {return npar;} int VectorSize() {return vector_size;} void Destroy(); // Members private: unsigned int npar; // No. of parity packets (n-k) UINT16 vector_size; // Size of biggest vector to encode unsigned char* lambda; // Erasure location polynomial ("2*npar" ints) unsigned char** s_vec; // Syndrome vectors (pointers to "npar" vectors) unsigned char** o_vec; // Omega vectors (pointers to "npar" vectors) unsigned char* scratch; }; // end class NormDecoderMDP #endif // _NORM_ENCODER_MDP norm-1.5.8+dfsg2/include/normEncoderRS16.h0000644000000000000000000000431511247552534015065 0ustar #ifndef _NORM_ENCODER_RS16 #define _NORM_ENCODER_RS16 #include "normEncoder.h" #include "protoDefs.h" // for UINT16 class NormEncoderRS16 : public NormEncoder { public: NormEncoderRS16(); ~NormEncoderRS16(); virtual bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize); virtual void Destroy(); virtual void Encode(unsigned int segmentId, const char* dataVector, char** parityVectorList); unsigned int GetNumData() {return ndata;} unsigned int GetNumParity() {return npar;} unsigned int GetVectorSize() {return vector_size;} private: unsigned int ndata; // max data pkts per block (k) unsigned int npar; // No. of parity packets (n-k) unsigned int vector_size; // Size of biggest vector to encode UINT8* enc_matrix; unsigned int enc_index; }; // end class NormEncoderRS16 class NormDecoderRS16 : public NormDecoder { public: NormDecoderRS16(); virtual ~NormDecoderRS16(); virtual bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize); virtual void Destroy(); virtual int Decode(char** vectorList, unsigned int numData, unsigned int erasureCount, unsigned int* erasureLocs); unsigned int GetNumParity() {return npar;} unsigned int GetVectorSize() {return vector_size;} private: bool InvertDecodingMatrix(); // used in Decode() method unsigned int ndata; // max data pkts per block (k) unsigned int npar; // No. of parity packets (n-k) UINT16 vector_size; // Size of biggest vector to encode UINT8* enc_matrix; UINT8* dec_matrix; unsigned int* parity_loc; // These "inv_" members are used in InvertDecodingMatrix() unsigned int* inv_ndxc; unsigned int* inv_ndxr; unsigned int* inv_pivt; UINT8* inv_id_row; UINT8* inv_temp_row; }; // end class NormDecoderRS16 #endif // _NORM_ENCODER_RS16 norm-1.5.8+dfsg2/include/normEncoderRS8.h0000644000000000000000000000423311247552534015005 0ustar #ifndef _NORM_ENCODER_RS8 #define _NORM_ENCODER_RS8 #include "normEncoder.h" #include "protoDefs.h" // for UINT16 class NormEncoderRS8 : public NormEncoder { public: NormEncoderRS8(); ~NormEncoderRS8(); virtual bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize); virtual void Destroy(); virtual void Encode(unsigned int segmentId, const char* dataVector, char** parityVectorList); unsigned int GetNumData() {return ndata;} unsigned int GetNumParity() {return npar;} unsigned int GetVectorSize() {return vector_size;} private: unsigned int ndata; // max data pkts per block (k) unsigned int npar; // No. of parity packets (n-k) unsigned int vector_size; // Size of biggest vector to encode UINT8* enc_matrix; }; // end class NormEncoder class NormDecoderRS8 : public NormDecoder { public: NormDecoderRS8(); virtual ~NormDecoderRS8(); virtual bool Init(unsigned int numData, unsigned int numParity, UINT16 vectorSize); virtual void Destroy(); virtual int Decode(char** vectorList, unsigned int numData, unsigned int erasureCount, unsigned int* erasureLocs); unsigned int GetNumParity() {return npar;} unsigned int GetVectorSize() {return vector_size;} private: bool InvertDecodingMatrix(); // used in Decode() method unsigned int ndata; // max data pkts per block (k) unsigned int npar; // No. of parity packets (n-k) UINT16 vector_size; // Size of biggest vector to encode UINT8* enc_matrix; UINT8* dec_matrix; unsigned int* parity_loc; // These "inv_" members are used in InvertDecodingMatrix() unsigned int* inv_ndxc; unsigned int* inv_ndxr; unsigned int* inv_pivt; UINT8* inv_id_row; UINT8* inv_temp_row; }; // end class NormDecoder #endif // _NORM_ENCODER_RS8 norm-1.5.8+dfsg2/include/normFile.h0000644000000000000000000001665410642472141013753 0ustar #ifndef _NORM_FILE #define _NORM_FILE // This module defines some simple classes for manipulating files. // Unix and Win32 platforms are supported. Routines for iterating // over directories are also provided. And a file/directory list // class is provided to manage a list of files. #ifdef WIN32 //#include #else #include #include #endif // if/else WIN32 #ifdef _WIN32_WCE #include #else #include #include #include #endif // if/else _WIN32_WCE // From PROTOLIB #include "protokit.h" // for Protolib stuff // (TBD) Rewrite this implementation to use // native WIN32 APIs on that platform !!! #ifdef _WIN32_WCE // Here we enumerate some stuff to // make the NormFile work on WinCE enum { O_CREAT = 0x01, O_TRUNC = 0x02, O_RDONLY = 0x04, O_WRONLY = 0x08, O_RDWR = 0x10, O_BINARY = 0x20 }; #endif // _WIN32_WCE class NormFile { public: #ifdef WIN32 typedef __int64 Offset; #else typedef off_t Offset; #endif // if/else WIN32/UNIX enum Type {INVALID, NORMAL, DIRECTORY}; NormFile(); ~NormFile(); bool Open(const char* path, int theFlags); bool Lock(); void Unlock(); bool Rename(const char* oldName, const char* newName); static bool Unlink(const char *path); void Close(); bool IsOpen() const { #ifdef _WIN32_WCE return (NULL != file_ptr); #else return (fd >= 0); #endif // _WIN32_WCE } size_t Read(char* buffer, size_t len); size_t Write(const char* buffer, size_t len); bool Seek(Offset theOffset); NormFile::Offset GetOffset() const {return (offset);} NormFile::Offset GetSize() const; bool Pad(Offset theOffset); // if file size is less than theOffset, writes a byte to force filesize // static helper methods static NormFile::Type GetType(const char *path); static NormFile::Offset GetSize(const char* path); static time_t GetUpdateTime(const char* path); static bool IsLocked(const char *path); static bool Exists(const char* path) { #ifdef WIN32 #ifdef _UNICODE wchar_t wideBuffer[MAX_PATH]; size_t count = mbstowcs(wideBuffer, path, strlen(path)+1); return (0xFFFFFFFF != GetFileAttributes(wideBuffer)); #else return (0xFFFFFFFF != GetFileAttributes(path)); #endif // if/else _UNICODE #else return (0 == access(path, F_OK)); #endif // if/else WIN32 } static bool IsWritable(const char* path) { #ifdef WIN32 #ifdef _UNICODE wchar_t wideBuffer[MAX_PATH]; size_t count = mbstowcs(wideBuffer, path, strlen(path)+1); DWORD attr = GetFileAttributes(wideBuffer); #else DWORD attr = GetFileAttributes(path); #endif // if/else _UNICODE return ((0xFFFFFFFF == attr) ? false : (0 == (attr & FILE_ATTRIBUTE_READONLY))); #else return (0 == access(path, W_OK)); #endif // if/else WIN32 } // Members //private: #ifdef _WIN32_WCE FILE* file_ptr; #else int fd; #endif // if/else _WIN32_WCE int flags; #ifdef WIN32 __int64 offset; #else off_t offset; #endif // if/else WIN32/UNIX }; // end class NormFile /****************************************** * The NormDirectory and NormDirectoryIterator classes * are used to walk directory trees for file transmission */ class NormDirectoryIterator { public: NormDirectoryIterator(); ~NormDirectoryIterator(); bool Open(const char*thePath); void Close(); bool GetPath(char* pathBuffer); // "buffer" should be PATH_MAX long! bool GetNextFile(char* buffer); private: class NormDirectory { friend class NormDirectoryIterator; private: char path[PATH_MAX]; NormDirectory* parent; #ifdef WIN32 HANDLE hSearch; #else DIR* dptr; #endif // if/else WIN32 NormDirectory(const char *thePath, NormDirectory* theParent = NULL); ~NormDirectory(); void GetFullName(char* namePtr); bool Open(); void Close(); const char* Path() const {return path;} void RecursiveCatName(char* ptr); }; // end class NormDirectoryIterator::NormDirectory NormDirectory* current; int path_len; }; // end class NormDirectoryIterator class NormFileList { public: NormFileList(); ~NormFileList(); void Destroy(); bool IsEmpty() {return (NULL == head);} void ResetIterator() { last_time = this_time; this_time = big_time; next = NULL; reset = true; } void InitUpdateTime(bool updatesOnly, time_t initTime = 0) { updates_only = updatesOnly; last_time = this_time = big_time = initTime; if (0 == initTime) { struct timeval currentTime; ProtoSystemTime(currentTime); this_time = currentTime.tv_sec; } } bool Append(const char* path); bool Remove(const char* path); bool GetNextFile(char* pathBuffer); void GetCurrentBasePath(char* pathBuffer); private: class FileItem { friend class NormFileList; public: FileItem(const char* thePath); virtual ~FileItem(); NormFile::Type GetType() {return NormFile::GetType(path);} NormFile::Offset Size() const {return size;} virtual bool GetNextFile(char* thePath, bool reset, bool updatesOnly, time_t lastTime, time_t thisTime, time_t& bigTime); protected: const char* Path() {return path;} char path[PATH_MAX]; NormFile::Offset size; FileItem* prev; FileItem* next; }; class DirectoryItem : public FileItem { friend class NormFileList; public: DirectoryItem(const char* thePath); ~DirectoryItem(); virtual bool GetNextFile(char* thePath, bool reset, bool updatesOnly, time_t lastTime, time_t thisTime, time_t& bigTime); private: NormDirectoryIterator diterator; }; time_t this_time; time_t big_time; time_t last_time; bool updates_only; FileItem* head; FileItem* tail; FileItem* next; bool reset; }; // end class NormFileList #endif // _NORM_FILE norm-1.5.8+dfsg2/include/normMessage.h0000644000000000000000000022430613205401424014445 0ustar #ifndef _NORM_MESSAGE #define _NORM_MESSAGE // PROTOLIB includes #include "protokit.h" // standard includes #include // for memcpy(), etc #include #include // for rand(), etc #ifdef _WIN32_WCE #include #else #include // for off_t #endif // if/else _WIN32_WCE #ifdef SIMULATE // IMPORTANT! This _assumes_ that the message header of interest _will_ be // aligned with a NormSegment (i.e. flush mode of active or passive // is used with flushing after _each_ message written to a // NORM_OBJECT_STREAM! #define SIM_PAYLOAD_MAX (36+8) // MGEN message size + StreamPayloadHeaderLen() #endif // SIMULATE const UINT8 NORM_PROTOCOL_VERSION = 1; // This value is used in a couple places in the code as // a safety check where some critical timeouts may be // less than expected operating system clock resolution const double NORM_TICK_MIN = 0.100; // in seconds // Pick a random number from 0..max inline double UniformRand(double max) {return (max * ((double)rand() / (double)RAND_MAX));} // Pick a random number from 0..max // (truncated exponential dist. lambda = log(groupSize) + 1) inline double ExponentialRand(double max, double groupSize) { double lambda = log(groupSize) + 1; double x = UniformRand(lambda/max)+lambda/(max*(exp(lambda)-1)); return ((max/lambda)*log(x*(exp(lambda)-1)*(max/lambda))); } // These are the GRTT estimation bounds set for the current // NORM protocol. (Note that our Grtt quantization routines // are good for the range of 1.0e-06 <= 1000.0 seconds) const double NORM_GRTT_MIN = 0.001; // 1 msec const double NORM_GRTT_MAX = 15.0; // 15 sec const double NORM_RTT_MIN = 1.0e-06; const double NORM_RTT_MAX = 1000.0; extern const double NORM_RTT[]; inline double NormUnquantizeRtt(UINT8 qrtt) {return NORM_RTT[qrtt];} UINT8 NormQuantizeRtt(double rtt); extern const double NORM_GSIZE[]; inline double NormUnquantizeGroupSize(UINT8 gsize) {return NORM_GSIZE[gsize];} UINT8 NormQuantizeGroupSize(double gsize); inline UINT16 NormQuantizeLoss(double lossFraction) { lossFraction = MAX(lossFraction, 0.0); lossFraction = lossFraction*65535.0 + 0.5; lossFraction = MIN(lossFraction, 65535.0); return (UINT16)lossFraction; } // end NormQuantizeLossFraction() inline double NormUnquantizeLoss(UINT16 lossQuantized) { return (((double)lossQuantized) / 65535.0); } // end NormUnquantizeLossFraction() // Extended precision Norm loss quantize/unquantize with // 32-bit precision (needed for low BER, high bandwidth*delay) inline UINT32 NormQuantizeLoss32(double lossFraction) { const double MAX_SCALE = (double)((unsigned int)0xffffffff); lossFraction = MAX(lossFraction, 0.0); lossFraction = lossFraction*MAX_SCALE + 0.5; lossFraction = MIN(lossFraction, MAX_SCALE); return (UINT32)lossFraction; } // end NormQuantizeLossFraction32() inline double NormUnquantizeLoss32(UINT32 lossQuantized) { const double MAX_SCALE = (double)((unsigned int)0xffffffff); return (((double)lossQuantized) / MAX_SCALE); } // end NormUnquantizeLossFraction32() inline UINT16 NormQuantizeRate(double rate) { if (rate <= 0.0) return 0x01; // rate = 0.0 UINT16 exponent = (UINT16)log10(rate); UINT16 mantissa = (UINT16)((4096.0/10.0) * (rate / pow(10.0, (double)exponent)) + 0.5); return ((mantissa << 4) | exponent); } inline double NormUnquantizeRate(UINT16 rate) { double mantissa = ((double)(rate >> 4)) * (10.0/4096.0); double exponent = (double)(rate & 0x000f); return mantissa * pow(10.0, exponent); } class NormObjectSize { public: #ifdef WIN32 #define _FILE_OFFSET_BITS 64 typedef __int64 Offset; #else typedef off_t Offset; #endif // if/else WIN32 NormObjectSize() : size(0) {} NormObjectSize(Offset theSize) : size(theSize) {} NormObjectSize(UINT16 msb, UINT32 lsb) { size = (Offset)lsb; #if (_FILE_OFFSET_BITS > 32) && !defined(ANDROID) size |= ((Offset)msb) << 32; #endif } Offset GetOffset() const {return size;} #if (_FILE_OFFSET_BITS > 32) && !defined(ANDROID) UINT16 MSB() const {return ((UINT16)((size >> 32) & 0x0000ffff));} #else UINT16 MSB() const {return 0;} #endif UINT32 LSB() const {return ((UINT32)(size & 0xffffffff));} // Operators bool operator==(const NormObjectSize& b) const {return (b.size == size);} bool operator!=(const NormObjectSize& b) const {return (b.size != size);} NormObjectSize operator+(const NormObjectSize& b) const { NormObjectSize result(size); result.size += b.size; return result; } void operator+=(const NormObjectSize& b) {size += b.size;} NormObjectSize operator-(const NormObjectSize& b) const { NormObjectSize result(size); result.size -= b.size; return result; } void operator-=(const NormObjectSize& b) {size -= b.size;} void operator+=(Offset increment) {size += increment;} bool operator>(const NormObjectSize& b) const {return (size > b.size);} NormObjectSize operator*(const NormObjectSize& b) const { NormObjectSize result(size); result.size *= b.size; return result; } // Note: this is a "round-upwards" division operator NormObjectSize operator/(const NormObjectSize& b) const { NormObjectSize result(size); result.size /= b.size; result.size = ((result.size * b.size) < size) ? result.size + 1 : result.size; return result; } private: Offset size; }; // end class NormObjectSize #ifndef _NORM_API typedef UINT32 NormNodeId; const NormNodeId NORM_NODE_NONE = 0x00000000; const NormNodeId NORM_NODE_ANY = 0xffffffff; #endif // !_NORM_API class NormObjectId { public: NormObjectId() {}; NormObjectId(UINT16 id) {value = id;} NormObjectId(const NormObjectId& id) {value = id.value;} operator UINT16() const {return value;} //INT16 operator-(const NormObjectId& id) const // {return ((INT16)(value - id.value));} bool operator<(const NormObjectId& id) const { UINT16 diff = value - id.value; return ((diff > 0x8000) || ((0x8000 == diff) && (value > id.value))); } bool operator>(const NormObjectId& id) const { UINT16 diff = id.value - value; return ((diff > 0x8000) || ((0x8000 == diff) && (id.value > value))); } bool operator<=(const NormObjectId& id) const {return ((value == id.value) || (*this < id));} bool operator>=(const NormObjectId& id) const {return ((value == id.value) || (*this > id));} bool operator==(const NormObjectId& id) const {return (value == id.value);} bool operator!=(const NormObjectId& id) const {return (value != id.value);} void operator-=(UINT16 delta) {value -= delta;} const char* GetValuePtr() const {return (const char*)(&value);} NormObjectId& operator++(int) {value++; return *this;} NormObjectId& operator--(int) {value--; return *this;} private: UINT16 value; }; // end class NormObjectId class NormBlockId { public: NormBlockId() {}; NormBlockId(UINT32 id) : value(id) {} UINT32 GetValue() const {return value;} const char* GetValuePtr() const {return ((const char*)&value);} bool operator==(const NormBlockId& id) const {return (value == id.value);} bool operator!=(const NormBlockId& id) const {return (value != id.value);} // These static helper methods provide a "mask" parameter to allow // for different bit-length NormBlockId values (depends upon FEC encoding scheme). // The "mask" is in the eye-of-the-beholder, i.e., the given NormObject // or NormBlockBuffer that is manipulating block id values for protocol purposes // provide the FEC block "mask" to these methods. // We may reconsider adding the "mask" as a NormBlockId member variable, but since // NormBlockId usage is so ubiquitous, it could be added overhead consider within // the context of sender, object, etc a common fec_block_mask is used. // Compute difference of (a - b). If a non-zero bit "mask" is given, the difference // is for the masked word size (e.g., mask = 0x00ffffff is a 24-bit integer). static INT32 Difference(const NormBlockId& a, const NormBlockId& b, UINT32 mask) { if (mask) { UINT32 sign = (mask ^ (mask >> 1)); UINT32 result = a.value - b.value; if (0 == (result & sign)) return (INT32)(result & mask); else if ((result != sign) || (a.value < b.value)) return (INT32)(result | ~mask); else return (INT32)(result & mask); } else { return ((INT32)(a.value - b.value)); } } // Compare two block ids. If a non-zero bit "mask" is given, the comparison // is a "sliding window" (signed) over the bit space. Otherwise, it is // simply an unsigned value comparison. // Returns -1, 0, +1 for (a < b), (a == b), and (a > b), respectively static int Compare(const NormBlockId& a, const NormBlockId& b, UINT32 mask) { if (mask) { // "Sliding window" comparison INT32 delta = Difference(a, b, mask); if (delta < 0) return -1; else if (0 == delta) return 0; else // if delta > 0 return 1; } else if (a.value < b.value) { return -1; } else if (a.value == b.value) { return 0; } else // if (a > b) { return 1; } } void Increment(UINT32 i, UINT32 mask) { value = value + i; if (mask) value &= mask; } void Decrement(UINT32 i, UINT32 mask) { if (mask && (value < i)) value = (mask - (i - value) + 1); else value -= i; } private: UINT32 value; }; // end class NormBlockId typedef UINT16 NormSymbolId; typedef NormSymbolId NormSegmentId; // Base class for NORM header extensions class NormHeaderExtension { public: enum Type { INVALID = 0, FTI = 64, // FEC Object Transmission Information (FTI) extension CC_FEEDBACK = 3, // NORM-CC Feedback extension CC_RATE = 128 // NORM-CC Rate extension }; NormHeaderExtension(); virtual ~NormHeaderExtension() {} virtual void Init(UINT32* theBuffer) { buffer = theBuffer; SetType(INVALID); SetWords(0); } void SetType(Type type) {((UINT8*)buffer)[TYPE_OFFSET] = (UINT8)type;} void SetWords(UINT8 words) {((UINT8*)buffer)[LENGTH_OFFSET] = words;} void AttachBuffer(const UINT32* theBuffer) {buffer = (UINT32*)theBuffer;} const UINT32* GetBuffer() {return buffer;} Type GetType() const { return buffer ? (Type)(((UINT8*)buffer)[TYPE_OFFSET]) : INVALID; } UINT16 GetLength() const { return (buffer ? ((GetType() < 128) ? ((((UINT8*)buffer)[LENGTH_OFFSET]) << 2) : 4) : 0); } protected: enum { TYPE_OFFSET = 0, // UINT8 offset LENGTH_OFFSET = TYPE_OFFSET + 1 // UINT8 offset }; UINT32* buffer; }; // end class NormHeaderExtension // This class is what we use to set/get // FEC Payload Id content. The FEC Payload // Id format is dependent upon the "fec_id" (FEC Type) // and, in some cases, its field size ("m") parameter class NormPayloadId { public: enum FecType { RS = 2, // fully-specified, general purpose Reed-Solomon RS8 = 5, // fully-specified 8-bit Reed-Solmon per RFC 5510 SB = 129 // partially-specified "small block" codes }; static bool IsValid(UINT8 fecId) { switch (fecId) { case 2: case 5: case 129: return true; default: return false; } } NormPayloadId(UINT8 fecId, UINT8 m, UINT32* theBuffer) : fec_id(fecId), fec_m(m), buffer(theBuffer) {} NormPayloadId(UINT8 fecId, UINT8 m, const UINT32* theBuffer) : fec_id(fecId), fec_m(m), cbuffer(theBuffer) {} static UINT16 GetLength(UINT8 fecId) { switch (fecId) { case 2: case 5: return 4; case 129: return 8; default: return 0; } } static UINT32 GetFecBlockMask(UINT8 fecId, UINT8 fecM) { switch (fecId) { case 2: if (8 == fecM) return 0x00ffffff; // 24-bit blockId, 8-bit symbolId else // (16 == fec_m) return 0x0000ffff; // 16-bit blockId,, 16-bit symbolId case 5: return 0x00ffffff; // 24-bit blockId case 129: return 0xffffffff; // 32-bit blockId default: return 0x00000000; // invalid fecId } } void SetFecPayloadId(UINT32 blockId, UINT16 symbolId, UINT16 blockLen) { switch (fec_id) { case 2: if (8 == fec_m) { blockId = (blockId << 8) | (symbolId & 0x00ff); *buffer = htonl(blockId); // 3 + 1 bytes } else // (16 == fec_m) { UINT16* payloadId = (UINT16*)buffer; payloadId[0] = htons(blockId); // 2 bytes payloadId[1] = htons(symbolId); // 2 bytes } break; case 5: blockId = (blockId << 8) | (symbolId & 0x00ff); *buffer = htonl(blockId); // 3 + 1 bytes break; case 129: *buffer = htonl(blockId); // 4 bytes UINT16* ptr = (UINT16*)(buffer + 1); ptr[0] = htons(blockLen); // 2 bytes ptr[1] = htons(symbolId); // 2 bytes break; } } // Message processing methods NormBlockId GetFecBlockId() const { switch (fec_id) { case 2: if (8 == fec_m) { UINT32 blockId = ntohl(*cbuffer); return (0x00ffffff & (blockId >> 8)); } else // (16 == fec_m) { UINT16* blockId = (UINT16*)cbuffer; return ntohs(*blockId); } case 5: { UINT32 blockId = ntohl(*cbuffer); return (0x00ffffff & (blockId >> 8)); } case 129: return ntohl(*cbuffer); default: ASSERT(0); return 0; } } UINT16 GetFecSymbolId() const { switch (fec_id) { case 2: if (8 == fec_m) { UINT32 payloadId = ntohl(*cbuffer); return (0x000000ff & payloadId); // lsb is symbolId } else // ( 16 == fec_m) { UINT16* payloadId = (UINT16*)cbuffer; return ntohs(payloadId[1]); } case 5: { UINT32 payloadId = ntohl(*cbuffer); return (0x000000ff & payloadId); // lsb is symbolId } case 129: { UINT16* ptr = (UINT16*)(cbuffer + 1); return ntohs(ptr[1]); } default: ASSERT(0); return 0; } } UINT16 GetFecBlockLength() const { if (129 == fec_id) { UINT16* blockLen = (UINT16*)(cbuffer + 1); return ntohs(*blockLen); } else { return 0; } } private: UINT8 fec_id; UINT8 fec_m; union { UINT32* buffer; const UINT32* cbuffer; }; }; // end class NormPayloadId class NormMsg { friend class NormMessageQueue; public: enum Type { INVALID = 0, INFO = 1, DATA = 2, CMD = 3, NACK = 4, ACK = 5, REPORT = 6 }; enum {MAX_SIZE = 65536}; NormMsg(); // Message building routines void SetVersion(UINT8 version) { ((UINT8*)buffer)[VERSION_OFFSET] = (((UINT8*)buffer)[VERSION_OFFSET] & 0x0f) | (version << 4); } void SetType(NormMsg::Type type) { ((UINT8*)buffer)[TYPE_OFFSET] = (((UINT8*)buffer)[VERSION_OFFSET] & 0xf0) | (type & 0x0f); } void SetSequence(UINT16 sequence) { ((UINT16*)buffer)[SEQUENCE_OFFSET] = htons(sequence); } void SetSourceId(NormNodeId sourceId) { buffer[SOURCE_ID_OFFSET] = htonl(sourceId); } // For messages to be sent, "addr" is destination void SetDestination(const ProtoAddress& dst) {addr = dst;} // For message received, "addr" is source void SetSource(const ProtoAddress& src) {addr = src;} void AttachExtension(NormHeaderExtension& extension) { extension.Init(buffer+(header_length/4)); ExtendHeaderLength(extension.GetLength()); } // Message processing routines bool InitFromBuffer(UINT16 msgLength); bool CopyFromBuffer(const char* theBuffer, unsigned int theLength) { if (theLength > MAX_SIZE) return false; memcpy(buffer, theBuffer, theLength); return InitFromBuffer(theLength); } UINT8 GetVersion() const {return (((UINT8*)buffer)[VERSION_OFFSET] >> 4);} NormMsg::Type GetType() const {return (Type)(((UINT8*)buffer)[TYPE_OFFSET] & 0x0f);} UINT16 GetHeaderLength() {return ((UINT8*)buffer)[HDR_LEN_OFFSET] << 2;} UINT16 GetBaseHeaderLength() {return header_length_base;} UINT16 GetSequence() const { return (ntohs((((UINT16*)buffer)[SEQUENCE_OFFSET]))); } NormNodeId GetSourceId() const { return (ntohl(buffer[SOURCE_ID_OFFSET])); } const ProtoAddress& GetDestination() const {return addr;} const ProtoAddress& GetSource() const {return addr;} const char* GetBuffer() const {return ((char*)buffer);} UINT16 GetLength() const {return length;} void Display() const; // hex output to log // To retrieve any attached header extensions bool HasExtensions() const {return (header_length > header_length_base);} bool GetNextExtension(NormHeaderExtension& ext) const { const UINT32* currentBuffer = ext.GetBuffer(); UINT16 nextOffset = (UINT16)(currentBuffer ? (currentBuffer - buffer + (ext.GetLength()/4)) : (header_length_base/4)); bool result = HasExtensions() ? (nextOffset < (header_length/4)) : false; ext.AttachBuffer(result ? (buffer+nextOffset) : (UINT32*)NULL); return result; } // For message reception and misc. char* AccessBuffer() {return ((char*)buffer);} ProtoAddress& AccessAddress() {return addr;} NormMsg* GetNext() {return next;} protected: // Common message header offsets // All of our offsets reflect their offset based on the field size! // (So we can efficiently dereference msg fields with proper alignment) enum { VERSION_OFFSET = 0, TYPE_OFFSET = VERSION_OFFSET, HDR_LEN_OFFSET = VERSION_OFFSET+1, SEQUENCE_OFFSET = (HDR_LEN_OFFSET+1)/2, SOURCE_ID_OFFSET = ((SEQUENCE_OFFSET*2)+2)/4, MSG_OFFSET = (SOURCE_ID_OFFSET*4)+4 }; void SetBaseHeaderLength(UINT16 len) { ((UINT8*)buffer)[HDR_LEN_OFFSET] = len >> 2; length = header_length_base = header_length = len; } void ExtendHeaderLength(UINT16 len) { header_length += len; length += len; ((UINT8*)buffer)[HDR_LEN_OFFSET] = header_length >> 2; } UINT32 buffer[MAX_SIZE / sizeof(UINT32)]; UINT16 length; // in bytes UINT16 header_length; UINT16 header_length_base; ProtoAddress addr; // src or dst address NormMsg* prev; NormMsg* next; }; // end class NormMsg // "NormObjectMsg" is a base class for the similar "NormInfoMsg" // and "NormDataMsg" types class NormObjectMsg : public NormMsg { friend class NormMsg; public: enum Flag { FLAG_REPAIR = 0x01, FLAG_EXPLICIT = 0x02, FLAG_INFO = 0x04, FLAG_UNRELIABLE = 0x08, FLAG_FILE = 0x10, FLAG_STREAM = 0x20, FLAG_SYN = 0x40 //FLAG_MSG_START = 0x40 deprecated }; UINT16 GetInstanceId() const {return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));} UINT8 GetGrtt() const {return ((UINT8*)buffer)[GRTT_OFFSET];} UINT8 GetBackoffFactor() const {return ((((UINT8*)buffer)[GSIZE_OFFSET] >> 4) & 0x0f);} UINT8 GetGroupSize() const {return (((UINT8*)buffer)[GSIZE_OFFSET] & 0x0f);} bool FlagIsSet(NormObjectMsg::Flag flag) const {return (0 != (flag & ((UINT8*)buffer)[FLAGS_OFFSET]));} bool IsStream() const {return FlagIsSet(FLAG_STREAM);} UINT8 GetFecId() const {return ((UINT8*)buffer)[FEC_ID_OFFSET];} NormObjectId GetObjectId() const {return (ntohs(((UINT16*)buffer)[OBJ_ID_OFFSET]));} // Message building routines void SetInstanceId(UINT16 instanceId) {((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);} void SetGrtt(UINT8 grtt) {((UINT8*)buffer)[GRTT_OFFSET] = grtt;} void SetBackoffFactor(UINT8 backoff) {((UINT8*)buffer)[BACKOFF_OFFSET] = (((UINT8*)buffer)[GSIZE_OFFSET] & 0x0f) | (backoff << 4);} void SetGroupSize(UINT8 gsize) {((UINT8*)buffer)[GSIZE_OFFSET] = (((UINT8*)buffer)[GSIZE_OFFSET] & 0xf0) | gsize;} void ResetFlags() {((UINT8*)buffer)[FLAGS_OFFSET] = 0;} void SetFlag(NormObjectMsg::Flag flag) {((UINT8*)buffer)[FLAGS_OFFSET] |= flag;} void SetObjectId(const NormObjectId& objectId) {((UINT16*)buffer)[OBJ_ID_OFFSET] = htons((UINT16)objectId);} protected: enum { INSTANCE_ID_OFFSET = MSG_OFFSET/2, GRTT_OFFSET = (INSTANCE_ID_OFFSET*2)+2, BACKOFF_OFFSET = GRTT_OFFSET+1, GSIZE_OFFSET = BACKOFF_OFFSET, FLAGS_OFFSET = GSIZE_OFFSET+1, FEC_ID_OFFSET = FLAGS_OFFSET+1, OBJ_ID_OFFSET = (FEC_ID_OFFSET+1)/2, OBJ_MSG_OFFSET = (OBJ_ID_OFFSET*2)+2 }; }; // end class NormObjectMsg // This FEC Object Transmission Information assumes "fec_id" == 2 (RFC 5510) // (This is an m-bit Reed-Solomon codec (we use it in NORM for m == 16) class NormFtiExtension2 : public NormHeaderExtension { public: // To build the FTI Header Extension virtual void Init(UINT32* theBuffer) { AttachBuffer(theBuffer); SetType(FTI); // HET = 64 SetWords(4); } void SetObjectSize(const NormObjectSize& objectSize) { ((UINT16*)buffer)[OBJ_SIZE_MSB_OFFSET] = htons(objectSize.MSB()); buffer[OBJ_SIZE_LSB_OFFSET] = htonl(objectSize.LSB()); } void SetFecFieldSize(UINT8 numBits) {((UINT8*)buffer)[FEC_M_OFFSET] = numBits;} // usually 16 for this FTI void SetFecGroupSize(UINT8 symbolsPerPkt) {((UINT8*)buffer)[FEC_G_OFFSET] = symbolsPerPkt;} // usually one void SetSegmentSize(UINT16 segmentSize) {((UINT16*)buffer)[SEG_SIZE_OFFSET] = htons(segmentSize);} void SetFecMaxBlockLen(UINT16 ndata) {((UINT16*)buffer)[FEC_NDATA_OFFSET] = htons(ndata);} void SetFecNumParity(UINT16 nparity) {((UINT16*)buffer)[FEC_NPARITY_OFFSET] = htons(nparity);} // FTI Extension parsing methods NormObjectSize GetObjectSize() const { return NormObjectSize(ntohs(((UINT16*)buffer)[OBJ_SIZE_MSB_OFFSET]), ntohl(buffer[OBJ_SIZE_LSB_OFFSET])); } UINT8 GetFecFieldSize() const {return ((UINT8*)buffer)[FEC_M_OFFSET];} // usually 16 for this FTI UINT8 GetFecGroupSize() const {return ((UINT8*)buffer)[FEC_G_OFFSET];} // usually 1 UINT16 GetSegmentSize() const {return (ntohs(((UINT16*)buffer)[SEG_SIZE_OFFSET]));} UINT16 GetFecMaxBlockLen() const {return (ntohs(((UINT16*)buffer)[FEC_NDATA_OFFSET]));} UINT16 GetFecNumParity() const {return (ntohs(((UINT16*)buffer)[FEC_NPARITY_OFFSET]));} private: enum { OBJ_SIZE_MSB_OFFSET = (LENGTH_OFFSET + 1)/2, OBJ_SIZE_LSB_OFFSET = ((OBJ_SIZE_MSB_OFFSET*2)+2)/4, FEC_M_OFFSET = ((OBJ_SIZE_LSB_OFFSET*4)+4), FEC_G_OFFSET = FEC_M_OFFSET + 1, SEG_SIZE_OFFSET = (FEC_G_OFFSET+1)/2, FEC_NDATA_OFFSET = ((SEG_SIZE_OFFSET*2)+2)/2, FEC_NPARITY_OFFSET = ((FEC_NDATA_OFFSET*2)+2)/2 }; }; // end class NormFtiExtension2 // Helper class for containing key FTI params class NormFtiData { public: NormFtiData() : object_size(NormObjectSize(0)), segment_size(0), num_data(0), num_parity(0), fec_m(0), instance_id(0) {} ~NormFtiData() {} void SetObjectSize(const NormObjectSize& objectSize) {object_size = objectSize;} void SetSegmentSize(UINT16 segmentSize) {segment_size = segmentSize;} void SetFecMaxBlockLen(UINT16 numData) {num_data = numData;} void SetFecNumParity(UINT16 numParity) {num_parity = numParity;} void SetFecFieldSize(UINT8 fecM) {fec_m = fecM;} void SetFecInstanceId(UINT16 instanceId) {instance_id = instanceId;} const NormObjectSize& GetObjectSize() const {return object_size;} UINT16 GetSegmentSize() const {return segment_size;} UINT16 GetFecMaxBlockLen() const {return num_data;} UINT16 GetFecNumParity() const {return num_parity;} UINT8 GetFecFieldSize() const {return fec_m;} UINT16 GetFecInstanceId() const {return instance_id;} private: NormObjectSize object_size; UINT16 segment_size; UINT16 num_data; UINT16 num_parity; UINT8 fec_m; UINT16 instance_id; }; // end class NormFtiData // This FEC Object Transmission Information assumes "fec_id" == 5 (RFC 5510) // (this is the fully-defined 8-bit Reed-Solomon codec) class NormFtiExtension5 : public NormHeaderExtension { public: // To build the fec_id=5 FTI Header Extension virtual void Init(UINT32* theBuffer) { AttachBuffer(theBuffer); SetType(FTI); // HET = 64 SetWords(3); } void SetObjectSize(const NormObjectSize& objectSize) { ((UINT16*)buffer)[OBJ_SIZE_MSB_OFFSET] = htons(objectSize.MSB()); buffer[OBJ_SIZE_LSB_OFFSET] = htonl(objectSize.LSB()); } void SetSegmentSize(UINT16 segmentSize) {((UINT16*)buffer)[SEG_SIZE_OFFSET] = htons(segmentSize);} void SetFecMaxBlockLen(UINT8 ndata) {((UINT8*)buffer)[FEC_NDATA_OFFSET] = ndata;} void SetFecNumParity(UINT8 nparity) {((UINT8*)buffer)[FEC_NPARITY_OFFSET] = nparity;} // FTI Extension parsing methods NormObjectSize GetObjectSize() const { return NormObjectSize(ntohs(((UINT16*)buffer)[OBJ_SIZE_MSB_OFFSET]), ntohl(buffer[OBJ_SIZE_LSB_OFFSET])); } UINT16 GetSegmentSize() const {return (ntohs(((UINT16*)buffer)[SEG_SIZE_OFFSET]));} UINT8 GetFecMaxBlockLen() const {return (((UINT8*)buffer)[FEC_NDATA_OFFSET]);} UINT8 GetFecNumParity() const {return (((UINT8*)buffer)[FEC_NPARITY_OFFSET]);} private: enum { OBJ_SIZE_MSB_OFFSET = (LENGTH_OFFSET + 1)/2, OBJ_SIZE_LSB_OFFSET = ((OBJ_SIZE_MSB_OFFSET*2)+2)/4, SEG_SIZE_OFFSET = ((OBJ_SIZE_LSB_OFFSET*4)+4)/2, FEC_NDATA_OFFSET = ((SEG_SIZE_OFFSET+1)*2), FEC_NPARITY_OFFSET = (FEC_NDATA_OFFSET+1) }; }; // end class NormFtiExtension5 // This FEC Object Transmission Information assumes "fec_id" == 129 class NormFtiExtension129 : public NormHeaderExtension { public: // To build the FTI Header Extension // (TBD) allow for different "fec_id" types in the future virtual void Init(UINT32* theBuffer) { AttachBuffer(theBuffer); SetType(FTI); SetWords(4); } void SetFecInstanceId(UINT16 instanceId) { ((UINT16*)buffer)[FEC_INSTANCE_OFFSET] = htons(instanceId);} void SetFecMaxBlockLen(UINT16 ndata) {((UINT16*)buffer)[FEC_NDATA_OFFSET] = htons(ndata);} void SetFecNumParity(UINT16 nparity) {((UINT16*)buffer)[FEC_NPARITY_OFFSET] = htons(nparity);} void SetSegmentSize(UINT16 segmentSize) {((UINT16*)buffer)[SEG_SIZE_OFFSET] = htons(segmentSize);} void SetObjectSize(const NormObjectSize& objectSize) { ((UINT16*)buffer)[OBJ_SIZE_MSB_OFFSET] = htons(objectSize.MSB()); buffer[OBJ_SIZE_LSB_OFFSET] = htonl(objectSize.LSB()); } // FTI Extension parsing methods UINT16 GetFecInstanceId() const { return (ntohs(((UINT16*)buffer)[FEC_INSTANCE_OFFSET])); } UINT16 GetFecMaxBlockLen() const {return (ntohs(((UINT16*)buffer)[FEC_NDATA_OFFSET]));} UINT16 GetFecNumParity() const {return (ntohs(((UINT16*)buffer)[FEC_NPARITY_OFFSET]));} UINT16 GetSegmentSize() const {return (ntohs(((UINT16*)buffer)[SEG_SIZE_OFFSET]));} NormObjectSize GetObjectSize() const { return NormObjectSize(ntohs(((UINT16*)buffer)[OBJ_SIZE_MSB_OFFSET]), ntohl(buffer[OBJ_SIZE_LSB_OFFSET])); } private: enum { OBJ_SIZE_MSB_OFFSET = (LENGTH_OFFSET + 1)/2, OBJ_SIZE_LSB_OFFSET = ((OBJ_SIZE_MSB_OFFSET*2)+2)/4, FEC_INSTANCE_OFFSET = ((OBJ_SIZE_LSB_OFFSET*4)+4)/2, SEG_SIZE_OFFSET = ((FEC_INSTANCE_OFFSET*2)+2)/2, FEC_NDATA_OFFSET = ((SEG_SIZE_OFFSET*2)+2)/2, FEC_NPARITY_OFFSET = ((FEC_NDATA_OFFSET*2)+2)/2 }; }; // end class NormFtiExtension129 class NormInfoMsg : public NormObjectMsg { public: void Init() { SetType(INFO); SetBaseHeaderLength(INFO_HEADER_LEN); ResetFlags(); } UINT16 GetInfoLen() const {return (length - header_length);} const char* GetInfo() const {return (((char*)buffer) + header_length);} // Message building methods (in addition to NormObjectMsg fields) void SetFecId(UINT8 fecId) {((UINT8*)buffer)[FEC_ID_OFFSET] = fecId;} // Note: apply any header extensions first void SetInfo(const char* data, UINT16 size) { memcpy(((char*)buffer)+header_length, data, size); length = size + header_length; } private: enum {INFO_HEADER_LEN = OBJ_MSG_OFFSET}; }; // end class NormInfoMsg class NormDataMsg : public NormObjectMsg { public: void Init() { SetType(DATA); ResetFlags(); // Note: for NORM_DATA base header length depends on fec_id } // Message building methods (in addition to NormObjectMsg fields) void SetFecId(UINT8 fecId) { ((UINT8*)buffer)[FEC_ID_OFFSET] = fecId; SetBaseHeaderLength(OBJ_MSG_OFFSET + NormPayloadId::GetLength(fecId)); } void SetFecPayloadId(UINT8 fecId, UINT32 blockId, UINT16 symbolId, UINT16 blockLen, UINT8 m) { NormPayloadId payloadId(fecId, m, buffer + FEC_PAYLOAD_ID_OFFSET); payloadId.SetFecPayloadId(blockId, symbolId, blockLen); } // Two ways to set payload content: // 1) Directly access payload to copy segment, then set data message length // (Note NORM_STREAM_OBJECT segments must already include "payload_len" // and "payload_offset" with the "payload_data" char* AccessPayload() {return (((char*)buffer)+header_length);} // For NORM_STREAM_OBJECT segments, "dataLength" must include the PAYLOAD_HEADER_LENGTH void SetPayloadLength(UINT16 payloadLength) {length = header_length + payloadLength;} // Set "payload" directly (useful for FEC parity segments) void SetPayload(char* payload, UINT16 payloadLength) { memcpy(((char*)buffer)+header_length, payload, payloadLength); length = header_length + payloadLength; } // AccessPayloadData() (useful for setting ZERO padding) char* AccessPayloadData() { UINT16 payloadIndex = IsStream() ? header_length+PAYLOAD_DATA_OFFSET : header_length; return (((char*)buffer)+payloadIndex); } // Message processing methods NormBlockId GetFecBlockId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockId(); } UINT16 GetFecSymbolId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecSymbolId(); } UINT16 GetFecBlockLength() const { NormPayloadId payloadId(GetFecId(), 8, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockLength(); } // Note: For NORM_OBJECT_STREAM, "payload" includes "payload_reserved", // "payload_len", "payload_offset", and "payload_data" fields // For NORM_OBJECT_FILE and NORM_OBJECT_DATA, "payload" includes // "payload_data" only const char* GetPayload() const {return (((char*)buffer)+header_length);} UINT16 GetPayloadLength() const {return (length - header_length);} const char* GetPayloadData() const { UINT16 dataIndex = IsStream() ? header_length+PAYLOAD_DATA_OFFSET : header_length; return (((char*)buffer)+dataIndex); } UINT16 GetPayloadDataLength() const { UINT16 dataIndex = IsStream() ? header_length+PAYLOAD_DATA_OFFSET : header_length; return (length - dataIndex); } // These routines are only applicable to messages containing NORM_OBJECT_STREAM content // Some static helper routines for reading/writing embedded payload length/offsets static UINT16 GetStreamPayloadHeaderLength() {return (PAYLOAD_DATA_OFFSET);} static void WriteStreamPayloadLength(char* payload, UINT16 len) { UINT16 temp16 = htons(len); memcpy(payload+PAYLOAD_LENGTH_OFFSET, &temp16, 2); } static void WriteStreamPayloadMsgStart(char* payload, UINT16 msgStartOffset) { UINT16 temp16 = htons(msgStartOffset); memcpy(payload+PAYLOAD_MSG_START_OFFSET, &temp16, 2); } static void WriteStreamPayloadOffset(char* payload, UINT32 offset) { UINT32 temp32 = htonl(offset); memcpy(payload+PAYLOAD_OFFSET_OFFSET, &temp32, 4); } static UINT16 ReadStreamPayloadLength(const char* payload) { UINT16 temp16; memcpy(&temp16, payload+PAYLOAD_LENGTH_OFFSET, 2); return (ntohs(temp16)); } static UINT16 ReadStreamPayloadMsgStart(const char* payload) { UINT16 temp16; memcpy(&temp16, payload+PAYLOAD_MSG_START_OFFSET, 2); return (ntohs(temp16)); } static UINT32 ReadStreamPayloadOffset(const char* payload) { UINT32 temp32; memcpy(&temp32, payload+PAYLOAD_OFFSET_OFFSET, 4); return (ntohl(temp32)); } private: enum { FEC_PAYLOAD_ID_OFFSET = OBJ_MSG_OFFSET/4 }; // IMPORTANT: These offsets are _relative_ to the NORM_DATA header // (incl. any extensions) enum { PAYLOAD_LENGTH_OFFSET = 0, PAYLOAD_MSG_START_OFFSET = PAYLOAD_LENGTH_OFFSET+2, PAYLOAD_OFFSET_OFFSET = PAYLOAD_MSG_START_OFFSET+2, PAYLOAD_DATA_OFFSET = PAYLOAD_OFFSET_OFFSET+4 }; }; // end class NormDataMsg class NormCmdMsg : public NormMsg { public: enum Flavor { INVALID = 0, FLUSH = 1, EOT = 2, SQUELCH = 3, CC = 4, REPAIR_ADV = 5, ACK_REQ = 6, APPLICATION = 7 }; // Message build void SetInstanceId(UINT16 instanceId) {((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);} void SetGrtt(UINT8 quantizedGrtt) {((UINT8*)buffer)[GRTT_OFFSET] = quantizedGrtt;} void SetBackoffFactor(UINT8 backoff) {((UINT8*)buffer)[BACKOFF_OFFSET] = (((UINT8*)buffer)[GSIZE_OFFSET] & 0x0f) | (backoff << 4);} void SetGroupSize(UINT8 gsize) {((UINT8*)buffer)[GSIZE_OFFSET] = (((UINT8*)buffer)[GSIZE_OFFSET] & 0xf0) | gsize;} void SetFlavor(NormCmdMsg::Flavor flavor) {((UINT8*)buffer)[FLAVOR_OFFSET] = (UINT8)flavor;} // Message parse UINT16 GetInstanceId() const {return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));} UINT8 GetGrtt() const {return ((UINT8*)buffer)[GRTT_OFFSET];} UINT8 GetBackoffFactor() const {return ((((UINT8*)buffer)[GSIZE_OFFSET] >> 4) & 0x0f);} UINT8 GetGroupSize() const {return (((UINT8*)buffer)[GSIZE_OFFSET] & 0x0f);} NormCmdMsg::Flavor GetFlavor() const {return (Flavor)((UINT8*)buffer)[FLAVOR_OFFSET];} protected: friend class NormMsg; enum { INSTANCE_ID_OFFSET = MSG_OFFSET/2, GRTT_OFFSET = (INSTANCE_ID_OFFSET+1)*2, BACKOFF_OFFSET = GRTT_OFFSET + 1, GSIZE_OFFSET = BACKOFF_OFFSET, FLAVOR_OFFSET = GSIZE_OFFSET + 1 }; }; // end class NormCmdMsg class NormCmdFlushMsg : public NormCmdMsg { friend class NormMsg; public: void Init() { SetType(CMD); SetFlavor(FLUSH); // base header length depends on fec payload id } void SetFecId(UINT8 fecId) {((UINT8*)buffer)[FEC_ID_OFFSET] = fecId;} void SetObjectId(const NormObjectId& objectId) {((UINT16*)buffer)[OBJ_ID_OFFSET] = htons((UINT16)objectId);} void SetFecPayloadId(UINT8 fecId, UINT32 blockId, UINT16 symbolId, UINT16 blockLen, UINT8 m) { SetFecId(fecId); SetBaseHeaderLength(4*FEC_PAYLOAD_ID_OFFSET + NormPayloadId::GetLength(fecId)); NormPayloadId payloadId(fecId, m, buffer + FEC_PAYLOAD_ID_OFFSET); payloadId.SetFecPayloadId(blockId, symbolId, blockLen); ResetAckingNodeList(); } void ResetAckingNodeList() {length = header_length;} bool AppendAckingNode(NormNodeId nodeId, UINT16 segmentSize) { if ((length-header_length+ 4) > segmentSize) return false; buffer[length/4] = htonl((UINT32)nodeId); length += 4; return true; } // Message processing UINT8 GetFecId() const {return ((UINT8*)buffer)[FEC_ID_OFFSET];} NormObjectId GetObjectId() const { return ntohs(((UINT16*)buffer)[OBJ_ID_OFFSET]);} NormBlockId GetFecBlockId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockId(); } UINT16 GetFecSymbolId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecSymbolId(); } UINT16 GetFecBlockLength() const { NormPayloadId payloadId(GetFecId(), 8, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockLength(); } UINT16 GetAckingNodeCount() const {return ((length - header_length) >> 2);} const UINT32* GetAckingNodeList() const {return (buffer+(header_length/4));} NormNodeId GetAckingNodeId(UINT16 index) const {return (ntohl(buffer[(header_length/4)+index]));} private: enum { FEC_ID_OFFSET = FLAVOR_OFFSET + 1, OBJ_ID_OFFSET = (FEC_ID_OFFSET + 1)/2, FEC_PAYLOAD_ID_OFFSET = ((OBJ_ID_OFFSET+1)*2)/4 }; }; // end class NormCmdFlushMsg class NormCmdEotMsg : public NormCmdMsg { public: void Init() { SetType(CMD); SetFlavor(EOT); SetBaseHeaderLength(EOT_HEADER_LEN); memset(((char*)buffer)+RESERVED_OFFSET, 0, 3); } private: enum { RESERVED_OFFSET = FLAVOR_OFFSET + 1, EOT_HEADER_LEN = RESERVED_OFFSET + 3 }; }; // end class NormCmdEotMsg class NormCmdSquelchMsg : public NormCmdMsg { public: // Message building void Init(UINT8 fecId) { SetType(CMD); SetFlavor(SQUELCH); SetFecId(fecId); // default "fec_id" SetBaseHeaderLength(4*FEC_PAYLOAD_ID_OFFSET + NormPayloadId::GetLength(fecId)); } void SetFecId(UINT8 fecId) {((UINT8*)buffer)[FEC_ID_OFFSET] = fecId;} void SetObjectId(const NormObjectId& objectId) {((UINT16*)buffer)[OBJ_ID_OFFSET] = htons((UINT16)objectId);} void SetFecPayloadId(UINT8 fecId, UINT32 blockId, UINT16 symbolId, UINT16 blockLen, UINT8 m) { SetFecId(fecId); SetBaseHeaderLength(4*FEC_PAYLOAD_ID_OFFSET + NormPayloadId::GetLength(fecId)); NormPayloadId payloadId(fecId, m, buffer + FEC_PAYLOAD_ID_OFFSET); payloadId.SetFecPayloadId(blockId, symbolId, blockLen); ResetInvalidObjectList(); } void ResetInvalidObjectList() {length = header_length;} // Note must apply any header extensions _before_ appending payload. bool AppendInvalidObject(NormObjectId objectId, UINT16 segmentSize) { if ((length-header_length+2) > segmentSize) return false; ((UINT16*)buffer)[length/2] = htons((UINT16)objectId); length += 2; return true; } // Message processing UINT8 GetFecId() const {return ((UINT8*)buffer)[FEC_ID_OFFSET];} NormObjectId GetObjectId() const {return (ntohs(((UINT16*)buffer)[OBJ_ID_OFFSET]));} NormBlockId GetFecBlockId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockId(); } UINT16 GetFecSymbolId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecSymbolId(); } UINT16 GetFecBlockLength() const { NormPayloadId payloadId(GetFecId(), 8, buffer + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockLength(); } // Use these to parse invalid object list UINT16 GetInvalidObjectCount() const {return ((length - header_length) >> 1);} UINT16* GetInvalidObjectList() const {return (UINT16*)(buffer+header_length);} NormObjectId GetInvalidObjectId(UINT16 index) const {return (ntohs(((UINT16*)buffer)[(header_length/2)+index]));} private: enum { FEC_ID_OFFSET = FLAVOR_OFFSET + 1, OBJ_ID_OFFSET = (FEC_ID_OFFSET + 1)/2, FEC_PAYLOAD_ID_OFFSET = ((OBJ_ID_OFFSET+1)*2)/4 }; }; // end class NormCmdSquelchMsg // These flag values are used "cc_flags" field of NORM_CMD(CC) CC_NODE_LIST // items and NORM_NACK and NORM_ACK messages class NormCC { public: enum Flag { CLR = 0x01, PLR = 0x02, RTT = 0x04, START = 0x08, LEAVE = 0x10, LIMIT = 0x20 // experimental, non-RFC5740 }; // (set when included rate is measured, not calculated) }; // end class NormCC class NormCmdCCMsg : public NormCmdMsg { public: void Init() { SetType(CMD); SetFlavor(CC); SetBaseHeaderLength(CC_HEADER_LEN); ((UINT8*)buffer)[RESERVED_OFFSET] = 0; } void SetCCSequence(UINT16 ccSequence) { ((UINT16*)buffer)[CC_SEQUENCE_OFFSET] = htons(ccSequence); } void SetSendTime(const struct timeval& sendTime) { buffer[SEND_TIME_SEC_OFFSET] = htonl(sendTime.tv_sec); buffer[SEND_TIME_USEC_OFFSET] = htonl(sendTime.tv_usec); } UINT16 GetCCSequence() const {return (ntohs(((UINT16*)buffer)[CC_SEQUENCE_OFFSET]));} void GetSendTime(struct timeval& sendTime) const { sendTime.tv_sec = ntohl(buffer[SEND_TIME_SEC_OFFSET]); sendTime.tv_usec = ntohl(buffer[SEND_TIME_USEC_OFFSET]); } bool AppendCCNode(UINT16 segMax, NormNodeId nodeId, UINT8 flags, UINT8 rtt, UINT16 rate) { if ((length-header_length+CC_ITEM_SIZE)> segMax) return false; UINT32* ptr = buffer + length/4; ptr[CC_NODE_ID_OFFSET] = htonl(nodeId); ((UINT8*)ptr)[CC_FLAGS_OFFSET] = flags; ((UINT8*)ptr)[CC_RTT_OFFSET] = rtt; ((UINT16*)ptr)[CC_RATE_OFFSET] = htons(rate); length += CC_ITEM_SIZE; return true; } bool GetCCNode(NormNodeId nodeId, UINT8& flags, UINT8& rtt, UINT16& rate) const; // This function uses the "reserved" field of the NORM_CMD(CC) message // and is not strictly compliant with RFC 5740 when invoked. enum {FLAG_SYN = 0x01}; bool SynIsSet() const {return (0 != (FLAG_SYN & ((UINT8*)buffer)[RESERVED_OFFSET]));} void SetSyn() {((UINT8*)buffer)[RESERVED_OFFSET] = FLAG_SYN;} class Iterator; friend class Iterator; class Iterator { public: Iterator(const NormCmdCCMsg& msg); void Reset() {offset = 0;} bool GetNextNode(NormNodeId& nodeId, UINT8& flags, UINT8& rtt, UINT16& rate); private: const NormCmdCCMsg& cc_cmd; UINT16 offset; }; private: enum { RESERVED_OFFSET = FLAVOR_OFFSET + 1, CC_SEQUENCE_OFFSET = (RESERVED_OFFSET + 1)/2, SEND_TIME_SEC_OFFSET = ((CC_SEQUENCE_OFFSET*2)+2)/4, SEND_TIME_USEC_OFFSET = ((SEND_TIME_SEC_OFFSET*4)+4)/4, CC_HEADER_LEN = (SEND_TIME_USEC_OFFSET*4)+4 }; enum { CC_NODE_ID_OFFSET = 0, CC_FLAGS_OFFSET = CC_NODE_ID_OFFSET + 4, CC_RTT_OFFSET = CC_FLAGS_OFFSET + 1, CC_RATE_OFFSET = (CC_RTT_OFFSET + 1)/2, CC_ITEM_SIZE = (CC_RATE_OFFSET*2)+2 }; }; // end class NormCmdCCMsg class NormCCRateExtension : public NormHeaderExtension { public: virtual void Init(UINT32* theBuffer) { AttachBuffer(theBuffer); SetType(CC_RATE); ((UINT8*)buffer)[RESERVED_OFFSET] = 0; } void SetSendRate(UINT16 sendRate) {((UINT16*)buffer)[SEND_RATE_OFFSET] = htons(sendRate);} UINT16 GetSendRate() {return (ntohs(((UINT16*)buffer)[SEND_RATE_OFFSET]));} private: enum { RESERVED_OFFSET = TYPE_OFFSET + 1, SEND_RATE_OFFSET = (RESERVED_OFFSET + 1)/2 }; }; // end class NormCCRateExtension // This implementation currently assumes "fec_id"= 129 class NormRepairRequest { public: class Iterator; friend class NormRepairRequest::Iterator; enum Form { INVALID = 0, ITEMS = 1, RANGES = 2, ERASURES = 3 }; enum Flag { SEGMENT = 0x01, BLOCK = 0x02, INFO = 0x04, OBJECT = 0x08 }; // Construction NormRepairRequest(); void Init(UINT32* bufferPtr, UINT16 bufferLen) { buffer = bufferPtr; buffer_len = bufferLen; length = 0; } // (TBD) these could be an enumeration for optimization static UINT16 RepairItemLength(UINT8 fecId) {return (4 + NormPayloadId::GetLength(fecId));} static UINT16 RepairRangeLength(UINT8 fecId) {return (2 * RepairItemLength(fecId));} static UINT16 ErasureItemLength(UINT8 fecId) {return RepairItemLength(fecId);} // Repair request building void SetForm(NormRepairRequest::Form theForm) {form = theForm;} void ResetFlags() {flags = 0;} void SetFlag(NormRepairRequest::Flag theFlag) {flags |= theFlag;} void ClearFlag(NormRepairRequest::Flag theFlag) {flags &= ~theFlag;} void SetFlags(int theFlags) {flags = theFlags;} // Returns length (each repair item requires 8 bytes of space) bool AppendRepairItem(UINT8 fecId, UINT8 fecM, const NormObjectId& objectId, const NormBlockId& blockId, UINT16 blockLen, UINT16 symbolId); bool AppendRepairRange(UINT8 fecId, UINT8 fecM, const NormObjectId& startObjectId, const NormBlockId& startBlockId, UINT16 startBlockLen, UINT16 startSymbolId, const NormObjectId& endObjectId, const NormBlockId& endBlockId, UINT16 endBlockLen, UINT16 endSymbolId); bool AppendErasureCount(UINT8 fecId, UINT8 fecM, const NormObjectId& objectId, const NormBlockId& blockId, UINT16 blockLen, UINT16 erasureCount); UINT16 Pack(); // Repair request processing UINT16 Unpack(const UINT32* bufferPtr, UINT16 bufferLen); NormRepairRequest::Form GetForm() const {return form;} bool FlagIsSet(NormRepairRequest::Flag theFlag) const {return (0 != (theFlag & flags));} int GetFlags() const {return flags;} UINT16 GetLength() const {return (ITEM_LIST_OFFSET + length);} UINT32* GetBuffer() const {return buffer;} // Outputs textual representation of RepairRequest content void Log(UINT8 fecId, UINT8 fecM) const; class Iterator { public: // Checks for matching fecId and assumes constant 'm' ?!?! Iterator(const NormRepairRequest& theRequest, UINT8 fecId, UINT8 fecM); void Reset() {offset = 0;} UINT16 NextRepairItem(NormObjectId* objectId, NormBlockId* blockId, UINT16* blockLen, UINT16* symbolId); private: const NormRepairRequest& request; UINT8 fec_id; UINT8 fec_m; UINT16 offset; }; // end class NormRepairRequest::Iterator private: UINT16 RetrieveRepairItem(UINT8 fecM, UINT16 offset, UINT8* fecId, NormObjectId* objectId, NormBlockId* blockId, UINT16* blockLen, UINT16* symbolId) const; enum { FORM_OFFSET = 0, FLAGS_OFFSET = FORM_OFFSET + 1, LENGTH_OFFSET = (FLAGS_OFFSET + 1)/2, ITEM_LIST_OFFSET = (LENGTH_OFFSET*2)+2 }; // These are the offsets for "fec_id" = 129 NormRepairRequest items enum { FEC_ID_OFFSET = 0, RESERVED_OFFSET = FEC_ID_OFFSET + 1, OBJ_ID_OFFSET = (RESERVED_OFFSET + 1)/2, FEC_PAYLOAD_ID_OFFSET = ((OBJ_ID_OFFSET+1)*2)/4 }; Form form; int flags; UINT16 length; // length of repair items UINT32* buffer; UINT16 buffer_len; // in bytes }; // end class NormRepairRequest class NormCmdRepairAdvMsg : public NormCmdMsg { public: enum Flag {NORM_REPAIR_ADV_FLAG_LIMIT = 0x01}; void Init() { SetType(CMD); SetFlavor(REPAIR_ADV); SetBaseHeaderLength(REPAIR_ADV_HEADER_LEN); ResetFlags(); ((UINT16*)buffer)[RESERVED_OFFSET] = 0; } // Message building void ResetFlags() {((UINT8*)buffer)[FLAGS_OFFSET] = 0;} void SetFlag(NormCmdRepairAdvMsg::Flag flag) {((UINT8*)buffer)[FLAGS_OFFSET] |= (UINT8)flag;} void AttachRepairRequest(NormRepairRequest& request, UINT16 segmentMax) { int buflen = segmentMax - (length - header_length); buflen = (buflen>0) ? buflen : 0; request.Init(buffer+length/4, buflen); } UINT16 PackRepairRequest(NormRepairRequest& request) { UINT16 requestLength = request.Pack(); length += requestLength; return requestLength; } // Message processing bool FlagIsSet(NormCmdRepairAdvMsg::Flag flag) const {return (0 != ((UINT8)flag | ((UINT8*)buffer)[FLAGS_OFFSET]));} //char* AccessRepairContent() {return (buffer + header_length);} const UINT32* GetRepairContent() const {return (buffer + header_length/4);} UINT16 GetRepairContentLength() const {return (length - header_length);} private: enum { FLAGS_OFFSET = FLAVOR_OFFSET + 1, RESERVED_OFFSET = FLAGS_OFFSET + 1, REPAIR_ADV_HEADER_LEN = RESERVED_OFFSET + 2 }; }; // end class NormCmdRepairAdvMsg // TBD - define NormCCFeedbackExtension2 for larger loss encoding range // the current 16-bit range is too limited for large RTT*rate combos class NormCCFeedbackExtension : public NormHeaderExtension { public: virtual void Init(UINT32* theBuffer) { AttachBuffer(theBuffer); SetType(CC_FEEDBACK); SetWords(3); ((UINT8*)buffer)[CC_FLAGS_OFFSET] = 0; //((UINT16*)buffer)[CC_RESERVED_OFFSET] = 0; } void SetCCSequence(UINT16 ccSequence) {((UINT16*)buffer)[CC_SEQUENCE_OFFSET] = htons(ccSequence);} void ResetCCFlags() {((UINT8*)buffer)[CC_FLAGS_OFFSET] = 0;} void SetCCFlag(NormCC::Flag flag) {((UINT8*)buffer)[CC_FLAGS_OFFSET] |= (UINT8)flag;} void SetCCRtt(UINT8 ccRtt) {((UINT8*)buffer)[CC_RTT_OFFSET] = ccRtt;} //void SetCCLoss(UINT16 ccLoss) // {((UINT16*)buffer)[CC_LOSS_OFFSET] = htons(ccLoss);} void SetCCRate(UINT16 ccRate) {((UINT16*)buffer)[CC_RATE_OFFSET] = htons(ccRate);} void SetCCLoss32(UINT32 ccLoss) { ccLoss = htonl(ccLoss); UINT16* ptr = (UINT16*)&ccLoss; ((UINT16*)buffer)[CC_LOSS_OFFSET] = ptr[0]; // msb ((UINT16*)buffer)[CC_LOSS_EX_OFFSET] = ptr[1]; // lsb } UINT16 GetCCSequence() const {return (ntohs(((UINT16*)buffer)[CC_SEQUENCE_OFFSET]));} UINT8 GetCCFlags() {return ((UINT8*)buffer)[CC_FLAGS_OFFSET];} bool CCFlagIsSet(NormCC::Flag flag) const {return (0 != ((UINT8)flag & ((UINT8*)buffer)[CC_FLAGS_OFFSET]));} UINT8 GetCCRtt() const {return ((UINT8*)buffer)[CC_RTT_OFFSET];} //UINT16 GetCCLoss() const // {return (ntohs(((UINT16*)buffer)[CC_LOSS_OFFSET]));} UINT16 GetCCRate()const {return (ntohs(((UINT16*)buffer)[CC_RATE_OFFSET]));} UINT32 GetCCLoss32() const { UINT32 lossQuantized; UINT16* ptr = (UINT16*)&lossQuantized; ptr[0] = ((UINT16*)buffer)[CC_LOSS_OFFSET]; // msb ptr[1] = ((UINT16*)buffer)[CC_LOSS_EX_OFFSET]; // lsb return ntohl(lossQuantized); // return in host byte order } private: enum { CC_SEQUENCE_OFFSET = (LENGTH_OFFSET+1)/2, CC_FLAGS_OFFSET = (CC_SEQUENCE_OFFSET*2)+2, CC_RTT_OFFSET = CC_FLAGS_OFFSET + 1, CC_LOSS_OFFSET = (CC_RTT_OFFSET + 1)/2, CC_RATE_OFFSET = ((CC_LOSS_OFFSET*2)+2)/2, //CC_RESERVED_OFFSET = ((CC_RATE_OFFSET*2)+2)/2 CC_LOSS_EX_OFFSET = ((CC_RATE_OFFSET*2)+2)/2 // extended precision loss estimate (non-RFC5940 compliant, but compatible) }; }; // end class NormCCFeedbackExtension // Note: Support for application-defined AckFlavors (32-255) // may be provided, but 0-31 are reserved values class NormAck { public: enum Type { INVALID = 0, CC = 1, FLUSH = 2, APP_BASE = 16 }; }; class NormCmdAckReqMsg : public NormCmdMsg { public: void Init() { SetType(CMD); SetFlavor(ACK_REQ); SetBaseHeaderLength(ACK_REQ_HEADER_LEN); ((UINT8*)buffer)[RESERVED_OFFSET] = 0; } // Message building void SetAckType(NormAck::Type ackType) {((UINT8*)buffer)[ACK_TYPE_OFFSET] = (UINT8)ackType;} void SetAckId(UINT8 ackId) {((UINT8*)buffer)[ACK_ID_OFFSET] = ackId;} void ResetAckingNodeList() {length = header_length;} bool AppendAckingNode(NormNodeId nodeId, UINT16 segmentSize) { if ((length - header_length + 4) > segmentSize) return false; buffer[length/4] = htonl(nodeId); length += 4; return true; } // Message processing NormAck::Type GetAckType() const {return (NormAck::Type)(((UINT8*)buffer)[ACK_TYPE_OFFSET]);} UINT8 GetAckId() const {return ((UINT8*)buffer)[ACK_ID_OFFSET];} UINT16 GetAckingNodeCount() const {return ((length - header_length) >> 2);} NormNodeId GetAckingNodeId(UINT16 index) const {return (ntohl(buffer[(header_length/4)+index]));} private: enum { RESERVED_OFFSET = FLAVOR_OFFSET + 1, ACK_TYPE_OFFSET = RESERVED_OFFSET + 1, ACK_ID_OFFSET = ACK_TYPE_OFFSET + 1, ACK_REQ_HEADER_LEN = ACK_ID_OFFSET + 1 }; }; // end class NormCmdAckReqMsg class NormCmdAppMsg : public NormCmdMsg { public: void Init() { SetType(CMD); SetFlavor(APPLICATION); SetBaseHeaderLength(APPLICATION_HEADER_LEN); memset(((UINT8*)buffer)+RESERVED_OFFSET, 0, 3); } bool SetContent(const char* content, UINT16 contentLen, UINT16 segmentSize) { UINT16 len = MIN(contentLen, segmentSize); memcpy(((char*)buffer)+header_length, content, len); length = header_length + len; return (contentLen <= segmentSize); } UINT16 GetContentLength() const {return (length - header_length);} const char* GetContent() const {return (((char*)buffer)+header_length);} private: enum { RESERVED_OFFSET = FLAVOR_OFFSET + 1, APPLICATION_HEADER_LEN = RESERVED_OFFSET + 3 }; }; // end class NormCmdAppMsg // Receiver Messages class NormNackMsg : public NormMsg { public: enum {DEFAULT_LENGTH_MAX = 40}; void Init() { SetType(NACK); ((UINT16*)buffer)[RESERVED_OFFSET] = 0; SetBaseHeaderLength(NACK_HEADER_LEN); } // Message building void SetSenderId(NormNodeId senderId) {buffer[SENDER_ID_OFFSET] = htonl(senderId);} void SetInstanceId(UINT16 instanceId) {((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);} void SetGrttResponse(const struct timeval& grttResponse) { buffer[GRTT_RESPONSE_SEC_OFFSET] = htonl(grttResponse.tv_sec); buffer[GRTT_RESPONSE_USEC_OFFSET] = htonl(grttResponse.tv_usec); } void AttachRepairRequest(NormRepairRequest& request, UINT16 segmentMax) { int buflen = segmentMax - (length - header_length); buflen = (buflen>0) ? buflen : 0; request.Init(buffer+length/4, buflen); } UINT16 PackRepairRequest(NormRepairRequest& request) { UINT16 requestLength = request.Pack(); length += requestLength; return requestLength; } // TBD - add some safety checks to these methods void InitFrom(NormNackMsg nack) { // Copy header from "nack" memcpy(buffer, nack.buffer, nack.GetHeaderLength()); header_length_base = nack.header_length_base; length = header_length = nack.GetHeaderLength(); } void AppendRepairRequest(const NormRepairRequest request) { memcpy(buffer+length/4, request.GetBuffer(), request.GetLength()); length += request.GetLength(); } void ResetPayload() {length = GetHeaderLength();} // Message processing NormNodeId GetSenderId() const {return (ntohl(buffer[SENDER_ID_OFFSET]));} UINT16 GetInstanceId() const {return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));} void GetGrttResponse(struct timeval& grttResponse) const { grttResponse.tv_sec = ntohl(buffer[GRTT_RESPONSE_SEC_OFFSET]); grttResponse.tv_usec = ntohl(buffer[GRTT_RESPONSE_USEC_OFFSET]); } //char* AccessRepairContent() {return (buffer + header_length);} const UINT32* GetRepairContent() const {return (buffer + header_length/4);} UINT16 GetRepairContentLength() const {return ((length > header_length) ? length - header_length : 0);} UINT16 UnpackRepairRequest(NormRepairRequest& request, UINT16 requestOffset) { int buflen = length - header_length - requestOffset; buflen = (buflen > 0) ? buflen : 0; return request.Unpack(buffer+(header_length+requestOffset)/4, buflen); } private: enum { SENDER_ID_OFFSET = MSG_OFFSET/4, INSTANCE_ID_OFFSET = ((SENDER_ID_OFFSET*4)+4)/2, RESERVED_OFFSET = ((INSTANCE_ID_OFFSET*2)+2)/2, GRTT_RESPONSE_SEC_OFFSET = ((RESERVED_OFFSET*2)+2)/4, GRTT_RESPONSE_USEC_OFFSET = ((GRTT_RESPONSE_SEC_OFFSET*4)+4)/4, NACK_HEADER_LEN = (GRTT_RESPONSE_USEC_OFFSET*4)+4 }; }; // end class NormNackMsg class NormAckMsg : public NormMsg { public: // Message building void Init() { SetType(ACK); SetBaseHeaderLength(ACK_HEADER_LEN); SetAckType(NormAck::INVALID); } void SetSenderId(NormNodeId senderId) {buffer[SENDER_ID_OFFSET] = htonl(senderId);} void SetInstanceId(UINT16 instanceId) {((UINT16*)buffer)[INSTANCE_ID_OFFSET] = htons(instanceId);} void SetAckType(NormAck::Type ackType) {((UINT8*)buffer)[ACK_TYPE_OFFSET] = (UINT8)ackType;} void SetAckId(UINT8 ackId) {((UINT8*)buffer)[ACK_ID_OFFSET] = ackId;} void SetGrttResponse(const struct timeval& grttResponse) { buffer[GRTT_RESPONSE_SEC_OFFSET] = htonl(grttResponse.tv_sec); buffer[GRTT_RESPONSE_USEC_OFFSET] = htonl(grttResponse.tv_usec); } bool SetAckPayload(const char* payload, UINT16 payloadLen, UINT16 segmentSize) { UINT16 len = MIN(payloadLen, segmentSize); memcpy(((char*)buffer)+header_length, payload, len); length += len; return (payloadLen <= segmentSize); } // Message processing NormNodeId GetSenderId() const {return (ntohl(buffer[SENDER_ID_OFFSET]));} UINT16 GetInstanceId() const {return (ntohs(((UINT16*)buffer)[INSTANCE_ID_OFFSET]));} void GetGrttResponse(struct timeval& grttResponse) const { grttResponse.tv_sec = ntohl(buffer[GRTT_RESPONSE_SEC_OFFSET]); grttResponse.tv_usec = ntohl(buffer[GRTT_RESPONSE_USEC_OFFSET]); } NormAck::Type GetAckType() const {return (NormAck::Type)((UINT8*)buffer)[ACK_TYPE_OFFSET];} UINT8 GetAckId() const {return ((UINT8*)buffer)[ACK_ID_OFFSET];} UINT16 GetPayloadLength() const {return (length - header_length);} const char* GetPayload() const {return (((char*)buffer) + header_length);} protected: enum { SENDER_ID_OFFSET = MSG_OFFSET/4, INSTANCE_ID_OFFSET = ((SENDER_ID_OFFSET*4)+4)/2, ACK_TYPE_OFFSET = (INSTANCE_ID_OFFSET*2)+2, ACK_ID_OFFSET = ACK_TYPE_OFFSET + 1, GRTT_RESPONSE_SEC_OFFSET = (ACK_ID_OFFSET + 1)/4, GRTT_RESPONSE_USEC_OFFSET = ((GRTT_RESPONSE_SEC_OFFSET+1)*4)/4, ACK_HEADER_LEN = (GRTT_RESPONSE_USEC_OFFSET+1)*4 }; }; // end class NormAckMsg class NormAckFlushMsg : public NormAckMsg { public: void Init() { SetType(ACK); SetBaseHeaderLength(ACK_HEADER_LEN); SetAckType(NormAck::FLUSH); ((UINT8*)buffer)[RESERVED_OFFSET] = 0; } // Note: must apply any header exts _before_ the payload is set void SetFecId(UINT8 fecId) {((UINT8*)buffer)[header_length+FEC_ID_OFFSET] = fecId;} void SetObjectId(NormObjectId objectId) {((UINT16*)buffer)[(header_length/2)+OBJ_ID_OFFSET] = htons((UINT16)objectId);} void SetFecPayloadId(UINT8 fecId, UINT32 blockId, UINT16 symbolId, UINT16 blockLen, UINT8 m) { SetFecId(fecId); ((UINT8*)buffer)[header_length+RESERVED_OFFSET] = 0; NormPayloadId payloadId(fecId, m, buffer + header_length/4 + FEC_PAYLOAD_ID_OFFSET); payloadId.SetFecPayloadId(blockId, symbolId, blockLen); length = header_length + 4*FEC_PAYLOAD_ID_OFFSET + NormPayloadId::GetLength(fecId); } UINT8 GetFecId() const {return ((UINT8*)buffer)[header_length+FEC_ID_OFFSET];} NormObjectId GetObjectId() const {return ntohs(((UINT16*)buffer)[(header_length/2)+OBJ_ID_OFFSET]);} NormBlockId GetFecBlockId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + header_length/4 + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockId(); } UINT16 GetFecSymbolId(UINT8 m) const { NormPayloadId payloadId(GetFecId(), m, buffer + header_length/4 + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecSymbolId(); } UINT16 GetFecBlockLength() const { NormPayloadId payloadId(GetFecId(), 8, buffer + header_length/4 + FEC_PAYLOAD_ID_OFFSET); return payloadId.GetFecBlockLength(); } private: // Note - These are the payload offsets for "fec_id" = 129 // "fec_payload_id" field // IMPORTANT - These are _relative_ to the NORM_ACK header (incl. extensions) enum { FEC_ID_OFFSET = 0, RESERVED_OFFSET = FEC_ID_OFFSET + 1, OBJ_ID_OFFSET = (RESERVED_OFFSET+1)/2, FEC_PAYLOAD_ID_OFFSET = ((OBJ_ID_OFFSET*2)+2)/4 }; }; // end class NormAckFlushMsg class NormReportMsg : public NormMsg { // (TBD) }; // end class NormReportMsg // One we've defined our basic message types, we // do some unions so we can easily use these // via casting or dereferencing the union members class NormMessageQueue { public: NormMessageQueue(); ~NormMessageQueue(); void Destroy(); void Prepend(NormMsg* msg); void Append(NormMsg* msg); void Remove(NormMsg* msg); NormMsg* RemoveHead(); NormMsg* RemoveTail(); NormMsg* GetHead() {return head;} bool IsEmpty() {return ((NormMsg*)NULL == head);} private: NormMsg* head; NormMsg* tail; }; // end class NormMessageQueue // Helper function to output report on repair content (e.g. NormNack content) to debug log void LogRepairContent(const UINT32* buffer, UINT16 bufferLen, UINT8 fecId, UINT8 fecM); #endif // _NORM_MESSAGE norm-1.5.8+dfsg2/include/normNode.h0000644000000000000000000007030413150575730013756 0ustar #ifndef _NORM_NODE #define _NORM_NODE #include "normMessage.h" #include "normObject.h" #include "normEncoder.h" #include "protokit.h" class NormNode { friend class NormNodeTree; friend class NormNodeTreeIterator; friend class NormNodeList; friend class NormNodeListIterator; public: enum Type { ACKER, SENDER, CC_NODE }; NormNode(Type theType, class NormSession& theSession, NormNodeId nodeId); virtual ~NormNode(); Type GetType() const {return node_type;} NormSession& GetSession() const {return session;} void Retain(); void Release(); void SetUserData(const void* userData) {user_data = userData;} const void* GetUserData() const {return user_data;} const ProtoAddress& GetAddress() const {return addr;} void SetAddress(const ProtoAddress& address) {addr = address;} const NormNodeId& GetId() const {return id;} void SetId(const NormNodeId& nodeId) {id = nodeId;} inline const NormNodeId& LocalNodeId() const; class Accumulator { public: Accumulator(); void Reset() {msb = lsb = 0;} void Increment(unsigned long count) { unsigned long lsbOld = lsb; lsb += count; if (lsb < lsbOld) msb++; } double GetValue() const {return ((((double)0xffffffff)*msb) + lsb);} double GetScaledValue(double factor) const {return ((((double)0xffffffff)*(factor*msb)) + (factor*lsb));} private: unsigned long msb; unsigned long lsb; }; protected: class NormSession& session; private: Type node_type; NormNodeId id; ProtoAddress addr; unsigned int reference_count; const void* user_data; // We keep NormNodes in a binary tree (TBD) make this a ProtoTree NormNode* parent; NormNode* right; NormNode* left; }; // end class NormNode // Weighted-history loss event estimator class NormLossEstimator { public: NormLossEstimator(); double LossFraction(); bool Update(const struct timeval& currentTime, unsigned short seqNumber, bool ecn = false); void SetLossEventWindow(double lossWindow) {event_window = lossWindow;} void SetInitialLoss(double lossFraction) { memset(history, 0, (DEPTH+1)*sizeof(unsigned int)); history[1] = (unsigned int)((1.0 / lossFraction) + 0.5); } unsigned int LastLossInterval() {return history[1];} private: enum {DEPTH = 8}; enum {MAX_OUTAGE = 100}; void Sync(unsigned short seq) { index_seq = seq; synchronized = true; } int SequenceDelta(unsigned short a, unsigned short b); static const double weight[8]; bool synchronized; unsigned short index_seq; bool seeking_loss_event; double event_window; struct timeval event_time; unsigned int history[DEPTH+1]; }; // end class NormLossEstimator class NormLossEstimator2 { public: NormLossEstimator2(); void SetLossEventWindow(double theTime) {event_window = theTime;} bool Update(const struct timeval& currentTime, unsigned short seqNumber, bool ecn = false); double LossFraction(); void SetInitialLoss(double lossFraction) { memset(history, 0, (DEPTH+1)*sizeof(unsigned int)); history[1] = (unsigned int)((1.0 / lossFraction) + 0.5); } unsigned long CurrentLossInterval() {return history[0];} unsigned int LastLossInterval() {return history[1];} void SetIgnoreLoss(bool state) {ignore_loss = state;} void SetTolerateLoss(bool state) {tolerate_loss = state;} unsigned short GetLagIndex() const {return lag_index;} private: enum {DEPTH = 8}; enum LossEventStatus { CONFIRMED = 0, CONFIRMING = 1, SEEKING = 2 }; // Members bool init; bool ignore_loss; bool tolerate_loss; unsigned long lag_mask; unsigned int lag_depth; unsigned long lag_test_bit; unsigned short lag_index; double event_window; struct timeval event_time; struct timeval event_time_orig; // (TBD - remove this, it's not used); LossEventStatus seeking_loss_event; unsigned long history[9]; // loss interval history double discount[9]; double current_discount; static const double weight[8]; void Init(unsigned short theSequence) {init = true; Sync(theSequence);} void Sync(unsigned short theSequence) {lag_index = theSequence;} void ChangeLagDepth(unsigned int theDepth) { theDepth = (theDepth > 20) ? 20 : theDepth; lag_depth = theDepth; lag_test_bit = 0x01 << theDepth; } int SequenceDelta(unsigned short a, unsigned short b); }; // end class NormLossEstimator2 class NormAckingNode : public NormNode { public: NormAckingNode(class NormSession& theSession, NormNodeId nodeId); ~NormAckingNode(); bool IsPending() const {return (!ack_received && (req_count > 0));} void Reset(unsigned int maxAttempts) { ack_received = false; req_count = maxAttempts; } void DecrementReqCount() {if (req_count > 0) req_count--;} void ResetReqCount(unsigned int maxAttempts) {req_count = maxAttempts;} unsigned int GetReqCount() const {return req_count;} bool AckReceived() const {return ack_received;} void MarkAckReceived() {ack_received = true;} private: bool ack_received; // was ack received? unsigned int req_count; // remaining request attempts }; // end NormAckingNode class NormCCNode : public NormNode { public: NormCCNode(class NormSession& theSession, NormNodeId nodeId); ~NormCCNode(); enum {ACTIVE_MAX = 7}; bool IsClr() const {return is_clr;} bool IsPlr() const {return is_plr;} bool IsActive() const {return is_active;} bool HasRtt() const {return rtt_confirmed;} double GetRtt() const {return rtt;} double GetRttSample() const {return rtt_sample;} double GetRttSqMean() const {return rtt_sqmean;} double GetLoss() const {return loss;} double GetRate() const {return rate;} UINT16 GetCCSequence() const {return cc_sequence;} const struct timeval& GetFeedbackTime() {return feedback_time;} void SetFeedbackTime(struct timeval& theTime) {feedback_time = theTime;} void SetActive(bool state) {is_active = state;} void SetClrStatus(bool state) {is_clr = state;} void SetPlrStatus(bool state) {is_plr = state;} void SetRttStatus(bool state) {rtt_confirmed = state;} void SetRtt(double value) { rtt_sqmean = sqrt(value); rtt = rtt_sample = value; } double UpdateRtt(double value) { rtt_sample = value; // save last rtt sample rtt_sqmean = 0.9*rtt_sqmean + 0.1*sqrt(value); rtt = 0.9*rtt + 0.1*value; return rtt; } void SetLoss(double value) {loss = value;} void SetRate(double value) {rate = value;} void SetCCSequence(UINT16 value) {cc_sequence = value;} private: bool is_clr; // true if worst path representative bool is_plr; // true if worst path candidate bool rtt_confirmed; bool is_active; struct timeval feedback_time; // time of last received feedback double rtt; // in seconds double rtt_sqmean; // ave sqrt(rtt), EWMA smoothed double rtt_sample; // last rtt sample value double loss; // loss fraction double rate; // in bytes per second UINT16 cc_sequence; }; // end class NormCCNode class NormSenderNode : public NormNode, public ProtoTree::Item { public: enum ObjectStatus {OBJ_INVALID, OBJ_NEW, OBJ_PENDING, OBJ_COMPLETE}; enum RepairBoundary {BLOCK_BOUNDARY, OBJECT_BOUNDARY}; enum SyncPolicy { SYNC_CURRENT, // sync to detect transmit point, iff NORM_DATA from first FEC block unless stream SYNC_STREAM, // same as SYNC_CURRENT, but attempts to recover stream block zero SYNC_ALL // permiscuously sync as far back as possible given rx cache size }; NormSenderNode(class NormSession& theSession, NormNodeId nodeId); ~NormSenderNode(); void SetInstanceId(UINT16 instanceId) {instance_id = instanceId;} bool PreallocateRxStream(unsigned int bufferSize, UINT16 segmentSize , UINT16 numData, UINT16 numParity); bool GetFtiData(const NormObjectMsg& msg, NormFtiData& ftiData); // Parameters NormObject::NackingMode GetDefaultNackingMode() const {return default_nacking_mode;} void SetDefaultNackingMode(NormObject::NackingMode nackingMode) {default_nacking_mode = nackingMode;} // Should generally inherit NormSession::GetRxRobustFactor() void SetRobustFactor(int value); RepairBoundary GetRepairBoundary() const {return repair_boundary;} // (TBD) force an appropriate RepairCheck on boundary change??? void SetRepairBoundary(RepairBoundary repairBoundary) {repair_boundary = repairBoundary;} SyncPolicy GetSyncPolicy() const {return sync_policy;} void SetSyncPolicy(SyncPolicy syncPolicy) {sync_policy = syncPolicy;} bool UnicastNacks() {return unicast_nacks;} void SetUnicastNacks(bool state) {unicast_nacks = state;} void UpdateGrttEstimate(UINT8 grttQuantized); double GetGrttEstimate() const {return grtt_estimate;} void ResetGrttNotification() {notify_on_grtt_update = true;} bool UpdateLossEstimate(const struct timeval& currentTime, unsigned short theSequence, bool ecnStatus = false); double LossEstimate() {return loss_estimator.LossFraction();} unsigned short GetCurrentSequence() const {return loss_estimator.GetLagIndex();} double GetRttEstimate() const {return rtt_estimate;} void CheckCCFeedback(); void UpdateRecvRate(const struct timeval& currentTime, unsigned short msgSize); void HandleCommand(const struct timeval& currentTime, const NormCmdMsg& cmd); void HandleObjectMessage(const NormObjectMsg& msg); void HandleCCFeedback(UINT8 ccFlags, double ccRate); void HandleNackMessage(const NormNackMsg& nack); void HandleAckMessage(const NormAckMsg& ack); bool Open(UINT16 instanceId); UINT16 GetInstanceId() {return instance_id;} bool IsOpen() const {return is_open;} void Close(); bool AllocateBuffers(unsigned int bufferSpace, UINT8 fecId, UINT16 fecInstanceId, UINT8 fecM, UINT16 segmentSize, UINT16 numData, UINT16 numParity); bool BuffersAllocated() {return (0 != segment_size);} void FreeBuffers(); void Activate(bool isObjectMsg); bool SyncTest(const NormObjectMsg& msg) const; void Sync(NormObjectId objectId); ObjectStatus UpdateSyncStatus(const NormObjectId& objectId); ObjectStatus GetObjectStatus(const NormObjectId& objectId) const; UINT8 GetFecFieldSize() const {return fec_m;} bool GetFirstPending(NormObjectId& objectId) const { UINT32 index; bool result = rx_pending_mask.GetFirstSet(index); objectId = (UINT16)index; return result; } bool GetNextPending(NormObjectId& objectId) const { UINT32 index = (UINT16)objectId; bool result = rx_pending_mask.GetNextSet(index); objectId = (UINT16)index; return result; } bool GetLastPending(NormObjectId& objectId) const { UINT32 index; bool result = rx_pending_mask.GetLastSet(index); objectId = (UINT16)index; return result; } void SetPending(NormObjectId objectId); void AbortObject(NormObject* obj); void DeleteObject(NormObject* obj); NormObject* GetNextPendingObject() { NormObjectId objid; if (GetNextPending(objid)) return rx_table.Find(objid); else return NULL; } UINT16 SegmentSize() {return segment_size;} UINT16 BlockSize() {return ndata;} UINT16 NumParity() {return nparity;} NormBlock* GetFreeBlock(NormObjectId objectId, NormBlockId blockId); void PutFreeBlock(NormBlock* block) { block->EmptyToPool(segment_pool); block_pool.Put(block); } bool SegmentPoolIsEmpty() {return segment_pool.IsEmpty();} char* GetFreeSegment(NormObjectId objectId, NormBlockId blockId); void PutFreeSegment(char* segment) {segment_pool.Put(segment);} void SetErasureLoc(UINT16 index, UINT16 value) { ASSERT(index < nparity); erasure_loc[index] = value; } UINT16 GetErasureLoc(UINT16 index) { return erasure_loc[index]; } void SetRetrievalLoc(UINT16 index, UINT16 value) { ASSERT(index < ndata); retrieval_loc[index] = value; } UINT16 GetRetrievalLoc(UINT16 index) { return retrieval_loc[index]; } char* GetRetrievalSegment() { char* s = retrieval_pool[retrieval_index++]; retrieval_index = (retrieval_index >= ndata) ? 0 : retrieval_index; return s; } UINT16 Decode(char** segmentList, UINT16 numData, UINT16 erasureCount) { return decoder->Decode(segmentList, numData, erasureCount, erasure_loc); } void CalculateGrttResponse(const struct timeval& currentTime, struct timeval& grttResponse) const; // Statistics kept on sender unsigned long CurrentBufferUsage() const {return (segment_size * segment_pool.CurrentUsage());} unsigned long PeakBufferUsage() const {return (segment_size * segment_pool.PeakUsage());} unsigned long BufferOverunCount() const {return segment_pool.OverunCount() + block_pool.OverrunCount();} unsigned long CurrentStreamBufferUsage(); unsigned long PeakStreamBufferUsage(); unsigned long StreamBufferOverunCount(); //unsigned long RecvTotal() const {return recv_total;} //unsigned long RecvGoodput() const {return recv_goodput;} // returns ave bytes/sec double GetRecvRate(double interval) const {return recv_total.GetScaledValue(1.0 / interval);} double GetRecvGoodput(double interval) const {return recv_goodput.GetScaledValue(1.0 / interval);} void IncrementRecvTotal(unsigned long count) {recv_total.Increment(count);} void IncrementRecvGoodput(unsigned long count) {recv_goodput.Increment(count);} void ResetRecvStats() { recv_total.Reset(); recv_goodput.Reset(); } void IncrementResyncCount() {resync_count++;} void DecrementResyncCount() {resync_count--;} unsigned long ResyncCount() const {return resync_count;} unsigned long NackCount() const {return nack_count;} unsigned long SuppressCount() const {return suppress_count;} unsigned long CompletionCount() const {return completion_count;} unsigned long PendingCount() const {return rx_table.GetCount();} unsigned long FailureCount() const {return failure_count;} class CmdBuffer { public: CmdBuffer(); ~CmdBuffer(); enum {CMD_SIZE_MAX = 8192}; void SetContent(const char* data, unsigned int numBytes) { ASSERT(numBytes <= CMD_SIZE_MAX); memcpy(buffer, data, numBytes); length = numBytes; } const char* GetContent() const {return buffer;} unsigned int GetContentLength() const {return length;} void Append(CmdBuffer* nextBuffer) {next = nextBuffer;} CmdBuffer* GetNext() const {return next;} private: char buffer[CMD_SIZE_MAX]; unsigned length; CmdBuffer* next; // to support singly-linked list }; // end class NormSenderNode::CmdBuffer CmdBuffer* NewCmdBuffer() const; bool ReadNextCmd(char* buffer, unsigned int* buflen); void SetAddress(const ProtoAddress& address) { unsigned int len = address.GetLength(); memcpy(key_buffer, address.GetRawHostAddress(), len); UINT16 port = htons(address.GetPort()); memcpy(key_buffer+len, &port, 2); key_size = (len+2) << 3; NormNode::SetAddress(address); } UINT8 GetGrttQuantized() const {return grtt_quantized;} UINT8 GetBackoffFactor() const {return backoff_factor;} UINT8 GetGroupSizeQuantized() const {return gsize_quantized;} UINT16 GetCCSequence() const {return cc_sequence;} double GetSendRate() const {return send_rate;} private: const char* GetKey() const {return key_buffer;} unsigned int GetKeysize() const {return key_size;} static const double DEFAULT_NOMINAL_INTERVAL; static const double ACTIVITY_INTERVAL_MIN; bool PassiveRepairCheck(NormObjectId objectId, NormBlockId blockId, NormSegmentId segmentId); void RepairCheck(NormObject::CheckLevel checkLevel, NormObjectId objectId, NormBlockId blockId, NormSegmentId segmentId); bool OnActivityTimeout(ProtoTimer& theTimer); bool OnRepairTimeout(ProtoTimer& theTimer); bool OnCCTimeout(ProtoTimer& theTimer); bool OnAckTimeout(ProtoTimer& theTimer); void AttachCCFeedback(NormAckMsg& ack); void HandleRepairContent(const UINT32* buffer, UINT16 bufferLen); void FragmentNack(NormNackMsg& superNack); UINT16 instance_id; int robust_factor; SyncPolicy sync_policy; bool synchronized; NormObjectId sync_id; // only valid if(synchronized) NormObjectId next_id; // only valid if(synchronized) NormObjectId max_pending_object; // index for NACK construction NormObjectId current_object_id; // index for suppression UINT16 max_pending_range; // max range of pending objs allowed bool is_open; UINT16 segment_size; UINT8 fec_id; UINT8 fec_m; unsigned int ndata; unsigned int nparity; NormStreamObject* preset_stream; NormObjectTable rx_table; ProtoSlidingMask rx_pending_mask; ProtoSlidingMask rx_repair_mask; RepairBoundary repair_boundary; NormObject::NackingMode default_nacking_mode; bool unicast_nacks; NormBlockPool block_pool; NormSegmentPool segment_pool; NormDecoder* decoder; unsigned int* erasure_loc; unsigned int* retrieval_loc; char** retrieval_pool; unsigned int retrieval_index; bool sender_active; ProtoTimer activity_timer; ProtoTimer repair_timer; // Watermark acknowledgement ProtoTimer ack_timer; bool ack_pending; NormObjectId watermark_object_id; NormBlockId watermark_block_id; NormSegmentId watermark_segment_id; // Remote sender grtt measurement state double grtt_estimate; UINT8 grtt_quantized; struct timeval grtt_send_time; struct timeval grtt_recv_time; double gsize_estimate; UINT8 gsize_quantized; double backoff_factor; bool notify_on_grtt_update; // for API // Remote sender congestion control state NormLossEstimator2 loss_estimator; UINT16 cc_sequence; bool cc_enable; bool cc_feedback_needed; double cc_rate; // ccRate at start of cc_timer ProtoTimer cc_timer; double rtt_estimate; UINT8 rtt_quantized; bool rtt_confirmed; bool is_clr; bool is_plr; bool slow_start; double send_rate; // sender advertised rate double recv_rate; // measured recv rate double recv_rate_prev; // for recv_rate measurement struct timeval prev_update_time; // for recv_rate measurement Accumulator recv_accumulator; // for recv_rate measurement double nominal_packet_size; // Buffering of app-defined commands received from Remote sender CmdBuffer* cmd_buffer_head; // the oldest received command is here (for FIFO) CmdBuffer* cmd_buffer_tail; // newly-received commands appended here CmdBuffer* cmd_buffer_pool; // we "pool" allocated buffers for possible reuse here // Used for NormSocket API extension to index by addr/port char key_buffer[16+2]; // big enough for IPv6 plus port unsigned int key_size; // For statistics tracking Accumulator recv_total; // total recvd accumulator Accumulator recv_goodput; // goodput recvd accumulator unsigned long resync_count; unsigned long nack_count; unsigned long suppress_count; unsigned long completion_count; unsigned long failure_count; // usually due to re-syncs }; // end class NormSenderNode // Used for binary trees of NormNodes sorted by NormNodeId // (TBD - update to use ProtoTree instead? class NormNodeTree { friend class NormNodeTreeIterator; public: // Methods NormNodeTree(); ~NormNodeTree(); NormNode* FindNodeById(NormNodeId nodeId) const; void AttachNode(NormNode *theNode); void DetachNode(NormNode *theNode); NormNode* GetRoot() const {return root;} void Destroy(); // delete all nodes in tree private: // Members NormNode* root; }; // end class NormNodeTree class NormNodeTreeIterator { public: NormNodeTreeIterator(const NormNodeTree& nodeTree, NormNode* prevNode = NULL); void Reset(NormNode* prevNode = NULL); NormNode* GetNextNode(); private: const NormNodeTree& tree; NormNode* next; }; // end class NormNodeTreeIterator class NormNodeList { friend class NormNodeListIterator; public: // Construction NormNodeList(); ~NormNodeList(); unsigned int GetCount() {return count;} NormNode* FindNodeById(NormNodeId nodeId) const; void Append(NormNode* theNode); void Remove(NormNode* theNode); void DeleteNode(NormNode* theNode) { ASSERT(NULL != theNode); Remove(theNode); theNode->Release(); } void Destroy(); // delete all nodes in list const NormNode* Head() {return head;} // Members private: NormNode* head; NormNode* tail; unsigned int count; }; // end class NormNodeList class NormNodeListIterator { public: NormNodeListIterator(const NormNodeList& nodeList) : list(nodeList), next(nodeList.head) {} void Reset() {next = list.head;} NormNode* GetNextNode() { NormNode* n = next; next = n ? n->right : NULL; return n; } private: const NormNodeList& list; NormNode* next; }; // end class NormNodeListIterator // Used to track remote client sender nodes for server/listener sessions class NormClientTree : public ProtoTreeTemplate { public: void InsertNode(NormSenderNode& sender) { sender.Retain(); Insert(sender); } void RemoveNode(NormSenderNode& sender) { Remove(sender); sender.Release(); } NormSenderNode* FindNodeByAddress(const ProtoAddress& addr) { char key[16+2]; unsigned int len = addr.GetLength(); memcpy(key, addr.GetRawHostAddress(), len); UINT16 port = htons(addr.GetPort()); memcpy(key+len, &port, 2); return Find(key, (len+2) << 3); } }; // end class NormClientTree #endif // NORM_NODE norm-1.5.8+dfsg2/include/normObject.h0000644000000000000000000006715513215251511014277 0ustar #ifndef _NORM_OBJECT #define _NORM_OBJECT #include "normSegment.h" // NORM segmentation classes #include "normEncoder.h" #include "normFile.h" #include #define USE_PROTO_TREE 1 // for more better performing NormObjectTable? #ifdef USE_PROTO_TREE #include "protoTree.h" class NormObject : public ProtoSortedTree::Item #else class NormObject #endif // if/else USE_PROTO_TREE { friend class NormObjectTable; public: enum Type { NONE, DATA, FILE, STREAM }; enum CheckLevel { TO_OBJECT, THRU_INFO, TO_BLOCK, THRU_SEGMENT, THRU_BLOCK, THRU_OBJECT }; enum NackingMode { NACK_NONE, NACK_INFO_ONLY, NACK_NORMAL }; virtual ~NormObject(); void Retain(); void Release(); unsigned int GetReferenceCount() {return reference_count;} // This must be reset after each update void SetNotifyOnUpdate(bool state) {notify_on_update = state;} // Object information NormObject::Type GetType() const {return type;} const NormObjectId& GetId() const {return transport_id;} const NormObjectSize& GetSize() const {return object_size;} void SetId(const NormObjectId transportId) {transport_id = transportId;} UINT16 GetSegmentSize() const {return segment_size;} UINT8 GetFecId() const {return fec_id;} UINT16 GetFecMaxBlockLen() const {return ndata;} UINT16 GetFecNumParity() const {return nparity;} UINT8 GetFecFieldSize() const {return fec_m;} // returns difference (a - b) INT32 Difference(NormBlockId a, NormBlockId b) const {return NormBlockId::Difference(a, b, fec_block_mask);} // returns -1, 0, or 1 for (a < b), (a == b), or (a > b), respectively int Compare(NormBlockId a, NormBlockId b) const {return NormBlockId::Compare(a, b, fec_block_mask);} void Increment(NormBlockId& b, UINT32 i = 1) const {b.Increment(i, fec_block_mask);} void Decrement(NormBlockId& b, UINT32 i = 1) const {b.Decrement(i, fec_block_mask);} bool HaveInfo() const {return (info_len > 0);} bool HasInfo() const {return (NULL != info_ptr);} void ClearInfo() { if (NULL != info_ptr) delete[] info_ptr; info_ptr = NULL; info_len = 0; pending_info = false; } const char* GetInfo() const {return info_ptr;} UINT16 GetInfoLength() const {return info_len;} bool IsStream() const {return (STREAM == type);} class NormSession& GetSession() const {return session;} NormNodeId LocalNodeId() const; class NormSenderNode* GetSender() const {return sender;} NormNodeId GetSenderNodeId() const; // for NORM API usage only void SetUserData(const void* userData) {user_data = userData;} const void* GetUserData() const {return user_data;} bool IsOpen() {return (0 != segment_size);} // Opens (inits) object for tx operation bool Open(const NormObjectSize& objectSize, const char* infoPtr, UINT16 infoLen, UINT16 segmentSize, UINT8 fecId, UINT8 fecM, UINT16 numData, UINT16 numParity); // Opens (inits) object for rx operation bool RxOpen(const NormObjectSize& objectSize, bool hasInfo, UINT16 segmentSize, UINT8 fecId, UINT8 fecM, UINT16 numData, UINT16 numParity) { return Open(objectSize, (char*)NULL, hasInfo ? 1 : 0, segmentSize, fecId, fecM, numData, numParity); } void Close(); virtual bool WriteSegment(NormBlockId blockId, NormSegmentId segmentId, const char* buffer) = 0; virtual UINT16 ReadSegment(NormBlockId blockId, NormSegmentId segmentId, char* buffer) = 0; virtual char* RetrieveSegment(NormBlockId blockId, NormSegmentId segmentId) = 0; NackingMode GetNackingMode() const {return nacking_mode;} void SetNackingMode(NackingMode nackingMode) { nacking_mode = nackingMode; // (TBD) initiate an appropriate NormSenderNode::RepairCheck // to prompt repair process if needed } // These are only valid after object is open NormBlockId GetFinalBlockId() const {return final_block_id;} UINT32 GetBlockSize(NormBlockId blockId) const { return ((blockId.GetValue() < large_block_count) ? large_block_size : small_block_size); } NormObjectSize GetBytesPending() const; bool IsPending(bool flush = true) const; bool IsRepairPending(); bool IsPendingInfo() {return pending_info;} bool PendingMaskIsSet() const {return pending_mask.IsSet();} unsigned int GetPendingMaskSize() const {return pending_mask.GetSize();} bool GetFirstPending(NormBlockId& blockId) const { UINT32 index = 0; bool result = pending_mask.GetFirstSet(index); blockId = NormBlockId(index); return result; } bool GetNextPending(NormBlockId& blockId) const { UINT32 index = blockId.GetValue(); bool result = pending_mask.GetNextSet(index); blockId = NormBlockId(index); return result; } bool GetLastPending(NormBlockId& blockId) const { UINT32 index = 0; bool result = pending_mask.GetLastSet(index); blockId = NormBlockId(index); return result; } bool GetFirstRepair(NormBlockId& blockId) const { UINT32 index = 0; bool result = repair_mask.GetFirstSet(index); blockId = NormBlockId(index); return result; } bool GetNextRepair(NormBlockId& blockId) const { UINT32 index = blockId.GetValue(); bool result = repair_mask.GetNextSet(index); blockId = NormBlockId(index); return result; } bool GetLastRepair(NormBlockId& blockId) const { UINT32 index = 0; bool result = repair_mask.GetLastSet(index); blockId = NormBlockId(index); return result; } bool FindRepairIndex(NormBlockId& blockId, NormSegmentId& segmentId); // Methods available to sender for transmission bool NextSenderMsg(NormObjectMsg* msg); NormBlock* SenderRecoverBlock(NormBlockId blockId); bool CalculateBlockParity(NormBlock* block); /*bool IsFirstPass() {return first_pass;} void ClearFirstPass() {first_pass = false};*/ bool TxReset(NormBlockId firstBlock = NormBlockId(0), bool requeue = false); bool TxResetBlocks(const NormBlockId& nextId, const NormBlockId& lastId); bool TxUpdateBlock(NormBlock* theBlock, NormSegmentId firstSegmentId, NormSegmentId lastSegmentId, UINT16 numErasures); bool HandleInfoRequest(bool holdoff); bool HandleBlockRequest(const NormBlockId& nextId, const NormBlockId& lastId); NormBlock* FindBlock(NormBlockId blockId) {return block_buffer.Find(blockId);} bool ActivateRepairs(); bool IsRepairSet(NormBlockId blockId) {return repair_mask.Test(blockId.GetValue());} bool IsPendingSet(NormBlockId blockId) {return pending_mask.Test(blockId.GetValue());} bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd); NormBlockId GetMaxPendingBlockId() const {return max_pending_block;} NormSegmentId GetMaxPendingSegmentId() const {return max_pending_segment;} // Used by sender for resource management scheme NormBlock* StealNonPendingBlock(bool excludeBlock, NormBlockId excludeId = 0); // Methods available to receiver for reception bool Accepted() {return accepted;} void HandleObjectMessage(const NormObjectMsg& msg, NormMsg::Type msgType, NormBlockId blockId, NormSegmentId segmentId); // Used by receiver for resource management scheme NormBlock* StealNewestBlock(bool excludeBlock, NormBlockId excludeId = 0); NormBlock* StealOldestBlock(bool excludeBlock, NormBlockId excludeId = 0); bool ReclaimSourceSegments(NormSegmentPool& segmentPool); bool PassiveRepairCheck(NormBlockId blockId, NormSegmentId segmentId); bool ReceiverRepairCheck(CheckLevel level, NormBlockId blockId, NormSegmentId segmentId, bool timerActive, bool holdoffPhase = false); bool ReceiverRewindCheck(NormBlockId blockId, NormSegmentId segmentId); bool IsRepairPending(bool flush); bool AppendRepairRequest(NormNackMsg& nack, bool flush, UINT16 payloadMax); void SetRepairInfo() {repair_info = true;} bool SetRepairs(NormBlockId first, NormBlockId last) { return ((first == last) ? repair_mask.Set(first.GetValue()) : repair_mask.SetBits(first.GetValue(), repair_mask.Difference(last.GetValue(),first.GetValue())+1)); } void SetLastNackTime(const ProtoTime& theTime) {last_nack_time = theTime;} const ProtoTime& GetLastNackTime() const {return last_nack_time;} double GetNackAge() const {return ProtoTime::Delta(ProtoTime().GetCurrentTime(), last_nack_time);} protected: NormObject(Type theType, class NormSession& theSession, class NormSenderNode* theSender, const NormObjectId& objectId); void Accept() {accepted = true;} #ifdef USE_PROTO_TREE // Proto::Tree item required overrides const char* GetKey() const {return transport_id.GetValuePtr();} unsigned int GetKeysize() const {return (8*sizeof(UINT16));} ProtoTree::Endian GetEndian() const {return ProtoTree::GetNativeEndian();} #endif // USE PROTO_TREE NormObject::Type type; class NormSession& session; class NormSenderNode* sender; // NULL value indicates local (tx) object unsigned int reference_count; NormObjectId transport_id; NormObjectSize object_size; UINT16 segment_size; UINT8 fec_id; UINT8 fec_m; UINT32 fec_block_mask; UINT16 ndata; UINT16 nparity; NormBlockBuffer block_buffer; bool pending_info; // set when we need to send or recv info ProtoSlidingMask pending_mask; bool repair_info; // receiver: set when ProtoSlidingMask repair_mask; NormBlockId current_block_id; // for suppression NormSegmentId next_segment_id; // for suppression NormBlockId max_pending_block; // for NACK construction NormSegmentId max_pending_segment; // for NACK construction UINT32 large_block_count; UINT32 large_block_size; UINT32 small_block_count; UINT32 small_block_size; NormBlockId final_block_id; UINT16 final_segment_size; NackingMode nacking_mode; ProtoTime last_nack_time; // time of last NACK received (used for flow control) char* info_ptr; UINT16 info_len; // Here are some members used to let us know // our status with respect to the rest of the world bool first_pass; // for sender objects bool accepted; bool notify_on_update; const void* user_data; // for NORM API usage only #ifndef USE_PROTO_TREE NormObject* next; #endif }; // end class NormObject class NormFileObject : public NormObject { public: NormFileObject(class NormSession& theSession, class NormSenderNode* theSender, const NormObjectId& objectId); ~NormFileObject(); bool Open(const char* thePath, const char* infoPtr = NULL, UINT16 infoLen = 0); bool Accept(const char* thePath); void Close(); const char* GetPath() {return path;} bool Rename(const char* newPath) { bool result = file.Rename(path, newPath); result ? strncpy(path, newPath, PATH_MAX) : NULL; return result; } bool PadToSize() {return file.IsOpen() ? file.Pad(NormObject::GetSize().GetOffset()) : false;} virtual bool WriteSegment(NormBlockId blockId, NormSegmentId segmentId, const char* buffer); virtual UINT16 ReadSegment(NormBlockId blockId, NormSegmentId segmentId, char* buffer); virtual char* RetrieveSegment(NormBlockId blockId, NormSegmentId segmentId); //private: char path[PATH_MAX+10]; NormFile file; NormObjectSize large_block_length; NormObjectSize small_block_length; }; // end class NormFileObject class NormDataObject : public NormObject { // (TBD) allow support of greater than 4GB size data objects public: typedef void (*DataFreeFunctionHandle)(char*); NormDataObject(class NormSession& theSession, class NormSenderNode* theSender, const NormObjectId& objectId, DataFreeFunctionHandle dataFreeFunc); ~NormDataObject(); bool Open(char* dataPtr, UINT32 dataLen, bool dataRelease, const char* infoPtr = NULL, UINT16 infoLen = 0); bool Accept(char* dataPtr, UINT32 dataMax, bool dataRelease); void Close(); const char* GetData() {return data_ptr;} char* DetachData() { char* dataPtr = data_ptr; data_ptr = NULL; return dataPtr; } virtual bool WriteSegment(NormBlockId blockId, NormSegmentId segmentId, const char* buffer); virtual UINT16 ReadSegment(NormBlockId blockId, NormSegmentId segmentId, char* buffer); virtual char* RetrieveSegment(NormBlockId blockId, NormSegmentId segmentId); private: NormObjectSize large_block_length; NormObjectSize small_block_length; char* data_ptr; UINT32 data_max; bool data_released; // when true, data_ptr is deleted DataFreeFunctionHandle data_free_func; // on NormDataObject destruction }; // end class NormDataObject class NormStreamObject : public NormObject { public: NormStreamObject(class NormSession& theSession, class NormSenderNode* theSender, const NormObjectId& objectId); ~NormStreamObject(); bool Open(UINT32 bufferSize, bool doubleBuffer = false, const char* infoPtr = NULL, UINT16 infoLen = 0); void Close(bool graceful = false); bool Accept(UINT32 bufferSize, bool doubleBuffer = false); enum FlushMode { FLUSH_NONE, // no flush action taken FLUSH_PASSIVE, // pending queued data is transmitted, but no CMD(FLUSH) sent FLUSH_ACTIVE // pending queued data is transmitted, _and_ active CMD(FLUSH) }; void SetFlushMode(FlushMode flushMode) {flush_mode = flushMode;} FlushMode GetFlushMode() {return flush_mode;} void Flush(bool eom = false) { FlushMode oldFlushMode = flush_mode; SetFlushMode((FLUSH_ACTIVE == oldFlushMode) ? FLUSH_ACTIVE : FLUSH_PASSIVE); Write(NULL, 0, eom); SetFlushMode(oldFlushMode); } void SetPushMode(bool state) {push_mode = state;} bool GetPushMode() const {return push_mode;} bool IsOldBlock(NormBlockId blockId) const {return (!stream_buffer.IsEmpty() && (Compare(blockId, stream_buffer.RangeLo()) < 0));} bool IsClosing() {return stream_closing;} bool HasVacancy() {return (stream_closing ? false : write_vacancy);} NormBlock* StreamBlockLo() {return stream_buffer.Find(stream_buffer.RangeLo());} void SetLastNackTime(NormBlockId blockId, const ProtoTime& theTime) { NormBlock* block = stream_buffer.Find(blockId); if (NULL != block) block->SetLastNackTime(theTime); } bool Read(char* buffer, unsigned int* buflen, bool findMsgStart = false); UINT32 Write(const char* buffer, UINT32 len, bool eom = false); UINT32 GetCurrentReadOffset() {return read_offset;} unsigned int GetCurrentBufferUsage() const // in segments {return segment_pool.CurrentUsage();} bool StreamUpdateStatus(NormBlockId blockId); // Note that the "pending_mask" should be cleared and the // "block_buffer" emptied before "StreamResync()" is invoked void StreamResync(NormBlockId blockId) { stream_sync = false; StreamUpdateStatus(blockId); } bool StreamAdvance(); NormBlockId GetSyncId() const {return stream_sync_id;} NormBlockId GetNextId() const {return stream_next_id;} virtual bool WriteSegment(NormBlockId blockId, NormSegmentId segmentId, const char* buffer); virtual UINT16 ReadSegment(NormBlockId blockId, NormSegmentId segmentId, char* buffer); virtual char* RetrieveSegment(NormBlockId blockId, NormSegmentId segmentId); // For receive stream, we can rewind to earliest buffered offset void Rewind(); bool LockBlocks(NormBlockId nextId, NormBlockId lastId, const ProtoTime& currentTime); void UnlockBlock(NormBlockId blockId); bool LockSegments(NormBlockId blockId, NormSegmentId firstId, NormSegmentId lastId); NormBlockId StreamBufferLo() const {return stream_buffer.RangeLo();} NormBlockId RepairWindowLo() const; void Prune(NormBlockId blockId, bool updateStatus); bool IsFlushPending() {return flush_pending;} NormBlockId FlushBlockId() const; NormSegmentId FlushSegmentId() const {return (write_index.segment ? (write_index.segment-1) : (ndata-1));} NormBlockId GetNextBlockId() const {return (sender ? read_index.block : write_index.block);} NormSegmentId GetNextSegmentId() const {return (sender ? read_index.segment : write_index.segment);} UINT32 GetBlockPoolCount() {return block_pool.GetCount();} void SetBlockPoolThreshold(UINT32 value) {block_pool_threshold = value;} unsigned long CurrentBufferUsage() const {return (segment_size * segment_pool.CurrentUsage());} unsigned long PeakBufferUsage() const {return (segment_size * segment_pool.PeakUsage());} unsigned long BufferOverunCount() const {return segment_pool.OverunCount() + block_pool.OverrunCount();} bool IsReadReady() const {return read_ready;} bool DetermineReadReadiness() //const { NormBlock* block = stream_buffer.Find(read_index.block); read_ready = ((NULL != block) && (NULL != block->GetSegment(read_index.segment))); return read_ready; } bool IsReadIndex(NormBlockId blockId, NormSegmentId segmentId) const {return ((blockId == read_index.block) && (segmentId == read_index.segment));} bool PassiveReadCheck(NormBlockId blockId, NormSegmentId segmentId); private: bool ReadPrivate(char* buffer, unsigned int* buflen, bool findMsgStart = false); void Terminate(); class Index { public: NormBlockId block; NormSegmentId segment; UINT16 offset; }; // Extra state for STREAM objects bool stream_sync; NormBlockId stream_sync_id; NormBlockId stream_next_id; NormBlockPool block_pool; NormSegmentPool segment_pool; NormBlockBuffer stream_buffer; Index write_index; UINT32 write_offset; Index tx_index; UINT32 tx_offset; bool write_vacancy; bool read_init; Index read_index; UINT32 read_offset; bool read_ready; bool flush_pending; bool msg_start; FlushMode flush_mode; bool push_mode; bool stream_broken; bool stream_closing; // For threaded API purposes UINT32 block_pool_threshold; }; // end class NormStreamObject #ifdef SIMULATE // This class is used to simulate file objects in the // network simulation build of NORM class NormSimObject : public NormObject { public: NormSimObject(class NormSession& theSession, class NormSenderNode* theSender, const NormObjectId& objectId); ~NormSimObject(); bool Open(UINT32 objectSize, const char* infoPtr = NULL, UINT16 infoLen = 0); bool Accept() {NormObject::Accept(); return true;} void Close() {NormObject::Close();} virtual bool WriteSegment(NormBlockId blockId, NormSegmentId segmentId, const char* buffer) {return true;} virtual UINT16 ReadSegment(NormBlockId blockId, NormSegmentId segmentId, char* buffer); virtual char* RetrieveSegment(NormBlockId blockId, NormSegmentId segmentId); }; // end class NormSimObject #endif // SIMULATE #ifdef USE_PROTO_TREE class NormObjectTree : public ProtoSortedTreeTemplate {}; #endif // USE_PROTO_TREE class NormObjectTable { public: class Iterator; friend class NormObjectTable::Iterator; NormObjectTable(); ~NormObjectTable(); bool Init(UINT16 rangeMax, UINT16 tableSize = 256); void SetRangeMax(UINT16 rangeMax); void Destroy(); UINT16 GetRangeMax() const {return range_max;} bool CanInsert(NormObjectId objectId) const; bool Insert(NormObject* theObject); bool Remove(NormObject* theObject); NormObject* Find(const NormObjectId& objectId) const; NormObjectId RangeLo() const {return range_lo;} NormObjectId RangeHi() const {return range_hi;} bool IsEmpty() const {return (0 == range);} UINT32 GetCount() const {return count;} const NormObjectSize& GetSize() const {return size;} #ifdef USE_PROTO_TREE class Iterator { public: Iterator(NormObjectTable& objectTable); NormObject* GetNextObject(); NormObject* GetPrevObject(); void Reset(); private: const NormObjectTable& table; NormObjectTree::Iterator iterator; NormObject* next_object; }; #else class Iterator { public: Iterator(const NormObjectTable& objectTable); NormObject* GetNextObject(); NormObject* GetPrevObject(); void Reset() {reset = true;} private: const NormObjectTable& table; bool reset; NormObjectId index; }; #endif // if/else USE_PROTO_TREE private: #ifndef USE_PROTO_TREE NormObject* Next(NormObject* o) const {return o->next;} #endif #ifdef USE_PROTO_TREE NormObjectTree tree; #else NormObject** table; UINT16 hash_mask; #endif // if/else USE_PROTO_TREE UINT16 range_max; // max range of objects that can be kept UINT16 range; // zero if "object table" is empty NormObjectId range_lo; NormObjectId range_hi; UINT16 count; NormObjectSize size; }; // end class NormObjectTable #endif // _NORM_OBJECT norm-1.5.8+dfsg2/include/normPostProcess.h0000644000000000000000000000143407752015155015354 0ustar #ifndef _NORM_POST_PROCESS #define _NORM_POST_PROCESS #include "protoDefs.h" // for NULL class NormPostProcessor { public: NormPostProcessor(); virtual ~NormPostProcessor(); // Implement this per derivation static NormPostProcessor* Create(); bool IsEnabled() {return (NULL != process_argv);} bool SetCommand(const char* cmd); void GetCommand(char* buffer, unsigned int buflen); virtual bool ProcessFile(const char* path) = 0; virtual void Kill() = 0; virtual bool IsActive() = 0; virtual void OnDeath() {}; protected: char** process_argv; unsigned int process_argc; }; // end class NormPostProcessor #endif // _NORM_POST_PROCESS norm-1.5.8+dfsg2/include/normSegment.h0000644000000000000000000003426513012767356014505 0ustar #ifndef _NORM_SEGMENT #define _NORM_SEGMENT #include "normMessage.h" #include "protoBitmask.h" #define USE_PROTO_TREE 1 // for more better performing NormBlockBuffer? // Norm uses preallocated (or dynamically allocated) pools of // segments (vectors) for different buffering purposes class NormSegmentPool { public: NormSegmentPool(); ~NormSegmentPool(); bool Init(unsigned int count, unsigned int size); void Destroy(); char* Get(); void Put(char* segment) { ASSERT(seg_count < seg_total); *((char**)((void*)segment)) = seg_list; // this might make a warning on Solaris seg_list = segment; seg_count++; } bool IsEmpty() const {return (NULL == seg_list);} unsigned int CurrentUsage() const {return (seg_total - seg_count);} unsigned long PeakUsage() const {return peak_usage;} unsigned long OverunCount() const {return overruns;} unsigned int GetSegmentSize() {return seg_size;} private: unsigned int seg_size; unsigned int seg_count; unsigned int seg_total; char* seg_list; char** seg_pool; unsigned long peak_usage; unsigned long overruns; bool overrun_flag; }; // end class NormSegmentPool #ifdef USE_PROTO_TREE class NormBlock : public ProtoSortedTree::Item #else class NormBlock #endif // if/else USE_PROTO_TREE { friend class NormBlockPool; friend class NormBlockBuffer; public: enum Flag { IN_REPAIR = 0x01 }; NormBlock(); ~NormBlock(); const NormBlockId& GetId() const {return blk_id;} void SetId(NormBlockId& x) {blk_id = x;} bool Init(UINT16 totalSize); void Destroy(); void SetFlag(NormBlock::Flag flag) {flags |= flag;} void ClearFlag(NormBlock::Flag flag) {flags &= ~flag;} bool InRepair() {return (0 != (flags & IN_REPAIR));} bool ParityReady(UINT16 ndata) {return (erasure_count == ndata);} UINT16 ParityReadiness() {return erasure_count;} void IncreaseParityReadiness() {erasure_count++;} void SetParityReadiness(UINT16 ndata) {erasure_count = ndata;} char** SegmentList(UINT16 index = 0) {return &segment_table[index];} char* GetSegment(NormSegmentId sid) { ASSERT(sid < size); return segment_table[sid]; } void AttachSegment(NormSegmentId sid, char* segment) { ASSERT(sid < size); ASSERT(!segment_table[sid]); segment_table[sid] = segment; } char* DetachSegment(NormSegmentId sid) { ASSERT(sid < size); char* segment = segment_table[sid]; segment_table[sid] = (char*)NULL; return segment; } void SetSegment(NormSegmentId sid, char* segment) { ASSERT(sid < size); ASSERT(!segment_table[sid]); segment_table[sid] = segment; } // Sender routines void TxInit(NormBlockId& blockId, UINT16 ndata, UINT16 autoParity) { blk_id = blockId; pending_mask.Clear(); pending_mask.SetBits(0, ndata+autoParity); repair_mask.Clear(); erasure_count = 0; parity_count = 0; parity_offset = autoParity; flags = 0; seg_size_max = 0; last_nack_time.GetCurrentTime(); } void TxRecover(NormBlockId& blockId, UINT16 ndata, UINT16 nparity) { blk_id = blockId; pending_mask.Clear(); repair_mask.Clear(); erasure_count = 0; parity_count = nparity; // force recovered blocks to parity_offset = nparity; // explicit repair mode ??? flags = IN_REPAIR; seg_size_max = 0; } bool TxReset(UINT16 ndata, UINT16 nparity, UINT16 autoParity, UINT16 segmentSize); bool TxUpdate(NormSegmentId nextId, NormSegmentId lastId, UINT16 ndata, UINT16 nparity, UINT16 erasureCount); void UpdateSegSizeMax(UINT16 segSize) {seg_size_max = (segSize > seg_size_max) ? segSize : seg_size_max;} UINT16 GetSegSizeMax() {return seg_size_max;} bool HandleSegmentRequest(NormSegmentId nextId, NormSegmentId lastId, UINT16 ndata, UINT16 nparity, UINT16 erasureCount); bool ActivateRepairs(UINT16 nparity); void ResetParityCount(UINT16 nparity) { parity_offset += parity_count; parity_offset = MIN(parity_offset, nparity); parity_count = 0; } bool AppendRepairAdv(NormCmdRepairAdvMsg& cmd, NormObjectId objectId, bool repairInfo, UINT8 fecId, UINT8 fecM, UINT16 numData, UINT16 payloadMax); // Receiver routines void RxInit(NormBlockId& blockId, UINT16 ndata, UINT16 nparity) { blk_id = blockId; pending_mask.Clear(); pending_mask.SetBits(0, ndata+nparity); repair_mask.Clear(); erasure_count = ndata; parity_count = 0; parity_offset = 0; flags = 0; } // Note: This invalidates the repair_mask state. bool IsRepairPending(UINT16 ndata, UINT16 nparity); void DecrementErasureCount() {erasure_count--;} void IncrementErasureCount() {erasure_count++;} UINT16 ErasureCount() const {return erasure_count;} void IncrementParityCount() {parity_count++;} UINT16 ParityCount() const {return parity_count;} bool GetFirstPending(NormSymbolId& symbolId) const { UINT32 index; bool result = pending_mask.GetFirstSet(index); symbolId = (UINT16)index; return result; } bool GetNextPending(NormSymbolId& symbolId) const { UINT32 index = (UINT32)symbolId; bool result = pending_mask.GetNextSet(index); symbolId = (UINT16)index; return result; } NormSymbolId GetFirstRepair(NormSymbolId& symbolId) const { UINT32 index; bool result = repair_mask.GetFirstSet(index); symbolId = (UINT16)index; return result; } bool GetNextRepair(NormSymbolId& symbolId) const { UINT32 index = (UINT32)symbolId; bool result = repair_mask.GetNextSet(index); symbolId = (UINT16)index; return result; } bool SetPending(NormSymbolId s) {return pending_mask.Set(s);} bool SetPending(NormSymbolId firstId, UINT16 count) {return pending_mask.SetBits(firstId, count);} void UnsetPending(NormSymbolId s) {pending_mask.Unset(s);} void ClearPending() {pending_mask.Clear();} bool SetRepair(NormSymbolId s) {return repair_mask.Set(s);} bool SetRepairs(NormSymbolId first, NormSymbolId last) { if (first == last) return repair_mask.Set(first); else return (repair_mask.SetBits(first, last-first+1)); } void UnsetRepair(NormSymbolId s) {repair_mask.Unset(s);} void ClearRepairs() {repair_mask.Clear();} bool IsPending(NormSymbolId s) const {return pending_mask.Test(s);} bool IsPending() const {return pending_mask.IsSet();} bool IsRepairPending() const {return repair_mask.IsSet();} bool IsTransmitPending() const {return (pending_mask.IsSet() || repair_mask.IsSet());} NormObjectSize GetBytesPending(UINT16 numData, UINT16 segmentSize, NormBlockId finalBlockId, UINT16 finalSegmentSize) const; bool AppendRepairRequest(NormNackMsg& nack, UINT8 fecId, UINT8 fecM, UINT16 numData, UINT16 numParity, NormObjectId objectId, bool pendingInfo, UINT16 payloadMax); void SetLastNackTime(const ProtoTime& theTime) {last_nack_time = theTime;} const ProtoTime& GetLastNackTime() const {return last_nack_time;} double GetNackAge() const {return ProtoTime::Delta(ProtoTime().GetCurrentTime(), last_nack_time);} //void DisplayPendingMask(FILE* f) {pending_mask.Display(f);} //bool IsEmpty() const; void EmptyToPool(NormSegmentPool& segmentPool); private: #ifdef USE_PROTO_TREE const char* GetKey() const {return blk_id.GetValuePtr();} unsigned int GetKeysize() const {return (8*sizeof(UINT32));} ProtoTree::Endian GetEndian() const {return ProtoTree::GetNativeEndian();} #endif // USE_PROTO_TREE NormBlockId blk_id; UINT16 size; char** segment_table; int flags; UINT16 erasure_count; UINT16 parity_count; // how many fresh parity we are currently planning to send UINT16 parity_offset; // offset from where our fresh parity will be sent UINT16 seg_size_max; ProtoBitmask pending_mask; ProtoBitmask repair_mask; ProtoTime last_nack_time; // for stream flow control NormBlock* next; // used for NormBlockPool }; // end class NormBlock class NormBlockPool { public: NormBlockPool(); ~NormBlockPool(); bool Init(UINT32 numBlocks, UINT16 totalSize); void Destroy(); bool IsEmpty() const {return (NULL == head);} NormBlock* Get() { NormBlock* b = head; head = b ? b->next : NULL; if (b) { blk_count--; overrun_flag = false; } else if (!overrun_flag) { PLOG(PL_DEBUG, "NormBlockPool::Get() warning: operating with constrained buffering resources\n"); overruns++; overrun_flag = true; } return b; } void Put(NormBlock* b) { b->next = head; head = b; blk_count++; } unsigned long OverrunCount() const {return overruns;} UINT32 GetCount() {return blk_count;} UINT32 GetTotal() {return blk_total;} private: NormBlock* head; UINT32 blk_total; UINT32 blk_count; unsigned long overruns; bool overrun_flag; }; // end class NormBlockPool #ifdef USE_PROTO_TREE class NormBlockTree : public ProtoSortedTreeTemplate {}; #endif // USE_PROTO_TREE class NormBlockBuffer { public: class Iterator; friend class NormBlockBuffer::Iterator; NormBlockBuffer(); ~NormBlockBuffer(); bool Init(unsigned long rangeMax, unsigned long tableSize, UINT32 fecBlockMask); void Destroy(); bool Insert(NormBlock* theBlock); bool Remove(NormBlock* theBlock); NormBlock* Find(const NormBlockId& blockId) const; NormBlockId RangeLo() const {return range_lo;} NormBlockId RangeHi() const {return range_hi;} NormBlockId RangeMin() const; bool IsEmpty() const {return (0 == range);} bool CanInsert(NormBlockId blockId) const; #ifdef USE_PROTO_TREE class Iterator { public: Iterator(NormBlockBuffer& blockBuffer); NormBlock* GetNextBlock(); void Reset(); private: NormBlockBuffer& buffer; NormBlockTree::Iterator iterator; NormBlock* next_block; }; #else class Iterator { public: Iterator(const NormBlockBuffer& blockBuffer); NormBlock* GetNextBlock(); void Reset() {reset = true;} private: const NormBlockBuffer& buffer; bool reset; NormBlockId index; }; #endif // if/else USE_PROTO_TREE private: int Compare(NormBlockId a, NormBlockId b) const {return NormBlockId::Compare(a, b, fec_block_mask);} INT32 Difference(NormBlockId a, NormBlockId b) const {return NormBlockId::Difference(a, b, fec_block_mask);} void Increment(NormBlockId& b, UINT32 i = 1) const {b.Increment(i, fec_block_mask);} void Decrement(NormBlockId& b, UINT32 i = 1) const {b.Decrement(i, fec_block_mask);} #ifdef USE_PROTO_TREE NormBlockTree tree; #else static NormBlock* Next(NormBlock* b) {return b->next;} NormBlock** table; unsigned long hash_mask; #endif // if/else USE_PROTO_TREE unsigned long range_max; // max range of blocks that can be buffered unsigned long range; // zero if "block buffer" is empty UINT32 fec_block_mask; NormBlockId range_lo; NormBlockId range_hi; }; // end class NormBlockBuffer #endif // _NORM_SEGMENT norm-1.5.8+dfsg2/include/normSession.h0000644000000000000000000011412313272500301014475 0ustar #ifndef _NORM_SESSION #define _NORM_SESSION #include "normMessage.h" #include "normObject.h" #include "normNode.h" #include "normEncoder.h" #include "protokit.h" #include "protoCap.h" // for ProtoCap for ECN_SUPPORT // When this is defined, our experimental tweak to // limiting suggested cc rate to 2.0* measured recv rate is // used during steady state similar to "slow start" // conditions. What this means is that when data transmission // is idle, the rate will be reduced. This _may_ impact // certain use cases. Our theory here is that preventing rate // overshoot will be more helpful and safer than the penalty // imposed. This uses the non-RFC5740 NORM_CC_FLAG_LIMIT in // NORM-CC feedback header extensions #define LIMIT_CC_RATE 1 class NormController { public: virtual ~NormController() {} enum Event { EVENT_INVALID = 0, TX_QUEUE_VACANCY, TX_QUEUE_EMPTY, TX_FLUSH_COMPLETED, TX_WATERMARK_COMPLETED, TX_CMD_SENT, TX_OBJECT_SENT, TX_OBJECT_PURGED, TX_RATE_CHANGED, LOCAL_SENDER_CLOSED, REMOTE_SENDER_NEW, REMOTE_SENDER_RESET, REMOTE_SENDER_ADDRESS, REMOTE_SENDER_ACTIVE, REMOTE_SENDER_INACTIVE, REMOTE_SENDER_PURGED, RX_CMD_NEW, RX_OBJECT_NEW, RX_OBJECT_INFO, RX_OBJECT_UPDATED, RX_OBJECT_COMPLETED, RX_OBJECT_ABORTED, GRTT_UPDATED, CC_ACTIVE, // posted when cc feedback is detected CC_INACTIVE, // posted when no cc feedback and min rate reached ACKING_NODE_NEW, SEND_ERROR, USER_TIMEOUT }; virtual void Notify(NormController::Event event, class NormSessionMgr* sessionMgr, class NormSession* session, class NormNode* node, class NormObject* object) = 0; }; // end class NormController class NormSessionMgr { friend class NormSession; public: NormSessionMgr(ProtoTimerMgr& timerMgr, ProtoSocket::Notifier& socketNotifier, ProtoChannel::Notifier* channelNotifier = NULL); ~NormSessionMgr(); void SetController(NormController* theController) {controller = theController;} void Destroy(); class NormSession* NewSession(const char* sessionAddress, UINT16 sessionPort, NormNodeId localNodeId = NORM_NODE_ANY); void DeleteSession(class NormSession* theSession); void Notify(NormController::Event event, class NormSession* session, class NormNode* node, class NormObject* object) { if (controller) controller->Notify(event, this, session, node, object); } void ActivateTimer(ProtoTimer& timer) {timer_mgr.ActivateTimer(timer);} ProtoTimerMgr& GetTimerMgr() const {return timer_mgr;} ProtoSocket::Notifier& GetSocketNotifier() const {return socket_notifier;} ProtoChannel::Notifier* GetChannelNotifier() const {return channel_notifier;} void DoSystemTimeout() {timer_mgr.DoSystemTimeout();} NormController* GetController() const {return controller;} void SetDataFreeFunction(NormDataObject::DataFreeFunctionHandle freeFunc) {data_free_func = freeFunc;} NormDataObject::DataFreeFunctionHandle GetDataFreeFunction() const {return data_free_func;} private: ProtoTimerMgr& timer_mgr; ProtoSocket::Notifier& socket_notifier; ProtoChannel::Notifier* channel_notifier; NormController* controller; NormDataObject::DataFreeFunctionHandle data_free_func; class NormSession* top_session; // top of NormSession list }; // end class NormSessionMgr class NormSession { friend class NormSessionMgr; public: enum {DEFAULT_MESSAGE_POOL_DEPTH = 16}; static const UINT8 DEFAULT_TTL; static const double DEFAULT_TRANSMIT_RATE; // in bytes per second static const double DEFAULT_GRTT_INTERVAL_MIN; static const double DEFAULT_GRTT_INTERVAL_MAX; static const double DEFAULT_GRTT_ESTIMATE; static const double DEFAULT_GRTT_MAX; static const unsigned int DEFAULT_GRTT_DECREASE_DELAY; static const double DEFAULT_BACKOFF_FACTOR; // times GRTT = backoff max static const double DEFAULT_GSIZE_ESTIMATE; static const UINT16 DEFAULT_NDATA; static const UINT16 DEFAULT_NPARITY; static const UINT16 DEFAULT_TX_CACHE_MIN; static const UINT16 DEFAULT_TX_CACHE_MAX; static const UINT32 DEFAULT_TX_CACHE_SIZE; static const double DEFAULT_FLOW_CONTROL_FACTOR; static const UINT16 DEFAULT_RX_CACHE_MAX; static const int DEFAULT_ROBUST_FACTOR; enum {IFACE_NAME_MAX = 31}; enum ProbingMode {PROBE_NONE, PROBE_PASSIVE, PROBE_ACTIVE}; enum AckingStatus { ACK_INVALID, ACK_FAILURE, ACK_PENDING, ACK_SUCCESS }; // This is currently used to determine whether // and how to "auto populate" the acking node // list based on received messages enum TrackingStatus { TRACK_NONE = 0x00, TRACK_RECEIVERS = 0x01, TRACK_SENDERS = 0x02, TRACK_ALL = 0x03 }; // General methods void SetNodeId(NormNodeId nodeId) {local_node_id = nodeId;} const NormNodeId& LocalNodeId() const {return local_node_id;} bool Open(); void Close(); bool IsOpen() {return (rx_socket.IsOpen() || tx_socket->IsOpen());} const ProtoAddress& Address() {return address;} void SetAddress(const ProtoAddress& addr) {address = addr;} bool SetMulticastInterface(const char* interfaceName); bool SetSSM(const char* sourceAddress); bool SetTTL(UINT8 theTTL) { bool result = tx_socket->IsOpen() ? tx_socket->SetTTL(theTTL) : true; ttl = result ? theTTL : ttl; return result; } bool SetTOS(UINT8 theTOS) { // (TBD) call tx_socket->SetFlowLabel() to set traffic class for IPv6 sockets // (or should we have ProtoSocket::SetTOS() do this for us?) bool result = tx_socket->IsOpen() ? tx_socket->SetTOS(theTOS) : true; tos = result ? theTOS : tos; return result; } bool SetLoopback(bool state) { bool result = state ? SetMulticastLoopback(true) : true; loopback = result ? state : loopback; return result; } bool SetMulticastLoopback(bool state) { bool result = tx_socket->IsOpen() ? tx_socket->SetLoopback(state) : true; mcast_loopback = result ? state : mcast_loopback; return result; } bool SetFragmentation(bool state) { bool result = tx_socket->IsOpen() ? tx_socket->SetFragmentation(state) : true; fragmentation = result ? state : fragmentation; return result; } // MUST be called _after_ SetAddress() bool SetTxPort(UINT16 txPort, bool enableReuse = false, const char* srcAddr = NULL); UINT16 GetTxPort() const; bool SetRxPortReuse(bool enableReuse, const char* rxAddress = NULL, // bind() to / const char* senderAddress = (const char*)0, // connect() to / UINT16 senderPort = 0); UINT16 GetRxPort() const; // "SetEcnSupport(true)" sets up raw packet capture (pcap) so that incoming packet // ECN status may be checked // NOTE: only effective _before_ sndr/rcvr startup! void SetEcnSupport(bool ecnEnable, bool ignoreLoss, bool tolerateLoss) { ecn_enabled = ecnEnable; ecn_ignore_loss = ecnEnable ? ignoreLoss : false; cc_tolerate_loss = ecn_ignore_loss ? false : tolerateLoss; } bool GetEcnIgnoreLoss() const {return ecn_ignore_loss;} bool GetCCTolerateLoss() const {return cc_tolerate_loss;} static double CalculateRate(double size, double rtt, double loss); NormSessionMgr& GetSessionMgr() {return session_mgr;} bool SetTxSocketBuffer(unsigned int bufferSize) {return tx_socket->SetTxBufferSize(bufferSize);} bool SetRxSocketBuffer(unsigned int bufferSize) {return rx_socket.SetRxBufferSize(bufferSize);} // Session parameters double GetTxRate(); // returns bits/sec // (TBD) watch timer scheduling and min/max bounds void SetTxRate(double txRate) { txRate /= 8.0; // convert to bytes/sec posted_tx_rate_changed = false; SetTxRateInternal(txRate); } void SetTxRateBounds(double rateMin, double rateMax); double BackoffFactor() {return backoff_factor;} void SetBackoffFactor(double value) {backoff_factor = value;} bool CongestionControl() {return cc_enable;} void SetCongestionControl(bool state, bool adjustRate = true) { if (state) SetGrttProbingMode(PROBE_ACTIVE); cc_enable = state; cc_adjust = adjustRate; if (state) probe_proactive = true; } // This method enables/disables flow control operation. void SetFlowControl(double flowControlFactor) {flow_control_factor = flowControlFactor;} double GetFlowControl() const {return flow_control_factor;} // This method is used by "internal" NormSession and NormObject code // to activate the timer-based flow control when needed. void ActivateFlowControl(double delay, NormObjectId objectId, NormController::Event event); void DeactivateFlowControl() {flow_control_timer.Deactivate();} bool FlowControlIsActive() const {return flow_control_timer.IsActive();} NormObjectId GetFlowControlObject() const {return flow_control_object;} // The value returned here is the time interval used to determine // whether there has been "recent" NACKing for a given object or block. // A larger "flow_control_factor" stretches the time interval that // is considered "recent" and thus imposes stronger flow control. // A _strong_ "flow_control_factor" would be on the order of // "tx_robust_factor", but note larger values require more // tx/rx caching and/or buffering to sustain high throughput // NOTE "flow_control_factor = 0.0" means _no_ timer-based // flow control is imposed double GetFlowControlDelay() const { if (0.0 == flow_control_factor) return 0.0; double fdelay = (flow_control_factor * (SenderGrtt() * (backoff_factor + 1))); return ((fdelay > 0.020) ? fdelay : 0.020); // minimum 20 msec flow control } // GRTT measurement management void SetGrttProbingMode(ProbingMode probingMode); void SetGrttProbingInterval(double intervalMin, double intervalMax); void SetGrttMax(double grttMax) {grtt_max = grttMax;} bool SetTxCacheBounds(NormObjectSize sizeMax, unsigned long countMin, unsigned long countMax); // For NormSocket API extension support only void SetServerListener(bool state) {is_server_listener = state;} bool IsServerListener() const {return is_server_listener;} void Notify(NormController::Event event, class NormNode* node, class NormObject* object) { notify_pending = true; session_mgr.Notify(event, this, node, object); notify_pending = false; } NormMsg* GetMessageFromPool() {return message_pool.RemoveHead();} void ReturnMessageToPool(NormMsg* msg) {message_pool.Append(msg);} void QueueMessage(NormMsg* msg); enum MessageStatus { MSG_SEND_FAILED, MSG_SEND_BLOCKED, MSG_SEND_OK }; MessageStatus SendMessage(NormMsg& msg); void ActivateTimer(ProtoTimer& timer) {session_mgr.ActivateTimer(timer);} void SetUserData(const void* userData) {user_data = userData;} const void* GetUserData() const {return user_data;} void SetUserTimer(double seconds); // set to value less than zero to cancel // Sender methods void SenderSetBaseObjectId(NormObjectId baseId) { next_tx_object_id = IsSender() ? next_tx_object_id : baseId; //instance_id = IsSender() ? instance_id : (UINT16)baseId; } bool IsSender() {return is_sender;} bool StartSender(UINT16 instanceId, UINT32 bufferSpace, UINT16 segmentSize, UINT16 numData, UINT16 numParity, UINT8 fecId = 0); void StopSender(); void SetTxOnly(bool txOnly, bool connectToSessionAddress = false); bool GetTxOnly() const {return tx_only;} NormStreamObject* QueueTxStream(UINT32 bufferSize, bool doubleBuffer = false, const char* infoPtr = NULL, UINT16 infoLen = 0); NormFileObject* QueueTxFile(const char* path, const char* infoPtr = NULL, UINT16 infoLen = 0); NormDataObject* QueueTxData(const char* dataPtr, UINT32 dataLen, const char* infoPtr = NULL, UINT16 infoLen = 0); bool RequeueTxObject(NormObject* obj); void DeleteTxObject(NormObject* obj, bool notify); NormObject* SenderFindTxObject(NormObjectId objectId) {return tx_table.Find(objectId);} // postive ack mgmnt void SenderSetWatermark(NormObjectId objectId, NormBlockId blockId, NormSegmentId segmentId, bool overrideFlush = false); void SenderResetWatermark(); void SenderCancelWatermark(); void SenderSetAutoAckingNodes(TrackingStatus trackingStatus) {acking_auto_populate = trackingStatus;} NormAckingNode* SenderAddAckingNode(NormNodeId nodeId, const ProtoAddress* srcAddr = NULL); void SenderRemoveAckingNode(NormNodeId nodeId); AckingStatus SenderGetAckingStatus(NormNodeId nodeId); // Set "prevNodeId = NORM_NODE_NONE" to init this iteration (returns "false" when done) bool SenderGetNextAckingNode(NormNodeId& prevNodeId, AckingStatus* ackingStatus = NULL); NormAckingNode* SenderFindAckingNode(NormNodeId nodeId) const { return static_cast(acking_node_tree.FindNodeById(nodeId)); } // App-defined command support methods bool SenderSendCmd(const char* cmdBuffer, unsigned int cmdLength, bool robust); void SenderCancelCmd(); void SenderSetSynStatus(bool state) {syn_status = state;} // robust factor void SetTxRobustFactor(int value) {tx_robust_factor = value;} int GetTxRobustFactor() const {return tx_robust_factor;} void SetRxRobustFactor(int value) {rx_robust_factor = value;} int GetRxRobustFactor() const {return rx_robust_factor;} UINT8 GetSenderFecId() const {return fec_id;} UINT8 GetSenderFecFieldSize() const {return fec_m;} UINT16 SenderSegmentSize() const {return segment_size;} UINT16 SenderBlockSize() const {return ndata;} UINT16 SenderNumParity() const {return nparity;} UINT16 SenderAutoParity() const {return auto_parity;} void SenderSetAutoParity(UINT16 autoParity) {ASSERT(autoParity <= nparity); auto_parity = autoParity;} UINT16 SenderExtraParity() const {return extra_parity;} void SenderSetExtraParity(UINT16 extraParity) {extra_parity = extraParity;} INT32 Difference(NormBlockId a, NormBlockId b) const {return NormBlockId::Difference(a, b, fec_block_mask);} int Compare(NormBlockId a, NormBlockId b) const {return NormBlockId::Compare(a, b, fec_block_mask);} void Increment(NormBlockId& b, UINT32 i = 1) const {b.Increment(i, fec_block_mask);} // EMCON Sender (useful when there are silent receivers) // (NORM_INFO is redundantly sent) void SndrSetEmcon(bool state) {sndr_emcon = true;} bool SndrEmcon() const {return sndr_emcon;} bool SenderGetFirstPending(NormObjectId& objectId) { UINT32 index; bool result = tx_pending_mask.GetFirstSet(index); objectId = (UINT16)index; return result; } bool SenderGetFirstRepairPending(NormObjectId& objectId) { UINT32 index; bool result = tx_repair_mask.GetFirstSet(index); objectId = (UINT16)index; return result; } double SenderGrtt() const {return grtt_advertised;} void ResetGrttNotification() {notify_on_grtt_update = true;} void SenderSetGrtt(double grttValue) { if (IsSender()) { double grttMin = 2.0 * ((double)(44+segment_size))/tx_rate; grttValue = (grttValue < grttMin) ? grttMin : grttValue; } grtt_quantized = NormQuantizeRtt(grttValue); grtt_measured = grtt_advertised = NormUnquantizeRtt(grtt_quantized); } double SenderGroupSize() {return gsize_measured;} void SenderSetGroupSize(double gsize) { gsize_measured = gsize; gsize_quantized = NormQuantizeGroupSize(gsize); gsize_advertised = NormUnquantizeGroupSize(gsize_quantized); } void SenderEncode(unsigned int segmentId, const char* segment, char** parityVectorList) {encoder->Encode(segmentId, segment, parityVectorList);} NormBlock* SenderGetFreeBlock(NormObjectId objectId, NormBlockId blockId); void SenderPutFreeBlock(NormBlock* block) { block->EmptyToPool(segment_pool); block_pool.Put(block); } char* SenderGetFreeSegment(NormObjectId objectId, NormBlockId blockId); void SenderPutFreeSegment(char* segment) {segment_pool.Put(segment);} void PromptSender() {QueueMessage(NULL);} void TouchSender() { posted_tx_queue_empty = false; PromptSender(); //if (!notify_pending) Serve(); } bool GetPostedTxQueueEmpty() const {return posted_tx_queue_empty;} // Receiver methods bool StartReceiver(unsigned long bufferSpace); void StopReceiver(); bool IsReceiver() const {return is_receiver;} unsigned long RemoteSenderBufferSize() const {return remote_sender_buffer_size;} bool InsertRemoteSender(NormSenderNode& sender); void DeleteRemoteSender(NormSenderNode& senderNode); // Call this to do remote sender memory allocations ahead of time bool PreallocateRemoteSender(unsigned int bufferSize, UINT16 segmentSize, UINT16 numData, UINT16 numParity, unsigned int streamBufferSize = 0); void ReceiverSetUnicastNacks(bool state) {unicast_nacks = state;} bool ReceiverGetUnicastNacks() const {return unicast_nacks;} void ReceiverSetSilent(bool state) {receiver_silent = state;} bool ReceiverIsSilent() const {return receiver_silent;} void RcvrSetIgnoreInfo(bool state) {rcvr_ignore_info = state;} bool RcvrIgnoreInfo() const {return rcvr_ignore_info;} // The default "rcvr_max_delay = -1" corresponds to typical // operation where source data for partially received FEC blocks // are only provided to the app when buffer constraints require it. // Otherwise, the "maxDelay" corresponds to the max number // of FEC blocks the receiver waits before passing partially // received blocks to the app. // Note a "maxDelay == 0" provides _no_ protection from // out-of-order received packets! void RcvrSetMaxDelay(INT32 maxDelay) {rcvr_max_delay = maxDelay;} bool RcvrIsLowDelay() {return (ReceiverIsSilent() && (rcvr_max_delay >= 0));} INT32 RcvrGetMaxDelay() const {return rcvr_max_delay;} // When "rcvr_realtime" is set to "true", the buffer managment scheme of // favoring newly arriving data over attempting reliable reception of // buffered data is observed. This is the same buffer management that // is used for silent receiver operation // (TBD) allow the above "low delay" option to work with this, too? void RcvrSetRealtime(bool state) {rcvr_realtime = state;} bool RcvrIsRealtime() const {return rcvr_realtime;} NormObject::NackingMode ReceiverGetDefaultNackingMode() const {return default_nacking_mode;} void ReceiverSetDefaultNackingMode(NormObject::NackingMode nackingMode) {default_nacking_mode = nackingMode;} NormSenderNode::RepairBoundary ReceiverGetDefaultRepairBoundary() const {return default_repair_boundary;} void ReceiverSetDefaultRepairBoundary(NormSenderNode::RepairBoundary repairBoundary) {default_repair_boundary = repairBoundary;} NormSenderNode::SyncPolicy ReceiverGetDefaultSyncPolicy() const {return default_sync_policy;} void ReceiverSetDefaultSyncPolicy(NormSenderNode::SyncPolicy syncPolicy) {default_sync_policy = syncPolicy;} // Set default "max_pending_range" of NormObjects for reception void SetRxCacheMax(UINT16 maxCount) {rx_cache_count_max = (maxCount > 0x7fff) ? 0x7fff : maxCount;} UINT16 GetRxCacheMax() const {return rx_cache_count_max;} // Debug settings void SetTrace(bool state) {trace = state;} void SetTxLoss(double percent) {tx_loss_rate = percent;} void SetRxLoss(double percent) {rx_loss_rate = percent;} void SetReportTimerInterval(double interval) {report_timer.SetInterval(interval);} double GetReportTimerInterval() {return report_timer.GetInterval();} #ifdef SIMULATE // Simulation specific methods NormSimObject* QueueTxSim(unsigned long objectSize); bool SimSocketRecvHandler(char* buffer, unsigned short buflen, const ProtoAddress& src, bool unicast); #endif // SIMULATE void SetProbeCount(unsigned probeCount) {probe_count = probeCount;} bool SenderQueueSquelch(NormObjectId objectId); private: // Only NormSessionMgr can create/delete sessions NormSession(NormSessionMgr& sessionMgr, NormNodeId localNodeId); ~NormSession(); void Serve(); bool QueueTxObject(NormObject* obj); double GetProbeInterval(); bool OnTxTimeout(ProtoTimer& theTimer); bool OnRepairTimeout(ProtoTimer& theTimer); bool OnFlushTimeout(ProtoTimer& theTimer); bool OnProbeTimeout(ProtoTimer& theTimer); bool OnReportTimeout(ProtoTimer& theTimer); bool OnCmdTimeout(ProtoTimer& theTimer); bool OnFlowControlTimeout(ProtoTimer& theTimer); bool OnUserTimeout(ProtoTimer& theTimer); void TxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent); void RxSocketRecvHandler(ProtoSocket& theSocket, ProtoSocket::Event theEvent); void HandleReceiveMessage(NormMsg& msg, bool wasUnicast, bool ecn = false); // This is used when raw packet capture is enabled void OnPktCapture(ProtoChannel& theChannel, ProtoChannel::Notification notifyType); // Sender message handling routines void SenderHandleNackMessage(const struct timeval& currentTime, NormNackMsg& nack); void SenderHandleAckMessage(const struct timeval& currentTime, const NormAckMsg& ack, bool wasUnicast); void SenderUpdateGrttEstimate(double rcvrRtt); double CalculateRtt(const struct timeval& currentTime, const struct timeval& grttResponse); void SenderHandleCCFeedback(struct timeval currentTime, NormNodeId nodeId, UINT8 ccFlags, double ccRtt, double ccLoss, double ccRate, UINT16 ccSequence); void AdjustRate(bool onResponse); void SetTxRateInternal(double txRate); // here, txRate is bytes/sec //bool SenderQueueSquelch(NormObjectId objectId); void SenderQueueFlush(); bool SenderQueueWatermarkFlush(); bool SenderBuildRepairAdv(NormCmdRepairAdvMsg& cmd); void SenderUpdateGroupSize(); bool SenderQueueAppCmd(); // The following method is only used for NormSocket purposes bool SenderSendAppCmd(const char* buffer, unsigned int length, const ProtoAddress& dst); // Receiver message handling routines void ReceiverHandleObjectMessage(const struct timeval& currentTime, const NormObjectMsg& msg, bool ecnStatus); void ReceiverHandleCommand(const struct timeval& currentTime, const NormCmdMsg& msg, bool ecnStatus); void ReceiverHandleNackMessage(const NormNackMsg& nack); void ReceiverHandleAckMessage(const NormAckMsg& ack); NormSessionMgr& session_mgr; bool notify_pending; ProtoTimer tx_timer; UINT16 tx_port; bool tx_port_reuse; ProtoAddress tx_address; // bind tx_socket to tx_address when valid ProtoSocket tx_socket_actual; ProtoSocket* tx_socket; ProtoSocket rx_socket; ProtoCap* rx_cap; // raw packet capture alternative to "rx_socket" bool rx_port_reuse; // enable rx_socket port (sessionPort) reuse when true ProtoAddress rx_bind_addr; ProtoAddress rx_connect_addr; ProtoAddressList dst_addr_list; // list of local addresses NormMessageQueue message_queue; NormMessageQueue message_pool; ProtoTimer report_timer; UINT16 tx_sequence; // General session parameters NormNodeId local_node_id; ProtoAddress address; // session destination address/port ProtoAddress ssm_source_addr; // optional SSM source address UINT8 ttl; // session multicast ttl UINT8 tos; // session IPv4 TOS (or IPv6 traffic class - TBD) bool loopback; // receive own traffic it true bool mcast_loopback; // enable socket multicast loopback if true bool fragmentation; // enable UDP/IP fragmentation (i.e. clear DF bit) if true bool ecn_enabled; // set true to get raw packets and check for ECN status char interface_name[IFACE_NAME_MAX+1]; double tx_rate; // bytes per second double tx_rate_min; double tx_rate_max; unsigned int tx_residual; // for NORM_CMD(CC)/NORM_DATA "packet pairing" // Sender parameters and state double backoff_factor; bool is_sender; int tx_robust_factor; UINT16 instance_id; UINT16 segment_size; UINT16 ndata; UINT16 nparity; UINT16 auto_parity; UINT16 extra_parity; bool sndr_emcon; bool tx_only; bool tx_connect; NormObjectTable tx_table; ProtoSlidingMask tx_pending_mask; ProtoSlidingMask tx_repair_mask; ProtoTimer repair_timer; NormBlockPool block_pool; NormSegmentPool segment_pool; NormEncoder* encoder; UINT8 fec_id; UINT8 fec_m; INT32 fec_block_mask; NormObjectId next_tx_object_id; unsigned int tx_cache_count_min; unsigned int tx_cache_count_max; NormObjectSize tx_cache_size_max; ProtoTimer flush_timer; int flush_count; bool posted_tx_queue_empty; bool posted_tx_rate_changed; // For postive acknowledgement collection NormNodeTree acking_node_tree; unsigned int acking_node_count; unsigned int acking_success_count; TrackingStatus acking_auto_populate; // whether / how to "auto populate" acking node list bool watermark_pending; bool watermark_flushes; bool watermark_active; NormObjectId watermark_object_id; NormBlockId watermark_block_id; NormSegmentId watermark_segment_id; bool tx_repair_pending; NormObjectId tx_repair_object_min; NormBlockId tx_repair_block_min; NormSegmentId tx_repair_segment_min; // for unicast nack/cc feedback suppression bool advertise_repairs; bool suppress_nonconfirmed; double suppress_rate; double suppress_rtt; ProtoTimer probe_timer; // GRTT/congestion control probes bool probe_proactive; bool probe_pending; // true while CMD(CC) enqueued bool probe_reset; bool probe_data_check; // refrain cc probe until data is send struct timeval probe_time_last; double grtt_interval; // current GRTT update interval double grtt_interval_min; // minimum GRTT update interval double grtt_interval_max; // maximum GRTT update interval double grtt_max; unsigned int grtt_decrease_delay_count; bool grtt_response; double grtt_current_peak; double grtt_measured; double grtt_age; double grtt_advertised; UINT8 grtt_quantized; double gsize_measured; double gsize_advertised; UINT8 gsize_quantized; // Sender congestion control parameters unsigned int probe_count; // for experimentation (cc probes per rtt) bool cc_enable; bool cc_adjust; UINT16 cc_sequence; NormNodeList cc_node_list; bool cc_slow_start; bool cc_active; NormNode::Accumulator sent_accumulator; // for sentRate measurement double nominal_packet_size; bool data_active; // true when actively sending data double flow_control_factor; ProtoTimer flow_control_timer; NormObjectId flow_control_object; NormController::Event flow_control_event; // Sender "app-defined" command state unsigned int cmd_count; char* cmd_buffer; unsigned int cmd_length; ProtoTimer cmd_timer; bool syn_status; // Receiver parameters bool is_receiver; int rx_robust_factor; NormSenderNode* preset_sender; NormNodeTree sender_tree; unsigned long remote_sender_buffer_size; bool unicast_nacks; bool receiver_silent; bool rcvr_ignore_info; INT32 rcvr_max_delay; bool rcvr_realtime; NormSenderNode::RepairBoundary default_repair_boundary; NormObject::NackingMode default_nacking_mode; NormSenderNode::SyncPolicy default_sync_policy; UINT16 rx_cache_count_max; // For NormSocket server-listener support bool is_server_listener; NormClientTree client_tree; // API-specific state variables bool notify_on_grtt_update; // State for some experimental congestion control bool ecn_ignore_loss; bool cc_tolerate_loss; // Protocol test/debug parameters bool trace; double tx_loss_rate; // for correlated loss double rx_loss_rate; // for uncorrelated loss double report_timer_interval; ProtoTimer user_timer; const void* user_data; // Linkers NormSession* next; }; // end class NormSession // This function prints out NORM message info void NormTrace(const struct timeval& currentTime, NormNodeId localId, const NormMsg& msg, bool sent, UINT8 fecM, UINT16 instId = 0); // this might not always be available to caller #endif // _NORM_SESSION norm-1.5.8+dfsg2/include/normSimAgent.h0000644000000000000000000001323112240476653014577 0ustar #ifndef _NORM_SIM_AGENT #define _NORM_SIM_AGENT // normSimAgent.h - Generic (base class) NORM simulation agent #include "normSession.h" #include "protokit.h" #include "protoSimAgent.h" // Base class for Norm simulation agents (e.g. ns-2, OPNET, etc) class NormSimAgent : public NormController, public ProtoMessageSink { public: virtual ~NormSimAgent(); bool ProcessCommand(const char* cmd, const char* val); // Note: don't allow receiver _and_ sender operation at same time bool StartSender(); // start sender bool StartReceiver(); // start receiver bool IsActive() {return (NULL != session);} void Stop(); bool SendMessage(unsigned int len, const char* txBuffer); enum NormCC { NORM_FIXED, // fixed-rate (no congestion control) NORM_CC, // "normal" TCP-friendly congestion control NORM_CCE, // strict ECN-based congestion control NORM_CCL // "loss-tolerant" congestion control }; // These functions support ACK-based flow-controlled streaming using // some additional state variables (stream_buffer_max, stream_buffer_count, etc) static unsigned int ComputeStreamBufferSegmentCount(unsigned int bufferBytes, UINT16 segmentSize, UINT16 blockSize); unsigned int WriteToStream(const char* buffer, unsigned int numBytes); bool AddAckingNode(NormNodeId nodeId); protected: NormSimAgent(ProtoTimerMgr& timerMgr, ProtoSocket::Notifier& socketNotifier); enum CmdType {CMD_INVALID, CMD_NOARG, CMD_ARG}; CmdType CommandType(const char* cmd); virtual unsigned long GetAgentId() = 0; ProtoMessageSink* msg_sink; #ifdef OPNET void HandleMessage(char* buffer, unsigned int len, const ProtoAddress& srcAddr); void SetSink(ProtoMessageSink* sink){msg_sink=sink;} #endif //OPNET private: void OnInputReady(); bool FlushStream(bool eom);// = true); virtual void Notify(NormController::Event event, class NormSessionMgr* sessionMgr, class NormSession* session, class NormSenderNode* sender, class NormObject* object); void ActivateTimer(ProtoTimer& theTimer) {session_mgr.ActivateTimer(theTimer);} bool OnIntervalTimeout(ProtoTimer& theTimer); void SetCCMode(NormCC ccMode); static const char* const cmd_list[]; NormSessionMgr session_mgr; NormSession* session; // session parameters char* address; // session address UINT16 port; // session port number UINT8 ttl; double tx_rate; // bits/sec unsigned int probe_count; bool cc_enable; bool ecn_enable; NormCC cc_mode; bool unicast_nacks; bool silent_receiver; double backoff_factor; UINT16 segment_size; UINT8 ndata; UINT8 nparity; UINT8 auto_parity; UINT8 extra_parity; double group_size; double grtt_estimate; unsigned long tx_buffer_size; // bytes unsigned long tx_cache_min; unsigned long tx_cache_max; NormObjectSize tx_cache_size; unsigned long rx_buffer_size; // bytes unsigned long rx_cache_max; // rx object max_pending count // for simulated transmission (streams or files) unsigned long tx_object_size; double tx_object_interval; unsigned long tx_object_size_min; unsigned long tx_object_size_max; int tx_repeat_count; double tx_repeat_interval; int tx_requeue; int tx_requeue_count; NormStreamObject* stream; bool auto_stream; unsigned int stream_buffer_max; unsigned int stream_buffer_count; unsigned int stream_bytes_remain; bool watermark_pending; bool flow_control; bool push_mode; NormStreamObject::FlushMode flush_mode; char* tx_msg_buffer; unsigned int tx_msg_len; unsigned int tx_msg_index; char mgen_buffer[64]; bool msg_sync; unsigned int mgen_bytes; unsigned int mgen_pending_bytes; ProtoTimer interval_timer; // protocol debug parameters bool tracing; FILE* log_file_ptr; double tx_loss; double rx_loss; }; // end class NormSimAgent #endif // NORM_SIM_AGENT norm-1.5.8+dfsg2/include/normVersion.h0000644000000000000000000000315713320172055014510 0ustar /********************************************************************* * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution, and * * (3) all advertising materials mentioning features or use of this * software display the following acknowledgment: * * "This product includes software written and developed * by Brian Adamson and Joe Macker of the Naval Research * Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ********************************************************************/ // This defines the NORM source code version // The real code library version is given by NORM_VERSION // in "normApi.h" #ifndef _NORM_VERSION #define _NORM_VERSION #define VERSION "1.5.8" #endif // _NORM_VERSION norm-1.5.8+dfsg2/makefiles/0000755000000000000000000000000013320270771012331 5ustar norm-1.5.8+dfsg2/makefiles/Makefile.arm-linux0000644000000000000000000000401611156550174015710 0ustar # # arm-linux Protean Makefile definitions # # 1) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = -I/usr/local/arm/2.95.3/arm-linux/include SYSTEM_LDFLAGS = -L/usr/local/arm/2.95.3/arm-linux/lib SYSTEM_LIBS = -ldl # 2) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -DHAVE_FLOCK for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if your system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # E) The MDP code's use of offset pointers requires special treatment # for some different compilers. Set -DUSE_INHERITANCE for some # to keep some compilers (gcc 2.7.2) happy. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # #add -DHAVE_IPV6 if you have ipv6 support export SYSTEM_HAVES = -DARM -DLINUX -DHAVE_GETLOGIN -DHAVE_LOCKF \ -DHAVE_OLD_SIGNALHANDLER -DNO_SCM_RIGHTS -DHAVE_DIRFD -DHAVE_ASSERT $(NETSEC) SYSTEM_SRC = linuxRouteMgr.cpp SYSTEM = arm-linux CC = arm-linux-g++ SYSTEM_CFLAGS = -Wall -Wcast-align -pedantic -fPIC SYSTEM_SOFLAGS = -shared SYSTEM_SOEXT = so RANLIB = arm-linux-ranlib AR = arm-linux-ar AS = arm-linux-as LD = arm-linux-ld NM = arm-linux-nm STRIP = arm-linux-strip OBJCOPY = arm-linux-objcopy OBJDUMP = arm-linux-objdump include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.common0000644000000000000000000001754012761666466015311 0ustar ######################################################################### # COMMON NORM MAKEFILE STUFF # SHELL=/bin/sh .SUFFIXES: .cpp -sim.o $(.SUFFIXES) PROTOLIB = ../protolib COMMON = ../src/common UNIX = ../src/unix EXAMPLE = ../examples NS = ../src/sim/ns INCLUDES = $(SYSTEM_INCLUDES) -I$(UNIX) -I../include -I$(PROTOLIB)/include CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 -O $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES) #CFLAGS = -g -DPROTO_DEBUG -DUNIX -D_FILE_OFFSET_BITS=64 $(SYSTEM_CFLAGS) $(SYSTEM_HAVES) $(INCLUDES) LDFLAGS = $(SYSTEM_LDFLAGS) # Note: Even command line app needs X11 for Netscape post-processing LIBS = $(SYSTEM_LIBS) -lm -lpthread XLIBS = -lXmu -lXt -lX11 TARGETS = norm raft # Rule for C++ .cpp extension .cpp.o: $(CC) -c $(CFLAGS) -o $*.o $*.cpp # NORM depends upon the NRL Protean Group's development library LIBPROTO = $(PROTOLIB)/lib/libprotokit.a NORM_SRC = $(COMMON)/normMessage.cpp $(COMMON)/normSession.cpp \ $(COMMON)/normNode.cpp $(COMMON)/normObject.cpp \ $(COMMON)/normSegment.cpp $(COMMON)/normEncoder.cpp \ $(COMMON)/normEncoderRS8.cpp $(COMMON)/normEncoderRS16.cpp \ $(COMMON)/normEncoderMDP.cpp $(COMMON)/galois.cpp \ $(COMMON)/normFile.cpp $(COMMON)/normApi.cpp $(SYSTEM_SRC) NORM_OBJ = $(NORM_SRC:.cpp=.o) LIB_SRC = $(NORM_SRC) LIB_OBJ = $(LIB_SRC:.cpp=.o) all: norm raft libnorm.a $(PROTOLIB)/lib/libprotokit.a: $(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) libprotokit.a # NORM as a static library libnorm.a: $(LIB_OBJ) rm -f $@ $(AR) rcv $@ $(LIB_OBJ) $(RANLIB) $@ mkdir -p ../lib cp $@ ../lib/$@ # NORM as a shared library (i.e. libnorm.so, libnorm.dylib, etc) # (Note - we are linking "libprotokit" in statically libnorm.$(SYSTEM_SOEXT): $(LIB_OBJ) $(LIBPROTO) $(CC) $(SYSTEM_SOFLAGS) $(LIB_OBJ) $(LIBPROTO) $(LIBS) -o $@ mkdir -p ../lib cp $@ ../lib/$@ SIM_SRC = $(NORM_SRC) $(COMMON)/normSimAgent.cpp SIM_OBJ = $(SIM_SRC:.cpp=-sim.o) libnormsim.a: $(SIM_OBJ) rm -f $@ $(AR) rcv $@ $(SIM_OBJ) $(RANLIB) $@ # (norm) command-line file broadcaster/receiver APP_SRC = $(COMMON)/normApp.cpp $(COMMON)/normPostProcess.cpp \ $(UNIX)/unixPostProcess.cpp APP_OBJ = $(APP_SRC:.cpp=.o) norm: $(APP_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(APP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # This section builds some of code "examples" that use the NORM API # NORM_OBJECT_FILE sender example FSEND_SRC = $(EXAMPLE)/normFileSend.cpp FSEND_OBJ = $(FSEND_SRC:.cpp=.o) normFileSend: $(FSEND_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(FSEND_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # NORM_OBJECT_FILE receiver example FRECV_SRC = $(EXAMPLE)/normFileRecv.cpp FRECV_OBJ = $(FRECV_SRC:.cpp=.o) normFileRecv: $(FRECV_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(FRECV_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # NORM_OBJECT_DATA sender example DSEND_SRC = $(EXAMPLE)/normDataSend.cpp DSEND_OBJ = $(DSEND_SRC:.cpp=.o) normDataSend: $(DSEND_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(DSEND_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # NORM_OBJECT_DATA receiver example DRECV_SRC = $(EXAMPLE)/normDataRecv.cpp DRECV_OBJ = $(DRECV_SRC:.cpp=.o) normDataRecv: $(DRECV_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(DRECV_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # NORM_OBJECT_STREAM sender example SSEND_SRC = $(EXAMPLE)/normStreamSend.cpp SSEND_OBJ = $(SSEND_SRC:.cpp=.o) normStreamSend: $(SSEND_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(SSEND_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # NORM_OBJECT_STREAM receiver example SRECV_SRC = $(EXAMPLE)/normStreamRecv.cpp SRECV_OBJ = $(SRECV_SRC:.cpp=.o) normStreamRecv: $(SRECV_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(SRECV_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (normTest) test of NORM API TEST_SRC = $(COMMON)/normTest.cpp TEST_OBJ = $(TEST_SRC:.cpp=.o) normTest: $(TEST_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(TEST_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (normThreadTest) test of threaded use of NORM API TTEST_SRC = $(COMMON)/normThreadTest.cpp TTEST_OBJ = $(TTEST_SRC:.cpp=.o) normThreadTest: $(TTEST_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(TTEST_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (normThreadTest2) alt test of threaded use of NORM API TTEST2_SRC = $(UNIX)/normThreadTest2.cpp TTEST2_OBJ = $(TTEST2_SRC:.cpp=.o) normThreadTest2: $(TTEST2_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(TTEST2_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (normMsgr) message sender/receiver MSGR_SRC = $(EXAMPLE)/normMsgr.cpp MSGR_OBJ = $(MSGR_SRC:.cpp=.o) normMsgr: $(MSGR_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(MSGR_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (normStreamer) message sender/receiver STREAMER_SRC = $(EXAMPLE)/normStreamer.cpp STREAMER_OBJ = $(STREAMER_SRC:.cpp=.o) normStreamer: $(STREAMER_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(STREAMER_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (pcap2norm) - parses pcap (e.g. tcpdump) file and prints NORM trace PCAP_SRC = $(COMMON)/pcap2norm.cpp PCAP_OBJ = $(PCAP_SRC:.cpp=.o) pcap2norm: $(PCAP_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(PCAP_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (n2m) - converts NORM "trace" to MGEN log format to enable TRPR (or other) analyses N2M_SRC = $(COMMON)/n2m.cpp N2M_OBJ = $(N2M_SRC:.cpp=.o) n2m: $(N2M_OBJ) $(CC) $(CFLAGS) -o $@ $(N2M_OBJ) $(LDFLAGS) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (npc) NORM Pre-Coder PCODE_SRC = $(COMMON)/normPrecode.cpp PCODE_OBJ = $(PCODE_SRC:.cpp=.o) npc: $(PCODE_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(PCODE_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (raft) reliable app for tunnel (command-line reliable UDP tunnel) RAFT_SRC = $(COMMON)/raft.cpp RAFT_OBJ = $(RAFT_SRC:.cpp=.o) raft: $(RAFT_OBJ) $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(RAFT_OBJ) $(LDFLAGS) $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (ntun) IP/NORM tunnel app using ProtoVif NTUN_SRC = $(COMMON)/ntun.cpp $(PROTOLIB)/common/protoVif.cpp $(PROTOLIB)/unix/unixVif.cpp NTUN_OBJ = $(NTUN_SRC:.cpp=.o) ntun: $(NTUN_OBJ) $(LIBPROTO) libnorm.a $(CC) $(CFLAGS) -o $@ $(NTUN_OBJ) $(LDFLAGS) libnorm.a $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (fect) fec tester code FECT_SRC = $(COMMON)/fecTest.cpp $(COMMON)/normEncoder.cpp $(COMMON)/galois.cpp \ $(COMMON)/normEncoderRS8.cpp $(COMMON)/normEncoderRS16.cpp FECT_OBJ = $(FECT_SRC:.cpp=.o) fect: $(FECT_OBJ) libnorm.a $(LIBPROTO) $(CC) $(CFLAGS) -o $@ $(FECT_OBJ) $(LDFLAGS) $(LIBPROTO) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ # (gtf) generate test file GTF_SRC = $(COMMON)/gtf.cpp GTF_OBJ = $(GTF_SRC:.cpp=.o) gtf: $(GTF_OBJ) $(CC) $(CFLAGS) -o $@ $(GTF_OBJ) $(LDFLAGS) $(LIBS) mkdir -p ../bin cp $@ ../bin/$@ clean: rm -f $(COMMON)/*.o $(UNIX)/*.o $(NS)/*.o $(EXAMPLE)/*.o \ libnorm.a libnorm.$(SYSTEM_SOEXT) ../lib/libnorm.a ../lib/libnorm.$(SYSTEM_SOEXT) \ norm raft normTest normTest2 normThreadTest normThreadTest2 ../bin/*; $(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) clean distclean: clean # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. norm-1.5.8+dfsg2/makefiles/Makefile.freebsd0000644000000000000000000000274612543021504015405 0ustar # # FreeBSD Protean Makefile definitions # # 1) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = SYSTEM_LDFLAGS = SYSTEM_LIBS = # 2) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) SYSTEM_SRC = SYSTEM = freebsd CC = c++ SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align SYSTEM_SOFLAGS = -shared SYSTEM_SOEXT = so RANLIB = ranlib AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.hpux0000644000000000000000000000263310301373040014745 0ustar # # HPUX Protean Makefile definitions # (This file is likely out of date) # System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = SYSTEM_LDFLAGS = SYTSTEM_LIBS = # 6) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DHAVE_CUSERID -DHAVE_LOCKF CC = gcc SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align SYSTEM_SOFLAGS = -shared RANLIB = touch AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.iphone0000644000000000000000000000360411167210733015254 0ustar # # Protean MacOS X (Darwin) Makefile definitions # SDK = /Developer/Platforms/iPhoneOS.platform/Developer ARCH = armv6 SYSROOT = $(SDK)/SDKs/iPhoneOS2.2.1.sdk # 1) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = SYSTEM_LDFLAGS = -L$(SYSROOT)/usr/lib SYSTEM_LIBS = -lresolv # 2) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # E) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # F) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DMACOSX -DECN_SUPPORT -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK \ -D_FILE_OFFSET_BITS=64 -DHAVE_DIRFD SYSTEM_SRC = ../protolib/src/unix/bpfCap.cpp # The "SYSTEM" keyword can be used for dependent makes SYSTEM = iphone CC = $(SDK)/usr/bin/arm-apple-darwin9-g++-4.0.1 -arch $(ARCH) -isysroot $(SYSROOT) SYSTEM_CFLAGS = -Wall -Wcast-align -pedantic -fPIC -I$(SDK)/usr/include/gcc/darwin/4.0 SYSTEM_SOFLAGS = -dynamiclib SYSTEM_SOEXT = dylib RANLIB = $(SDK)/usr/bin/ranlib AR = $(SDK)/usr/bin/ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.linux0000644000000000000000000000344213313750162015131 0ustar # # Linux NORM Makefile definitions # # 5) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = -Wall -I/usr/X11R6/include SYSTEM_LDFLAGS = -L/usr/X11R6/lib SYSTEM_LIBS = -ldl # 6) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -DHAVE_FLOCK for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if your system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DLINUX -DECN_SUPPORT -DHAVE_IPV6 -DHAVE_GETLOGIN -D_FILE_OFFSET_BITS=64 -DHAVE_LOCKF \ -DHAVE_OLD_SIGNALHANDLER -DHAVE_DIRFD -DHAVE_ASSERT -DNO_SCM_RIGHTS -DHAVE_SCHED -DUNIX \ -DUSE_SELECT -DUSE_TIMERFD -DUSE_EVENTFD -DHAVE_PSELECT SYSTEM_SRC = ../protolib/src/linux/linuxCap.cpp SYSTEM = linux export CC = g++ export SYSTEM_CFLAGS = -Wall -Wcast-align -pedantic -fPIC -Wno-variadic-macros export SYSTEM_SOFLAGS = -shared -Wl,-soname,libnorm.so.1 SYSTEM_SOEXT = so export RANLIB = ranlib export AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.macosx0000644000000000000000000000323012335202300015244 0ustar # # Protean MacOS X (Darwin) Makefile definitions # # 1) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = SYSTEM_LDFLAGS = SYSTEM_LIBS = -lresolv -lpcap # 2) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # E) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # F) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DMACOSX -DECN_SUPPORT -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK \ -D_FILE_OFFSET_BITS=64 -DHAVE_DIRFD -DUSE_SELECT SYSTEM_SRC = ../protolib/src/unix/bpfCap.cpp # The "SYSTEM" keyword can be used for dependent makes SYSTEM = macosx CC = g++ SYSTEM_CFLAGS = -Wall -Wcast-align -fPIC -arch x86_64 -arch i386 SYSTEM_SOFLAGS = -dynamiclib SYSTEM_SOEXT = dylib RANLIB = ranlib AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.mklinux0000644000000000000000000000273410301373040015452 0ustar # # NORM mklinux Makefile # # 5) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = -I/usr/X11R6/include SYSTEM_LDFLAGS = -L/usr/X11R6/lib SYSTEM_LIBS = -ldl # 6) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # export SYSTEM_HAVES = -DHAVE_CUSERID -DHAVE_LOCKF -DHAVE_DIRFD $(NETSEC) export CC = gcc export SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align export SYSTEM_SOFLAGS = -shared export RANLIB = ranlib export AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.netbsd0000644000000000000000000000267410301373040015245 0ustar # # NORM NetBSD Makefile # # 5) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = -I/usr/X11R6/include SYSTEM_LDFLAGS = -L/usr/X11R6/lib SYSTEM_LIBS = # 6) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DHAVE_GETLOGIN -DHAVE_ASSERT -DHAVE_FLOCK -DHAVE_DIRFD $(DNETSEC) CC = gcc SYSTEM_CFLAGS = -fPIC -Wall -pedantic -Wcast-align SYSTEM_SOFLAGS = -shared RANLIB = ranlib AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.sgi0000644000000000000000000000275410301373040014547 0ustar # # IRIX Protean Makefile definitions # # 1) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = -DIRIX -n32 -woff 3333 SYSTEM_LDFLAGS = SYSTEM_LIBS = # 6) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # SYSTEM_HAVES = -DHAVE_IPV6 -DHAVE_GETLOGIN -DHAVE_LOCKF \ -DHAVE_DIRFD -DHAVE_ASSERT $(NETSEC) SYSTEM_SRC = SYSTEM = sgi # g++ #CC = g++ #SYSTEM_CFLAGS = -Wall -Wcast-align -pedantic -fPIC # SGI CC CC = CC SYSTEM_CFLAGS = -KPIC -pedantic SYSTEM_SOFLAGS = -shared RANLIB = touch AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.solaris0000644000000000000000000000304610301373040015434 0ustar # # NORM Solaris Makefile # # 1) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = SYSTEM_LDFLAGS = SYSTEM_LIBS = -ldl -lnsl -lsocket -lresolv # 2) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # E) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # F) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DHAVE_DIRFD -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF \ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DSOLARIS SYSTEM = solaris CC = CC # -xarch=v9 makes the output run only on 64-bit Solaris SYSTEM_CFLAGS = -KPIC -Wall -Wcast-align SYSTEM_SOFLAGS = -shared RANLIB = touch AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/Makefile.solx860000644000000000000000000000475210301373040015130 0ustar # # MDPv2 Solaris x86 (Solaris Version 2.7) Makefile # # TO BUILD THE TK GUI VERSION OF MDP EDIT THE FOLLOWING NUMBERED # ITEMS AS NEEDED FOR YOUR SYSTEM # (This has only been tested with TCL/TK 8.0 but it probably # will work with Tcl7.x/Tk4.x with a little tweaking to # the list of TCL_SCRIPTS (library scripts) given below) # 1) Where to find the Tcl standard library scripts # (e.g. init.tcl, ...) TCL_SCRIPT_PATH = /usr/local/lib/tcl8.0 # 2) Where to find the Tk standard library scripts # (e.g. button.tcl, entry.tcl, ...) TK_SCRIPT_PATH = /usr/local/lib/tk8.0 # 3) Where to find Tcl/Tk header files # (e.g. tcl.h, tk.h, ...) TCL_INCL_PATH = -I/usr/local/include # 4) Point to specific libtcl.a and libtk.a to use TCL_LIB = /usr/local/lib/libtcl8.0.a TK_LIB = /usr/local/lib/libtk8.0.a # 5) System specific additional libraries, include paths, etc # (Where to find X11 libraries, etc) # SYSTEM_INCLUDES = -I/usr/openwin/include SYSTEM_LDFLAGS = -L/usr/openwin/lib -R/usr/openwin/lib SYSTEM_LIBS = -ldl -lnsl -lsocket # 6) System specific capabilities # Must choose appropriate for the following: # # A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin() # functions to obtain user's login name (We may change this to getpwd() # if that is better across different platforms and login environments) # # B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking # functions to attempt exclusive lock on writing to files # # C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function # (Most don't have it defined ... but some do) # # D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT() # routine. # # E) The MDP code's use of offset pointers requires special treatment # for some different compilers. Set -DUSE_INHERITANCE for some # to keep some compilers (gcc 2.7.2) happy. # # F) Some systems (SOLARIS/SUNOS) have a few gotchas which require # some #ifdefs to avoid compiler warnings ... so you might need # to specify -DSOLARIS or -DSUNOS depending on your OS. # # G) Uncomment this if you have the NRL IPv6+IPsec software #DNETSEC = -DNETSEC -I/usr/inet6/include # # (We export these for other Makefiles as needed) # SYSTEM_HAVES = -DHAVE_DIRFD -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_CUSERID -DHAVE_LOCKF \ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DSOLARIS SYSTEM = solaris SYSTEM_CFLAGS = -PIC -Wall -Wcast-align CC = gcc SYSTEM_SOFLAGS = -shared RANLIB = touch AR = ar include Makefile.common norm-1.5.8+dfsg2/makefiles/android/0000755000000000000000000000000013320270771013751 5ustar norm-1.5.8+dfsg2/makefiles/android/AndroidManifest.xml0000644000000000000000000000046013121325141017531 0ustar norm-1.5.8+dfsg2/makefiles/android/README0000644000000000000000000000365512010423236014631 0ustar This directory contains an Android NDK import module for NORM, which builds a shared library, and the JNI bindings. Using NORM in your pure Java Android Application ------------------------------------------------ 1. First, update the library project to point to your Android SDK: android update lib-project --target --path /path/to/norm/makefiles/android android update lib-project --target --path /path/to/protolib/makefiles/android Use "android list targets" to see the ids of the SDK targets you have installed. 2. Add a "jni/Application.mk" in the root of your project to reference NORM: * You must at least set "APP_MODULES := norm-jni" * You should set "APP_BUILD_SCRIPT := /path/to/norm/makefiles/android/jni/Android.mk" * You should also set "NDK_MODULE_PATH" to point to the base norm directory so that the NDK can find protolib. See the example. Example: LOCAL_PATH := $(call my-dir) APP_MODULES := mil_navy_nrl_norm APP_ABI := all APP_BUILD_SCRIPT := $(LOCAL_PATH)/../library/norm/makefiles/android/jni/Android.mk NDK_MODULE_PATH := $(LOCAL_PATH)../library/norm/ 3. Reference the NORM Android library project in your "project.properties" file. Add the following: android.library.reference.1=/path/to/norm/makefiles/android Now, you should be able to run "ndk-build" in your root project directory to build the shared libraries, and run "ant debug" to build your APK. Using NORM in your C/C++/Java Android Application ------------------------------------------------- 1. Add a "jni/Application.mk" with your C/C++ code specified. 2. Reference the NORM Android project as an NDK Import Module. See "IMPORT-MODULE.html" in the NDK docs. Put something like the following at the bottom of your "Android.mk" $(call import-module,norm/makefiles/android/jni) This is relative to the "NDK_MODULE_PATH" variable that must be defined in "Application.mk". norm-1.5.8+dfsg2/makefiles/android/ant.properties0000644000000000000000000000132611717536644016667 0ustar # This file is used to override default values used by the Ant build system. # # This file must be checked in Version Control Systems, as it is # integral to the build system of your project. # This file is only used by the Ant script. # You can use this to override default values such as # 'source.dir' for the location of your java source folder and # 'out.dir' for the location of your output folder. # You can also use it define how the release builds are signed by declaring # the following properties: # 'key.store' for the location of your keystore and # 'key.alias' for the name of the key to use. # The password will be asked during the build when you use the 'release' target. source.dir=../../src/java/src norm-1.5.8+dfsg2/makefiles/android/build.xml0000644000000000000000000000643111717536644015612 0ustar norm-1.5.8+dfsg2/makefiles/android/jni/0000755000000000000000000000000013320270771014531 5ustar norm-1.5.8+dfsg2/makefiles/android/jni/Android.mk0000644000000000000000000000347512301172250016442 0ustar LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := norm LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/../../../protolib/include \ $(LOCAL_PATH)/../../../include LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_STATIC_LIBRARIES := protolib ifeq ($(APP_OPTIM),debug) LOCAL_CFLAGS += -DNORM_DEBUG endif LOCAL_EXPORT_CFLAGS := $(LOCAL_CFLAGS) LOCAL_SRC_FILES := \ ../../../src/common/galois.cpp \ ../../../src/common/normApi.cpp \ ../../../src/common/normEncoder.cpp \ ../../../src/common/normEncoderMDP.cpp \ ../../../src/common/normEncoderRS16.cpp \ ../../../src/common/normEncoderRS8.cpp \ ../../../src/common/normFile.cpp \ ../../../src/common/normMessage.cpp \ ../../../src/common/normNode.cpp \ ../../../src/common/normObject.cpp \ ../../../src/common/normSegment.cpp \ ../../../src/common/normSession.cpp include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := mil_navy_nrl_norm LOCAL_STATIC_LIBRARIES := norm protolib LOCAL_SRC_FILES := \ ../../../src/java/jni/normDataJni.cpp \ ../../../src/java/jni/normEventJni.cpp \ ../../../src/java/jni/normFileJni.cpp \ ../../../src/java/jni/normInstanceJni.cpp \ ../../../src/java/jni/normJni.cpp \ ../../../src/java/jni/normNodeJni.cpp \ ../../../src/java/jni/normObjectJni.cpp \ ../../../src/java/jni/normSessionJni.cpp \ ../../../src/java/jni/normStreamJni.cpp include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := norm-app LOCAL_STATIC_LIBRARIES := norm LOCAL_SRC_FILES := \ ../../../src/common/normApp.cpp \ ../../../src/common/normPostProcess.cpp \ ../../../src/unix/unixPostProcess.cpp include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_MODULE := normMsgr LOCAL_STATIC_LIBRARIES := norm LOCAL_SRC_FILES := \ ../../../examples/normMsgr.cpp include $(BUILD_EXECUTABLE) $(call import-module,protolib/makefiles/android/jni) norm-1.5.8+dfsg2/makefiles/android/jni/Application.mk0000644000000000000000000000012313121325141017310 0ustar APP_ABI := all APP_PLATFORM := android-14 NDK_MODULE_PATH := ../..:../../protolib/ norm-1.5.8+dfsg2/makefiles/android/proguard-project.txt0000644000000000000000000000141512010423236017771 0ustar # To enable ProGuard in your project, edit project.properties # to define the proguard.config property as described in that file. # # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in ${sdk.dir}/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the ProGuard # include property in project.properties. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} norm-1.5.8+dfsg2/makefiles/android/project.properties0000644000000000000000000000057613142742165017550 0ustar # This file is automatically generated by Android Tools. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file must be checked in Version Control Systems. # # To customize properties used by the Ant build system use, # "ant.properties", and override values to adapt the script to your # project structure. android.library=true # Project target. target=android-18 norm-1.5.8+dfsg2/makefiles/java/0000755000000000000000000000000013320270771013252 5ustar norm-1.5.8+dfsg2/makefiles/java/Makefile.common0000644000000000000000000000306712277772241016220 0ustar ######################################################################### # COMMON NORM-JNI MAKEFILE STUFF # .SUFFIXES: .cpp -sim.o $(.SUFFIXES) NORMJNI = ../../src/java/jni INCLUDES = $(SYSTEM_INCLUDES) -I../../include CFLAGS = -g -O $(SYSTEM_CFLAGS) $(INCLUDES) LIBNORM = ../../lib/libnorm.a PROTOLIB = ../../protolib LIBPROTO = $(PROTOLIB)/lib/libprotokit.a LIBS = $(SYSTEM_LIBS) -lm -lpthread # Rule for C++ .cpp extension .cpp.o: $(CC) -c $(CFLAGS) -o $*.o $*.cpp LIB_SRC = \ $(NORMJNI)/normJni.cpp \ $(NORMJNI)/normInstanceJni.cpp \ $(NORMJNI)/normSessionJni.cpp \ $(NORMJNI)/normObjectJni.cpp \ $(NORMJNI)/normDataJni.cpp \ $(NORMJNI)/normFileJni.cpp \ $(NORMJNI)/normStreamJni.cpp \ $(NORMJNI)/normEventJni.cpp \ $(NORMJNI)/normNodeJni.cpp LIB_OBJ = $(LIB_SRC:.cpp=.o) LIB_DEP = $(LIB_SRC:.cpp=.d) all: libmil_navy_nrl_norm.$(SYSTEM_SOEXT) # NORM JNI shared library libmil_navy_nrl_norm.$(SYSTEM_SOEXT): $(LIB_OBJ) $(LIBNORM) $(LIBPROTO) $(CC) $(SYSTEM_SOFLAGS) $(LIB_OBJ) $(LIBNORM) $(LIBPROTO) $(LIBS) -o $@ mkdir -p ../../lib cp $@ ../../lib/$@ $(LIBNORM): $(MAKE) -C ../../makefiles -f Makefile.$(SYSTEM) libnorm.a $(LIBPROTO): $(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) libprotokit.a -include $(LIB_DEP) %.d: %.cpp $(CC) -MM -MT $(@:.d=.o) -MF $@ $(CFLAGS) $< clean: rm -f $(NORMJNI)/*.o \ $(NORMJNI)/*.d \ libmil_navy_nrl_norm.$(SYSTEM_SOEXT) \ ../../lib/libmil_navy_nrl_norm.$(SYSTEM_SOEXT) distclean: clean # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. norm-1.5.8+dfsg2/makefiles/java/Makefile.linux0000644000000000000000000000061611337315542016055 0ustar # # Linux NORM-JNI Makefile definitions # # System specific additional libraries, include paths, etc SYSTEM_INCLUDES = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux SYSTEM_LIBS = SYSTEM_SRC = SYSTEM = linux export CC = g++ export SYSTEM_CFLAGS = -fPIC -Wall -Wcast-align -D_FILE_OFFSET_BITS=64 export SYSTEM_SOFLAGS = -shared -Wl,--no-undefined SYSTEM_SOEXT = so include Makefile.common norm-1.5.8+dfsg2/makefiles/java/Makefile.macosx0000644000000000000000000000056212277772241016217 0ustar # # MacOSX NORM-JNI Makefile definitions # # System specific additional libraries, include paths, etc SYSTEM_INCLUDES = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/darwin SYSTEM_LIBS = SYSTEM_SRC = SYSTEM = macosx CC = g++ SYSTEM_CFLAGS = -Wall -Wcast-align -fPIC -arch x86_64 -arch i386 SYSTEM_SOFLAGS = -dynamiclib SYSTEM_SOEXT = dylib include Makefile.common norm-1.5.8+dfsg2/makefiles/java/build.xml0000644000000000000000000000457611316204003015073 0ustar norm-1.5.8+dfsg2/makefiles/win32/0000755000000000000000000000000013320270771013273 5ustar norm-1.5.8+dfsg2/makefiles/win32/Norm-2008.sln0000644000000000000000000000742112406100313015303 0ustar Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormLib", "NormLib.vcproj", "{D7B0023C-8798-4918-8DA0-05C9054D70B9}" ProjectSection(ProjectDependencies) = postProject {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "norm", "norm\norm.vcproj", "{6E1308A6-D40F-489E-A4F1-40D859380D64}" ProjectSection(ProjectDependencies) = postProject {D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normTest", "normTest.vcproj", "{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}" ProjectSection(ProjectDependencies) = postProject {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} {182006F3-188F-466E-89FE-8421C0478691} = {182006F3-188F-466E-89FE-8421C0478691} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormDll", "NormDll.vcproj", "{182006F3-188F-466E-89FE-8421C0478691}" ProjectSection(ProjectDependencies) = postProject {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} = {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npc", "npc.vcproj", "{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}" ProjectSection(ProjectDependencies) = postProject {D7B0023C-8798-4918-8DA0-05C9054D70B9} = {D7B0023C-8798-4918-8DA0-05C9054D70B9} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Protokit", "..\..\protolib\makefiles\win32\Protokit.vcproj", "{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.ActiveCfg = Debug|Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.Build.0 = Debug|Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|Win32.ActiveCfg = Release|Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|Win32.Build.0 = Release|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.ActiveCfg = Debug|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.Build.0 = Debug|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Release|Win32.ActiveCfg = Release|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Release|Win32.Build.0 = Release|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.ActiveCfg = Debug|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.Build.0 = Debug|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.ActiveCfg = Release|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.Build.0 = Release|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Debug|Win32.ActiveCfg = Debug|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Debug|Win32.Build.0 = Debug|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.ActiveCfg = Release|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.Build.0 = Release|Win32 {7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Release|Win32.ActiveCfg = Release|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.ActiveCfg = Debug|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.Build.0 = Debug|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.ActiveCfg = Release|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal norm-1.5.8+dfsg2/makefiles/win32/Norm.sln0000644000000000000000000000605012520752475014734 0ustar Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Windows Desktop VisualStudioVersion = 12.0.30723.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormLib", "NormLib.vcxproj", "{D7B0023C-8798-4918-8DA0-05C9054D70B9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "norm", "norm\norm.vcxproj", "{6E1308A6-D40F-489E-A4F1-40D859380D64}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "normTest", "normTest.vcxproj", "{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NormDll", "NormDll.vcxproj", "{182006F3-188F-466E-89FE-8421C0478691}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npc", "npc.vcxproj", "{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Protokit", "..\..\protolib\makefiles\win32\Protokit.vcxproj", "{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.ActiveCfg = Debug|Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.Build.0 = Debug|Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|Win32.ActiveCfg = Release|Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|Win32.Build.0 = Release|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.ActiveCfg = Debug|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.Build.0 = Debug|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Release|Win32.ActiveCfg = Release|Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64}.Release|Win32.Build.0 = Release|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.ActiveCfg = Debug|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.Build.0 = Debug|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.ActiveCfg = Release|Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.Build.0 = Release|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Debug|Win32.ActiveCfg = Debug|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Debug|Win32.Build.0 = Debug|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.ActiveCfg = Release|Win32 {182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.Build.0 = Release|Win32 {7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Release|Win32.ActiveCfg = Release|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.ActiveCfg = Debug|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.Build.0 = Debug|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.ActiveCfg = Release|Win32 {DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal norm-1.5.8+dfsg2/makefiles/win32/Norm.suo0000644000000000000000000017400012343464342014743 0ustar ÐÏࡱá>þÿ þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ  .!("#$%&'+)*:/z;K0136452789DZ<?>þÿÿÿ@ABCyEFGHIJL]MNOPQRSTUVWXY[l\^o_`abcdefghijkmvnpþÿÿÿqrstuw,x=þÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿ05̌ϴProjInfoExÿÿÿÿÿÿÿÿÿÿÿÿTaskListUserTasks$)ÿÿÿÿIToolboxService  ÿÿÿÿÂþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿÿ þÿÿÿþÿÿÿ¦Ž$þÿÿÿ !"#)%&'Œþÿÿÿ*+,-./0123456[89:;<=>?@ABþÿÿÿDEFGHIJKLþÿÿÿNOPQRSTUVWXþÿÿÿZb\]^_`alcdefghijkþÿÿÿynopqrstuvwxþÿÿÿz{|}~5wØ)Ù¼B’"™6è/<úðC Device ControlsCrystal ReportsData XML Schema Dialog EditorMobile Web Forms Web Forms Components Windows FormsHTMLClipboard RingGeneralLC:\Adamson\NORM\norm\makefilIVSMDPropertyBrowser*ÿÿÿÿ?ÿÿÿÿþÿÿÿDebuggerWatches ÿÿÿÿÿÿÿÿÿÿÿÿDebuggerBreakpoints(ÿÿÿÿÿÿÿÿXDebuggerExceptions&ÿÿÿÿÿÿÿÿÿÿÿÿ es\win32\€C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\crt\src\ŽC:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc\ŽC:\Program Files\Microsoft Visual Studio .NETDebuggerFindSource& ÿÿÿÿ ¼DebuggerFindSymbol&ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿDebuggerMemoryWindows,ÿÿÿÿTExternalFilesProjectContents:ÿÿÿÿÿÿÿÿÿÿÿÿ ö 2003\Vc7\atlmfc\src\atl\ RoÍ«4ïþîÿF\Í«4ïþîÿ MultiStartupProj=;4{D7B0023C-8798-4918-8DA0-05C9054D70B9}.dwStartupOpt=;StartupProject=&{D7B0023C-8798-4918-8DA0DocumentWindowPositions0ÿÿÿÿÿÿÿÿÿÿÿÿ-¯DocumentWindowUserData. ÿÿÿÿ SolutionConfiguration,ÿÿÿÿÿÿÿÿÿÿÿÿ¢ ObjMgrContents%ÿÿÿÿ·-05C9054D70B9};?{D7B0023C-8798-4918-8DA0-05C9054D70B9}.Release|NSܾï MŠ%˜¿Ÿøç%Ò¯##G¶åá}'bm4Élü #Oÿ‡øÏ¤EQ lC:\Adamson\NORM\norm\makefiles\win32\norm\norm.vcprojhC:\XÏ bug|Win32.fBatchBld=;4{Win32.fBatchBld=;={D7B0023C-8798-4918-8DA0-05C9054D70B9}.Debug|Win32.fBatchBld=;4{6E1308A6-D40F-489E-A4F1-40D859380D64}.dwStartupOpt=;?{6E1308A6-D40F-489E-A4F1-40D859380D64}.RelAdamson\NORM\norm\makefiles\win32\NormDll.vcprojhC:\Adamson\NORM\norm\makefiles\win32\NormDll.vcprojhC:\Adamson\NORM\normè"ÿþ EndOfStream104FC72598ease|Win32.fBatchBld=;={6E1308A6-D40F-489E-A4F1-40D859380D64}.Debug|Win32.fBatchBld=;4{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.dwStartupOpt=;?{32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Release|Win32.fBatchBld=;={32CF83E0-D2E0-4E43-8F7B-72BD0AB64647}.Debug|Win32.fBatchBld=;4{182006F3-188F-466E-89FE-8421C0478691}.dwStartupOpt=;?{182006F3-188F-466E-89FE-8421C0478691}.Release|Win32.fBatchBld=;={182006F3-188F-466E-89FE-8Debug|Win32DebugSettingsClassViewContents$ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿProjExplorerState$$ÿÿÿÿÿÿÿÿ¨UnloadedProjects"ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿNormLibÿÿÿÿÿÿÿÿ7äô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£(.\Debug/NormLib.bsc(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£,.\Release/NormLib.bsc(EndConfigPropertiesDebug|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesRelProtokitÿÿÿÿÿÿÿÿClnorm ÿÿÿÿMØTaskListShortcuts$ÿÿÿÿÿÿÿÿÿÿÿÿIVSMDDesignerService*>ÿÿÿÿþÿÿÿease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertieskeTool ¢Debug|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£".\Debug/norm.bsc(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£&.\Release/norm.bsc(EndConfigPropertiesCBscMakeTool ¢ÿÿ£Debug|Win32DebugSettingsô.õ.ö. ø.÷.ù.421C0478691}.Debug|Win32.fBatchBld=;4{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.dwStartupOpt=;?{7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Release|Win32.fBatchIVsServerExplorer$1ÿÿÿÿþÿÿÿnormTestÿÿÿÿYèNormLibraryÿÿÿÿmäNormDllÿÿÿÿÿÿÿÿÿÿÿÿ€lBld=;={7BF4525B-9185-4296-A2BF-FFE77BB66EAF}.Debug|Win32.fBú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£*.\Debug/normTest.bsc(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£..\Release/normTest.bsc(EndConfigPropertiesMakeTool ¢atchBld=;4{DE94F096-A09B-44Debug|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£(.\Debug/NormLib.bsc(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool ¢ÿÿ£,.\Release/NormLib.bsc(EndConfigProperties|Win32.fBatchBB6-8EFE-C7BF1F65C4C9}.dwStartupOpt=;={DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|x64.fBatchBld=;?{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Release|Win32.fBatchBld=;;{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug‚ƒ„…†‡ˆ‰þÿÿÿþÿÿÿ’þÿÿÿ‘“”•–—˜™š›œþÿÿÿXŸ¢þÿÿÿþÿÿÿ§þÿÿÿ¥þÿÿÿ ¨©ª«¬Ó¸¯°±²³´µ¶·þÿÿÿ¹º»¼½¾ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑþÿÿÿþÿÿÿÔÕÖáØÙÚÛÜÝÞßàþÿÿÿâãäåæçèéêëìíîïðñòóôõö¾øùúûüýþÿDebug|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesMakeTooltupOpt=; ActiveCfg= RelDebug|Win32DebugSettings\makefiles\win32\NormLib.vcprojjC:\Adamson\NORM\norm\makefilNormDllÃNormLibProtokit3npc normënormTest32.fes\win32\normTest.vcproj`C:\Adamson\NORM\norm\makefiles\win3ô.õ.ö.\decode ibuf 0 input Release\giger203_jpg.npc ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesMakeTool(EndConfigPropert2\npc.vcproj|C:\Adamson\NORMZc:\Adamson\NORM\norm\src\common\normNode.cppNC:\Adamso7 `ÿÿÿÿnormënormTest2003\FilesVC:\Adamson\NORM\normn\NORM\norm\include\normApi.h$Bookmarks V001.01n\NORM\norm\NC:\Adamson\NORM\norm\include\normApi.hªºøÿÿÿÿTWÍ«4ïþîÿ˜ ¡ Í«4ïþîÿ¥¶ Í«4ïþîÿXc:\Adamson\NORM\norm\src\common\normApp.cpplc:\Adamson\NORM\norm\protolib\src\common\protoNet.cppTc:\adamson\norm\norm\include\normObject.hrc:\Adamson\NORM\norm\protolib\src\common\pdc:\Adamson\NORM\norm\protolib\iDebug|Win32DebugSettingsô.õ.ö. ø.÷.ù.NormDll2ÿÿÿÿ®lNormDll3ÿÿÿÿÿÿÿÿÿÿÿÿ×lnpcÿÿÿÿÿÿÿÿÿÿÿÿ‹ÈSourceCodeControl$ÿÿÿÿ(,ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesnclude\protoDefs.h-pÀµ) &<K!La"ef h:Q/{O/{%ˆ“'—˜%šÆBÈ€ÚÞ'áâ%ã4~î ?îï÷=ùTc:\adamson\norm\norm\include\normObject.hlëð   %*- 04S W k1l4h m6q u%|*}8~ „7… ‹7Œ ’7“ ™6› ¡6¢ ¨±5²8¹ Â<ê î6ï'ð0ñ$ò!ôTõ;  ((8 =>A?)Re j)|I}S€ •$™ Ÿ2£¥§>¨"ªA«K¬ °¹Dº.» ¿"ÙBÛ&Ü7Þ*àEá.âKã0æ+ç0êBë-ì?í/îLï+óøLùZú !"=Y f@ttÿÿÿÿ;ld=; ActiveCfg=Rel\Protokit.vcprojSource FrotoSocket.cppdc:\adamson\norm\norm\protolib\include\protoDefs.hlc:\Adamson\NORM\norm\protolib\src\common\protoCap.cpp`Debug|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesRelease|Win32DebugSettingsô.õ.ö. ø.÷.ù.ú.û.ü.ý. ÿ.,GeneralConfigSettingsVCBscMakeTool(EndConfigPropertiesc:\Adamson\NORM\norm\src\common\normSegment.cppnc:\Adamson\NORM\norm\protolib\src\common\protoPipe.cppZc:\Adamson\NORM\norm\src\common\normFile.cppPC:\Adamson\NORM\norm\include\normFile.hjc:\Adamson\NORM\norm\proOutliningState1 ÿÿÿÿÿÿÿÿÿÿÿÿ VsToolboxService"@ÿÿÿÿ¡ObjMgrContentsV8"ÿÿÿÿ8ÿÿÿÿŠHiddenSlnFolders"ÿÿÿÿ"ÿÿÿÿþÿÿÿOutliningStateDir$ÿÿÿÿÿÿÿÿÿÿÿÿžÌ BookmarkStateÿÿÿÿÿÿÿÿÿÿÿÿ£(OutliningState4 (6ÿÿÿÿ¤^OutliningState3 ÿÿÿÿÿÿÿÿÿÿÿÿ­¤OutliningState2 'ÿÿÿÿ¿ˆXmlPackageOptions$ÿÿÿÿÿÿÿÿÒOutliningState19"-:ÿÿÿÿOutliningState14"ÿÿÿÿÿÿÿÿÿÿÿÿjtolib\src\win32\win32Net.cppdc:\Adamson\NORM\norm\protolib\include\protoPipe.h`c:\Adamson\NORM\norm\src\common\normSession.cppXc:\Adamson\NORM\norm\src\common\normApi.cpp `c:\Adamson\NORM\norm\src\common\normPrecode.cppfc:\Adamson\NORM\norm\sOutliningState23";!ÿÿÿÿ;OutliningState24"ÿÿÿÿÿÿÿÿÿÿÿÿ›¦164B10B9-B200-11D0_ProjState: ÿÿÿÿ¶WpfDesigner-E58C2A8B*ÿÿÿÿÿÿÿÿÿÿÿÿ\kèSš ÿÿî8m† l† j{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\src\common\protoTime.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}1234Sš ÿÿî8m† l† `{DE94F  / _*þÿÿÿþÿÿÿþÿÿÿ þÿÿÿ"þÿÿÿ$%&'()5+þÿÿÿ-.a02)4þÿÿÿ6789:þÿÿÿ<=>?@ABCDEFGPIÇKþÿÿÿMþÿÿÿOþÿÿÿQRSTUVWþÿÿÿYZ[þÿÿÿ]^·`þÿÿÿbcdefghijklmnopqrstuvwxyz{|}~€rc\common\normEncoderMDP.cpp Zc:\Adamson\NORM\norm\makefiles\Junk\Junk.cppbC:\Adamson\NORM\norm\protolib\include\protoNet.h Vc:\Adamson\NORM\norm\include\normSession.h`c:\Adamson\NORM\norm\makefiles\Junk\dllmain.cphc:\Adamson\NORM\norm\protolib\include\protoSocket.hƒSiX  ./0*2 456=>A CDEFBGaBcrd.k p*r ‚6ƒ1‰!Š„!Š Œ8‘ •žŸ %“£ © ¿Ñ"Ô×@ßô ûü   & %   % $ "#$)% *(+05?8k: BD(EI M\`1ej4koa:uw{>„3…|7 N(“—rmnode.hFj”âÿÿÿÿ&ZglXc:\Adamson\NORM\norm\src\common\normApi.cppãVÛ²ÿÿÿÿbC:\Adamson\NORM\norm\protolib\include\protoNet.hCj%"$) 1F235 6(7 9WDIR0Y1Z:[3\7],^;_›œ£¤¨U®K¯%±p²ª ¶ÂGÃÆ^Ç Ï(Ô ÝAÞprotokit.lib C:\Adamson\NORM\norm\makefiles\win32\protokit.lib MMÍ«4ïþîÿ!9Í«4ïþîÿP]+Í«4Zc:\Adamson\NORM\norm\src\common`c:\Adamson\NORM\norm\src\common\normPrecode.cpp7Dãy  ,BCD>* F>G J ]^c dj!knouv†@‡ñFò D '@(=!>EFGBHVoIqŸU¡sW´ÛUÝáHâs¶ú8*9bCc ç+èû,"-:*<+A8CVW®L¯»ÿÿÿÿ8]| \|\normFile.cppcD¡’ÿÿÿÿ$fc:\Adamson\NORM\norm\src\common\normEncoderMDP.cpp×#MÿÿÿÿPc:\adamson\norm\norm\include\no@`(b,c1d-e:f,g1h,i8j,kF5tïþîÿFOÍ«4ïþîÿçðÍ«4ïþîÿÒ Ù Í«4ïþîÿn32\Protokit.vcproj|c:\Adarc:\Adamson\NORM\norm\protolib\src\common\protoSocket.cppDð>)  +112jc:\Adamson\NORM\norm\protolib\src\win32\win32Net.cppÛ€fÅlc:\Adamson\NORM\norm\protolib\src\common\protoNet.cppmÅñ`c:\Adamson\NORM\norm\src\common\normEncoder.cppT»ÿÿÿÿYZ|x64.fBatchBld=;={DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}.Debug|Win32.fBatchBld=;4{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}.dwStartupOpt=; ActiveCfg= Release|Win32;akefiles\win32\Xc:\Adamson\NORM\norm\src\common\normApp.cppÓ9…Ì   ("*71+203'4*9':/;-<+ @ X.Y Å:ÆÊ(ËÎÏ÷ø H[\žUŸ#ÄÙJÚ ÓQÖ ýQ,&29Æ6‚ ?¡Ã8Ä@ ,lNm nIoz†¢)£¨<© ¬J­®E¯ ¸8OutliningState18"ÿÿÿÿÿÿÿÿÿÿÿÿHDOutliningState17".,ÿÿÿÿJpOutliningState16"ÿÿÿÿÿÿÿÿÿÿÿÿLnOutliningState15"7*ÿÿÿÿNj096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\include\protoDefs.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456Sš ÿÿî8m† l† h{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\src\common\protoCap.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456Sš ÿÿî8m† l† {D7B0023C-8798-4918-8DA0-05C9054D70B9}|NormLib.vcproj|c:\Adamson\NORM\norm\src\common\normSessBatchBld=;={5D469547-BDB0-4688-8365-19F5C4520E9E}.Debug|Win32.fBatchBld=; ActiveCfg= Release|Win32; l^{1orm\makefiles\win32\npc.vcprojSource Files|C:\Adamson\NORM\norm\protolib\makefiles\win32\Protokit.vcproj-9B60-33659n\normObject.cpp`c:\Adamson\NORM\norm\src\common\normEncoder.cpp478691}|NormDll.vcproj|c:Zc:\Adamson\NORM\norm\makefiles\Junk\Junk.cpp> ‹[ÿÿÿÿ9`c:\Adamson\NORM\norm\makefiles\Junk\dllmain.cppßÝ0Åÿÿÿÿ0-AE1A-00A0C90FFFC3}ion.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}12Sš ÿÿî8m† l† {A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|<MiscFiles>|C:\Adamson\NORM\norm\protolib\include\protoNet.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456Sš ÿÿî8m† l† h{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\src\common\protoNet.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456Sš ÿÿî8m† l†  `{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\include\protoPipe.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}123456Sš ÿÿî8m† l† j{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\src\common\protoPipe.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}1234Sš ÿÿî8m† l† f{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\src\win32\win32Net.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}Sš ÿÿî8m† l† d{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\include\protoSocket.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}`c:\Adamson\NORM\norm\src\common\normSession.cppik4Œ`c:\Adamson\NORM\norm\src\common\normSegment.cppÝâˆÿÿÿÿÍ Ø^c:\Adamson\NORM\norm\src\common\normObject.cpp1ÇàvÿÿÿÿQ“©Zc:\Adamson\NORM\norm\src\common\normNode.cppA¼š¡ÿÿÿÿúZû2¹ ¼¾¿_À Ë"@#<J>H(\]/^ G_`f˜:š¯L± ( ;$=2ÐÌ;Í9' @#A9(Î ×?ØÙ9ÚÏì ð" í ÿÿÿÿ ( +-Ý2F\norm\protolib\makefiles\win32\Protokit.vcproj|C:\Adamson\NORM\norm\protolib\makefiles\win32\Protokit.vcprojeCfg= RelÿÿÿÿñSystem.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Collections.Hashtable, msco C:\Adamson\NORM\norm\protolib\include\protoNet.h<open> þ<?EF HIGJ MGNO;PVW \_;Sefp sƒ,q‡Aˆ²»'½¿%Á0³ÇÈÌÓàø6ùúû0)7g0hj\k ÷yz1˜ ›¢ ¥³ÇAÉ ËÌ7ÏÑ6Òã&ä% H%KL_5&‹ ÅÆÖ ÙÝîðá÷àøHŒ  !)" +6,-%.D M U Y!]^_EhqGst4u ~‹Œ›¨ ©ª«¼À ÂÆ9iÐÖ#× Û ùú2Ñ "*#$%(-9 :;< ?^HIOJ N W \)^ n)p} ƒ‡ - š&›œ  ¢ ©0.Å Ë íî 4Ç :;Y1\€ … ˆ:” —%™5_¥¯%°±² º ÆÇ Ò7¨ãå-ç䂃„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š.œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µþÿÿÿþÿÿÿ¸¹º»¼½þÿÿÿ¿ÀÁÂÃÄÅÆþÿÿÿÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþþÿÿÿèëïùQû ø'!b&'](DHaIJZK'P^UVYW>ñou›Ÿa ¡Z¢?qÂÃ$**/9:l+-x…Q”–‘ ŸŽ£&y­®±+²Ç Ë*ÌÍ"ÎÊÕ.ÈÚ Ýãä6/Û 4(,J- + 4,>AHJ$MIP9?S \_`PcY f'k^rsYtBT‰2ŒŽ “_•–W—’œŸ©&Š­ ±½¾Ç%¯Ê ÍÙÚæ&Ë+è®+è:ìý+þ :  + + 0 : ,- %K , %K P T U Y !Z f 9g w <x Œ X ™ 5š ž GŸ ¤ ¥ ¯ &± ¶ Bº ¾ MÂ È YÉ Í FÎ Ò dÓ Ø YÙ Þ aß ä Vc:\Adamson\NORM\norm\include\normSession.h2ÕË 8A9J)K1V Za*bBpŒ ’”,–— !§ ¬ ¯H°!­ ´$µ º)¼ ÁÏ;ÑNÒ ×%Ø%Ù&Ú&Û7à<á7â;ãæ:ç%è íð$ñ+ò%ó ôõEö ü5ÿ6%)@$.( 3 1 )  "* 1& +.3#4'5679 ==W-XDc4d)p'q%r&s)t'u%v&w3F€5‚)ƒ†*‡%ˆ ‰Š ‹: “@” š, ¦-¨ ­_¯D°1´ ¸¿ Ä*Æ+Ç4Í/Î*Ø&Ù*Ü'Ý#Þ.ßá)è,é(êëCì%í$îðKô(õ$ö#÷#øEú*ûOü1ýOÿ-\7G)P/+ , $ ( 'Iq ÿÿÿÿ­ @ ,C ECSPY f\ ] c^  h )l rlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]VersionComparerHashSize’System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] ’System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 5922C2A22}pnc:\Adamson\NORM\norm\protolib\src\common\protoTime.cppPc:\adamson\norm\norm\include\normnode.h hc:\Adamson\NORM\norm\protolib\include\protoSocket.h ^c:\Adamson\NORM\norm\src\common\normObject.cpp`c:\Adamson\NORM\norm\src\common\normEncoder.cppAdamson\NORM\norm\protolibl(nLst} œ: ÂZà Ï%ÒM~dx~e‚Bƒ–;šºS»Ñ%ÒÜß á%Ýçð öøKúFè&9 #!G#QZR2$jAk(‹ÍÕÖÞì ñ6’;<p9q} ~Ž@–;™ºäFåæ>çG+ 7M9`Of$Œk»ÊAÎß(àñ)òö8÷;OBJSL]Cg ³ ¶-h2Ñ- $Ó:#!&+4,#?=Ba=e…Ÿ D‰«¬#ËÖ*ß0Î2.>/<<?m@o¡=£¯B±ÒÔÛëQ2! %&Fß+5\8RGSv9w~NA‘B.%¦,%¦Õ ÜÝ"ß ÿ $¯{ U| ô #> \? P÷ B \ $] #‘ \’ HE • « 9­ D— µ >¶ Ü ß Mã GÝ ê ÷ .ø  Y   7  ! 1 +2 Dñ /Î   $ _% sÑ @ L N )9 H: Q XT Ï jÐ Xrw_A „A…’D“¡ª1®;¢['#(1%2X4Y^g_ip[q {W| „I…Y <j¦@§?UB;OutliningState13"ÿÿÿÿ+ÿÿÿÿvOutliningState11"&/ÿÿÿÿ!hOutliningState5 ÿÿÿÿ4ÿÿÿÿ3pOutliningState8 ÿÿÿÿÿÿÿÿÿÿÿÿ,FQR S]1^ A’ —2™ œ+ª º&½7TÇÍ?Ï9$P%+È`Pa‚Kƒ=€¬¯9°¹ ÀÒ+×åì(I)081KMLQdTV'Yl.q:­z ƒ`ˆ&{¦ ¶$·ÂpÃÜtÝó&õú ::?-§AG NO"Q;BH„‰!ŠŽ˜Ÿ0¨©)ª@›ÁAÂÕÿÿÿÿnorm\protolib\src\win32\win32Nnc:\Adamson\NORM\norm\protolib\s þÿÿÿ   þÿÿÿþÿÿÿþÿÿÿ !"#$%&'(þÿÿÿ*+,-þÿÿÿþÿÿÿþÿÿÿ1234þÿÿÿ67þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrc\common\protoPipe.cppnµ:     +#$(3)67"8+OPSWAX_!bcd„!†‡ˆ+U¦*§¬¯A±¸!»¼½ÅÇÈÉ,­  )  ñÿÿÿÿ `efl]nc:\Adamson\NORM\norm\protolib\src\common\protoTime.cpp#óú F  * 3$!;"(.)3&4O(PTW-XAUce$g doÿÿÿÿ&·Ç&ÊÚ ýþÿ ü      ÿÿÿÿ lc:\Adamson\NORM\norm\protolib\src\common\protoCap.cpp'(ßo"#,/50<-67 @C5D`AHÿÿÿÿ\½Ç% );<?GJRSQ »PS LROPWQ³¶LÃãJäaÄüýOCP^’4”•M—^_§¨­°6·¾ÁÈÉÇ PMRSUUaAb~S€]ƒf®Mž§O¨²ÁÂÄ*ÅÆÌר´ÜÝ.Þ.ßã"äè#éì(ð ()9::H3I^o:p(`¯'°³(´¶³·ÿÿÿÿ*D9'(,3.JK?LVM[?_e f-’•š›Ÿ! §"¨«ÿÿÿÿ319%>Yÿÿÿÿ[c1gv3x….&ââÿÿÿÿ¤°±dc:\Adamson\NORM\norm\protolib\include\protoPipe.hn»s=97 9! %')&5((7;;ÿÿÿÿn\NORM\norm\protolib\s+&{}T~DŽ ‘k•˜š ±mµ¼¼ÿÿÿÿMNLO RGST;U[\ ad;Xjku xˆ,vŒA·À'ÂÄ%Æ0¸ÌÍÑ×äü6ýþÿ').^0_a\b ûpq1y |ƒ †”¨Aª ¬­7Ô±&²ò %,5óXl‘’¢ ¥©®°(­¶¬·ÍÐHYÙ ÜÝÞ)ß è6éê%ëÚ   !%.G0142 ;HIX9&g q wx~h‚  *¡¢£(ƒ«± ²³´ ·^ÁÂOÃ Ç Ð Õ)× ç)éõø úý - &   0¬: @ bc ~4<ˆ Œ¯°Î1ŠÑõ ú ý: % 5Ô#%$%& - 9: E7VX-ZW[^blQn k†'”b™š]›‰·»a¼½Z¾'Ã^ÈÉYÊ>dâèaZ?ä5*84<=Q+6\iQqu {r&]‰Š+Ž£ §*¨©"ª¦±.¤¶ º4¾¿ËÏJÐ Î ×,·áäëí$ðìó9âö ÿPü '^YB÷,2/012 6_89W:5?BL&-P T`ah%Rk nz{…&l+‡Q+‡:‹œ+ª:«¼+½ÊÏÙ,Ì%êË%êïóôø!ù9<+X,859=G>CDN6PUBY]MagYhlFmqdrwYx}a~ƒÿÿÿÿlc:\Adamson\NORM\norm\protolib\src\common\protoNet.cppá[„OutliningState6 ÿÿÿÿÿÿÿÿÿÿÿÿ1”OutliningState9 3#ÿÿÿÿ÷(OutliningState7 25ÿÿÿÿ/vOutliningState12"ÿÿÿÿ0ÿÿÿÿ`3 .?289<=Dÿÿÿÿhc:\Adamson\NORM\norm\protolib\include\protoSocket.h‡ÎJÍ  .)-.(0 234;<? ABCD@E ^*` p6qrGu w8| €‰Š‹%~ޤ"§ª@²K¾L¾Ç ÎÏ Õ Ü Ý&Ø à%á åæç ì í%è ð$ñ õö÷)ø ý(þ? k    "151:?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²³´µ¶·¸¹º»¼½¾þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÌþÿÿÿÎÏþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ4@D6:KMQ>Z3[R7f #(imqryz~U„K…%‡pˆ€ Œ—G˜  (¥ ®A¯$³³ÿÿÿÿjc:\Adamson\NORM\norm\protolib\src\win32\win32Net.cppS8˜‡# '9<=EHPQO ¹PSJRMNWO±´LÁáJâaÂúVûKCLZ4M‘V[¡¢§ª6²¹¼ÃÄ H<JKULXAYuBwx]y^¨“ÿÿÿÿPc:\adamson\norm\norm\include\normnode.hFj”â!$"3#(')@*:+R,0>2H(I0J N%U Y@f/k%l0q u&y{--‘-’&“2• šgž¤8¥,¦ ª4¬&­Ÿ·.Ë"Ì4Í%Î Ó×%ØÞ¸óü -'= * G 1 0%=/(!1'%DE:G M9N T9U [+g k*n(o6q u*v y8z ~, ‚#ƒ ˆNŠ 0“B”-•?–/—L˜Ÿ ¢1£?¤4¥A¦4¨*©6ª,«¬ °HÁÆ.È$É5Ê$Ë2Í(Î*Ï"й2ÕôDHZ[%f*t yhƒ:‡1ˆŠ „%“%“ÿÿÿÿbC:\Adamson\NORM\norm\protolib\include\protoNet.hbãê;" *F+,. /(0 2W<AH0M1N:O3P7Q,R(T,U1V-W:X,Y>5`$&OutliningState10"ÿÿÿÿÿÿÿÿÿÿÿÿ#fOutliningState20"ÿÿÿÿÿÿÿÿÿÿÿÿ±DOutliningState21"9<ÿÿÿÿË~OutliningState22"ÿÿÿÿÿÿÿÿÿÿÿÿ͘g€€ÿÿÿÿPC:\Adamson\NORM\norm\include\normFile.h:y¯n    ( ./01>&?@A< CTAWX;Y SZ[-\,Q ^c7fg1h bIkl-m0` orstuvw z{|}+ƒ† š(›œ%”A§ˆ­µ »B¼ ÆÎ äåó®þþÿÿÿÿ65-19F5C4520E9E}.Release|Win32.f12Sš ÿÿî8m† l† n{DE94F096-A09B-44B6-8EFE-C7BF1F65C4C9}|..\..\protolib\makefiles\win32\Protokit.vcproj|c:\Adamson\NORM\norm\protolib\src\common\protoSocket.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}OutliningState25"=Aÿÿÿÿÿ†OutliningState28"Bÿÿÿÿ –OutliningState27"Cÿÿÿÿÿÿÿÿ0OutliningState26"ÿÿÿÿÿÿÿÿÿÿÿÿ0norm-1.5.8+dfsg2/makefiles/win32/NormDll.vcproj0000644000000000000000000001264511754475326016113 0ustar norm-1.5.8+dfsg2/makefiles/win32/NormDll.vcxproj0000755000000000000000000001477213251301475016274 0ustar  Debug Win32 Release Win32 {182006F3-188F-466E-89FE-8421C0478691} Win32Proj 10.0.16299.0 DynamicLibrary v141 MultiByte DynamicLibrary v141 MultiByte <_ProjectFileVersion>11.0.50727.1 Debug\ Debug\ true Release\ Release\ false Disabled ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) NORM_USE_DLL;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) $(OutDir)Norm.dll true $(OutDir)NormDll.pdb Windows false $(OutDir)Norm.lib MachineX86 ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) NORM_USE_DLL;NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies) $(OutDir)Norm.dll true Windows true true false $(OutDir)Norm.lib MachineX86 {de94f096-a09b-44b6-8efe-c7bf1f65c4c9} false norm-1.5.8+dfsg2/makefiles/win32/NormLib.vcproj0000644000000000000000000001173211556620275016075 0ustar norm-1.5.8+dfsg2/makefiles/win32/NormLib.vcproj.vs20080000644000000000000000000005715011446136447017043 0ustar norm-1.5.8+dfsg2/makefiles/win32/NormLib.vcxproj0000755000000000000000000001463013272152527016265 0ustar  Debug Win32 Release Win32 {D7B0023C-8798-4918-8DA0-05C9054D70B9} 10.0.16299.0 StaticLibrary v141 false MultiByte false StaticLibrary v141 false MultiByte false <_ProjectFileVersion>11.0.50727.1 .\Debug\ .\Debug\ .\Release\ .\Release\ Disabled ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL .\Debug/NormLib.pch .\Debug/ .\Debug/ .\Debug/ Level3 true Default _DEBUG;%(PreprocessorDefinitions) 0x0409 .\Debug\NormLib.lib true MaxSpeed OnlyExplicitInline ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreadedDLL true .\Release/NormLib.pch .\Release/ .\Release/ .\Release/ Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 .\Release\NormLib.lib true norm-1.5.8+dfsg2/makefiles/win32/README.TXT0000755000000000000000000000115012412333255014627 0ustar Visual Studio 2012 and 2013 require different versions of the Platform Toolset: Visual Studio 2012 v110 (or v110_xp for applications that need to run under Windows XP) Visual Studio 2013 v120 (or v120_xp for applications that need to run under Windows XP) For each project included by the solution file modify the Platform Toolset under project Configuration Properties, General as appropriate for your Visual Studio version. A Visual Studio solutions file and associated .vcproj files are included as a convenience for those using earlier versions of visual studio (2008 and 2010): Norm-2008.sln norm-1.5.8+dfsg2/makefiles/win32/norm/0000755000000000000000000000000013320270771014246 5ustar norm-1.5.8+dfsg2/makefiles/win32/norm/norm.vcproj0000644000000000000000000001316411556622655016466 0ustar norm-1.5.8+dfsg2/makefiles/win32/norm/norm.vcxproj0000755000000000000000000002006113272520557016646 0ustar  Debug Win32 Release Win32 {6E1308A6-D40F-489E-A4F1-40D859380D64} 10.0.16299.0 Application v141 false MultiByte Application v141 false MultiByte <_ProjectFileVersion>11.0.61030.0 .\Debug\ .\Debug\ false .\Release\ .\Release\ false _DEBUG;%(PreprocessorDefinitions) true true Win32 .\Debug/norm.tlb /vmg %(AdditionalOptions) Disabled ..\..\..\include;..\..\..\protolib\include;%(AdditionalIncludeDirectories) _CONSOLE,_DEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL .\Debug/norm.pch .\Debug/ .\Debug/ .\Debug/ Level3 true EditAndContinue Default _DEBUG;%(PreprocessorDefinitions) 0x0409 iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) .\Debug/norm.exe true true .\Debug/norm.pdb Windows false MachineX86 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\Release/norm.tlb /vmg %(AdditionalOptions) MaxSpeed OnlyExplicitInline ..\..\..\include;..\..\..\protolib\include;%(AdditionalIncludeDirectories) _CONSOLE,NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreadedDLL true .\Release/norm.pch .\Release/ .\Release/ .\Release/ true Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) .\Release/norm.exe true .\Release/norm.pdb Windows false MachineX86 {de94f096-a09b-44b6-8efe-c7bf1f65c4c9} {d7b0023c-8798-4918-8da0-05c9054d70b9} norm-1.5.8+dfsg2/makefiles/win32/normTest.vcproj0000644000000000000000000001242011556620275016341 0ustar norm-1.5.8+dfsg2/makefiles/win32/normTest.vcxproj0000755000000000000000000001717013251301475016533 0ustar  Debug Win32 Release Win32 {32CF83E0-D2E0-4E43-8F7B-72BD0AB64647} normTest 10.0.16299.0 Application v141 false MultiByte Application v141 false MultiByte <_ProjectFileVersion>11.0.50727.1 .\Debug\ .\Debug\ .\Release\ .\Release\ false false .\Debug/normTest.tlb Disabled ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) NORM_USE_DLL;PROTO_DEBUG;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true .\Debug/normTest.pch .\Debug/ .\Debug/ .\Debug/ Level3 true EditAndContinue Default _DEBUG;%(PreprocessorDefinitions) 0x0409 iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) .\Debug/normTest.exe true ./;%(AdditionalLibraryDirectories) true .\Debug/normTest.pdb Console false MachineX86 .\Release/normTest.tlb MaxSpeed OnlyExplicitInline ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) NORM_USE_DLL;PROTO_DEBUG;WIN32;HAVE_ASSERT;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreadedDLL true .\Release/normTest.pch .\Release/ .\Release/ .\Release/ Level3 true ProgramDatabase Default NDEBUG;%(PreprocessorDefinitions) 0x0409 iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) .\Release/normTest.exe true .\Release/normTest.pdb Console false MachineX86 {de94f096-a09b-44b6-8efe-c7bf1f65c4c9} false {182006f3-188f-466e-89fe-8421c0478691} false norm-1.5.8+dfsg2/makefiles/win32/npc.vcproj0000644000000000000000000001213511556620275015311 0ustar norm-1.5.8+dfsg2/makefiles/win32/npc.vcxproj0000755000000000000000000001622413251301475015477 0ustar  Debug Win32 Release Win32 {7BF4525B-9185-4296-A2BF-FFE77BB66EAF} normTest 10.0.16299.0 Application v141 false MultiByte Application v141 false MultiByte <_ProjectFileVersion>11.0.50727.1 .\Debug\ .\Debug\ .\Release\ .\Release\ false false .\Debug/normTest.tlb Disabled ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true .\Debug/normTest.pch .\Debug/ .\Debug/ .\Debug/ Level3 true EditAndContinue Default _DEBUG;%(PreprocessorDefinitions) 0x0409 iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) true ./;%(AdditionalLibraryDirectories) true Windows false MachineX86 .\Release/normTest.tlb MaxSpeed OnlyExplicitInline ..\..\include;..\..\protolib\include;%(AdditionalIncludeDirectories) NDEBUG;PROTO_DEBUG;HAVE_IPV6;HAVE_ASSERT;WIN32;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreadedDLL true .\Release/normTest.pch .\Release/ .\Release/ .\Release/ Level3 true ProgramDatabase Default NDEBUG;%(PreprocessorDefinitions) 0x0409 iphlpapi.lib;ws2_32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) true Windows false MachineX86 {d7b0023c-8798-4918-8da0-05c9054d70b9} false norm-1.5.8+dfsg2/makefiles/wince/0000755000000000000000000000000013320270771013436 5ustar norm-1.5.8+dfsg2/makefiles/wince/Norm.vco0000644000000000000000000024400010670314070015056 0ustar ÐÏࡱá>þÿ þÿÿÿþÿÿÿzÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ  þÿÿÿ þÿÿÿþÿÿÿy"#$%&'()*þÿÿÿ,-./0123456789:;<þÿÿÿ>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijþÿÿÿlmnopqrstuvwxþÿÿÿþÿÿÿýÿÿÿ|}~€Root Entryÿÿÿÿÿÿÿÿ°aôÕ|ñÇþÿÿÿWorkspace State ÿÿÿÿBrowserÿÿÿÿ Editorÿÿÿÿÿÿÿÿprotokit0C:\Adamson\NORM\norm\protolib\wince\Protokit.vcpnorm#C:\Adamson\NORM\norm\wince\Norm.vcpnormapp.C:\Adamson\NORM\norm\wince\normApp\normApp.vcp$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR it0C:\Adamson\NORM\norm\protolib\wince\Protokit.vcpnorm#C:\Adamson\NORM\norm\wince\Norm.vcpnormapp.C:\Adamson\NORM\norm\wince\normApp\normApp.vcp$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR MLJLit0C:\Adamson\NORM\norm\protolib\wince\Protokit.vcpnorm#C:\Adamson\NORM\norm\wince\Norm.vcpnormapp.C:\Adamson\NORM\norm\wince\normApp\normApp.vcp$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR Workspace Window" ÿÿÿÿÿÿÿÿ!IPI_Norm ÿÿÿÿ+$IPI_Protokitÿÿÿÿÿÿÿÿÿÿÿÿ=\IPI_normAppÿÿÿÿkNorm ClassViewnormApp classesProtokit classesFileViewWorkspace 'Norm': 3 project(s) Norm files Norm filesWorkspace 'Norm': 3 project(s)FileViewûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR (ë Norm - Win32 (WCE ARMV4) ReleaseNorm.vcpCProject Norm - Win32 (WCE ARMV4) Release#Norm - Win32 (WCE emulator) ReleaseêûÀ!Norm - Win32 (WCE emulator) DebugêûÀ Norm - Win32 (WCE ARMV4) ReleaseêûÀNorm - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem#Norm - Win32 (WCE emulator) Release!Norm - Win32 (WCE emulator) Debug Norm - Win32 (WCE ARMV4) ReleaseNorm - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWdepCDependencyContainerSSBRgalois.hCDependencyFileSSBR normApi.hCDependencyFileSSBR normEncoder.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRgalois.hCDependencyFileSSBR normApi.hCDependencyFileSSBR normEncoder.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRgalois.hCDependencyFileSSBR normApi.hCDependencyFileSSBR normEncoder.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRgalois.hCDependencyFileSSBR normApi.hCDependencyFileSSBR normEncoder.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR basetsd.hCDependencyFileSSBR guiddef.hCDependencyFileSSBRDJWDJWDJWDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR ìoi¨Ûä ÀX¿ependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileì r@à ðè hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFilÄã ðÂ(ë$PROTOKIT - WIN32 (WCE ARMV4) RELEASE Protokit.vcpCProject$PROTOKIT - WIN32 (WCE ARMV4) RELEASE(Protokit - Win32 (WCE MIPSII_FP) Releaseû&Protokit - Win32 (WCE MIPSII_FP) Debugû%Protokit - Win32 (WCE MIPSII) Releaseû#Protokit - Win32 (WCE MIPSII) Debugû"Protokit - Win32 (WCE SH4) Releaseû Protokit - Win32 (WCE SH4) Debugû"Protokit - Win32 (WCE SH3) Releaseû Protokit - Win32 (WCE SH3) Debugû%Protokit - Win32 (WCE MIPSIV) Releaseû#Protokit - Win32 (WCE MIPSIV) Debugû'Protokit - Win32 (WCE emulator) Releaseû%Protokit - Win32 (WCE emulator) Debugû%Protokit - Win32 (WCE ARMV4I) Releaseû#Protokit - Win32 (WCE ARMV4I) Debugû(Protokit - Win32 (WCE MIPSIV_FP) Releaseû&Protokit - Win32 (WCE MIPSIV_FP) Debugû$Protokit - Win32 (WCE ARMV4) Releaseû"Protokit - Win32 (WCE ARMV4) Debugû"Protokit - Win32 (WCE x86) Releaseû Protokit - Win32 (WCE x86) DebugûSSBR CTargetItem(Protokit - Win32 (WCE MIPSII_FP) Release&Protokit - Win32 (WCE MIPSII_FP) Debug%Protokit - Win32 (WCE MIPSII) Release#Protokit - Win32 (WCE MIPSII) Debug"Protokit - Win32 (WCE SH4) Release Protokit - Win32 (WCE SH4) Debug"Protokit - Win32 (WCE SH3) Release Protokit - Win32 (WCE SH3) Debug%Protokit - Win32 (WCE MIPSIV) Release#Protokit - Win32 (WCE MIPSIV) Debug'Protokit - Win32 (WCE emulator) Release%Protokit - Win32 (WCE emulator) Debug%Protokit - Win32 (WCE ARMV4I) Release#Protokit - Win32 (WCE ARMV4I) Debug(Protokit - Win32 (WCE MIPSIV_FP) Release&Protokit - Win32 (WCE MIPSIV_FP) Debug$Protokit - Win32 (WCE ARMV4) Release"Protokit - Win32 (WCE ARMV4) Debug"Protokit - Win32 (WCE x86) Release Protokit - Win32 (WCE x86) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWDJWDJWöEùý~ÌöOùÌöVùÌömù%Ìötù,Ìö¥ù]Ìö§ù_Ìöèù Ìö €ùÄÌö€ùËÌö€ùÑÌö€ùÔÌö€ùÖÌöM€ù€ÌöP€ù€Ìöh€ù €Ìök€ù#€Ìöm€ù%€Ìö­€ùe€Ìöë€ù£€Ìö/ùç€Ìöpù(Ìö±ùiÌöñù©Ìöôù¬Ìö‚ù½Ìö ‚ùÅÌö]‚ù‚Ìö«‚ùc‚Ìöö‚ù®‚Ìö@ƒùø‚Ìö`ƒùƒÌö{ƒù3ƒÌö†ƒù>ƒÌöÁƒùyƒÌöÿƒù·ƒÌö=„ùõƒÌöƒ„ù;„Ìö¢„ùZ„Ìö°„ùh„ÌöÔ„ùŒ„Ìöß„ù—„ÌöC…ùû„Ìöa…ù…Ìöm…ù%…Ìöu…ù-…Ìö…ùU…ÌöÁ…ùy…Ìöá…ù™…Ìö)†ùá…Ìö1†ùé…Ìöb†ù†Ìö•†ùM†ÌöŸ†ùW†Ìö¾†ùv†Ìöì†ù¤†Ìöô†ù¬†Ìö‡ùÖ†ÌöL‡ù‡Ìög‡ù‡Ìös‡ù+‡Ìö¶‡ùn‡Ìöó‡ù«‡Ìö9ˆùñ‡ÌöHˆùˆÌönˆù&ˆÌö(ë#NORMAPP - WIN32 (WCE ARMV4) RELEASE normApp.vcpCProject#NORMAPP - WIN32 (WCE ARMV4) RELEASE&normApp - Win32 (WCE emulator) ReleaseêûÀ$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileIPI_ ÿÿÿÿÿÿÿÿÿÿÿÿ{ClassView Window"ÿÿÿÿÿÿÿÿÿÿÿÿ…DebuggerÿÿÿÿÿÿÿÿÿÿÿÿDocumentsÿÿÿÿÿÿÿÿÿÿÿÿ™‚ƒ„þÿÿÿ†‡ˆ‰Š‹ŒŽþÿÿÿ‘’“”•–—˜þÿÿÿš›œžŸ ¡¢þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(ëNormnormAppProtokitÿÿÿÿÿÿWCEPOCKET PC 2003 ITLDevicePOCKET PC 2003 Device2 (WCE emulator) ReleaseêûÀ$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR ÿÿ CClsFldSlobNorm€Protokit€normAppÿÿWCEPOCKET PC 2003 ITLDevicePOCKET PC 2003 Device2 (WCE emulator) ReleaseêûÀ$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR ÿÿÿÿWatch1Watch2Watch3Watch4WCEPOCKET PC 2003 ITLDevicePOCKET PC 2003 Device2 (WCE emulator) ReleaseêûÀ$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR ä ÿÿÿÿWatch1Watch2Watch3Watch4WCEPOCKET PC 2003 ITLDevicePOCKET PC 2003 Device2 (WCE emulator) ReleaseêûÀ$normApp - Win32 (WCE emulator) DebugêûÀ#normApp - Win32 (WCE ARMV4) Releaseêûý'STANDARDSDK_420::\;;POCKET PC 2003::\;;À!normApp - Win32 (WCE ARMV4) DebugêûÀSSBR CTargetItem&normApp - Win32 (WCE emulator) Release$normApp - Win32 (WCE emulator) Debug#normApp - Win32 (WCE ARMV4) Release!normApp - Win32 (WCE ARMV4) DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWNormCProjectDependencySSBRProtokitCProjectDependencySSBRdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRprotoAddress.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBRDJWdepCDependencyContainerSSBR normEncoder.hCDependencyFileSSBR normFile.hCDependencyFileSSBR normMessage.hCDependencyFileSSBR normNode.hCDependencyFileSSBR normObject.hCDependencyFileSSBRnormPostProcess.hCDependencyFileSSBR normSegment.hCDependencyFileSSBR normSession.hCDependencyFileSSBRDJWDJWDJWncyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR protokit.hCDependencyFileSSBR protoPipe.hCDependencyFileSSBRprotoRouteMgr.hCDependencyFileSSBRprotoRouteTable.hCDependencyFileSSBR protoTree.hCDependencyFileSSBRprotoVersion.hCDependencyFileSSBR protoPkt.hCDependencyFileSSBR protoPktEth.hCDependencyFileSSBR protoPktIP.hCDependencyFileSSBR protoPktRTP.hCDependencyFileSSBRDJWdepCDependencyContainerSSBRprotoAddress.hCDependencyFileSSBR protoDebug.hCDependencyFileSSBR protoDefs.hCDependencyFileSSBRtpipv6.hCDependencyFileSSBR wspiapi.hCDependencyFileSSBR protoApp.hCDependencyFileSSBRprotoDispatcher.hCDependencyFileSSBR protoSocket.hCDependencyFileSSBR protoTimer.hCDependencyFileSSBRprotoBitmask.hCDependencyFileSSBRprotoChannel.hCDependencyFileSSBR norm-1.5.8+dfsg2/makefiles/wince/Norm.vcp0000644000000000000000000012370610231013410015053 0ustar # Microsoft eMbedded Visual Tools Project File - Name="Norm" - Package Owner=<4> # Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02 # ** DO NOT EDIT ** # TARGTYPE "Win32 (WCE ARMV4) Static Library" 0xa304 # TARGTYPE "Win32 (WCE emulator) Static Library" 0xa604 CFG=Norm - Win32 (WCE emulator) Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Norm.vcn". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Norm.vcn" CFG="Norm - Win32 (WCE emulator) Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Norm - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Static Library") !MESSAGE "Norm - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Static Library") !MESSAGE "Norm - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Static Library") !MESSAGE "Norm - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Static Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" # PROP ATL_Project 2 !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "emulatorRel" # PROP BASE Intermediate_Dir "emulatorRel" # PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "emulatorRel" # PROP Intermediate_Dir "emulatorRel" # PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Target_Dir "" CPP=cl.exe # ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_LIB" /YX /Gs8192 /GF /O2 /c # ADD CPP /nologo /W3 /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "_i386_" /D "_X86_" /D "x86" /D "NDEBUG" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /Gs8192 /GF /O2 /c LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "emulatorDbg" # PROP BASE Intermediate_Dir "emulatorDbg" # PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "emulatorDbg" # PROP Intermediate_Dir "emulatorDbg" # PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Target_Dir "" CPP=cl.exe # ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_LIB" /YX /Gs8192 /GF /c # ADD CPP /nologo /W3 /Zi /Od /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "DEBUG" /D "_i386_" /D "_X86_" /D "x86" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /Gs8192 /GF /c LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ARMV4Rel" # PROP BASE Intermediate_Dir "ARMV4Rel" # PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ARMV4Rel" # PROP Intermediate_Dir "ARMV4Rel" # PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Target_Dir "" CPP=clarm.exe # ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "NDEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /O2 /M$(CECrtMT) /c # ADD CPP /nologo /W3 /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "NDEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /FR /YX /O2 /M$(CECrtMT) /c LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "ARMV4Dbg" # PROP BASE Intermediate_Dir "ARMV4Dbg" # PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "ARMV4Dbg" # PROP Intermediate_Dir "ARMV4Dbg" # PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Target_Dir "" CPP=clarm.exe # ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /M$(CECrtMTDebug) /c # ADD CPP /nologo /W3 /Zi /Od /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /M$(CECrtMTDebug) /c LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo !ENDIF # Begin Target # Name "Norm - Win32 (WCE emulator) Release" # Name "Norm - Win32 (WCE emulator) Debug" # Name "Norm - Win32 (WCE ARMV4) Release" # Name "Norm - Win32 (WCE ARMV4) Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\common\galois.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_GALOI=\ "..\common\galois.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_GALOI=\ "..\common\galois.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_GALOI=\ "..\common\galois.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_GALOI=\ "..\common\galois.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normApi.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMA=\ "..\common\normApi.h"\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMA=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMA=\ "..\common\normApi.h"\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMA=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMA=\ "..\common\normApi.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoBitmask.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMA=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMA=\ "..\common\normApi.h"\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMA=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normEncoder.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORME=\ "..\common\galois.h"\ "..\common\normEncoder.h"\ "..\common\normMessage.h"\ "..\protolib\common\debug.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORME=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORME=\ "..\common\galois.h"\ "..\common\normEncoder.h"\ "..\common\normMessage.h"\ "..\protolib\common\debug.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORME=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORME=\ "..\common\galois.h"\ "..\common\normEncoder.h"\ "..\common\normMessage.h"\ "..\protolib\common\debug.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORME=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORME=\ "..\common\galois.h"\ "..\common\normEncoder.h"\ "..\common\normMessage.h"\ "..\protolib\common\debug.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORME=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normFile.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMF=\ "..\common\normFile.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMF=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMF=\ "..\common\normFile.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMF=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMF=\ "..\common\normFile.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMF=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMF=\ "..\common\normFile.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMF=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normMessage.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMM=\ "..\common\normMessage.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMM=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMM=\ "..\common\normMessage.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMM=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMM=\ "..\common\normMessage.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMM=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMM=\ "..\common\normMessage.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMM=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normNode.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMN=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMN=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMN=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMN=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMN=\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoBitmask.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMN=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMN=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMN=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normObject.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMO=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMO=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMO=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMO=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMO=\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoBitmask.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMO=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMO=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMO=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normSegment.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMS=\ "..\common\normBitmask.h"\ "..\common\normMessage.h"\ "..\common\normSegment.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMS=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMS=\ "..\common\normBitmask.h"\ "..\common\normMessage.h"\ "..\common\normSegment.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMS=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMS=\ "..\common\normMessage.h"\ "..\common\normSegment.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoBitmask.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMS=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMS=\ "..\common\normBitmask.h"\ "..\common\normMessage.h"\ "..\common\normSegment.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMS=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\common\normSession.cpp !IF "$(CFG)" == "Norm - Win32 (WCE emulator) Release" DEP_CPP_NORMSE=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMSE=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE emulator) Debug" DEP_CPP_NORMSE=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMSE=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Release" DEP_CPP_NORMSE=\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoBitmask.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMSE=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "Norm - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMSE=\ "..\common\normBitmask.h"\ "..\common\normEncoder.h"\ "..\common\normFile.h"\ "..\common\normMessage.h"\ "..\common\normNode.h"\ "..\common\normObject.h"\ "..\common\normSegment.h"\ "..\common\normSession.h"\ "..\protolib\common\protoAddress.h"\ "..\protolib\common\protoApp.h"\ "..\protolib\common\protoChannel.h"\ "..\protolib\common\protoDebug.h"\ "..\protolib\common\protoDefs.h"\ "..\protolib\common\protoDispatcher.h"\ "..\protolib\common\protokit.h"\ "..\protolib\common\protoPipe.h"\ "..\protolib\common\protoRouteMgr.h"\ "..\protolib\common\protoRouteTable.h"\ "..\protolib\common\protoSocket.h"\ "..\protolib\common\protoTimer.h"\ "..\protolib\common\protoTree.h"\ "..\protolib\common\protoVersion.h"\ "..\protolib\win32\tpipv6.h"\ "..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMSE=\ "..\protolib\common\config.h"\ "..\protolib\common\ip_addr_v4.h"\ "..\protolib\common\nsProtoSimAgent.h"\ "..\protolib\common\opnet.h"\ "..\protolib\common\scheduler.h"\ !ENDIF # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=..\common\normFile.h # End Source File # End Group # End Target # End Project norm-1.5.8+dfsg2/makefiles/wince/Norm.vcw0000644000000000000000000000213210231013410015047 0ustar Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Norm"=.\Norm.vcp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Project: "Protokit"=..\protolib\wince\Protokit.vcp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Project: "normApp"=.\normApp\normApp.vcp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ Begin Project Dependency Project_Dep_Name Norm End Project Dependency Begin Project Dependency Project_Dep_Name Protokit End Project Dependency }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### norm-1.5.8+dfsg2/makefiles/wince/normApp/0000755000000000000000000000000013320270771015052 5ustar norm-1.5.8+dfsg2/makefiles/wince/normApp/normApp.vcp0000644000000000000000000003640510231013410017167 0ustar # Microsoft eMbedded Visual Tools Project File - Name="normApp" - Package Owner=<4> # Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02 # ** DO NOT EDIT ** # TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301 # TARGTYPE "Win32 (WCE emulator) Application" 0xa601 CFG=normApp - Win32 (WCE emulator) Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "normApp.vcn". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "normApp.vcn" CFG="normApp - Win32 (WCE emulator) Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "normApp - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application") !MESSAGE "normApp - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application") !MESSAGE "normApp - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application") !MESSAGE "normApp - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" # PROP ATL_Project 2 !IF "$(CFG)" == "normApp - Win32 (WCE emulator) Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "emulatorRel" # PROP BASE Intermediate_Dir "emulatorRel" # PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "emulatorRel" # PROP Intermediate_Dir "emulatorRel" # PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" RSC=rc.exe # ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r # ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r CPP=cl.exe # ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c # ADD CPP /nologo /W3 /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "_i386_" /D "i_386_" /D "_X86_" /D "x86" /D "NDEBUG" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /Gs8192 /GF /O2 /c MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86 # ADD LINK32 $(CEx86Corelibc) ws2.lib iphlpapi.lib commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86 !ELSEIF "$(CFG)" == "normApp - Win32 (WCE emulator) Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "emulatorDbg" # PROP BASE Intermediate_Dir "emulatorDbg" # PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "emulatorDbg" # PROP Intermediate_Dir "emulatorDbg" # PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" RSC=rc.exe # ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r # ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r CPP=cl.exe # ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c # ADD CPP /nologo /W3 /Zi /Od /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "DEBUG" /D "_i386_" /D "i_386_" /D "_X86_" /D "x86" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /Gs8192 /GF /c MTL=midl.exe # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86 # ADD LINK32 $(CEx86Corelibc) ws2.lib iphlpapi.lib commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86 !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ARMV4Rel" # PROP BASE Intermediate_Dir "ARMV4Rel" # PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ARMV4Rel" # PROP Intermediate_Dir "ARMV4Rel" # PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" RSC=rc.exe # ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r # ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r CPP=clarm.exe # ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /YX /O2 /M$(CECrtMT) /c # ADD CPP /nologo /W3 /I "..\..\common" /I "..\..\protolib\common" /I "..\..\protolib\win32" /D "ARM" /D "_ARM_" /D "ARMV4" /D "NDEBUG" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /O2 /M$(CECrtMT) /c MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM # ADD LINK32 ws2.lib iphlpapi.lib commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "ARMV4Dbg" # PROP BASE Intermediate_Dir "ARMV4Dbg" # PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "ARMV4Dbg" # PROP Intermediate_Dir "ARMV4Dbg" # PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" # PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" RSC=rc.exe # ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r # ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r CPP=clarm.exe # ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /YX /M$(CECrtMTDebug) /c # ADD CPP /nologo /W3 /Zi /Od /I "..\common" /I "..\protolib\common" /I "..\protolib\win32" /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D "WIN32" /D "PROTO_DEBUG" /D "HAVE_ASSERT" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /U "UNIX" /U "HAVE_IPV6" /U "SIMULATE" /U "NS2" /U "OPNET" /YX /M$(CECrtMTDebug) /c MTL=midl.exe # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM # ADD LINK32 ws2.lib iphlpapi.lib commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM !ENDIF # Begin Target # Name "normApp - Win32 (WCE emulator) Release" # Name "normApp - Win32 (WCE emulator) Debug" # Name "normApp - Win32 (WCE ARMV4) Release" # Name "normApp - Win32 (WCE ARMV4) Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\..\common\normApp.cpp !IF "$(CFG)" == "normApp - Win32 (WCE emulator) Release" DEP_CPP_NORMA=\ "..\..\common\normBitmask.h"\ "..\..\common\normEncoder.h"\ "..\..\common\normFile.h"\ "..\..\common\normMessage.h"\ "..\..\common\normNode.h"\ "..\..\common\normObject.h"\ "..\..\common\normPostProcess.h"\ "..\..\common\normSegment.h"\ "..\..\common\normSession.h"\ NODEP_CPP_NORMA=\ "..\..\common\protoDefs.h"\ "..\..\common\protokit.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE emulator) Debug" DEP_CPP_NORMA=\ "..\..\common\normBitmask.h"\ "..\..\common\normEncoder.h"\ "..\..\common\normFile.h"\ "..\..\common\normMessage.h"\ "..\..\common\normNode.h"\ "..\..\common\normObject.h"\ "..\..\common\normPostProcess.h"\ "..\..\common\normSegment.h"\ "..\..\common\normSession.h"\ NODEP_CPP_NORMA=\ "..\..\common\protoDefs.h"\ "..\..\common\protokit.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Release" DEP_CPP_NORMA=\ "..\..\common\normEncoder.h"\ "..\..\common\normFile.h"\ "..\..\common\normMessage.h"\ "..\..\common\normNode.h"\ "..\..\common\normObject.h"\ "..\..\common\normPostProcess.h"\ "..\..\common\normSegment.h"\ "..\..\common\normSession.h"\ "..\..\protolib\common\protoAddress.h"\ "..\..\protolib\common\protoApp.h"\ "..\..\protolib\common\protoBitmask.h"\ "..\..\protolib\common\protoChannel.h"\ "..\..\protolib\common\protoDebug.h"\ "..\..\protolib\common\protoDefs.h"\ "..\..\protolib\common\protoDispatcher.h"\ "..\..\protolib\common\protokit.h"\ "..\..\protolib\common\protoPipe.h"\ "..\..\protolib\common\protoRouteMgr.h"\ "..\..\protolib\common\protoRouteTable.h"\ "..\..\protolib\common\protoSocket.h"\ "..\..\protolib\common\protoTimer.h"\ "..\..\protolib\common\protoTree.h"\ "..\..\protolib\common\protoVersion.h"\ "..\..\protolib\win32\tpipv6.h"\ "..\..\protolib\win32\wspiapi.h"\ {$(INCLUDE)}"basetsd.h"\ {$(INCLUDE)}"guiddef.h"\ NODEP_CPP_NORMA=\ "..\..\protolib\common\config.h"\ "..\..\protolib\common\ip_addr_v4.h"\ "..\..\protolib\common\nsProtoSimAgent.h"\ "..\..\protolib\common\opnet.h"\ "..\..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMA=\ "..\..\common\normBitmask.h"\ "..\..\common\normEncoder.h"\ "..\..\common\normFile.h"\ "..\..\common\normMessage.h"\ "..\..\common\normNode.h"\ "..\..\common\normObject.h"\ "..\..\common\normPostProcess.h"\ "..\..\common\normSegment.h"\ "..\..\common\normSession.h"\ NODEP_CPP_NORMA=\ "..\..\common\protoDefs.h"\ "..\..\common\protokit.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\..\common\normPostProcess.cpp !IF "$(CFG)" == "normApp - Win32 (WCE emulator) Release" DEP_CPP_NORMP=\ "..\..\common\normPostProcess.h"\ NODEP_CPP_NORMP=\ "..\..\common\protoDebug.h"\ "..\..\common\protoDefs.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE emulator) Debug" DEP_CPP_NORMP=\ "..\..\common\normPostProcess.h"\ NODEP_CPP_NORMP=\ "..\..\common\protoDebug.h"\ "..\..\common\protoDefs.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Release" DEP_CPP_NORMP=\ "..\..\common\normPostProcess.h"\ "..\..\protolib\common\protoDebug.h"\ "..\..\protolib\common\protoDefs.h"\ {$(INCLUDE)}"basetsd.h"\ NODEP_CPP_NORMP=\ "..\..\protolib\common\opnet.h"\ "..\..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Debug" DEP_CPP_NORMP=\ "..\..\common\normPostProcess.h"\ NODEP_CPP_NORMP=\ "..\..\common\protoDebug.h"\ "..\..\common\protoDefs.h"\ !ENDIF # End Source File # Begin Source File SOURCE=..\..\win32\win32PostProcess.cpp !IF "$(CFG)" == "normApp - Win32 (WCE emulator) Release" NODEP_CPP_WIN32=\ "..\..\win32\normPostProcess.h"\ "..\..\win32\protoDebug.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE emulator) Debug" NODEP_CPP_WIN32=\ "..\..\win32\normPostProcess.h"\ "..\..\win32\protoDebug.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Release" DEP_CPP_WIN32=\ "..\..\common\normPostProcess.h"\ "..\..\protolib\common\protoDebug.h"\ "..\..\protolib\common\protoDefs.h"\ {$(INCLUDE)}"basetsd.h"\ NODEP_CPP_WIN32=\ "..\..\protolib\common\opnet.h"\ "..\..\protolib\common\scheduler.h"\ !ELSEIF "$(CFG)" == "normApp - Win32 (WCE ARMV4) Debug" NODEP_CPP_WIN32=\ "..\..\win32\normPostProcess.h"\ "..\..\win32\protoDebug.h"\ !ENDIF # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project norm-1.5.8+dfsg2/protolib/0000755000000000000000000000000013325321451012220 5ustar norm-1.5.8+dfsg2/protolib/BUILD.TXT0000644000000000000000000000351611726221527013473 0ustar Building Protolib ================= Protolib can be built using the Waf build tool, included in the distribution. To see a full list of options, run: ./waf -h Configuring ----------- To perform the configure checks, run: ./waf configure Some options for the configure step: --prefix=

- Directory to install files to (Default - /usr/local) --debug - Builds a debug build (with debugging symbols), otherwise an optimized library is built. --build-python - Builds the Python extension (*see notes for building protolib python bindings via setup.py outside w/out waf) --build-java - Builds the Java extension You must set the JAVA_HOME environment variable to the location of your JDK directory Waf has issues building the java extensions with OpenJDK. Oracle JDK is recommended. Building -------- To build the library, simply run: ./waf To build examples along with the library, run: ./waf --targets=ex1,ex2,... Where ex1,ex2 is the name of the example you want to build (see ./waf list). Additionally, you can add the "--targets=*" flag to build all the example programs. Installing ---------- To install, run: ./waf install This will install the compiled library and headers to wherever your prefix was specified. (See configure flags) Uninstalling ------------ Waf tracks the files it installs, so run: ./waf uninstall to remove all files from a previous ./waf install Cleaning -------- ./waf clean will delete all compiled files and configuration settings. ./waf distclean will do the same as clean, and additionally delete the waf cache files. Building protolib python bindings without waf --------------------------------------------- Build protolib (make -f Makefile.) python setup.py install (build & install protolib python bindings)norm-1.5.8+dfsg2/protolib/LICENSE.TXT0000644000000000000000000000235512153446220013710 0ustar /********************************************************************* * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution. * * "This product includes software written and developed * by Code 5520 of the Naval Research Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * ********************************************************************/norm-1.5.8+dfsg2/protolib/README.TXT0000644000000000000000000001745213124266656013603 0ustar Protean Protocol Prototyping Library (PROTOLIB) OVERVIEW Protolib is not so much a library as it is a toolkit. The goal of the Protolib is to provide a set of simple, cross-platform C++ classes that allow development of network protocols and applications that can run on different platforms and in network simulation environments. Although Protolib is principally for research purposes, the code has been constructed to provide robust, efficient performance and adaptability to real applications. Currently Protolib supports most Unix platforms (including MacOS X) and WIN32 platforms. The most recent version also supports building Protolib-based code for the ns-2 simulation environment. The OPNET simulation tool has also been supported in the past and could be once again with a small amount of effort. CLASSES: ProtoAddress: Network address container class with support for IPv4, IPv6, and "SIM" address types. Also includes functions for name/address resolution. ProtoSocket: Network socket container class that provides consistent interface for use of operating system (or simulation environment) transport sockets. Provides support for asynchronous notification to ProtoSocket::Listeners. The ProtoSocket class may be used stand-alone, or with other classes described below. A ProtoSocket may be instantiated as either a UDP or TCP socket. ProtoTimer: This is a generic timer class which will notify a ProtoTimer::Listener upon timeout. ProtoTimerMgr: This class manages ProtoTimer instances when they are "activated". The ProtoDispatcher (below) derives from this to manage ProtoTimers for an application. (The ProtoSimAgent base class contains a ProtoTimerMgr to similarly manage timers for a simulation instance). ProtoTree: Flexible implementation of a Patricia tree data structure. Includes a ProtoTree::Item which may be derived from or used as a container for whatever data structures and application may require. ProtoRouteTable: Class based on the ProtoTree Patricia tree to store routing table information. Uses the ProtoAddress class to store network routing addresses. It's a pretty dumbed-down routing table at the moment, but may be enhanced in the future. Example use of the ProtoTree. ProtoRouteMgr: Base class for providing a conistent interface to manage operating system (or other) routing engines. ProtoPipe: Socket-like mechanism (with both datagram and stream support) useful for interprocess communications (uses Unix domain sockets on Unix, other stuff on Win32 & WinCE) ProtoCap: Interface class for raw MAC-layer packet capture. Platform implementations of this class vary including a "pcap" based implementation. ProtoDetour: Inbound/outbound packet _interception_ class. Platform implementations vary ... works with firewall stuff. Win32 version based around NDIS intermediate driver in progress. ProtoDispatcher: This class provides a core around which Unix and Win32 applications using Protolib can be implemented. It's "Run()" method provides a "main loop" which uses the "select()" system call on Unix and the similar "MsgWaitForMultipleObjectsEx()" system call on Win32. It is planned to eventually provide some built-in support for threading in the future (e.g. the ProtoDispatcher::Run() method might execute in a thread, dispatching events to a parent thread). ProtoApp: Provides a base class for implementing Protolib-based command-line applications. Note that "ProtoApp" and "ProtoSimAgent" are designed such that subclasses can be derived from either to reuse the same code in either a real-world applications or as an "agent" (entity) within a network simulation environment (e.g. ns-2, OPNET). A "background" command is included for Win32 to launch the app without a terminal window. ProtoSimAgent: Base class for simulation agent derivations. Currently an ns-2 agent base class is derived from this, but it is possible that other simulation environments (e.g. OPNET, Qualnet) might be supported in a similar fashion. NsProtoSimAgent: Simulation agent base class for creating ns-2 instantiations of Protolib-based network protocols and applications. ProtoExample: Example class which derives either from ProtoApp or NsProtoSimAgent, depending upon compile-time macro definitions. It provides equivalent functionality in either the simulation environment or as a real-world command-line application. It demonstrates the use/operation of ProtoSocket based UDP transmission/reception, a ProtoTimer, and an example ProtoSocket-based TCP client-server exchange. (NOTE: TCP operation is not yet supported in the simulation environment. This will completed in coming months. I plan to extend ns-2 TCP agents to support actual transfer of user data to support this.) NsProtoTCPSocketAgent: TCP implementation of the NSSocketProxy class for providing TCP support within Protolib. This class provides a hub for interfacing with the underlying TCP toolkit for providing access to the TCP support. NsProtoTCPSocketAgent essentially auto-detects which sockets it should be (i.e. a client or a server) and then instantiates the underlying implementations in order to provide that behaviour, which are either a TCPSocketAgent or a TCPServerSocketAgent: TCPSocketAgent: The TCP socket agent implementation that can be used for clients and that can be used as the socket responsible for the server-side of the connection after a call to accept. TCPServerSocketAgent: The TCP server implementation that only implements part of the TCP protocol (by listening for the initial SYN connection requests from clients). The server simply acts as a broker for assigning TCPSocketAgents when clients request connections, either by creating the sockets itself or by sending an ACCEPT event to the application in order for it to create the socket and call the accept function manually. The latter approach is the norm. OTHER: The Protolib code also includes some simple, general purpose debugging routines which can output to "stderr" or optionally log to a specified file. See "protoDebug.h" for details. There are also some supporting classes not described here and some work to be done. For example, the ProtoRouteMgr includes implementations for Linux and BSD (incl. MacOS), but not yet for WIN32 (This is work in progress). Also, more complete documentation, including Doxygen-based code documentation and a "Developer's Guide" with examples needs to be provided. Brian Adamson 26 June 2017 norm-1.5.8+dfsg2/protolib/TODO.TXT0000644000000000000000000000117413124267556013405 0ustar Protolib is a work in progress. Its features reflect the current (and past) needs of our research group. This list is a list of things we might add in the future: 0) Documentation, documentation, documentation!!! Code documentation and "Developers' Guide" materials. 1) Generalize the Mutex stuff used in ProtoDispatcher for general purpose thread synchronization purposes ... 2) Make code truly UNICODE compliant ... In particular, any functions which take/return strings (currently "char*") should instead use "tchar" types/functions as appropriate. Brian Adamson 26 June 2017 norm-1.5.8+dfsg2/protolib/VERSION.TXT0000644000000000000000000000627613146462743013774 0ustar This file provides information on changes to Protolib code indexed by the version number found in the "common/protoVersion.h" file. Serious version tracking was not maintained for Protolib for a long time since it was typically included in full source form in the projects for which it was used and those projects were assumed to maintain configuration control for themselves and the Protolib code they used. Protolib has matured into a more substantial code base and used by multiple projects, so the time has come to provide some additional description of significant changes made. Additionally, the developers will try to provide more timely releases of the Protolib source tree outside of the SVN repository. Version 3.0b2 ============= - Fix to protoTree.h to resolve issue with gcc7 compilation (Thanks to Thomas Petazzoni!) Version 3.0b1 ============= - ProtoDispatcher can now use "epoll()" (Linux), "kqueue()" (BSD), and "/dev/poll" (Solaris), and "pselect()" for enhanced performance over the current use of "select()" Version 2.1b1 ============= - Added "ProtoTime" class that is used by ProtoTimer, etc to provide a basis for time references, manipulations, etc. The scope of ProtoTime will likely be expanded in our quest to eventually provide a standards means to access precision time facilities as they come available to different operating system environments. - The "ManetMsg" implementation of the "draft-ietf-manet-packetbb" specification was updated to Draft Version 13. (Thanks to Ulrich Herberg for this!) - The ns-2 ProtoSocket(TCP) adaption was fixed to be consistent with the real-world behavior of the ProtoSocket(TCP). - Initial support for Doxygen-based documentation of the Protolib code base was integrated. - Fixed WIN32 ProtoDispatcher::BoostPriority() by using THREAD_SET_INFORMATION access level (more portable) Thanks to Renee Carignan! Version 2.0b4 ============= - This was the last version annotation _before_ this tracking file was established. The "2.x" indicates the refactoring of the code after the original miscellaneous collection of C++ classes that became the foundation for the Protolib "toolkit". (aka "Protokit"). With 2.0, the code was written to be far more consistent in design and conventions. The philosophy of the code is to provide a suite of C++ classes where each can be used fairly independently if desired, but also to provide a framework for the suite of classes to be used for experimental protocol implementations, applications. For example, individual classes like "ProtoSocket", "ProtoTimer", etc can be used somewhat independently and/or adapted into other codes or be used with the provided ProtoDispatcher/ ProtoApp "framework" to build simple applications. In some cases (e.g., wxProtoApp), code is provided to allow Protolib components/implementations to be integrated as part other application code. Similarly, the ProtoSimAgent provides a means to adapt Protolib code into discrete event network simulation environments with a relatively small amount of care on the programmers' part. norm-1.5.8+dfsg2/protolib/doc/0000755000000000000000000000000013320271270012763 5ustar norm-1.5.8+dfsg2/protolib/doc/BUILD_RTEMS.TXT0000644000000000000000000000513713124265255015213 0ustar # # README,v 1.2 2002/10/07 19:44:18 joel Exp # Building and Installing MDP & PROTOLIB for RTEMS ===================================== 1. Build and install RTEMS for your BSP with POSIX and networking enabled. The following is a prototypical command sequence that would be used to do this for the mips-rtems target and jmr3904 BSP. mkdir b-rtems cd b-rtems ..../rtems-XXX/configure --target=mips-rtems --enable-rtemsbsp=jmr3904 \ --enable-posix --enable-networking --prefix=/opt/rtems make make install Once this is done, return to this directory and proceed with the MDP build. 2. Set the RTEMS_MAKEFILE_PATH to point to the above BSP. export RTEMS_MAKEFILE_PATH=/opt/rtems/mips-rtems/jmr3904 3. To build the MDP and ProtoLib libraries, perform commands similar to the following: export RTEMS_MAKEFILE_PATH=/opt/rtems/mips-rtems/jmr3904 cd mdp make -f Makefile.rtems libs_only At this point you should have libProto.a and libMdp.a. Copy them to the appropriate BSP specific install point by hand. Integrating NTP Executables Into Your Application ================================================= No RTEMS specific steps are required to use the MDP library. Port Background =============== The RTEMS port is derived from the UNIX source base. The MDP package includes example applications that cannot be built for RTEMS as they depend upon X11 and Tk. Thus the port includes only the MDP communications protocol. The RTEMS port assumes that Protolib and MDP will be built for a particular BSP which has been previously built and installed. Two RTEMS specific sub-Makefiles have been added to the unix/ subdirectory of each package. + Makefile.rtems + Makefile.rtems-sub Makefile.rtems acts as the normal MDP/Protolib adapter. Makefile.rtems-sub acts as a query facility to obtain information from the RTEMS Application Makefile infrastructure. By using this approach, the MDP/Protolib libraries should be able to be compiled for any RTEMS BSP. Protolib/MDP Assembly Instructions ================================== The RTEMS MDP/Protolib tarball was assembled from separate MDP and Protolib tarballs which were combined to provide a unified build process. These instructions are based upon the following versions: src-mdp-1.9a5.tgz src-protolib-1.0a3d.tgz 1. Make a working directory and "cd" into that directory. 2. untar mdp and protolib 3. If mdp/protolib exists and is a symbolic link, then remove it. 4. mv protolib under mdp (mv protolib-1.0 mdp) These results in the following directory structure. ./mdp ./mdp/protolib norm-1.5.8+dfsg2/protolib/doc/README-DOXYGEN0000644000000000000000000000635611214264331014770 0ustar Generating doxygen output on Windows: 1. Make sure the doc/doxygen/Doxyfile configuration file points to the correct location of graphwiz's "dot" exectuable for your system. (DOT_PATH variable) 2. Load the doxygen configuration file (doc/doxygen/Doxyfile) into the doxygen wizard. 3. Start, output will be put in /doc/doxygen/html. Generating doxygen output on Linux: 1. Make sure the doc/doxygen/Doxyfile file points to the correct location of graphwiz's "dot" exectuable for your system. (DOT_PATH variable) 2. Run "doxygen doxyfile", output will be put in /doc/doxygen/html 3. Rumor has it that there is a doxygen wizard (gui) available for linux. ------------------------------------------------------------------------- Supplemental Documentation Supplemental documentation (e.g. Introduction, Summarized class list by category etc. are stored in the doc/doxygen/mainpages directory. How to document classes: /** * @class ClassName * * @brief Enter a brief description of the * class, the first sentence (deliminated by a period) * will be included in the brief description. * * Anything after the first sentence, and included * in the "@class" block will be part of the * detailed description. * * The "@brief" description will be used to * describe the class on the class list. * */ How to document functions: -------------------------- Keep the Doxygen function documentation with the function definition, e.g. in either the .h or the .cpp file. Placing "/**" before the comments will cause Doxygen to generate a link to the function documentation. /** * * @brief Description of the function. Will appear before function * definition. Don't really need "@brief" as JAVADOC_AUTOBRIEF is * turned on. * * @param Defailed parameter text, if needed. Will appear in * separate parameter secion. * * @retval Detailed text about return value, if needed. * */ void someFunc() {} Placing "///" before the comments will cause Doxygen to include the associated text next to the function name in the function listing only. Other Notes: 1. Sometimes the html directory has to be cleared out and the entire doxygen output regenerated if the graphics get screwed up. 2. Need "dot" from graphwiz. In some doxygen implementations it is included. 3. Can generate called/call graphs. To enable or disable call graphs for each function, toggle CALL_GRAPH and CALLER_GRAPH variables in the config file. To enable for specific functions when CALL_GRAPH is set to no, use the @callgraph/@callergraph commands. 4. @sa "See also" alias. @note "Note" alias @exception @class @param @return @retval ProtoGraph::~Vertice has an example of function text and a @note. 5. Can turn off documentation of inherited functions and properties. 8. We are generating documentation from all src files included under the doc tree. This can be changed to include/exclude specific directories. Modify INPUT in config file to add additional code/directories, e.g. INPUT = ../common #Add protolib to the doxygen output #INPUT += ../../protolib/common #To add files #INPUT += ../../protolib/common/protoApp.h ../../protolib/common/protoApp.cppnorm-1.5.8+dfsg2/protolib/doc/README-UNIX.TXT0000644000000000000000000000056713124265255015122 0ustar This directory contains a simple example of a Unix command-line application "protoApp" using the PROTOLIB ProtocolTimer and UdpSocket classes. TO BUILD: type "make protoApp" (Note: The "Makefile" has been tested for Linux using gcc 2.96. It can be easily modified for other platforms or compilers.) Brian Adamson 18 December 2001 norm-1.5.8+dfsg2/protolib/doc/README-WIN32.TXT0000644000000000000000000000103713124265255015132 0ustar This directory contains the VC++ project files for building the PROTOLIB and example "protoApp" command-line project. The VC++ project contains a couple of options to build a Win32 "console" (subsystem:console) or a Win32 "gui" (subsystem:windows) application with a command-line interface. The "gui" version can be easily modified to have no user interface for background processing or as an example to use the PROTOLIB classes in classical GUI Win32 applications. Brian Adamson 18 December 2001 norm-1.5.8+dfsg2/protolib/doc/README-WINCE.TXT0000644000000000000000000000012413124265255015171 0ustar These are project files for Embedded VC++ 4.2 More details will be provided later. norm-1.5.8+dfsg2/protolib/doc/doxygen/0000755000000000000000000000000013320271270014440 5ustar norm-1.5.8+dfsg2/protolib/doc/doxygen/Doxyfile0000755000000000000000000017703711214551564016177 0ustar # Doxyfile 1.5.9 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = Protolib # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 2.1b1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = C:/cygwin/home/ljt/protolib/doc/doxygen # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set # FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = YES # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = doc/doxygen/DoxygenLayout.xml #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = doxygen.log #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ./ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = build # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = ./doc/doxygen/header.html # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = ./doc/doxygen/footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = YES # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = ..\wx.chm # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = hhc.exe # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.wxwidgets.doxygen # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = NONE # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = NO # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO norm-1.5.8+dfsg2/protolib/doc/doxygen/DoxygenLayout.xml0000755000000000000000000001273711210023717020007 0ustar norm-1.5.8+dfsg2/protolib/doc/doxygen/customdoxygen.css0000755000000000000000000001400311210023717020060 0ustar body, table, div, p, dl { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; font-size: 12px; } /* @group Heading Levels */ h1 { text-align: center; font-size: 150%; } h2 { font-size: 120%; } h3 { font-size: 100%; } /* @end */ caption { font-weight: bold; } div.qindex, div.navtab{ background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; padding: 2px; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #153788; font-weight: normal; text-decoration: none; } .contents a:visited { color: #1b77c5; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #6666cc; color: #ffffff; border: 1px double #9295C2; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code { } a.codeRef { } /* @end */ dl.el { margin-left: -1cm; } .fragment { font-family: monospace, fixed; font-size: 105%; } pre.fragment { border: 1px solid #CCCCCC; background-color: #f5f5f5; padding: 4px 6px; margin: 4px 8px 4px 2px; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } div.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background: white; color: black; margin-right: 20px; margin-left: 20px; } td.indexkey { background-color: #e8eef2; font-weight: bold; border: 1px solid #CCCCCC; margin: 2px 0px 2px 0; padding: 2px 10px; } td.indexvalue { background-color: #e8eef2; border: 1px solid #CCCCCC; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #f0f0f0; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } /* @end */ .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #84b0c7; } th.dirtab { background: #e8eef2; font-weight: bold; } hr { height: 0; border: none; border-top: 1px solid #666; } /* @group Member Descriptions */ .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #FAFAFA; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memItemRight, .memTemplParams { border-top: 1px solid #ccc; } .memTemplParams { color: #606060; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #606060; font-weight: normal; margin-left: 3px; } .memnav { background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .memitem { padding: 0; } .memname { white-space: nowrap; font-weight: bold; } .memproto, .memdoc { border: 1px solid #84b0c7; } .memproto { padding: 0; background-color: #d5e1e8; font-weight: bold; -webkit-border-top-left-radius: 8px; -webkit-border-top-right-radius: 8px; -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; } .memdoc { padding: 2px 5px; background-color: #eef3f5; border-top-width: 0; -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; -moz-border-radius-bottomleft: 8px; -moz-border-radius-bottomright: 8px; } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } /* @end */ /* @group Directory (tree) */ /* for the tree view */ .ftvtree { font-family: sans-serif; margin: 0.5em; } /* these are for tree view when used as main index */ .directory { font-size: 9pt; font-weight: bold; } .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } /* The following two styles can be used to replace the root node title with an image of your choice. Simply uncomment the next two styles, specify the name of your image and be sure to set 'height' to the proper pixel height of your image. */ /* .directory h3.swap { height: 110px; background-repeat: no-repeat; background-image: url("../nrlheadbkg.gif"); } .directory h3.swap span { display: none; } */ .directory > h3 { margin-top: 0; } .directory p { margin: 0px; white-space: nowrap; } .directory div { display: none; margin: 0px; } .directory img { vertical-align: -30%; } /* these are for tree view when not used as main index */ .directory-alt { font-size: 100%; font-weight: bold; } .directory-alt h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } .directory-alt > h3 { margin-top: 0; } .directory-alt p { margin: 0px; white-space: nowrap; } .directory-alt div { display: none; margin: 0px; } .directory-alt img { vertical-align: -30%; } /* @end */ address { font-style: normal; color: #333; } norm-1.5.8+dfsg2/protolib/doc/doxygen/footer.html0000755000000000000000000000041711207336636016643 0ustar
Generated on $datetime for $projectname by doxygen $doxygenversion
norm-1.5.8+dfsg2/protolib/doc/doxygen/header.html0000755000000000000000000000047611210023717016565 0ustar $title norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/0000755000000000000000000000000013320271270016404 5ustar norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/building.h0000755000000000000000000000052611214267472020371 0ustar /** @page mainpage_building Building @li @subpage building_with_waf @li @subpage building_with_make @li @subpage building_with_visual_studio @li @subpage building_examples_with_waf @li @subpage building_protolibJni_with_waf (Protolib-Jni is a java native library that allows java applications access to the Protolib ProtoPipe class). */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/buildingExamplesWithWaf.h0000755000000000000000000000366711224450652023366 0ustar /** @page building_examples_with_waf Building Protolib Examples with WAF @li @ref building_with_waf @li @ref building_configuring_waf @li @ref building_the_examples @li @ref building_cleaning
@section building_with_waf Building with WAF Protolib examples can be built using the Waf build tool, included in the distribution. To see a full list of example programs, run: @verbatim ./waf -h @endverbatim
@section building_configuring_waf Configuring WAF To perform the configure checks, run: @verbatim ./waf configure @endverbatim Some options for the configure step: @verbatim --prefix= - Directory to install files to (Default - /usr/local) --debug - Builds a debug build (with debugging symbols), otherwise an optimized library is built. --static - Builds a statically linked library, otherwise a shared library is built. --build-python - Builds the Python ProtoPipe extension --build-java - Builds the Java ProtoPipe extension You must set the JAVA_HOME environment variable to the location of your JDK directory --build-ns3 - Builds the NS3 extensions You must set the NS3_HOME environment variable to the location of your NS3 directory --disable-X - Disables the feature X (See ./waf -h for descriptions) @endverbatim
@section building_the_examples Building the Examples To build all the examples, simply run: @verbatim ./waf -ex-all @endverbatim To build a specific example, run: @verbatim ./waf --ex-XXX @endverbatim Where XXX is the name of the example you want to build (see ./waf -h).
@section building_cleaning Cleaning @verbatim ./waf clean @endverbatim will delete all compiled files and configuration settings. @verbatim ./waf distclean @endverbatim will do the same as clean, and additionally delete the waf cache files. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/buildingProtolibJNI.h0000755000000000000000000000172511224450652022442 0ustar /** @page building_protolibJni_with_waf Building ProtolibJni with WAF
@section building_protolibJni_with_waf Building ProtolibJni ProtolibJNI is a java native library that allows java applications access to the Protolib ProtoPipe class. The source code is available in the protolib/src/java directory. To build the library, you may find it helpful to load the protolib project into Visual Studio (see @ref building_with_vs) and open a Visual Studio command so that the correct environment variables are set. First clean the distribution using waf distclean: @verbatim waf distclean @endverbatim Next configure waf to build the protolibJni library, dll, and jar files: @verbatim waf configure --disable-wx --disable-vif --disable-manet --static --build-java @endverbatim Now build the library: @verbatim waf @endverbatim The ProtolibJni.dll, ProtolibJni.jar, and ProtolibJni.lib files will be created in the build/default directory. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/buildingWithMake.h0000755000000000000000000000160611211314301022000 0ustar /** @page building_with_make Building Protolib with Make @li @ref building_with_make @li @ref building_with_make_the_library @li @ref building_with_make_cleaning
@section building_with_make Building Protolib with Make Protolib can be built using the Make build tool. Makefile configuration files for a variety of platforms are included in the distribution in the makefiles directory.
@section building_with_make_the_library Building the Library To build the library, simply run: @verbatim make -f Makefile. @endverbatim To build examples along with the library, run: @verbatim make -f Makefile. @endverbatim Where XXX is the name of the example you want to build.
@section building_with_make_cleaning Cleaning @verbatim make -f Makefile. clean @endverbatim will delete all compiled files. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/buildingWithVisualStudio.h0000755000000000000000000000120611211314301023552 0ustar /** @page building_with_visual_studio Building Protolib with Visual Studio @li @ref building_with_vs
@section building_with_vs Building Protolib with Visual Studio Visual Studio solution files for building protolib are included in the distribution in the protolib/makefiles/win32 directory. Load the appropriate solution file into Visual Studio (project files for Visual Studio 2008 Express and Pro Editions are provided) and configure VS to build either a Debug or Release version of the library. The library will be placed in the protolib/makefiles/win32/Release or protolib/makefiles/Debug as appropriate. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/buildingWithWaf.h0000755000000000000000000000472511214267472021670 0ustar /** @page building_with_waf Building Protolib with WAF @li @ref building_with_waf @li @ref building_configuring_waf @li @ref building_the_library @li @ref building_installing @li @ref building_uninstalling @li @ref building_cleaning
@section building_with_waf Building Protolib with WAF Protolib can be built using the Waf build tool, included in the distribution. To see a full list of options, run: @verbatim ./waf -h @endverbatim
@section building_configuring_waf Configuring WAF To perform the configure checks, run: @verbatim ./waf configure @endverbatim Some options for the configure step: @verbatim --prefix= - Directory to install files to (Default - /usr/local) --debug - Builds a debug build (with debugging symbols), otherwise an optimized library is built. --static - Builds a statically linked library, otherwise a shared library is built. --build-python - Builds the Python ProtoPipe extension --build-java - Builds the Java ProtoPipe extension You must set the JAVA_HOME environment variable to the location of your JDK directory --build-ns3 - Builds the NS3 extensions You must set the NS3_HOME environment variable to the location of your NS3 directory --disable-X - Disables the feature X (See ./waf -h for descriptions) @endverbatim
@section building_the_library Building the Library To build the library, simply run: @verbatim ./waf @endverbatim To build examples along with the library, run: @verbatim ./waf --ex-XXX @endverbatim Where XXX is the name of the example you want to build (see ./waf -h). Additionally, you can add the --ex-all flag to build all the example programs.
@section building_installing Installing To install, run: @verbatim ./waf install @endverbatim This will install the compiled library and headers to wherever your prefix was specified. (See configure flags)
@section building_uninstalling Uninstalling Waf tracks the files it installs, so run: @verbatim ./waf uninstall @endverbatim to remove all files from a previous ./waf install
@section building_cleaning Cleaning @verbatim ./waf clean @endverbatim will delete all compiled files and configuration settings. @verbatim ./waf distclean @endverbatim will do the same as clean, and additionally delete the waf cache files. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/class_summary.h0000644000000000000000000001413311214264331021441 0ustar /** @page mainpage_class_sum Summarized Class List by Category This page contains a summarized listing of classes, please see the Class List page for a full listing.
@li @ref mainpage_core_io @li @ref mainpage_pkt_parsing @li @ref mainpage_data_structure @li @ref mainpage_timer_classes @li @ref mainpage_application @li @ref mainpage_helper_classes @li @ref mainpage_manet

@section mainpage_core_io I/O Classes The following are the Protolib I/O Classes @li ProtoCap Interface class for raw MAC-layer packet capture. Platform implementations of this class vary. @li PcapCap An implementation of the ProtoCap class using "libpcap" for packet capture. @li ProtoDetour Inbound/outbound packet _interception_ class. Platform implementations vary ... but generally leverages system firewall interfaces. A Win32 version based around NDIS intermediate driver is in progress. @li ProtoChannel Base class for hooking into asynchronouse I/O (via Unix file descriptors or WIN32 HANDLEs). Used as a base class for ProtoPipe, ProtoDetour, ProtoCap, etc. @li ProtoPipe Socket-like mechanism (with both datagram and stream support) useful for interprocess communications (uses Unix domain sockets on Unix, other stuff on Win32 & WinCE). @li ProtoSocket Network socket container class that provides consistent interface for use of operating system (or simulation environment) transport sockets. @li ProtoVif Base class providing virtual interfaces support.
@section mainpage_pkt_parsing Packet Parsing These are the classes relevant to packet parsing: @li ProtoPkt Base class for a suite of network protocol packet/message building/parsing classes that provide methods for setting/getting protocol field values to/from a buffer. @li ProtoPktARP Useful for building/parsing ARP packets. @li ProtoPktAUTH IPv6 Authentication Header (AUTH) extension. @li ProtoPktDPD IPv6 Simplified Multicast Forwarding Duplicate Packet Detection (DPD) option. @li ProtoPktESP IPv6 Encapsulating Security Protocol (ESP) header. @li ProtoPktETH This class provides access to and control of ETHernet header fields for the associated buffer space. @li ProtoPktFRAG Builds IPv6 FRAG extension. @li ProtoPktIP Classes are provided for building/parsing IPv4 and IPv6 packets to/from a buffer space. @li ProtoPktRTP Useful for building/parsing Real-Time Protocol(RTP), RFC3550, messages. @li ProtoPktUDP Parses UDP Packets
@section mainpage_data_structure Data Structures @li ProtoList This class provides a simple double linked-list class with a ProtoList::Item base class to use for deriving your own classes you wish to store in a ProtoList. @li ProtoGraph Base class for managing graph data structures. @li ProtoRouteMgr Base class used to provide a common interface to system (or other external) router tables. Implementations for Linux, BSD (incl. MacOS), and Win32/WinCE are included. Implementations for other routing/forwarding daemons like Quagga or Xorp may be provided in the future. @li ProtoRouteTable Class based on the ProtoTree Patricia tree to store routing table information. Uses the ProtoAddress class to store network routing addresses. It's a pretty dumbed-down routing table at the moment, but may be enhanced in the future. @li ProtoSpace Maintains a set of "nodes" in two dimensional space @li ProtoSlidingMask This class provides space-efficient binary storage. @li ProtoStack The ProtoStack class is like the ProtoList and similarly provides a ProtoStackTemplate that can be used for deriving easier-to- use variants for custom items sub-classed from the ProtoStack::Item. @li ProtoTree Flexible implementation of a Patricia tree data structure. Includes a ProtoTree::Item which may be derived from or used as a container for whatever data structures and application may require.
@section mainpage_timer_classes Timer Classes @li ProtoTime Provides system time conversion routines. @li ProtoTimer A generic timer class which will notify a ProtoTimer::Listener upon timeout. @li ProtoTimerMgr This class manages ProtoTimer instances when they are "activated". The ProtoDispatcher derives from this to manage ProtoTimers for an application. (The ProtoSimAgent base class contains a ProtoTimerMgr to similarly manage timers for a simulation instance).
@section mainpage_application Application Classes @li ProtoApp Base class for implementing protolib-based command-line applications. @li ProtoDispatcher This class provides a core around which Unix and Win32 applications using Protolib can be implemented. @li ProtoDispatcher::Controller Handles dispatching for the ProtoDispatcher @li ProtoSimAgent Provides a base class for developing support for Protolib code in various network simulation environments (e.g. ns-2, OPNET, etc). Contains a ProtoSocket instance that acts as a liason to a corresponding simulation transport "Agent" instance.
@section mainpage_helper_classes Helper Classes @li ProtoAddress Network address container class with support for IPv4, IPv6, ETH, and "SIM" address types. Also includes functions for name/address resolution. @li ProtoAddressList The "ProtoAddressList" helper class uses a Patrica tree (ProtoTree) to keep a listing of addresses. @li ProtoBitmask Classes for managing and manipulating bitmasks to maintain binary state. A "sliding" bitmask class is provided that uses a circular buffer approach to maintain continuing, sequenced state. @li ProtoDebug Set of routines useful for debugging. @li ProtoXmlTree, ProtoXmlNode Classes for parsing and creating XML content.
@section mainpage_manet Manet Classes @li ManetMsg Class that implements the General packet format being developed by the IETF MANET working group (based on ProtoPkt). @li ManetPkt Manet Pakcet parsing class. @li ManetGraph Derived from ProtoGraph and uses ProtoAddress structures to provide a suitable graph structure for keeping and exploring multi-hop network state. Supports a notion of multiple interfaces per node, etc. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/introduction.h0000755000000000000000000002520011211314301021266 0ustar /** @page mainpage_introduction Introduction @li @ref page_introduction_whatis @li @ref page_introduction_key_classes @li @ref page_introduction_downloads @li @ref page_introduction_acknowledgements @li @ref page_introduction_authorization
@section page_introduction_whatis What is Protolib? The Protean Protocol Prototyping Library (ProtoLib) is a cross-platform C/C++ library that allows applications to be built while supporting a variety of platforms including Linux, Windows, WinCE/PocketPC, MacOS, FreeBSD, Solaris, etc as well as the simulation environments of NS2 and Opnet. Protolib is not so much a library as it is a toolkit. "Protokit" is a term we have gravitated towards. In either case, the goal of the Protolib is to provide a set of simple, cross-platform C++ classes that allow development of network protocols and applications that can run on different platforms and in network simulation environments. While Protolib provides an overall framework for developing working protocol implementations, applications, and simulation modules, the individual classes are designed for use as stand-alone components when possible. Although Protolib is principally for research purposes, the code has been constructed to provide robust, inefficient performance and adaptability to real applications. In some cases, the code consists of data structures, etc useful in protocol implementations and, in other cases, provides common, cross-platform interfaces to system services and functions (e.g., sockets, timers, routing tables, etc). Currently Protolib supports most Unix platforms (including MacOS X) and WIN32 platforms. The most recent version also supports building Protolib-based code for the ns-2 and OPNET simulation environments. Some code is also provided to allow code based on Protolib to be used in a wxWidgets application. The wxWidgets project is a cross-platform graphical user interface (GUI) toolkit for creating applications using the C++ programming language. We have used wxWidgets for providing graphical user interfaces for some of our prototype network applications. A java native interface for ProtoPipe is included as well.
@section page_introduction_key_classes Some of the classes available This table provides a listing and explanation of many of the classes contained in Protolib. Work is in progress to create and embed Doxygen-based documentation within the Protolib source code tree. @li ProtoAddress: Network address container class with support for IPv4, IPv6, ETH, and "SIM" address types. Also includes functions for name/address resolution. @li ProtoSocket: Network socket container class that provides consistent interface for use of operating system (or simulation environment) transport sockets. Provides support for synchronous notification to ProtoSocket::Listeners. The ProtoSocket class may be used stand-alone, or with other classes described below. A ProtoSocket may be instantiated as either a UDP or TCP socket. @li ProtoTimer This is a generic timer class which will notify a ProtoTimer::Listener upon timeout. @li ProtoTimerMgr This class manages ProtoTimer instances when they are "activated". The ProtoDispatcher(see below) derives from this to manage ProtoTimers for an application. (The ProtoSimAgent base class contains a ProtoTimerMgr to similarly manage timers for a simulation instance). @li ProtoTree Flexible implementation of a Patricia tree data structure. Includes a ProtoTree::Item which may be derived from or used as a container for whatever data structures and application may require. @li ProtoRouteTable Class based on the ProtoTree Patricia tree to store routing table information. Uses the ProtoAddress class to store network routing addresses. It's a pretty dumbed-down routing table at the moment, but may be enhanced in the future. @li ProtoRouteMgr Base class used to provide a common interface to system (or other external) router tables. Implementations for Linux, BSD (incl. MacOS), and Win32/WinCE are included. Implementations for other routing/forwarding daemons like Quagga or Xorp may be provided in the future. @li ProtoPkt Base class for a suite of network protocol packet/message building/parsing classes that provide methods for setting/getting protocol field values to/from a buffer. @li ProtoPktIP Classes are provided for building/parsing IPv4 and IPv6 packets to/from a buffer space. A ProtoPktUDP class is also provided. @li ProtoPktETH This class that provides access to and control of ETHernet header fields for the associated buffer space. @li ProtoPktARP Useful for building/parsing ARP packets. @li ProtoPktRTP Useful for building/parsing Real-Time Protocol (RTP), RFC3550, messages. @li ProtoGraph Base class for managing graph data structures. @li ManetMsg Class that implements the General packet format being developed by the IETF MANET working group (based on ProtoPkt). @li ManetGraph Derived from ProtoGraph and uses ProtoAddress structures to provide a suitable graph structure for keeping and exploring multi-hop network state. Supports a notion of multiple interfaces per node, etc. @li ProtoBitmask Classes for managing and manipulating bitmasks to maintain binary state. A "sliding" bitmask class is provided that uses a circular buffer approach to maintain continuing, sequenced state. @li ProtoXml Classes for parsing and creating XML content. @li ProtoPipe Socket-like mechanism (with both datagram and stream support) useful for interprocess communications (uses Unix domain sockets on Unix, other stuff on Win32 & WinCE) @li ProtoCap Interface class for raw MAC-layer packet capture. Platform implementations of this class vary including a "libpcap" based implementation. @li ProtoVif Base class providing interface support for virtual interfaces. @li ProtoDetour Inbound/outbound packet _interception_ class. Platform implementations vary ... but generally leverages system firewall interfaces. A Win32 version based around NDIS intermediate driver is in progress. @li ProtoChannel Base class for hooking into asynchronous I/O (via Unix file descriptors or Win32 HANDLEs). Used as base class for ProtoPipe, ProtoDetour, ProtoCap, etc (ProtoSocket is currently an exception here because of distinction of SOCKETs vs. HANDLEs on Win32 platforms - This may be revisited in the future). @li ProtoDispatcher This class provides a core around which Unix and Win32 applications using Protolib can be implemented. It's "Run()" method provides a "main loop" which uses the "select()" system call on Unix and the similar "MsgWaitForMultipleObjectsEx()" system call on Win32. It is planned to eventually provide some built-in support for threading in the future (e.g. the ProtoDispatcher::Run() method might execute in a thread, dispatching events to a parent thread). @li ProtoApp Provides a base class for implementing Protolib-based command-line applications. Note that "ProtoApp" and "ProtoSimAgent" are designed such that subclasses can be derived from either to reuse the same code in either a real-world applications or as an "agent" (entity) within a network simulation environment (e.g. ns-2, OPNET). Also note a built-in "background" command is included for Win32 to launch the app without a terminal window. @li wxProtoApp Base class that can be used to create applications using Protolib components and the wxWidgets GUI toolkit. @li ProtoSimAgent Base class for simulation agent derivations. Currently an ns-2 agent base class is derived from this, but it is possible that other simulation environments (e.g. OPNET, Qualnet) might be supported in a similar fashion. @li NsProtoSimAgent Simulation agent base class for creating ns-2 instantiations of Protolib-based network protocols and applications. @li OpnetProtoSimProcess Simulation process base class for creating OPNET instantiations of Protolib-based network protocols and applications. @li ProtoExample Example class which derives either from ProtoApp or NsProtoSimAgent, depending upon compile-time macro definitions. It provides equivalent functionality in either the simulation environment or as a real-world command-line application. It demonstrates the use/operation of ProtoSocket based UDP transmission/reception, a ProtoTimer, and an example ProtoSocket-based TCP client-server exchange. (NOTE: Protolib TCP operation is not yet supported in the ns-2 simulation environment. This will completed in the near future. The plan is to extend ns-2 TCP agents to support actual transfer of user data to support this.)
@section page_introduction_downloads Downloads Protolib source code is available at: http://downloads.pf.itd.nrl.navy.mil/protolib/. However, it is important to note that the tarballs (other than the "nightly build") are not updated very often and the appropriate version of the Protolib source tree is generally packaged as part of source code distributions for stable releases of other NRL/Protean products. If you are interested in more information about ProtoLib, please contact protolib@pf.itd.nrl.navy.mil. There is also a ProtoLib Users mailing list. This mailing list is monitored by the ProtoLib developer(s).
@section page_introduction_acknowledgements Acknowledgements Protolib was developed by the Networks and Communications Systems Branch of the Naval Research Library by: @li Brian Adamson @li Joe Macker
@section page_introduction_authorization Authorization to Use and Distribute * * AUTHORIZATION TO USE AND DISTRIBUTE * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: * * (1) source code distributions retain this paragraph in its entirety, * * (2) distributions including binary code include this paragraph in * its entirety in the documentation or other materials provided * with the distribution, and * * (3) all advertising materials mentioning features or use of this * software display the following acknowledgment: * * "This product includes software written and developed * by Brian Adamson and Joe Macker of the Naval Research * Laboratory (NRL)." * * The name of NRL, the name(s) of NRL employee(s), or any entity * of the United States Government may not be used to endorse or * promote products derived from this software, nor does the * inclusion of the NRL written and developed software directly or * indirectly suggest NRL or United States Government endorsement * of this product. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ norm-1.5.8+dfsg2/protolib/doc/doxygen/mainpages/mainpage.h0000755000000000000000000000035411214267472020354 0ustar /** @mainpage Protolib Documentation @date May, 2009 @image html ../nrlheadbkg.gif @section manual_user User Documentation: @li @subpage mainpage_introduction @li @subpage mainpage_class_sum @li @subpage mainpage_building */ norm-1.5.8+dfsg2/protolib/doc/doxygen/nrlheadbkg.gif0000755000000000000000000004033511207336636017252 0ustar GIF89a„d÷‹–_¥¥º]̼F†“`Zuh+e“š\ÿÙ4<=ÿÚ355pMÚÉ>ALLŠc|f Aœ¡WèæëQEòÕ7((avuƒx§C.òÒ9ÊÉÖîÑ:Kef&&^tIÿÜ2ʹHĸIѾEêÎ;b""Z9|l£ÿÞ0)iЬšžZ®©RGG„,,fy‹bœ›¶`³°NCWb¨¥U¹±M xqFUôÙ46t‰b¥¤UùÖ633mª¨RPÿà0ÿÕ6$ odÇ»GôòõMáÉ>ÛÚã¡¢VøÙ4¼±M¡¤U..i•‘²00kîÔ7u qåÌ<ÓÒÝæÉ>çÑ:ÿç+tZD”519_ÎÁD¾´Lm‘¯o…bý×5¬«¿žž¸)$_æÏ;Qnh.-^¿µK}aoDCiTSv§¨RQ:‘ÃÂÏ*`ìØ5x'_ßÌ<€`¤£VSÝÇ@¥§T.3^˜–µúøù ¡XüÖ6 ~¨¨TûÙ4‰¬ÞÆA®«Qt-0_ÿÝ2€š#¹µJ·¯O˜]6íëïâÆ@¹´M˜ŸX4A_™˜­ª«Qüúûqü×5¡Ÿ»>=døÜ2áÏ;¯®P [("`ÿÛ3ÿß0ø÷øûà0S¬©S÷Ô7ǸIº²LûÕ6(‚v,(_x''_set,+UûÛ3þüüÿÖ6;z3 @8 E7CC€44o??{77s X**c$$[ÿ×5ÿÖ7GþÖ6àßæÏÎÙcbMLoýÖ7£¥Tÿ×7žŸX~À·IrLñïó½¹GaL—–Zq^ž*._'$^üÝ1üØ3õá/ÿí(CŸ—¸4¡¡¹3!ù,„dÿý H° ÁƒÖZ²Ó'!äÉ0fŠ;SÆdÈ£'äÓš5KŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ =¸äS z‹ŒM‹‚ƒÙ¡CÜD‘â*U8¦[D¯È§CÊK¶¬Ù³hÓª]˶­Û·o—²ˆŽ=°â8¶« "8ší:ÐÇŽ/€=ìY,ÅÔ"!EÁL¹²å˘3kÞ̹³ç”kèÉ0µ‡™^{(¢¸©Ó‹=¢ = 'Õ!Iófe „£÷bŽéaúL¼¸ñãÈ“+_μùÈOLÃ;ˆ)RTTqr(ÊC†ôÿË0ì;HRÒ¡1ðÀ†”(ð™Þ}d ÃçøóëßÏ¿¿ÿÿž­aÇ1y½§Di óÞO ñ† ±Qd°Ã!(E'<!`ðá@D'D¼w×4ò|"€,¶èâ‹0Æ(#~ŸÈ#ÊRàă<̃Â8ˆò*.Ì#…$J#D„ÑIˆ²!_ôððI!É0½e©Ø4öÍ(æ˜d–iæ™hª„ =Æ0ƒƒN„b‰ÉôNDA„} €Å4ÒÌ+îÌò…!N43Þ»\pL|8XÁ!RIÑH”MCXi@™@#ꨤ–jꩨ¦ªêª¬¶êê«°Æÿ*무Öjë­¸æªë®¼öêë¯À+ì°ÄëR à…;Ëìp@iñE¨643 U‡HÑÛ|! –Q<åÆ2äJqÉDt·G#pÀQbXÉPD§PŽ/Åöëï¿,ðÀlðÁ'¬ðÀ,‚RØÓÄ ‡@L*hãFMP¢î4‚B¨ðÐCrøà¬ô°ƒ„Jìr¥Ía DaO$!E×y0 =+¢©/¿ÐüaË?L7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`?ÝÏØd—möÙh§­¶ÙV´íöÛpÇ-÷ÜtËÁÝxç­÷Þ|÷ÿBÂà„nøá…›‚â&4îøãCÞ‚ “·`ùå˜gŽy-pžÃç ‡.z$NÂ騧®:ê,Ð: °Ç.ûì,hP{íä®ûî¼ë¿ÁðÄoüñ@üò4ïüóÐGÿ<ÔWoýõØWÿÃöÜwïý÷à‡¿=ä—oþùè¯ô‰ {à E0ØàD*xÛŒôA ( )t ^ˆ@@ÀyÁ ÐrQ‡C¡Ð7Ì‚%¸‚î²>œ)4à—,&€ˆ°¹ð…0Œ¡ gHÃnmm8Ì¡ËV·úð‡që›ÿ‡(ÄÀpˆK¢ÇÄÈ91r•£å4GÅÍu®s£ËâçJ·º.®îu®£cg»Þ™ñŒÁÞñÖÈÆá-OyÒ‹£›—½:ÚQ|xÌcøÐÇÇ>ª$¤ñ€aƒ ¸‚DQ(@;úÐ )!aƆÀ pD㒘̤&/‰t!  Àuƒ# âhC¶`ßP eb„DÅBÚò–¸Ì¥.½F^úò—À ¦0‡IÌaÞá˜ÈL¦2—‰LU8ó™ÐŒ&4±AÍjZ³šAȦ6·ÉÍnnSà §8Å ‚ršóœè4g ÖÉÎv¦`ðŒ§<ã9…zÚóžõl€>÷ÉÿO}ŽáŸ è?¹@Ђ” ”HhB©ÀІ:´í&JQ |㢽F7ze(ã é ¼AÒ’&á¤(M‚VÊR5°á¥0Õ‚LgªmØT#È©N¹ÁÓžòT@ ªP%€¢õ¨E݆R—ºT8õ©P͆T§:UXõªXͪU‘ÀÕ®z•` «XÇ Ö˜õ¬hEë ÖÊÖ¶ž@p«\çJ׸¦„ÓdBaCl!D˜Ç¤Q‡]`C肼à…M:ö±^Gb]Ð'à "{ƒ\q=ÌOa;„ ¦ ¬‚–çØ¥jWËÚÖºök;Œ­lÙÄÚÿÚ6ˆDÌmn(¸%ú–pŒ[܇+Å(Vñ¸Wôœ³ÈE/:×uУtËxÆêúxjl£v‰÷Æ9z7zv ïõôH^òöñ¼æC‰<ܰ‡7 ¡è€Þ0€ÙT°G¨B†ŽÆ>ö¿†'ϰ¬fpp‚$z0à Š!-Œ&°Q1¯Ͱ†7Ìá\Îöñ½­ˆo«Ûñˆ½ý­oƒK\â¹Uô—+ºæ>·‹`”®ˈ;ëš1ÂÛn» Çï~W¼HfBy—,>ô:ù$h áƒA¢ ®ÀÁ^a(¸ :ˆ†LæÿŠ€gÐÃ.ša€-@éÿ®À,ñ­E ‡¨âƒûùÏ€ôÕ@LhŽøÐ?4±¢õÆ[$ªxÅMl±;EgNÆ4o¬ºë˜vÔõ1±+d!w×ÈFN²x™Ìjï9½&‘3â#…"_hB=êÐŒ Ô€¤@À˜ÉŒê@–¶c R,  ©X†¾0‹ `‡Å°Ã èe4Vð A›ûÜè¾Z1×Íîv “™ðŽ·4ç-ÍkÚ›šÞÌ·¾ƒ0Î~‡3G§;>ςߟB?Þ:| ¸BêЊGT¢(F3ÊQzT¤!-©ISzÒ–²¦1ÿ¥©LoŠSæÔ§>ªÌ‘Jó0õæP͹¨Ês­ú«^ :ÈJt±¦õègu«ÒëÊô¦—nŠÏTÖŠ©X0tpÈ ‚ý"`;8D ƒ^ ! p°Àæ ‚^ô‚{4Ä.‚!ô°@è†zÌbØ‚¡€‚C4’ÞϧB Xˆ#ݼämYèÊ£ ј§Û¢7b?ÒŒ“4‹[iK_Ó™ݦ9ͺè~zv¡uï€\jížÕÞUux[Íû¼ú¼$‘Ǥ"u¼AD¨ƒ J 9"ó €%òà?p’¤à-jPbDÀBÿô5Á2Ì “vïEöýàƒ˜é \u%4ã z°D:ÑŒ/¨à ‚KùBHóÎ0y˜€ Ø5–×€d“y7œ·höy '\¢'9Åez—–\©:«ÇzÑF¯;<&{³GjÙU{ÆCd¸—{ºWG½×j¿çG"í#uðñ Õ J°wÐM0pÀO`*p@’°„p*0 XpP  Ð!Gh©à„Nxf°“ À – >°]Çðp5Óa€¢àËp/Î!KаBK³€~ø‡€è4è€XˆV0ŠV¨D,–ÿCihEÊõ¤c:"Øz¯S‚dÔc(¸;´Ç‚kt{/G1(ƒ3Èd5ÈG" œ°¢Àò‘%80C°;I5€p ¬ð;0 Â8 ;P¬ p`zÀ¨ ‹ À!hPh0aðä–P§ÐÐ]P PD°Ð {` ÷±¦EK‰ˆôX3änø˜Æoü˜LôöÎtoö¶oùMþÖo— 0pîdp—pøÄpýôpq5q”PqQ§q×q÷Q 7R"ç $Wr&çR(Ç*·r7år/s?%sBUsHusLÿ¥sQÅsUõs?'t_UtE‡tH§tnÕtH9W É"(@ _Ð Þò РБPOÐ*`=ÐhÐO0 e‰OШà20Np½° >ð=ðhðO€R˜–õõ3`}=`¸@-a Ža©NP—}ðÌ ÊAa†aöX™–ynƒØ€†ˆhbЏˆˆÓˆŽØ8‰–ƒz”‚¬çišx;˜‚AŠ-¨{¡¢Rp ÇP¢ðƒTX1¶¶I–´IáI^ s`a0}:°ap R€ À ý ô‰‡žnâ¶ Ÿ€ Z¦fÚZZyšyª[ ª Ài Zš¦‰š¨šœÆšš{¯©‚Š<ú¡·¢Ö3¢$Z¢åƒÉâÿ€°€ É@]] ¡ÐfØA|n0BXª´V¤e¶l"P$ 0R   8ðD2‘pR°2À)š¡/Œ·w¦À ¬ú8¬ÃÚÆzùyMÙ¬‰ p ÙN9OyOÉOPiP©‘Å‘¹qß’%’ W’&y’)©’(×’5õ’0)“3I“@e“G…“M¥“NÅ“=é“Z”]%”CI”ie”m•” «!k"Ò~…PpYp¼à"@©àG€:ø± ›%¦šIà¤ê áàÿ% Ðp~^€ uð íÿÐP ¯à˜ú¹z( ¬B;´5”¦…¶¦˜×¦»Õypz8 êˆt‰všzxzczZ‚|úšŸø§n¨‚ =„Z¨†ªGˆš¨ÁÞâ>J ®` (à€X—äC@y°p äÒ%!"é2²s' rà› çrp¤˜ä¤€Ãð±Ðþ…¤PÛbY°mòq Ã’ µD´¢;ºac´„†´ˆ¦´Dô¦Mû´P»:µ™VµÏuµŸv‚}ê§*›.øµ ¶J6¶yT¶äc‹À Çà·Ú‚ ³p <ЋK Äm ×ñ©žªƒRð¥*ž˜ÿÄ  € gàëP ]0Rªl"°•pdfá+/€×î pvpඇå@™¤Àœ5¦ b¨{hª;D¬ §®+zQ˲Kc´ë\¶{»ªµ¤ÆµÜåµ¾KGÀ¼ÂÛdÄ[EÀ Í ó@/D€ à’°Š{I3p€¥#ôÐop|+ªôïQkà+f½p‚°<@p½0fŒÛP0* ¹JÚ  xP"@C 4^ú‹ b:ÀfˆÄšÆîv¬ý˜¬ô¶¬ÖÔ¬ù¬ã­Ò:­ëT­òt­ö”­û´­Õ­õ­àÊPבõ‘ ÿùq#©®'©R)¹’,Ù’,“#@¯Ü`¯A…¯F¥¯Jůýê¯Ù°>'°\E°Dg°‹°kµ°I™/ìã ¡ý»0«IÏ@h°W mn` PN ·‚ä-¢€y°œBœI ð =€“@XZI™4š0aðÄš÷³°?65`ìµEÓz ðg\Ïö,6<[Ä QícÈði€S!M`ÅšÄ  pÐ_0BÇ(`1¹`6€;ÿpN@Jð·C X\Uð_ tÐJà Š‹Â€ w’1ŒIC _€MP_°ÓÆj Û‡÷üÕõœÏú¼Ï$ÖÏ|³À ÚÀ »u¡w:¡—¨Ðc„»}ª¡Ý»,]Ñ"\¶±×=`P@ P MÍIp`r0 ·aÉà ë° —€D][à•¸ìys060t€[@ c¦`'-ÎFz©8`%2 ‚ÔòÀü Ö¾Öbbdm[f}ÖL Ðqzsê ±ëÖT ×"(×s}Á ›\롾»×|mÑ#,Eÿ0 £ª'x°Q½òk¤. ‚ûs(à„±Éð€¢± Ó™D T-‚ঠ…C0f¤€ p¨ ÚËF ‚0JR€ ¿íعg1Æ+P ¿á§Æ^LlÌnõù®ï9Äïîïxê‹(ê.ÆÜm=‰ ¯ðj¡¬.{®þ§ØýµÚ]ñÜsñþ@³æ¯P•@1R`•*ìp̸fõcà-0pÕ"KíéûËü(Àᾕ F0 "`KÚ9o…a° {гBñ)âváT¿ú~Öá®L.o!M#Žo%®o'þo)~N+Îâ-þâ0îÇ3Nã‚LÈ…|ÈãªÈçã"åÈìÉ+Iäòêr˜ŒäD¥äž¼ M.Ê£ÿ å@'åSntUnVWŽåY^Wþ°ÉâÍ`Ay?DP þ_HM€0H ‡ËR8dcÞ²Y*ðH‰EJRÑ$F¦@…HQTЙ‡…×D^=P@#bâI”à²Ôó@ÄÀ!)îŽí‘áÏæMœ9uî乓†/hЖ4øWÔèQ¤I•.eÚÔéS¨Q¥N¥ZÕêU¬YµnUÚÏëW°aÅŽ%[6¬´iÕ®eÛÖíÛ¶äÎ¥[×î]¼!"èåÂï_À6¢° ĉ/VÜ„cÈ-$O¦\YrŽ˜slæÜÙs IŒ&]Ú4i$R³`ÝÚõkÖXh ]ÛöÿmÜ4è†ÐÛ÷oàÁ} €@\ÀqäÉ•/_ÎÄùsèÑ¥?ÿQÝúuìÙµo¯ÆûwðáÅûûäF {QêDÉ Å)(åƒãuàªAR¡„#¦ŠX©CŠf$qƒG‚%a<颂(Ré¢R¼ðB¢ `€øä“<ˆ>°¦8¤'[dq‚U‚šà®j´ñFsÔqG{ŒÊ, ƒ,¸Š4òH¶ðRrI%ùÚk¯Á¢”Ò0*³ÒJȳlËÊ4Ëì307 í42O[M5ØÒŒm¶Ùpsó6ÞvÛM8:ƒ3®¸â˜ÓsO¦óóOît;ñ 5ÔŸöÿ‰v.P¡‡TXàBO"¥“P:)AˆÂC dƒC–9pÀAÁˆN."q#:tС“¢a4Ré¡ÃJAêa ©¤Eú˜E !VtñÙÿ(#(FññZl³Õv[n»5jHpÃ= IrËM’ItÑu²¯)Ûýë0î”÷1z#ã’K/à sÌ2ûUí_5–íM‚m‹³N„»“O†›ûóaè•XbC+yöpè #îã‹Y*¨0؉†¸à,l¨£TøÂ¿(æyD ˆè$a%f¤Q  =®èÁqDè¡×€% ‰"$Aÿ! )öÇYh»Îé'hà)Å[²Ë6ûl´‘¢fm¶Ûvûm¸ã–;î;ê¶ûn¼ó¶[¾ûöûo¿±|pÂâpÄW|ñÄ¥qüqÈ!arÊ+·œò2×|óöñüsÐ?ŸbtÒK½ÔSWõ1ZwýõÖ¹}vÚ¹ äöÛ©Ð}wÞ»ñ½ ‚ˆoŠ/þä“¿Ae^pþù¼‘~ú$ª·> 5²×^ 6º÷^ ðÃ×Bòµá|ô¹Q}õ%pÿ}ø%H`~úëŸüóÏßþû÷?0€ ` x@"A d ø@FР`-hÁdPƒ<<øÿA†P„ÄöpŒy @Nø‚ §Ëd[xq‰Nãix…Ð`€ÄbÄèÄ.òVId:Ä”ð…`6èÃ%PPðê¿"ÙDÀÁÄY8d¨ ²¶ˆ%xMþ€QPþðŽ´ÅQŽs¤c‘".<‚Ë\{4Wºüؤ'±Ë]í‚×¼ä•%{ÝË2ùÒ×gøå/2)`jXÁ v°„era ãdŸ öɉ…’;#å8!…:láO˜Ç+ Ò‹ptQ‰ÀBiÖ )¼ÁXG>Œ€'¼A Ÿj%òª¹82T@†ô‚rx@1x1€‘ÿ W²ìE(¤ ‰T@¸Ä0±FhI‹ZÖ²c;ÝùNxæ(óíy¤?æ³.ë‚Ò Y%C^ ‘ŠÄWf¾ÔÈÎ<’¦‘ä$_3°6Y27râM&봰‹  ¨Øf‡0Œ(àô³èáØtºˆ™ÛØâyV´¦U­]¡g[ÅrO¸¾EŸs d ýùÏÔ1ˆÔA»dP„zF¡ E ÀúЈJt¢µèEñ¤Ñ†qÿb¥ìBZ±"hŒ¤ú9Ά¡— Y À.àŸ¦¶ÍÀRûÓId´èEx±€_àj(@Å.µ˜a¼‡,£AŠJ&8 @v „µ'€‡á¸VìfW»T™[w½û]¸éM¼ã\yW8ô Žqëeo"÷ÞÇ]N¾–ã\}Cw_Ï™N¿SX];¡vÆ]îxwàßoxÁ3Þñ”‡<æAïyÓ£Þõª·=íyï{â_ù̇¾ó±}ñ#±ýLœý¥Ø+v€]Œ@3F‚m Á 渂äñ}ücz0ãµ$ý‚bX)^” ¨ÿPÄ}ZS'õ˜à*861ƒ3ôÂ3 rPý`0Ìã Æ/jЈ7(¢¸°Íp°éêä䀆,ªµ]<çYÏÚrkŸ¿W@¯…®úäç]ñ/½6¦^}õëdX1‰†°¥ièa[SIÅ.vN¥Ó&!»'É>¬²½¬¡ä!¢×ÖldæÅ04Ñ%0Äɳ.fl+…*ƒ£ËÑ*v€ ìúi¼°(®P€-T «ªIœm€±BcfÝsµ­}m­øÙÏæ¶ÏBZJ…LôbÚhÊ<Òƒt¥- ÑLÉ¢›æôo0úiP‡ÚO£öh© %Í¦Ö †ÿ°+%TMÃïÄöK±þXü?0Æ1¦qo|cë˜ÇüqõChІóž0.v0v(Á ®ux”!‚ô£ègÿ&ÖÏ~tŒCý]ˆÅ0ð€‘‘ ½HEO_Ë÷°*²Zj<<@’ñ‚^3€2»ˆ›¸YÀqbø‚ …C Ѓy0‚0H…7˜8€V˜Â`Ù¿Tð€,¤Åg‰6äEˆŒÈ©8<ФHÅ»Èÿ;h<Æ{¼Â‘<¤¼Ê»<ùʼÍÙ¼Ðé¼Òù<Õ ½×=Ú)½ÓëÔS½û†Ö[ž×“0Ù›=Ú³½ÛÓ0ÝÞë½ß¾àsŸá«ŸâÛŸããŸäS¾åC æ[ çƒ¾è» éÛ ëÛJ0†©³))…«ë" (L¢uä5wô©cxƒcpO©Gˆ‚WàTø‚CÈG(H#@…a0]Ó¿^ Yô)†|‘’ó¢HÆlÌnñÅyÆ{F&QÃb<ÆDKÆ[F„jFHzF‡ŠÆœFjì¼FOÊFçØFnìF0T£ºF(¸`!ÇV˜‡ßJKv\ˆðp‡ÿT@†Y¨h†NP–[ªQè2…H…<ÐýCˆÍÔ¹ €8ø;ÇüNð¼ÈÌ#É´'Ê\Ë\CÌÌL8ŒCÎl$ÏôÐ6áÃ>,MÓ|¬ŒBMÕ¤Ö ×ƒŒùM’")"à2’é‚TàØ¬›²íMz„²š™B2€'&7p‡zH…»ÜP€&8^ˆÐh@@ɾfë Fƒ àƒð¬QÅ‘ñÄ£òä£ó¤u)FÂhC \´8¬ƒZ7;ºù¤Oû¤ Ò,ÍÓ¼Æþ\Íÿ%× ²†8†…zôÕJðbÈ?‰ðp …! @SÿRŒ‹†v¦@cø)¨€¦(HW@]p‡óÀ¦ PxA irÿxò{Q9£³[¤‘­Ô]¬HL/ŒT<4/Ž$”<Œ‘I’Ì“”$•L–t—œ˜ŒIÝI0Õ#Ök½ƒ½¤=ì±=ÜË=Ýó°Þ¢ä†£|Ÿ¤¤Ÿ¥ÄŸ¦tʧ̆¨„±©T ª´±«ÄÊ¬Ì ®´¾DÑR'@ð7u”.˜„W3ד GRx€€> €PÀ¿‹C‰8•‚T†—)&8€08¨ ÈÐR7(© è€ D…ÓHP.°<0ÿ†xyà‰h#°TýXªÈQqÙÑ=êѼ F eürCÍD·÷Ô—øì—%¥$,º'¥Æ( Ä)e‚*µÒnäUyƒ\Ð=pT)H‡{0‚€ˆ.¨ø¸W'h„¨„.À×µt ’‚‰/H…>x…ªÍ#ÀˆÃz€V€‚W´”˜wx€_Uá!Љ62¹)Y¿ý[¦Ùp!Ù>2Y»HÏ\O½:7eÄ@$½ÃÂZ¡«ÏšU¬ƒñãDÔLMÕìYBqMLà„=Ð)8Ðð‚J0ƒ (Oˆ%‰èT¢0h^ Rhƒ×&è…ÿ]‹Ó(ÐÒ\%0„4p\rƒ °Ûì Î\ P€1«”!@…M„‚6˜‡/Ø àœàNY`'À=_ô\="\r1ÜÃEÙ”­DRÆuYÇeÆ$m7¡ÓÃÊÍ´›ýCkÜÜõ\íÐ%ðʆ°(H7h„MxAÈ#† ئ!h‡7Є.è^èà!èMxƒVH¢8]•cÈ€T„¨Óp…Q(€vXQ˜:°‹‚-ò uÈ:RTû‚>X ‰4²‰ Qh€ômâ•ËT(ž›MM¼N-¯O5œPm¯Q•œR¥¯SíœTͯUå¯Vý¯W°Xµÿ£ÕZɫɛÜU”=_õÉ` Jb%Ê¢LV¤\VkÖgm±hV©¬Ök• lÅ mí ný±%°q-ò«ÇJ­AMðËøð"0‚ˆ^…Aê‡0€ƒ\ÉWõ€Q¿%‚AèEø<àÞ’B+^¸€H9xPpKh†ñÞUÑ›°Å À'Žæ¿Uß!aßöu_º@ÜšS\CjÙF{Ù}Éß ÜßlRÄÏü4ŽÍ=Ž&`ìP‚€{2Â7T `…øðÛøWY¡)¸³ë'0„)Ô#h„¹ü”šÂ%€„ÿd„Q&ŠU•fÈ€+&dÐA°„¦ñ^x.}²†Øƒf›èXi~é¥f!±f$Áæl†ß”åænnÏÆÃ gg$çЬOi‡?·Ó®·œ%ÁBgmx¶‰Œi­Tp(X•Cèƒ{Ø5pÀT@Ðí!€]¨³ë…>h„TЇtØ8»!¸Hh‚çvG…KØx"x%ˆp„ V^)x„7h„¯Ÿd€8((°ä2í0ˆ‡H¸è(`†F°–ŸüwšoË_›ú¯ûÆïüÞoþîoiøoÿâ0ãU-c3~Õ4VcÜac*`ð7vpåð £ã ǰ;Ö OŸÿ=æc?þã¥üðAñªÖ+ñ:q_ä÷±›ˆ-…(¨šÊ¥8W|­¦2†FèX"4 = ƒ0€ …pX€`h„,ˆ|u8È3˜@¡*0À¢ˆ4Q¤DÁ!Å•#ŽD ÕCD´ˆÑt¸h$¥Ù+G]ˆÚãfÌ¿"G’,iò$Ê”*W²léò%̘2gÒ¬ió&Μ%ûñìéó'РB‡þ´bô(Ò¤J—2mº4Ô¨R§R­j5D¬ZCpíêõ+X¯&BŒ5aö,Ú´h[˜`ë¶ܸrçÂÍÑÂn޼z÷òÍAÂ/‰À‚Ì‚ÄaŠÿ3n¬X ’'S®l‚Ì6sîìù3gD (mú4êÔ©™°níú5ìÖ?fÓ®mû6îܳÁðîíû7pÂÉÀ…ˆ$u¢¸9Ô§W8‰:б \4/Cæ8ÃË‹8袡“C+œˆ3\uñ2ñ‚"GÚ5fžeÞeXà"ƒlðH4ò€ŠláÃ<¬`8]¤ã…î @ÀQ0CD:yø!ˆ!Š8"‰%šx"ID©¸"‹>9õ"Œ1*e5Ò¨UVY…µ#dù¨@ºÕ]EÎ…×]})™×_…9YXbˆ96åc‘Ef–•i–Yf yùi£¦ÿ™e šiê¶&›¹÷&œÂ 'ÄÆc\¹F/îM4À:GìQ4àSO]Ø1 )]ôñ‚0DDJ(RdÆ_ð€$‘(ò…D¤âD3n¸ãNAo¸ÑGóìàC3<8ÑåiÜQì±$( ;,±Å{,²9µ¸,³EÉø,´3Ú8í´8nÕ#¶]•EVݶõí[F‰ä’K6ù$ºˆ©K%»eù.e[~9¯gašyïjiêëZ›ýö 'À¾ÉéÏìQPž K±-–F#‚“X€Ê3~ê@$Ô°@/"0„QÑECÊn °ÀW\ñÿ@'],84³L»~aÃ_@Q(œ!8½0KÎ3óÅ>É:ý4ÔQK-"5U[}5ÖYk½5×[ßñ5Øa‹=6ت˜}6Úi£ Ûm»ÝvqË=7ÝuÏ- Þyë­7}ûý7à~§08á…§°â‰+žø;þxã H>9å’q9æ™_Îç{Î%¡‡Né¥›Þ êݱ:ë@|óúë7È>û Ê(óà ï½'ñ;ðI¨1<ñj°q<òZ(¿¼Ú8¯ÍÑKÏ õÕS/öÙk/AÝ{ÿ}÷Ûˆ?þø˜>úÙ¨¿þú ¸ÿ>üñ»ýõÛÏþùë¿ÿ?þøÿ?x‚°€'P¨À20óG ˜A ¤Ä €/ª 8,C  p€Jð‚"(ÁñŠJtA"'³ÄÂ@@máðDRA¤éìB6@ÅrBy0 £àv1µ%2±‰N|¢ˆš%ÅeE«ŠÑ¢o”£ke [ÛòV·†.qÑ…\åê˹Òå¤(±‹JäE¯9Ú _v<Ó¾òè¯=ê&`~|àdp0Já hO4º‹ì ¤ð“zÑ#¼ÂN(€ ñ W¸‘AÙž ‰0¤¢¸2Њ;ñ9Dxå:. ‡+TÀÿap2¤àîá €"0ƒ)ÌasŠÆT‘“£,2s*ÖÒQ½ø#0IŒd×]’tƽ¤Q„acã®+Áñ2\ÒÌ¿d¯1ÝÑLyÔ#ãY?ìþ(3ð”´C¼¢ :ˆ6A€¤ã”ˆzá‚\à@zAÄO>á ¨ÐCæ „bu0„vØÊøð a8@°£Ž^HB¤9ÃÁ¨@̙Ҵ¦6-Ñ1seò´)Íüé·Mi–…šj#‘®y¤ln“/Ýô¦aÖNq’³œæDg:Õ)¦vâëû’'X@O€ÙÓ‹`F+qàIü^ÿX@'Ö!M´.d/òš×F¹¢o¨š°…|á wr) ¢‚Àá<Ð{`‰#&mCظ)f3«Y§u­³žý¬ÖÈ&ÚѪ­´j{jÙf·Õ²6{{mÞ'[À®¶‹»-â §Û)T®· ÐpÇð¹áŠnt¦;nêT׺ÕÁ.v´“ít—»Þù.x¿+ñ—<æ)ïyГ^ô¬g½í‘|æMùÒ‹¾õ:€}î•|ág¿ù"öÕ_óû?ò·þýoY×À‰A&Biè8Àá Cäá“p]û*á “â oÀÅ/F1,BŸúÌ™p0‹  b2¬Tÿ4†7 6O{H6+ãÓ¸¦:½qOzªã¤µ™Ï*Q¹eÔµ€+©J‹›Ê$À@u0àœêbÞhÕ«v)«^ª#WËäU}…UžcSYéQ§VR íáE 2€‹L" ß™0œ/µ…7@¡DpA<ÐJ  Ph‚ 2‡!x¡ • B‹ ÂŒ`ոю~´ÔpŒãSÚ =fæÌ£/9-Ö<²\’¬ä§6ùÉP电tÎ*[¹3ë̲–·Œ¦.ÇóËo*«p¹g)¸£íB!ú0‡<˜AÿŒó„uиƒ?ùx….÷\š¡ MprR¡‡Ø33 ÿÐ!H“»ÜæÆ©¤uZé_:‹™ÖtX8Ýi³ Ô¡fª’—ÜäoJÊUJ5•[}å­ÂšL²ž5­÷hëààœøpΤð†atácÄÈ@$Èp€‡ˆàVÈ~OͱŽ9|a—i•‚ 0@!‡*X·w‘h_¹£ç¾9Îe ÚóÜk£ýyØL+t³¥µ­=úÝ`ûÚÙ2µ5no»[Èù¶rÁÕÜp?W\J¹©[.s›û\èÞNº»£®7¬{]ìO»lànwŸÞðŠ÷zäÕÞyÁ—^ò±7}îm_|ãKßûÝ÷¾úÕ/ øßÅ/׉ ž0й " EúÐÿ\  À‡<gÀ'òð@‹ ¢g{ ¡ÈÃ$¡ ^   €Ä!R•X#ç¾ÿ=ðS’nu¯»§íÆâ»áýyÏ»Þö® ¾óMj¨šúÔUøª,5M¾p9Þ3£ÐŒG¨`%Œ„!æ!2t¢=p)B?õ•ô(7€#ÌC3艂ží¤µež#‰ÀèÁ‚© Bä% 0C#vàï _NŸñ_µ•òÅÛ4ͽËóA^ä›_0Ù¾­‹”øªa_ö±šö½Z÷yß÷½FøùËø‘Ÿã‚ ÕK™JÌ‚(ÿÁX>X‚Ä‚ ”€C5A)ô‚þ¹‡x²íAà#8A24¯y HB0œ@DÂÂô)܃ ,Ã!|œÂ Ü.Á”Pƒ¢!B“ò – µœàò¥`óY 2•6š î[õM•”á iŸ«\žÆa¶ÉöFùÉÉ"èYÂ4ƒ$ \‚ÌB=ô€åu˜$¨€8B Áh*ô€Âè@@Á1Á ̃$À<A:„ÂØßÜß ‚ A/ÀA œ@;Ì‚\LjÛ!Æ£<žHÏÕc=ÿ>ÞÁÐ ]ѽ Òý£Ò-]ÓÉÖÓNÔ-ÎÔ=NÕQÎÕeNÖyÎÖuÝé|Ø5×7Œ]í”t¡]Ú©ÛµvÁ]óÈÝÜÕÝÝöäÝ÷ì]ùôùüàžü ^ýžá^%^1O*À*‡®„;ð€äA.4¾ÁA*°h*¬C,è|Ì~!¼R¨ìB%üá À”ÿÊ{ʧ“>é±Ð§Ù§á§=âcr™ó=_enÓeªQf¶Ñ¦Zgz&hŽâhÊ„öÑiR¨p,Ô ¤Â-H‚ˆ½A,¤;4G @;T‰~Lè@ÀÁ4A.Á˜ËÁ„B(4AøÀ&ü(/ˆ@ÜÃ\x€.áÀð€$p‚<À@ Ý>šV?ºÍ?"]@îÍ@dAÎA*NB:ÎBNNCbÎCvNDJ$é$Ø¹ŽØ]t™Gªð°Û½Üy×Ü€IrJfJzKŠK¾$LfƒLÂMÒMÚNæ¤NPO2ÿœH¼ C%ð@ŸºAÌÂ2Œ‚ À˜P‚ñB/tÁw’‚'„‚%<)la AÇ1JSÖ@Ø€;€jÄ+8$„Lñ!º*˶lˆHi³PiYéU˜`–j©$vZ—þç J_&–Z¿ÙàõÜ™‚bšöàš’f›ºÉ›Þë㱨6ÃÀA`¹Ã<ä‚=HÁ,4ÃΤŒ.l^‰€ /ˆ- Ùž-)d ‚©_ÍP¦Ì€¼Á‹õžËî-ßÞÌ2‹Ì^ÍR…~žà–r) ¶à—žQ˜¦Ë˜º‘zböyæV‰bh&-,-Ó¦¢ÓÊÉjîÿ ô@8A@dˆ># h +ø@¸ÀœA´ÈAÂ(È-¸&ô+2TCß>/ôÂÄßRQà>Ëà®ÍÞìáRÓ΂Úâ–Kã¢ËãB.NFÑî å^nÒj.nHhçÊ `'0ƒžY€ àÀ%‚!ˆŒt€×€ê,|ÛA 8 Ø€Œ‚¸ŠÂ!8𠜂À:DÞÜæ‰0ƒ(èÂD/b¬Žp×ÌêÏÕjiÝ*Üäjkí*ßô*mýêákn +oëo«p%+è³6+E.—Ebä´n$ÚYëGfÿ«HrkIšd¸¦ä¸¢W¹žk{¥ëºÎd»¾+ÿÄ«ÍëÕ+€½¯œ|œ&‘;AHÂ!HŒ\ÀÔA¸Ca¹z@$C2ÔA6ƒ(A|+èAˆ‚2Ü10ÒˆB°¯à€\CO2%§Èô²HõZïõJEá*ßö‚Q÷Ù÷šËÏR_ÐZ_ùJÆù.húªéú²¯m¸¯ïÈ3ðÚ$ÄBæIÁ¸ž€=ô€DAàAŸ¥ ì‚@! À<‚+„‚ C*4*À$,€xšAžõ0XC%3%_2&gò2mrTt2¼}2('®—¨e–ÿ2fž²fF.gN.šVnƒ–æÂr,7í,{®Ì8Á,ÀÂ1ª¢‚ÐÂ+l ¼Ád¨À1@'XÀ@ô€ p Ã#HB'¸Á<€|¼A8“³L‡°9¯:§³:› 4e©;‡%*®<ƒ)=‹©=ßs*ë3åm÷ý3@Ó†,ôÀ`B-?è6‚ÌB'¤Â!\4@ê@CH‚$4[B3Â<@A3À²}!¨•ÃÄôLçõÍ‘0_g “ § « ³– Ç ÿ Ï0 Ûð «ïp².+³:kEFës±îT«Gbÿ«Û-1I‚×·>1÷Dq¹n§«º^±|e±ãû17T—ÕÄ€Ã20ü ëA ¼Áê†A$ˆ‚ tJ,ø@_nLà4 B#üŠž00\–^owßÖ42Ýô‹ä4T°³¦õt5ýt<÷l€ ( è¿¥ò*·šRS7µX ôm? ðØ)Â-A뢀17Až Â)„‚A3A:pˆÕÃÜr.¤ÀÊr·†»¬wx‡·x“7™÷yÏ^â<³w{è æs|§ƒªïšÚ÷nàw~Û |BЃ pU{@¼A¼AàÁܺ ÿ s¼$C5|ð†G9‡w¸P|¸Sˆ·Nß,Ε †²R²’„)‚žå~f+#í+Û÷Sßxù-ÁðA ÐÃ"ȃ1°CGx„(,0\C5ˆ³”:¤õµ¢WÍ_‹V` ö`¶a¶4$¶bË0 ×ð°âp+÷°èü0X¶c6íhötqgc—okhO?qK1K¦¶³öû´k}½vþĶl{qmûW@;norm-1.5.8+dfsg2/protolib/examples/0000755000000000000000000000000013320271272014036 5ustar norm-1.5.8+dfsg2/protolib/examples/arposer.cpp0000644000000000000000000003406212371317132016223 0ustar #include "protoApp.h" #include "protoCap.h" #include "protoPktIP.h" #include "protoPktETH.h" #include "protoPktARP.h" #include "protoNet.h" #include #include #include #include // for "isspace()" /** * @class ArposerApp * * @brief simple app that gratuitously responds to ARP requests * with its own MAC address as the response * */ class ArposerApp : public ProtoApp { public: ArposerApp(); ~ArposerApp(); bool OnStartup(int argc, const char*const* argv); bool ProcessCommands(int argc, const char*const* argv); void OnShutdown(); private: enum CmdType {CMD_INVALID, CMD_ARG, CMD_NOARG}; static const char* const CMD_LIST[]; static CmdType GetCmdType(const char* string); bool OnCommand(const char* cmd, const char* val); void Usage(); void PeekPkt(ProtoPktETH& ethPkt, bool inbound); void OnInboundPkt(ProtoChannel& theChannel, ProtoChannel::Notification notifyType); ProtoCap* cap; char if_name[256]; }; // end class ArposerApp void ArposerApp::Usage() { fprintf(stderr, "Usage: arposer interface [debug ][help]\n"); } const char* const ArposerApp::CMD_LIST[] = { "-help", // print help info an exit "+interface", // name of interface on which to listen / respond "+debug", // NULL }; /** * This macro creates our ProtoApp derived application instance */ PROTO_INSTANTIATE_APP(ArposerApp) ArposerApp::ArposerApp() : cap(NULL) { if_name[0] = '\0'; } ArposerApp::~ArposerApp() { } ArposerApp::CmdType ArposerApp::GetCmdType(const char* cmd) { if (!cmd) return CMD_INVALID; unsigned int len = strlen(cmd); bool matched = false; CmdType type = CMD_INVALID; const char* const* nextCmd = CMD_LIST; while (*nextCmd) { if (!strncmp(cmd, *nextCmd+1, len)) { if (matched) { // ambiguous command (command should match only once) return CMD_INVALID; } else { matched = true; if ('+' == *nextCmd[0]) type = CMD_ARG; else type = CMD_NOARG; } } nextCmd++; } return type; } // end ArposerApp::GetCmdType() bool ArposerApp::OnStartup(int argc, const char*const* argv) { // Seed rand() with time of day usec // (comment out for repeatable results) struct timeval currentTime; ProtoSystemTime(currentTime); srand((unsigned int)currentTime.tv_usec); if (!ProcessCommands(argc, argv)) { PLOG(PL_ERROR, "ArposerApp::OnStartup() error processing command line options\n"); Usage(); return false; } // Check for valid parameters. if (0 == strlen(if_name)) { PLOG(PL_ERROR, "ArposerApp::OnStartup() error: missng required 'interface' command!\n"); Usage(); return false; } // Create our cap instance and initialize ... if (!(cap = ProtoCap::Create())) { PLOG(PL_ERROR, "ArposerApp::OnStartup() new ProtoCap error: %s\n", GetErrorString()); return false; } cap->SetNotifier(static_cast(&dispatcher)); cap->SetListener(this,&ArposerApp::OnInboundPkt); if (!cap->Open(if_name)) { PLOG(PL_ERROR,"ArposerApp::OnStartup() ProtoCap::Open(\"%s\") error\n", if_name); Usage(); return false; } PLOG(PL_INFO, "arposer: running on interface: %s\n", if_name); return true; } // end ArposerApp::OnStartup() void ArposerApp::OnShutdown() { if (NULL != cap) { cap->Close(); delete cap; cap = NULL; } PLOG(PL_INFO, "arposer: Done.\n"); } // end ArposerApp::OnShutdown() bool ArposerApp::ProcessCommands(int argc, const char*const* argv) { // Dispatch command-line commands to our OnCommand() method int i = 1; while ( i < argc) { // Is it a arposer command? switch (GetCmdType(argv[i])) { case CMD_INVALID: { PLOG(PL_ERROR, "ArposerApp::ProcessCommands() Invalid command:%s\n", argv[i]); Usage(); return false; } case CMD_NOARG: if (!OnCommand(argv[i], NULL)) { PLOG(PL_ERROR, "ArposerApp::ProcessCommands() ProcessCommand(%s) error\n", argv[i]); Usage(); return false; } i++; break; case CMD_ARG: if (!OnCommand(argv[i], argv[i+1])) { PLOG(PL_ERROR, "ArposerApp::ProcessCommands() ProcessCommand(%s, %s) error\n", argv[i], argv[i+1]); Usage(); return false; } i += 2; break; } } return true; } // end ArposerApp::ProcessCommands() bool ArposerApp::OnCommand(const char* cmd, const char* val) { // (TBD) move command processing into Mgen class ??? CmdType type = GetCmdType(cmd); ASSERT(CMD_INVALID != type); size_t len = strlen(cmd); if ((CMD_ARG == type) && !val) { PLOG(PL_ERROR, "ArposerApp::ProcessCommand(%s) missing argument\n", cmd); Usage(); return false; } else if (!strncmp("help", cmd, len)) { Usage(); exit(0); } else if (!strncmp("interface", cmd, len)) { strncpy(if_name, val, 255); if_name[255] = '\0'; } else if (!strncmp("debug", cmd, len)) { SetDebugLevel(atoi(val)); } else { PLOG(PL_ERROR, "arposer error: invalid command\n"); Usage(); return false; } return true; } // end ArposerApp::OnCommand() void ArposerApp::PeekPkt(ProtoPktETH& ethPkt, bool inbound) { switch (ethPkt.GetType()) { case ProtoPktETH::IP: case ProtoPktETH::IPv6: { unsigned int payloadLength = ethPkt.GetPayloadLength(); ProtoPktIP ipPkt; // The void* cast here suppresses the alignment warning we get otherwise. This cast is OK // because of how we set up the "alignedBuffer" elsewhere if (!ipPkt.InitFromBuffer(payloadLength, (UINT32*)((void*)ethPkt.AccessPayload()), payloadLength)) { PLOG(PL_ERROR, "arposer::PeekPkt() error: bad %sbound IP packet\n", inbound ? "in" : "out"); break; } ProtoAddress dstAddr; ProtoAddress srcAddr; switch (ipPkt.GetVersion()) { case 4: { ProtoPktIPv4 ip4Pkt(ipPkt); ip4Pkt.GetDstAddr(dstAddr); ip4Pkt.GetSrcAddr(srcAddr); break; } case 6: { ProtoPktIPv6 ip6Pkt(ipPkt); ip6Pkt.GetDstAddr(dstAddr); ip6Pkt.GetSrcAddr(srcAddr); break; } default: { PLOG(PL_ERROR,"ArposerApp::PeekPkt() Error: Invalid IP pkt version.\n"); break; } } PLOG(PL_ALWAYS, "ArposerApp::PeekPkt() %sbound packet IP dst>%s ", inbound ? "in" : "out", dstAddr.GetHostString()); PLOG(PL_ALWAYS, "src>%s length>%d\n", srcAddr.GetHostString(), ipPkt.GetLength()); break; } case ProtoPktETH::ARP: { ProtoPktARP arp; // The void* cast here suppresses the alignment warning we get otherwise. This cast is OK // because of how we set up the "alignedBuffer" elsewhere if (!arp.InitFromBuffer((UINT32*)((void*)ethPkt.AccessPayload()), ethPkt.GetPayloadLength())) { PLOG(PL_ERROR, "ArposerApp::PeekPkt() received bad ARP packet?\n"); break; } PLOG(PL_ALWAYS,"ArposerApp::PeekPkt() %sbound ARP ", inbound ? "in" : "out"); switch(arp.GetOpcode()) { case ProtoPktARP::ARP_REQ: PLOG(PL_ALWAYS, "request "); break; case ProtoPktARP::ARP_REP: PLOG(PL_ALWAYS, "reply "); break; default: PLOG(PL_ALWAYS, "??? "); break; } ProtoAddress addr; arp.GetSenderHardwareAddress(addr); PLOG(PL_ALWAYS, "from eth:%s ", addr.GetHostString()); arp.GetSenderProtocolAddress(addr); PLOG(PL_ALWAYS, "ip:%s ", addr.GetHostString()); arp.GetTargetProtocolAddress(addr); PLOG(PL_ALWAYS, "for ip:%s ", addr.GetHostString()); if (ProtoPktARP::ARP_REP == arp.GetOpcode()) { arp.GetTargetHardwareAddress(addr); PLOG(PL_ALWAYS, "eth:%s ", addr.GetHostString()); } PLOG(PL_ALWAYS, "\n"); break; } default: PLOG(PL_ERROR, "ArposerApp::PeekPkt() unknown %s packet type\n", inbound ? "inbound" : "outbound"); break; } } // end ArposerApp::PeekPkt() /** * @note We offset the buffer here by 2 bytes since * Ethernet header is 14 bytes * (i.e. not a multiple of 4 (sizeof(UINT32)) * This gives us a properly aligned buffer for * 32-bit aligned IP packets */ void ArposerApp::OnInboundPkt(ProtoChannel& theChannel, ProtoChannel::Notification notifyType) { ProtoTime currentTime; if (ProtoChannel::NOTIFY_INPUT != notifyType) return; while(1) { ProtoCap::Direction direction; const int BUFFER_MAX = 4096; UINT32 alignedBuffer[BUFFER_MAX/sizeof(UINT32)]; // offset by 2-bytes so IP content is 32-bit aligned UINT16* ethBuffer = ((UINT16*)alignedBuffer) + 1; unsigned int numBytes = BUFFER_MAX - 2; if (!cap->Recv((char*)ethBuffer, numBytes, &direction)) { PLOG(PL_ERROR, "ArposerApp::OnInboundPkt() ProtoCap::Recv() error\n"); break; } if (numBytes == 0) break; // no more packets to receive if ((ProtoCap::OUTBOUND != direction)) { // Map ProtoPktETH instance into buffer and init for processing // (void* cast here is OK since ProtoPktETH is OK w/ UINT16* ProtoPktETH ethPkt((UINT32*)((void*)ethBuffer), BUFFER_MAX - 2); if (!ethPkt.InitFromBuffer(numBytes)) { PLOG(PL_ERROR, "ArposerApp::OnInboundPkt() error: bad Ether frame\n"); continue; } // In "MNE" environment, ignore packets from blocked MAC sources ProtoAddress srcMacAddr; ethPkt.GetSrcAddr(srcMacAddr); // Only handle ARP packets (skip others) if (ProtoPktETH::ARP == ethPkt.GetType()) { ProtoPktARP arp; if (!arp.InitFromBuffer((UINT32*)((void*)ethPkt.AccessPayload()), ethPkt.GetPayloadLength())) { PLOG(PL_ERROR, "ArposerApp::PeekPkt() received bad ARP packet?\n"); break; } // Skip ARP replies (only respond to ARP requests) if (ProtoPktARP::ARP_REQ != arp.GetOpcode()) continue; PLOG(PL_ALWAYS,"ArposerApp::PeekPkt() inbound ARP "); switch(arp.GetOpcode()) { case ProtoPktARP::ARP_REQ: PLOG(PL_ALWAYS, "request "); break; case ProtoPktARP::ARP_REP: PLOG(PL_ALWAYS, "reply "); break; default: PLOG(PL_ALWAYS, "??? "); break; } ProtoAddress senderMAC; arp.GetSenderHardwareAddress(senderMAC); PLOG(PL_ALWAYS, "from eth:%s ", senderMAC.GetHostString()); ProtoAddress senderIP; arp.GetSenderProtocolAddress(senderIP); PLOG(PL_ALWAYS, "ip:%s ", senderIP.GetHostString()); ProtoAddress targetIP; arp.GetTargetProtocolAddress(targetIP); PLOG(PL_ALWAYS, "for ip:%s ", targetIP.GetHostString()); if (ProtoPktARP::ARP_REP == arp.GetOpcode()) { ProtoAddress targetMAC; arp.GetTargetHardwareAddress(targetMAC); PLOG(PL_ALWAYS, "eth:%s ", targetMAC.GetHostString()); } PLOG(PL_ALWAYS, "\n"); // Build our ARP reply arp.InitIntoBuffer((UINT32*)((void*)ethPkt.AccessPayload()), BUFFER_MAX - 16); arp.SetOpcode(ProtoPktARP::ARP_REP); arp.SetSenderHardwareAddress(cap->GetInterfaceAddr()); arp.SetSenderProtocolAddress(targetIP); // target IP from above arp.SetTargetHardwareAddress(senderMAC); // hw addr of requestor arp.SetTargetProtocolAddress(senderIP); // IP addr of requestor // Send the reply ethPkt.SetSrcAddr(cap->GetInterfaceAddr()); ethPkt.SetDstAddr(srcMacAddr); ethPkt.SetPayloadLength(arp.GetLength()); numBytes = ethPkt.GetLength(); cap->Send((char*)ethBuffer, numBytes); // tbd - check result } } } // end while(1) } // end ArposerApp::OnInboundPkt norm-1.5.8+dfsg2/protolib/examples/averageExample.cpp0000644000000000000000000000220311633720617017474 0ustar #include "protoAverage.h" #include #include #include int main(int argc,char** argv) { double total = 0; double count = 0; ProtoAverage table; int i=0; double bignumber =pow(2,1023); for(i = 0;i<10000000;i++) { total +=bignumber; count++; if(!table.AddNumber(bignumber)) { exit(0); } } double littlenumber = .01; for(i = 0;i<10000000;i++) { total+=littlenumber;count++; if(!table.AddNumber(littlenumber)) { exit(0); } } //table.Print(); double average; average = table.GetAverage(); printf("%f with protoAverage %f with straight average\n",average,total/count); printf("%f is the average divided by the really big number which should be ~.5\n",average/bignumber); for(i = 0;i<80000000;i++) { total+=littlenumber;count++; if(!table.AddNumber(littlenumber)) { exit(0); } } average = table.GetAverage(); printf("%f is the average divided by the really big number which should be ~.1\n",average/bignumber); } norm-1.5.8+dfsg2/protolib/examples/base64Example.cpp0000644000000000000000000000251111567016240017144 0ustar #include "protoBase64.h" #include // for printf() ... #include // for strlen() int main(int argc, char* argv[]) { char text[] = "Hello, ProtoBase64 ..."; unsigned int tlen = strlen(text); unsigned int maxLineLength = 0; bool includePadding = true; char encodeBuffer[256]; char decodeBuffer[256]; unsigned int encodeEst = ProtoBase64::ComputeEncodedSize(tlen, maxLineLength, includePadding); printf("base64 encoding text: \"%s\"\n", text); unsigned int encodeLen = ProtoBase64::Encode(text, tlen, encodeBuffer, 256, maxLineLength, includePadding); encodeBuffer[encodeLen] = '\0'; unsigned int decodeEst = ProtoBase64::EstimateDecodedSize(encodeLen, maxLineLength); unsigned int decodeSize = ProtoBase64::DetermineDecodedSize(encodeBuffer, encodeLen); printf("base64 decoding data: \"%s\"\n", encodeBuffer); unsigned int decodeLen = ProtoBase64::Decode(encodeBuffer, encodeLen, decodeBuffer, 256); decodeBuffer[decodeLen] = '\0'; printf("base64 encode/decode sizes:: orig:%u encodeEst:%u encodeLen:%u decodeEst:%u decodeSize:%u decodeLen:%u\n", tlen, encodeEst, encodeLen, decodeEst, decodeSize, decodeLen); printf("base64 decoding result: \"%s\"\n", decodeBuffer); } // end main() norm-1.5.8+dfsg2/protolib/examples/detourExample.cpp0000644000000000000000000002651513124265255017377 0ustar #include "protoApp.h" #include "protoDetour.h" #include "protoPktIP.h" #include // for atoi() #include // for stdout/stderr printouts #include #include "protoBase64.h" /** * @class DetourExample * * @brief An example using a ProtoDetour class instance to intercept * outbound packets */ class DetourExample : public ProtoApp { public: DetourExample(); ~DetourExample(); // Overrides from ProtoApp or NsProtoSimAgent base bool OnStartup(int argc, const char*const* argv); bool ProcessCommands(int argc, const char*const* argv); void OnShutdown(); private: void DetourEventHandler(ProtoChannel& theChannel, ProtoChannel::Notification theNotification); enum CmdType {CMD_INVALID, CMD_ARG, CMD_NOARG}; static const char* const CMD_LIST[]; static CmdType GetCmdType(const char* string); bool OnCommand(const char* cmd, const char* val); void Usage(); ProtoDetour* detour; bool ipv6_mode; bool allow; // toggled variable for test }; // end class DetourExample const char* const DetourExample::CMD_LIST[] = { "-ipv6", // IPv6 test (instead of IPv4) NULL }; // This macro creates our ProtoApp derived application instance PROTO_INSTANTIATE_APP(DetourExample) DetourExample::DetourExample() : detour(NULL), ipv6_mode(false), allow(true) { } DetourExample::~DetourExample() { } void DetourExample::Usage() { #ifdef WIN32 fprintf(stderr, "detourExample [ipv6][background]\n"); #else fprintf(stderr, "detourExample\n"); #endif // if/else WIN32/UNIX } // end DetourExample::Usage() DetourExample::CmdType DetourExample::GetCmdType(const char* cmd) { if (!cmd) return CMD_INVALID; unsigned int len = strlen(cmd); bool matched = false; CmdType type = CMD_INVALID; const char* const* nextCmd = CMD_LIST; while (*nextCmd) { if (!strncmp(cmd, *nextCmd+1, len)) { if (matched) { // ambiguous command (command should match only once) return CMD_INVALID; } else { matched = true; if ('+' == *nextCmd[0]) type = CMD_ARG; else type = CMD_NOARG; } } nextCmd++; } return type; } // end DetourExample::GetCmdType() bool DetourExample::OnStartup(int argc, const char*const* argv) { SetDebugLevel(3); if (!ProcessCommands(argc, argv)) { PLOG(PL_ERROR, "detourExample::OnStartup() error processing command line options\n"); return false; } // Create our cap_rcvr instance and initialize ... if (!(detour = ProtoDetour::Create())) { PLOG(PL_ERROR, "detourExample::OnStartup() new ProtoDetour error: %s\n", GetErrorString()); return false; } detour->SetNotifier(static_cast(&dispatcher)); detour->SetListener(this, &DetourExample::DetourEventHandler); // Set detour filter for outbound multicast packets ProtoAddress srcFilter; ProtoAddress dstFilter; unsigned int dstFilterMask; if (ipv6_mode) { srcFilter.Reset(ProtoAddress::IPv6); // unspecified address dstFilter.ResolveFromString("ff00::"); dstFilterMask = 8; } else { srcFilter.Reset(ProtoAddress::IPv4); // unspecified address dstFilter.ResolveFromString("239.0.0.0"); dstFilterMask = 4; } if (!detour->Open(ProtoDetour::INPUT, srcFilter, 0, dstFilter, dstFilterMask)) { PLOG(PL_ERROR, "detourExample::OnStartup() ProtoDetour::Open() error\n"); } #ifdef NEVER //HAVE_SCHED // Boost process priority for real-time operation // (This _may_ work on Linux-only at this point) struct sched_param schp; memset(&schp, 0, sizeof(schp)); schp.sched_priority = sched_get_priority_max(SCHED_FIFO); if (sched_setscheduler(0, SCHED_FIFO, &schp)) { schp.sched_priority = sched_get_priority_max(SCHED_OTHER); if (sched_setscheduler(0, SCHED_OTHER, &schp)) PLOG(PL_ERROR, "detourExample: Warning! Couldn't set any real-time priority: %s\n", GetErrorString()); } #endif // HAVE_SCHED #ifdef WIN32 #ifndef _WIN32_WCE if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) PLOG(PL_ERROR, "detourExample: Warning! SetPriorityClass() error: %s\n", GetErrorString()); #endif // !_WIN32_WCE if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) PLOG(PL_ERROR, "detourExample: Warning! SetThreadPriority() error: %s\n", GetErrorString()); #endif // WIN32 TRACE("startup returning control to dispatcher ...\n"); return true; } // end DetourExample::OnStartup() void DetourExample::OnShutdown() { if (NULL != detour) { detour->Close(); delete detour; detour = NULL; } PLOG(PL_ERROR, "detourExample: Done.\n"); CloseDebugLog(); } // end DetourExample::OnShutdown() bool DetourExample::ProcessCommands(int argc, const char*const* argv) { // Dispatch command-line commands to our OnCommand() method int i = 1; while ( i < argc) { // Is it a class DetourExample command? switch (GetCmdType(argv[i])) { case CMD_INVALID: { PLOG(PL_ERROR, "DetourExample::ProcessCommands() Invalid command:%s\n", argv[i]); return false; } case CMD_NOARG: if (!OnCommand(argv[i], NULL)) { PLOG(PL_ERROR, "DetourExample::ProcessCommands() ProcessCommand(%s) error\n", argv[i]); return false; } i++; break; case CMD_ARG: if (!OnCommand(argv[i], argv[i+1])) { PLOG(PL_ERROR, "DetourExample::ProcessCommands() ProcessCommand(%s, %s) error\n", argv[i], argv[i+1]); return false; } i += 2; break; } } return true; } // end DetourExample::ProcessCommands() bool DetourExample::OnCommand(const char* cmd, const char* val) { // (TBD) move command processing into Mgen class ??? CmdType type = GetCmdType(cmd); ASSERT(CMD_INVALID != type); size_t len = strlen(cmd); if ((CMD_ARG == type) && !val) { PLOG(PL_ERROR, "DetourExample::ProcessCommand(%s) missing argument\n", cmd); return false; } else if (!strncmp("ipv6", cmd, len)) { ipv6_mode = true; } else { PLOG(PL_ERROR, "detourExample:: invalid command\n"); return false; } return true; } // end DetourExample::OnCommand() void DetourExample::DetourEventHandler(ProtoChannel& theChannel, ProtoChannel::Notification theNotification) { if (ProtoChannel::NOTIFY_INPUT == theNotification) { UINT32 buffer[8192/4]; unsigned int numBytes = 8192; if (detour->Recv((char*)buffer, numBytes)) { TRACE("detour recv'd packet ...\n"); if (0 != numBytes) { allow = true; if (allow) { TRACE("detour allowing packet len:%u\n", numBytes); ProtoPktIP ipPkt(buffer, numBytes); ipPkt.InitFromBuffer(numBytes); // This some example code that "translates" the dst addr // of certain outbound IP packets 224.0.0.251 -> 224.1.2.3 // (These are MDNS packets, by the way) ProtoAddress dstAddr; ipPkt.GetDstAddr(dstAddr); ProtoAddress matchAddress; matchAddress.ResolveFromString("224.0.0.251"); ProtoAddress goalAddress; goalAddress.ResolveFromString("224.1.2.3"); if (dstAddr.HostIsEqual(matchAddress)) { ipPkt.SetDstAddr(goalAddress); // Need to update UDP checksum if UDP packet // (yucky cross-layer UDP checksum) ProtoPktUDP udpPkt; if (udpPkt.InitFromPacket(ipPkt)) udpPkt.FinalizeChecksum(ipPkt); } // Some UDP packet manipulation code ProtoPktUDP udpPkt; if (udpPkt.InitFromPacket(ipPkt))// && (5000 == udpPkt.GetDstPort())) { if (udpPkt.ChecksumIsValid(ipPkt)) { TRACE(" UDP with valid checksum %04x (computed: %04x)\n", udpPkt.GetChecksum(), udpPkt.ComputeChecksum(ipPkt)); } else { TRACE(" UDP with INVALID checksum %04x (computed: %04x)\n", udpPkt.GetChecksum(), udpPkt.ComputeChecksum(ipPkt)); ProtoAddress srcAddr; ipPkt.GetSrcAddr(srcAddr); TRACE(" src:%s\n", srcAddr.GetHostString()); TRACE(" dst:%s\n", dstAddr.GetHostString()); ProtoPktIPv4 ipv4Pkt(ipPkt); TRACE(" proto:%d\n", ipv4Pkt.GetProtocol()); /* char base64Buffer[8192]; unsigned int length = ProtoBase64::Encode((char*)buffer, numBytes, base64Buffer, 8192); TRACE("packet(base64)=\n %s\n", base64Buffer); */ for (unsigned int i = 0; i < numBytes; i++) { if (0 == i) ; else if (0 == (i%16)) TRACE("\n"); else if (0 == (i%2)) TRACE(" "); unsigned char* ptr = (unsigned char*)buffer; TRACE("%02x", ptr[i]); } } } detour->Allow((char*)buffer, numBytes); //allow = false; // uncomment this to drop every other packet } else { TRACE("detour dropping/injecting packet ...\n"); detour->Drop(); detour->Inject((char*)buffer, numBytes); allow = true; } } numBytes = 8192; } } } // end DetourExample::DetourEventHandler() norm-1.5.8+dfsg2/protolib/examples/eventExample.cpp0000644000000000000000000001302613313744564017214 0ustar #include "protokit.h" #ifdef UNIX #include // for sleep() function #endif // UNIX /** * @class SimpleThread * * @brief This example illustrates the use of the ProtoEvent class threaded ProtoDispatcher. * * A "SimpleThread" class that uses a threaded ProtoDispatcher is defined that contains * a ProtoTimer that can be started that fires with a one-second interval and also * contains a ProtoEvent that can be signaled. The main() routine also has a * ProtEvent and uses its "Wait()" method to be signaled by the ProtoDispatcher. So, * this illustrates "procedural, "stand-alone" use of the ProtoEvent along with the * asynchronous I/O, notification-based use within the SimpleThread() * * When using a threaded ProtoDispatcher, make sure to call SuspendThread() * before manipulating dispatcher objects. (See SimpleThread::StartTimer() and * SimpleThread::StopTimer() as an example) */ class SimpleThread { public: SimpleThread(); ~SimpleThread(); bool Start(ProtoEvent* parentEvent); void Stop(); bool StartTimer() { bool result = dispatcher.SuspendThread(); if (result) { if (!timer.IsActive()) dispatcher.ActivateTimer(timer); dispatcher.ResumeThread(); } return result; } bool StopTimer() { bool result = dispatcher.SuspendThread(); { if (timer.IsActive()) timer.Deactivate(); dispatcher.ResumeThread(); } return result; } bool TimerIsActive() { bool result = dispatcher.SuspendThread(); if (result) { result = timer.IsActive(); dispatcher.ResumeThread(); } return result; } bool SetEvent() { bool result = dispatcher.SuspendThread(); if (result) { result = event.Set(); dispatcher.ResumeThread(); } return result; } private: void OnTimeout(ProtoTimer& theTimer); void OnEvent(ProtoEvent& theEvent); ProtoDispatcher dispatcher; ProtoTimer timer; ProtoEvent event; ProtoEvent* parent_event; unsigned int timeout_count; // how many timeouts before we signal parent_event }; // end class SimpleThread SimpleThread::SimpleThread() : event(true), parent_event(NULL), timeout_count(15) { timer.SetListener(this, &SimpleThread::OnTimeout); timer.SetInterval(1.0); timer.SetRepeat(-1); event.SetNotifier(&dispatcher); event.SetListener(this, &SimpleThread::OnEvent); } SimpleThread::~SimpleThread() { Stop(); } bool SimpleThread::Start(ProtoEvent* parentEvent) { if (!event.Open()) { PLOG(PL_ERROR, "eventExample: SimpleThread::Start() event open failure ...\n"); return false; } dispatcher.ActivateTimer(timer); if (dispatcher.StartThread()) { parent_event = parentEvent; return true; } else { PLOG(PL_ERROR, "eventExample: SimpleThread::Start() thread start failure ...\n"); timer.Deactivate(); event.Close(); return false; } } // end SimpleThread::Start() void SimpleThread::Stop() { dispatcher.Stop(); if (timer.IsActive()) timer.Deactivate(); event.Close(); } // end SimpleThread::Stop() /** * IMPORTANT NOTE @note Remember this timeout handler * is being called by the dispatcher child thread, _not_ * the main thread since we're using ProtoDispatcher::StartThread() * to run the dispatcher */ void SimpleThread::OnTimeout(ProtoTimer& theTimer) { TRACE("eventExample: child thread SimpleThread::OnTimeout() timeout_count:%d ...\n", timeout_count); if ((1 == timeout_count) && (NULL != parent_event)) { TRACE("eventExample: child thread signaling main thread ...\n"); parent_event->Set(); } if (0 != timeout_count) timeout_count--; } // end SimpleThread::OnTimeout() void SimpleThread::OnEvent(ProtoEvent& theEvent) { TRACE("eventExample: child thread SimpleThread::OnEvent() ...\n"); } // end SimpleThread::OnTimeout() int main(int argc, char* argv[]) { SimpleThread simpleThread; ProtoEvent myEvent(false); if (!myEvent.Open()) { PLOG(PL_ERROR, "eventExample:myEvent.Open() error:%s\n", GetErrorString()); return -1; } // This "starts" the simpleThread thread if (!simpleThread.Start(&myEvent)) { PLOG(PL_ERROR, "eventExample: SimpleThread::Start() error\n"); return -1; } int count = 2; while (count--) { #ifdef WIN32 Sleep(3000); #else sleep(3); #endif // if/else WIN32 TRACE("eventExample: main thread countdown = %d\n",count); if (0 == count) { TRACE("eventExample: main thread waiting for event signal from child ...\n"); myEvent.Wait(); TRACE("eventExample: main thread got event signal from child ...\n"); simpleThread.Stop(); } if (1 == count) { TRACE("eventExample: main thread signaling child thread ...\n"); simpleThread.SetEvent(); } } TRACE("eventExample: main thread simpleThread stopped.\n"); TRACE("eventExample: main thread Done.\n"); return 0; } // end main() norm-1.5.8+dfsg2/protolib/examples/graphExample.cpp0000644000000000000000000010110213124265255017160 0ustar // The purpose of this program is to illustrate use of the "MyGraph" class // (Note the "NetGraphTemplate" allows different graph subclasses to be // created with different metric properties. The "MyGraph" assumes // a non-negative "double" value metric for "link cost". #include "manetGraph.h" #include "protoSpace.h" // we use this for its bounding box iteration #include #include #include // for sprintf() #include // for rand(), srand() #include // for "isprint()" #include // for "sqrt()" // "FastReader" is handy class I use for doing // buffered (fast) reading of an input file. class FastReader { public: enum Result {OK, ERROR_, DONE, TIMEOUT}; FastReader(FILE* filePtr); FastReader::Result Read(char* buffer, unsigned int* len, double timeout = -1.0); FastReader::Result Readline(char* buffer, unsigned int* len, double timeout = -1.0); bool Seek(int offset); private: enum {BUFSIZE = 2048}; FILE* file_ptr; char savebuf[BUFSIZE]; char* saveptr; unsigned int savecount; }; // end class FastReader void Usage() { fprintf(stderr, "Usage: graphExample \n"); } const unsigned int MAX_LINE = 256; class MyNode; class MyInterface : public NetGraph::InterfaceTemplate { public: MyInterface(MyNode& theNode, const ProtoAddress& addr) : NetGraph::InterfaceTemplate(theNode, addr) {} MyInterface(MyNode& theNode) : NetGraph::InterfaceTemplate(theNode) {} }; // end class MyInterface class MyInterface; class MyNode : public NetGraph::NodeTemplate, public ProtoSpace::Node { public: MyNode(); ~MyNode(); // _MUST_ call init to create a default interface bool Init(const ProtoAddress& addr); unsigned int GetId() const; void SetRtrPriority(UINT8 value) {rtr_priority = value;} UINT8 GetRtrPriority() const {return rtr_priority;} void SetRelayStatus(bool state) {relay_status = state;} bool GetRelayStatus() const {return relay_status;} void SetVisited(bool state) {visited = state;} bool WasVisited() const {return visited;} void SetPosition(double xPos, double yPos) { ordinate[0] = xPos; ordinate[1] = yPos; } double GetOrdinateX() const {return ordinate[0];} double GetOrdinateY() const {return ordinate[1];} // ProtoSpace::Node required overrides unsigned int GetDimensions() const {return 2;} double GetOrdinate(unsigned int index) const {return (ordinate[index]);} const double* GetOrdinatePtr() const {return ordinate;} private: UINT8 rtr_priority; bool relay_status; bool visited; double ordinate[2]; // x,y coordinates }; // end class MyNode class MyGraph : public NetGraphTemplate {}; MyNode::MyNode() : rtr_priority(0) { ordinate[0] = ordinate[1] = 0.0; } MyNode::~MyNode() { } bool MyNode::Init(const ProtoAddress& addr) { MyGraph::Interface* iface = new MyGraph::Interface(*this, addr); if (NULL != iface) { return AppendInterface(*iface); } else { PLOG(PL_ERROR, "MyNode::Init() new MyGraph::Interface() error: %s\n", GetErrorString()); return false; } } // end MyNode::Init() unsigned int MyNode::GetId() const { MyGraph::Interface* iface = GetDefaultInterface(); if (NULL != iface) { UINT8* addrPtr = (UINT8*)(iface->GetAddress().GetRawHostAddress()); unsigned int id = addrPtr[2]; id = (id << 8) + addrPtr[3]; return id; } else { ASSERT(0); return ((unsigned int)-1); } } // end MyNode::GetId() const double RANGE_MAX = 300.0; inline double CalculateDistance(double x1, double y1, double x2,double y2) { double dx = x1 - x2; double dy = y1 - y2; return sqrt(dx*dx + dy*dy); } // end CalculateDistance() // This updates the "space" with data from the next time "epoch" double ReadNextEpoch(FastReader& reader, ProtoSpace& space, MyGraph& graph); // This updates the graph connectivity from the "space" and using "RANGE_MAX" comms range bool UpdateGraphFromSpace(MyGraph& graph, ProtoSpace& space, ProtoGraph::Vertice::SortedList::ItemPool* sortedVerticeItemPool); // This calculates an ECDS relay set given the "graph" int CalculateFullECDS(MyGraph& graph, MyGraph::Interface::SimpleList& relayList, ProtoGraph::Vertice::SortedList::ItemPool* sortedVerticeItemPool); // This calculates the nodal neighbor "density" of the given "graph" double CalculateDensity(MyGraph& graph); // Some "hacky" scaling factors to output a "GPS" version // (some other code needs to be uncommented, etc to use this) double X_MIN = -77.028633; double X_MAX = -77.021267; double X_SCALE = (X_MAX - X_MIN) / 1600.0; double Y_MIN = 38.828533; double Y_MAX = 38.822817; double Y_SCALE = (Y_MAX - Y_MIN) / 600.0; int main(int argc, char* argv[]) { // argv[1] is expected to be an ns-2 "mobility trace" file // (i.e. with "setdest" commands). This program uses the // "destinations" given from "setdest" commands to as node // positions. It does _not_ interpolate the "setdest" // locations itself. We will eventually create a more useful // version of this program (likely under a different name, etc) // that can use our more recently developed node location/motion // XML schema (See the NRL Mobile Network Modeling Tools). if (argc < 2) { Usage(); return -1; } // Create a MyGraph instance that we will populate // with nodes/interfaces from our "mobility trace file" MyGraph graph; // This is a pool of ProtoGraph::Vertice::SortedList::Items // that are used for temporary lists of MyGraph::Interfaces // as we adjust graph connectivity, etc. Note that the use of an // "external" item pool is _optional_ for the ProtoGraph/MyGraph // list classes, but can boost performance by reducing memory // alloc/deallocs when doing a lot of list manipulation. // If a list was inited with a "pool", then it is important to // keep the "pool" valid until after any associate "lists" are // destroyed as "pools" do _not_ keep track of which lists are // using them (yet!). ProtoGraph::Vertice::SortedList::ItemPool sortedVerticeItemPool; // We use the ProtoSpace to organize nodes by their position // and use the ProtoSpace bounding box iterator to efficiently // find adjacencies ProtoSpace space; // Open the trace file for reading FILE* infile = fopen(argv[1], "r"); if (NULL == infile) { perror("graphExample: fopen error"); return -1; } printf("bgbounds -100,-100,1500,500\n"); // Uncomment this for the "GPS" version //printf("bgbounds -77.028633,38.828533,-77.021267,38.822817\n"); double lastTime = -1.0; double nextTime; FastReader reader(infile); // "ReadNextEpoch" adds new "Nodes" to the "space" (and updates // the position of Nodes from prior epochs - the "graph" is provided // so that already existing "Nodes" can be found.) while (0.0 <= (nextTime = ReadNextEpoch(reader, space, graph))) { // Output "wait" command for SDT visualization, if applicable if (lastTime >= 0.0) printf("wait %f\n", (float)(1000.0 * (nextTime - lastTime))); lastTime = nextTime; // "UpdateGraphFromSpace()" adds/removes "links" between the Nodes depending // upon their spatial distance and the "RANGE_MAX" communications range // (TBD - pass the "comms range" as a parameter to this function?) TRACE("graphExample: Updating graph connections for time:%lf ..................................\n", nextTime); if (!UpdateGraphFromSpace(graph, space, &sortedVerticeItemPool)) { PLOG(PL_ERROR, "graphExample: error updating graph ...\n"); return -1; } TRACE("graphExample: Performing E-CDS relay set selection for time:%lf ===================================\n", nextTime); // "CalculateFullECDS" implements the ECDS relay set selection // algorithm, marking selected nodes using the MyNode::SetRelayStatus() // method. It also copies the selected nodes into the "relayList" // that is passed to it. (This is mainly for illustrative purposes // to demonstrate the utility of the MyGraph lists, iterators, etc MyGraph::Interface::SimpleList relayList; int relays = CalculateFullECDS(graph, relayList, &sortedVerticeItemPool); TRACE("relays is %d\n", relays); // Iterate over our relay set and color the relays "blue" and their // (non-relay) one-hop neighbors "green" // We also build up a "disconnectedList" by first putting all nodes // into it and then remove the relays and their one-hop neighbors. // The disconnected nodes remaining in the list are colored "red" // a) Initialize our "disconnectedList" with all ifaces in graph // (note we _could_ have used the "sortedVerticeItemPool" here as // well, but didn't to illustrate that it is optional. We // would perform better here if did use it, though. MyGraph::Interface::SortedList disconnectedList(&sortedVerticeItemPool); MyGraph::InterfaceIterator ifaceIterator(graph); MyGraph::Interface* iface; while (NULL != (iface = ifaceIterator.GetNextInterface())) disconnectedList.Insert(*iface); // b) Remove relays (and their neighbors) from the "disconnectedList" // and output appropriate node colors MyGraph::Interface::SimpleList::Iterator relayIterator(relayList); MyGraph::Interface* relayIface; while (NULL != (relayIface = relayIterator.GetNextInterface())) { // It's a relay, so remove from disconnected list if (NULL != disconnectedList.FindInterface(relayIface->GetAddress())) disconnectedList.Remove(*relayIface); MyNode& relayNode = relayIface->GetNode(); printf("node %d symbol circle,blue,3\n", relayNode.GetId()); MyGraph::AdjacencyIterator neighborIterator(*relayIface); MyGraph::Interface* neighborIface; while (NULL != (neighborIface = neighborIterator.GetNextAdjacency())) { // It's a relay neighbor, so remove from disconnected list if (NULL != disconnectedList.FindInterface(neighborIface->GetAddress())) disconnectedList.Remove(*neighborIface); MyNode& neighborNode = neighborIface->GetNode(); if (!neighborNode.GetRelayStatus()) printf("node %d symbol circle,green,3\n", neighborNode.GetId()); } } // c) Color any nodes remaining in "disconnectedList" red MyGraph::Interface::SortedList::Iterator dcIterator(disconnectedList); MyGraph::Interface* disconnectedIface; while (NULL != (disconnectedIface = dcIterator.GetNextInterface())) { MyNode& disconnectedNode =disconnectedIface->GetNode(); printf("node %d symbol circle,red,3\n", disconnectedNode.GetId()); } double nodedensity = 0; nodedensity = CalculateDensity(graph); TRACE("density is %f\n",nodedensity); } fprintf(stderr, "graphExample: Done.\n"); return 0; } // end main() double ReadNextEpoch(FastReader& reader, ProtoSpace& space, MyGraph& graph) { double lastTime = -1.0; // Read the "setdest" lines from the file, finding // new nodes and their x,y positions versus time // line format we want is ' at