diff options
| author | Chris Hiszpanski <chris@liburtc.org> | 2021-04-23 11:17:03 -0400 | 
|---|---|---|
| committer | Chris Hiszpanski <chris@liburtc.org> | 2021-04-23 11:17:03 -0400 | 
| commit | 79f4f70de1a6014d53b245b8069c833ce943f943 (patch) | |
| tree | eb998bbcb5348ff61428b8e9f00ce55c33419fd6 | |
| parent | bf35c493b425886f12e3daf530239b5e6b1bca7d (diff) | |
Update inline license blocks and expand tabs
| -rw-r--r-- | examples/callee.c | 62 | ||||
| -rw-r--r-- | examples/demo.html | 15 | ||||
| -rw-r--r-- | examples/sandbox.c | 33 | ||||
| -rw-r--r-- | include/config.h | 34 | ||||
| -rw-r--r-- | include/ice.h | 34 | ||||
| -rw-r--r-- | include/peerconn.h | 34 | ||||
| -rw-r--r-- | include/runloop.h | 34 | ||||
| -rw-r--r-- | include/str.h | 34 | ||||
| -rw-r--r-- | include/stun.h | 134 | ||||
| -rw-r--r-- | include/urtc.h | 34 | ||||
| -rw-r--r-- | src/err.h | 88 | ||||
| -rw-r--r-- | src/g711.c | 58 | ||||
| -rw-r--r-- | src/g711.h | 36 | ||||
| -rw-r--r-- | src/g711_tables.c | 1470 | ||||
| -rw-r--r-- | src/log.h | 99 | ||||
| -rw-r--r-- | src/mdns.c | 949 | ||||
| -rw-r--r-- | src/mdns.h | 45 | ||||
| -rw-r--r-- | src/prng.c | 53 | ||||
| -rw-r--r-- | src/prng.h | 45 | ||||
| -rw-r--r-- | src/sdp.c | 1013 | ||||
| -rw-r--r-- | src/sdp.h | 177 | ||||
| -rw-r--r-- | src/urtc.c | 530 | ||||
| -rw-r--r-- | src/urtc.h | 48 | ||||
| -rw-r--r-- | src/uuid.c | 87 | ||||
| -rw-r--r-- | src/uuid.h | 57 | 
25 files changed, 2629 insertions, 2574 deletions
| diff --git a/examples/callee.c b/examples/callee.c new file mode 100644 index 0000000..4fb7ddf --- /dev/null +++ b/examples/callee.c @@ -0,0 +1,62 @@ +/** + * Simple callee example (web browser is caller). Sends video to caller upon + * incoming calls. + * + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + +#include <signal.h> +#include <unistd.h> + +#include "urtc.h" + + +int main() { +	sigset_t ss; +	int signal; + +	const char *stun[] = { +		"stun.liburtc.org", +		NULL +	}; + +	sigemptyset(&ss); +	sigaddset(&ss, SIGINT); +	sigaddset(&ss, SIGTERM); +	sigaddset(&ss, SIGQUIT); + +        // create a new peer connection (no actual network communication yet) +	urtc_peerconn_t *pc = urtc_peerconn_create(NULL); + +	// connect to signaling service + +	sigwait(&ss, &signal); + +	urtc_peerconn_destroy(pc); + +	return 0; +} + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ diff --git a/examples/demo.html b/examples/demo.html new file mode 100644 index 0000000..03e07b9 --- /dev/null +++ b/examples/demo.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +  <head> +    <title>liburtc demo</title> +    <script src="//webrtchacks.github.io/adapter/adapter-latest.js"></script> +    <script> +      // call liburtc peer +    </script> +  </head> +  <body> +    <h1>liburtc demo</h1> + +    <video autoplay controls muted playsinline id="remoteVideo"></video> +  </body> +</html> diff --git a/examples/sandbox.c b/examples/sandbox.c deleted file mode 100644 index 2f3728d..0000000 --- a/examples/sandbox.c +++ /dev/null @@ -1,33 +0,0 @@ -#include <signal.h> -#include <unistd.h> - -#include "mdns.h" -#include "urtc.h" - - -int main() { -	sigset_t ss; -	int signal; - -	const char *stun[] = { -		"stun.l.google.com:19302", -		"stun2.l.google.com:19302", -		NULL -	}; - -	sigemptyset(&ss); -	sigaddset(&ss, SIGINT); -	sigaddset(&ss, SIGTERM); -	sigaddset(&ss, SIGQUIT); - -	urtc_peerconn_t *pc = urtc_peerconn_create(stun); - -	// query for raspberry.local -	mdns_query("raspberry"); - -	sigwait(&ss, &signal); - -	urtc_peerconn_destroy(pc); - -	return 0; -} diff --git a/include/config.h b/include/config.h index a003218..ef59ab1 100644 --- a/include/config.h +++ b/include/config.h @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef URTC_CONFIG_H diff --git a/include/ice.h b/include/ice.h index 8b7251f..0f929f7 100644 --- a/include/ice.h +++ b/include/ice.h @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef URTC_ICE_H diff --git a/include/peerconn.h b/include/peerconn.h index feecc0e..63e83ce 100644 --- a/include/peerconn.h +++ b/include/peerconn.h @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef URTC_PEERCONN_H diff --git a/include/runloop.h b/include/runloop.h index ea840e7..8162016 100644 --- a/include/runloop.h +++ b/include/runloop.h @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  /** diff --git a/include/str.h b/include/str.h index f0164d3..d8dc6fb 100644 --- a/include/str.h +++ b/include/str.h @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef URTC_STR_H diff --git a/include/stun.h b/include/stun.h deleted file mode 100644 index 126e7f5..0000000 --- a/include/stun.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski - *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. - */ - -#ifndef URTC_STUN_H -#define URTC_STUN_H - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define SIZEOF_STUN_HDR				20 - -// STUN Classes -#define STUN_CLASS_REQUEST			0 -#define STUN_CLASS_INDICTATION		1 -#define STUN_CLASS_SUCCESS			2 -#define STUN_CLASS_ERROR			3 - -// STUN Methods -#define STUN_METHOD_RESERVED		0 -#define STUN_METHOD_BINDING			1 - - -/////////////////////////////  TYPE DEFINITIONS  ///////////////////////////// - -typedef struct { -	int rc;								// Retransmission count -	int rto;							// Retransmission timeout (in ms) -	int sockfd;							// Socket file descriptor -} stun_client_t; - -typedef struct { -	char *server; -} stun_client_config_t; - -// STUN Message Header -typedef struct __attribute__((__packed__)) { -	uint16_t reserved:2;				// Upper two bits are 0 -	uint16_t type:14;					// 14-bit type -	uint16_t msglen;					// Message length -	uint32_t cookie;					// Magic cookie -	uint8_t  txid[12];					// Transaction ID -} stun_msg_hdr_t; - -// STUN Attribute -typedef struct { -	uint16_t type;						// Attribute type -	uint16_t len;						// Value length, prior to padding -	uint8_t *val;						// Pointer to attribute value -} stun_attr_t; - -// STUN Attribute: MAPPED-ADDRESS -typedef struct __attribute__((__packed__)) { -	uint8_t reserved; -	uint8_t family; -	uint16_t port; -	union { -		uint8_t ipv4[4];				// IPv4 address is 32-bits -		uint8_t ipv6[16];				// IPv6 address is 128-bits -	}; -} stun_attr_mapped_address_t; - -// STUN Attribute: XOR-MAPPED-ADDRESS -typedef stun_attr_mapped_address_t stun_attr_xor_mapped_address_t; - -// STUN Attribute: USERNAME - - -//////////////////////////////////  MACROS  ////////////////////////////////// - -// Get class from message header type -#define CLASS(typ) (((typ >> 7) & 0x2) | ((typ >> 4) & 0x1)) - -// Get method from message header type -#define METHOD(typ) (((typ >> 2) & 0xF80) | ((typ >> 1) & 0x70) | (typ & 0xF)) - -#define TYPE(cls, mthd) ( \ -		((mthd & 0xF80) << 2) | \ -		((cls & 0x2) << 7) | \ -		((mthd & 0x70) << 1) | \ -		((cls & 0x1) << 4) | \ -		(mthd & 0xF) \ -) - - -///////////////////////////  FORWARD DECLARATIONS  /////////////////////////// - -/** - * (callback) Binding request response handler - * - * @param[in] name - * @param[in] arg  User argument - */ -typedef void (*stun_client_binding_response_callback)( -	const char *name, -	      void *arg -); - -/** - * Sends a STUN binding request to the specified server - * - * @param[in] srv  Server (hostname or IP address) - * @param[in] cb   Handler to call when a response is received - * @param[in] arg  Optional user argument to pass to callback - */ -err_t stun_client_binding_request( -	runloop_t *rl, -	const char *srv, -	stun_client_binding_response_callback cb, -	void *arg -); - -#ifdef __cplusplus -} -#endif - -#endif /* URTC_STUN_H */ diff --git a/include/urtc.h b/include/urtc.h index 3eabba0..abf2939 100644 --- a/include/urtc.h +++ b/include/urtc.h @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef URTC_H @@ -1,26 +1,30 @@ -/* - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */ +  #ifndef _URTC_ERR_H  #define _URTC_ERR_H @@ -29,26 +33,26 @@ extern "C" {  #endif  typedef enum err { -	URTC_SUCCESS = 0, - -	URTC_ERR, - -	URTC_ERR_BAD_ARGUMENT, -	URTC_ERR_INSUFFICIENT_MEMORY, -	URTC_ERR_MALFORMED, -	URTC_ERR_NOT_IMPLEMENTED, - -	URTC_ERR_PEERCONN_MISSING_REMOTE_DESC, - -	URTC_ERR_SDP_MALFORMED, -	URTC_ERR_SDP_MALFORMED_VERSION, -	URTC_ERR_SDP_MALFORMED_ORIGIN, -	URTC_ERR_SDP_MALFORMED_TIMING, -	URTC_ERR_SDP_MALFORMED_MEDIA, -	URTC_ERR_SDP_MALFORMED_ATTRIBUTE, -	URTC_ERR_SDP_UNSUPPORTED_FINGERPRINT_ALGO, -	URTC_ERR_SDP_UNSUPPORTED_MEDIA_PROTOCOL, -	URTC_ERR_SDP_UNSUPPORTED_MEDIA_TYPE +    URTC_SUCCESS = 0, + +    URTC_ERR, + +    URTC_ERR_BAD_ARGUMENT, +    URTC_ERR_INSUFFICIENT_MEMORY, +    URTC_ERR_MALFORMED, +    URTC_ERR_NOT_IMPLEMENTED, + +    URTC_ERR_PEERCONN_MISSING_REMOTE_DESC, + +    URTC_ERR_SDP_MALFORMED, +    URTC_ERR_SDP_MALFORMED_VERSION, +    URTC_ERR_SDP_MALFORMED_ORIGIN, +    URTC_ERR_SDP_MALFORMED_TIMING, +    URTC_ERR_SDP_MALFORMED_MEDIA, +    URTC_ERR_SDP_MALFORMED_ATTRIBUTE, +    URTC_ERR_SDP_UNSUPPORTED_FINGERPRINT_ALGO, +    URTC_ERR_SDP_UNSUPPORTED_MEDIA_PROTOCOL, +    URTC_ERR_SDP_UNSUPPORTED_MEDIA_TYPE  } err_t;  #ifdef __cplusplus @@ -56,3 +60,5 @@ typedef enum err {  #endif  #endif /* _URTC_ERR_H */ + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #include <stdio.h> @@ -21,20 +29,22 @@  #include "g711.h"  void g711_encode(uint8_t *dst, const int16_t *src, size_t n) { -	int i; +    int i; -	for (i = 0; i < n; i++) { -		dst[i] = pcm2ulaw[0x1FFF & (src[i] >> 3)]; -	} +    for (i = 0; i < n; i++) { +        dst[i] = pcm2ulaw[0x1FFF & (src[i] >> 3)]; +    }  }  void g711_decode(int16_t *dst, const uint8_t *src, size_t n) { -	int i; +    int i; -	for (i = 0; i < n; i++) { -		fprintf(stderr, "i = %i, src[i] = %i\n", i, src[i]); -		fprintf(stderr, "ulaw2pcm[i] = %i\n", ulaw2pcm[0]); -//		dst[i] = ulaw2pcm[src[i]] << 3; -		dst[i] = 0; -	} +    for (i = 0; i < n; i++) { +        fprintf(stderr, "i = %i, src[i] = %i\n", i, src[i]); +        fprintf(stderr, "ulaw2pcm[i] = %i\n", ulaw2pcm[0]); +//      dst[i] = ulaw2pcm[src[i]] << 3; +        dst[i] = 0; +    }  } + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright (C) 2019 Chris Hiszpanski +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved.   *  - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met:   *  - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.   *  - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef URTC_G711_H @@ -66,3 +74,5 @@ void g711_decode(int16_t *dst, const uint8_t *src, size_t n);  #endif  #endif /* URTC_G711_H */ + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ diff --git a/src/g711_tables.c b/src/g711_tables.c index 0690d1a..f306a3d 100644 --- a/src/g711_tables.c +++ b/src/g711_tables.c @@ -1,19 +1,27 @@ -/* - * liburtc - * Copyright 2019 Chris Hiszpanski - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program.  If not, see <https://www.gnu.org/licenses/>. +/** + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #include <stdint.h> @@ -22,724 +30,724 @@  /* Table for ITU-T G.711 mu-law companding from 16-bit signed PCM */  const uint8_t pcm2ulaw[] = { -	0xff, 0xfe, 0xfe, 0xfd, 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, -	0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, -	0xf3, 0xf2, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, -	0xee, 0xee, 0xee, 0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, -	0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, -	0xe8, 0xe8, 0xe8, 0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, -	0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, -	0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, -	0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, -	0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, -	0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, -	0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, -	0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, -	0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, -	0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, -	0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, -	0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, -	0xd2, 0xd2, 0xd2, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, -	0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, -	0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, -	0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, -	0xce, 0xce, 0xce, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, -	0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, -	0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, -	0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, -	0xcb, 0xcb, 0xcb, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, -	0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, -	0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, -	0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, -	0xc8, 0xc8, 0xc8, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, -	0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -	0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, -	0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, -	0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, -	0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, -	0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, -	0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, -	0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, -	0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -	0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, -	0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, -	0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, -	0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, -	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, -	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, -	0xbe, 0xbe, 0xbe, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, -	0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, -	0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, -	0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, -	0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, -	0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, -	0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, -	0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, -	0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, -	0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, -	0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, -	0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, -	0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, -	0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, -	0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, -	0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, -	0xb8, 0xb8, 0xb8, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, -	0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, -	0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, -	0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, -	0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, -	0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, -	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, -	0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, -	0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, -	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, -	0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, -	0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, -	0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, -	0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, -	0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, -	0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, -	0xb2, 0xb2, 0xb2, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, -	0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, -	0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, -	0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, -	0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, -	0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, -	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, -	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, -	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, -	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, -	0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, -	0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, -	0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, -	0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, -	0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, -	0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, -	0xae, 0xae, 0xae, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, -	0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, -	0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, -	0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, -	0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, -	0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, -	0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, -	0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, -	0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, -	0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, -	0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, -	0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, -	0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, -	0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, -	0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, -	0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, -	0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, -	0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, -	0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, -	0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, -	0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, -	0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, -	0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, -	0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, -	0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, -	0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, -	0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, -	0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, -	0xa8, 0xa8, 0xa8, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, -	0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, -	0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, -	0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, -	0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, -	0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, -	0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, -	0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, -	0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, -	0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, -	0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, -	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, -	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, -	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, -	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, -	0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, -	0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, -	0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, -	0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, -	0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, -	0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, -	0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, -	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, -	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, -	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, -	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, -	0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, -	0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, -	0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, -	0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, -	0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, -	0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, -	0xa2, 0xa2, 0xa2, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, -	0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, -	0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, -	0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, -	0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, -	0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, -	0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, -	0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, -	0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, -	0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, -	0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, -	0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, -	0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, -	0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, -	0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, -	0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, -	0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, -	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, -	0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, -	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, -	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, -	0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, -	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, -	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, -	0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, -	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, -	0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, -	0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, -	0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, -	0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, -	0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, -	0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, -	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, -	0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, -	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, -	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, -	0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, -	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, -	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, -	0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, -	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 +    0xff, 0xfe, 0xfe, 0xfd, 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, +    0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, +    0xf3, 0xf2, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, +    0xee, 0xee, 0xee, 0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, +    0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, +    0xe8, 0xe8, 0xe8, 0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, +    0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, +    0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, +    0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, +    0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, +    0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, +    0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, +    0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, +    0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, +    0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, +    0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, +    0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, +    0xd2, 0xd2, 0xd2, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, +    0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, +    0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, +    0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, +    0xce, 0xce, 0xce, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, +    0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, +    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, +    0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, +    0xcb, 0xcb, 0xcb, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, +    0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, +    0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, +    0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, +    0xc8, 0xc8, 0xc8, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, +    0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +    0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, +    0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, +    0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, +    0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, +    0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, +    0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, +    0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, +    0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, +    0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, +    0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, +    0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, +    0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, +    0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, +    0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, +    0xbe, 0xbe, 0xbe, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, +    0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, +    0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, +    0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, +    0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, +    0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, +    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, +    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, +    0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, +    0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, +    0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, +    0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, +    0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, +    0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, +    0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, +    0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, +    0xb8, 0xb8, 0xb8, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, +    0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, +    0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, +    0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, +    0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, +    0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, +    0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, +    0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, +    0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, +    0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, +    0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, +    0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, +    0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, +    0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, +    0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, +    0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, +    0xb2, 0xb2, 0xb2, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, +    0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, +    0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, +    0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, +    0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, +    0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, +    0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, +    0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, +    0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, +    0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, +    0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, +    0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, +    0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, +    0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, +    0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, +    0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, +    0xae, 0xae, 0xae, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, +    0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, +    0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, +    0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, +    0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, +    0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, +    0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, +    0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, +    0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, +    0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, +    0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, +    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, +    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, +    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, +    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, +    0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, +    0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, +    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, +    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, +    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, +    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, +    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, +    0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, +    0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, +    0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, +    0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, +    0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, +    0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, +    0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, +    0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, +    0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, +    0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, +    0xa8, 0xa8, 0xa8, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, +    0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, +    0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, +    0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, +    0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, +    0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, +    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, +    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, +    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, +    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, +    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, +    0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, +    0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, +    0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, +    0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, +    0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, +    0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, +    0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, +    0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, +    0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, +    0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, +    0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, +    0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, +    0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, +    0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, +    0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, +    0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, +    0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, +    0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, +    0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, +    0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, +    0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, +    0xa2, 0xa2, 0xa2, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, +    0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, +    0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, +    0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, +    0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, +    0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, +    0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, +    0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, +    0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, +    0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, +    0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, +    0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, +    0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, +    0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, +    0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, +    0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, +    0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, +    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, +    0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, +    0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, +    0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, +    0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, +    0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, +    0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, +    0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, +    0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, +    0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, +    0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, +    0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, +    0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, +    0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, +    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, +    0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +    0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, +    0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, +    0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, +    0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, +    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, +    0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, +    0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, +    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80  };  /* Table for ITU-T G.711 mu-law decompanding to 16-bit signed PCM */  const int16_t ulaw2pcm[] = { -	-32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -	-23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -	-15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, -	-11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -	-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -	-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -	-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, -	-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -	-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, -	-1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -	-876, -844, -812, -780, -748, -716, -684, -652, -	-620, -588, -556, -524, -492, -460, -428, -396, -	-372, -356, -340, -324, -308, -292, -276, -260, -	-244, -228, -212, -196, -180, -164, -148, -132, -	-120, -112, -104, -96, -88, -80, -72, -64, -	-56, -48, -40, -32, -24, -16, -8, 0, +    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, +    -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, +    -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, +    -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, +    -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, +    -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, +    -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, +    -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, +    -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, +    -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, +    -876, -844, -812, -780, -748, -716, -684, -652, +    -620, -588, -556, -524, -492, -460, -428, -396, +    -372, -356, -340, -324, -308, -292, -276, -260, +    -244, -228, -212, -196, -180, -164, -148, -132, +    -120, -112, -104, -96, -88, -80, -72, -64, +    -56, -48, -40, -32, -24, -16, -8, 0, -	32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, -	23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, -	15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, -	11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, -	7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, -	5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, -	3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, -	2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, -	1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, -	1372, 1308, 1244, 1180, 1116, 1052, 988, 924, -	876, 844, 812, 780, 748, 716, 684, 652, -	620, 588, 556, 524, 492, 460, 428, 396, -	372, 356, 340, 324, 308, 292, 276, 260, -	244, 228, 212, 196, 180, 164, 148, 132, -	120, 112, 104, 96, 88, 80, 72, 64, -	56, 48, 40, 32, 24, 16, 8, 0 +    32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, +    23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, +    15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, +    11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, +    7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, +    5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, +    3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, +    2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, +    1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, +    1372, 1308, 1244, 1180, 1116, 1052, 988, 924, +    876, 844, 812, 780, 748, 716, 684, 652, +    620, 588, 556, 524, 492, 460, 428, 396, +    372, 356, 340, 324, 308, 292, 276, 260, +    244, 228, 212, 196, 180, 164, 148, 132, +    120, 112, 104, 96, 88, 80, 72, 64, +    56, 48, 40, 32, 24, 16, 8, 0  }; @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef _URTC_LOG_H @@ -31,40 +34,40 @@ extern "C" {  #endif  enum level { -	TRACE = 0, -	DEBUG, -	INFO, -	WARN, -	ERROR, -	FATAL, -	NUM_LEVELS // must be last +    TRACE = 0, +    DEBUG, +    INFO, +    WARN, +    ERROR, +    FATAL, +    NUM_LEVELS // must be last  };  static const char *logl[NUM_LEVELS] = { -	"\033[0;37m",	// trace	(gray) -	"\033[0;32m",	// debug	(green) -	          "",	// info		(white) -	"\033[0;33m",	// warn		(yellow) -	"\033[0;35m",	// error	(magenta) -	"\033[0;31m"	// fatal	(red) +    "\033[0;37m",   // trace    (gray) +    "\033[0;32m",   // debug    (green) +              "",   // info     (white) +    "\033[0;33m",   // warn     (yellow) +    "\033[0;35m",   // error    (magenta) +    "\033[0;31m"    // fatal    (red)  };  static const char *logn[NUM_LEVELS] = { -	"[trace] ",		// trace	(gray) -	"[debug] ",		// debug	(green) -	"[info] ",		// info		(white) -	"[warn] ",		// warn		(yellow) -	"[error] ",		// error	(magenta) -	"[fatal] "		// fatal	(red) +    "[trace] ",     // trace    (gray) +    "[debug] ",     // debug    (green) +    "[info] ",      // info     (white) +    "[warn] ",      // warn     (yellow) +    "[error] ",     // error    (magenta) +    "[fatal] "      // fatal    (red)  };  static const char *logr[NUM_LEVELS] = { -	"\033[0m\n",			// trace -	"\033[0m\n",			// debug -	       "\n",			// info -	"\033[0m\n",			// warn -	"\033[0m\n",			// error -	"\033[0m\n"				// fatal +    "\033[0m\n",            // trace +    "\033[0m\n",            // debug +           "\n",            // info +    "\033[0m\n",            // warn +    "\033[0m\n",            // error +    "\033[0m\n"             // fatal  };  #define STRINGIFY(x) #x @@ -72,9 +75,9 @@ static const char *logr[NUM_LEVELS] = {  #define AT __FILE__ ":" TOSTRING(__LINE__)  #define log(lvl, format, ...) \ -	do { \ -		fprintf(stderr, "%s" AT " %s" format "%s", logl[lvl], logn[lvl], ##__VA_ARGS__, logr[lvl]); \ -	} while (0); +    do { \ +        fprintf(stderr, "%s" AT " %s" format "%s", logl[lvl], logn[lvl], ##__VA_ARGS__, logr[lvl]); \ +    } while (0);  #ifdef _cplusplus  } @@ -1,40 +1,43 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #include <errno.h> -#include <net/if.h>						// IFF_LOOPBACK (include pre ifaddrs.h) -#include <ifaddrs.h>					// getifaddrs -#include <limits.h>						// HOST_NAME_MAX +#include <net/if.h>                     // IFF_LOOPBACK (include pre ifaddrs.h) +#include <ifaddrs.h>                    // getifaddrs +#include <limits.h>                     // HOST_NAME_MAX  #include <stdbool.h> -#include <string.h>						// memcpy -#include <unistd.h>						// sleep +#include <string.h>                     // memcpy +#include <unistd.h>                     // sleep  #include <arpa/inet.h>  #include <netinet/in.h>  #ifdef WITH_IPV6    #include <netinet6/in6.h>  #endif -#include <sys/socket.h>					// sendto, setsocketopt, socket +#include <sys/socket.h>                 // sendto, setsocketopt, socket  #include "err.h"  #include "log.h" @@ -46,7 +49,7 @@  #define DEFAULT_TTL                120  // time-to-live recommended by RFC 6762 -#define CLASS_INTERNET	             1 +#define CLASS_INTERNET               1  #define CACHE_FLUSH           (1 << 15)  #define FLAG_RESPONSE         (1 << 15) @@ -57,26 +60,26 @@  #endif  struct __attribute__((__packed__)) header { -	uint16_t id; -	uint16_t flags; -	uint16_t n_question;				// number of question records -	uint16_t n_answer;					// number of answer records -	uint16_t n_authority;				// number of authority records -	uint16_t n_additional;				// number of additional records +    uint16_t id; +    uint16_t flags; +    uint16_t n_question;                // number of question records +    uint16_t n_answer;                  // number of answer records +    uint16_t n_authority;               // number of authority records +    uint16_t n_additional;              // number of additional records  };  struct __attribute__((__packed__)) qname { -	uint8_t size; -	uint8_t name[]; +    uint8_t size; +    uint8_t name[];  };  struct __attribute__((__packed__)) answer { -	// variable length name precedes answer -	uint16_t type; -	uint16_t class; -	uint32_t ttl; -	uint16_t size; -	uint8_t  data[]; +    // variable length name precedes answer +    uint16_t type; +    uint16_t class; +    uint32_t ttl; +    uint16_t size; +    uint8_t  data[];  };  /** @@ -88,88 +91,88 @@ struct __attribute__((__packed__)) answer {   * \return Socket file descriptor on success, negative on error.   */  int mdns_subscribe() { -	// create socket -	int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); -	if (-1 == sockfd) { -		log(ERROR, "%s", strerror(errno)); -		goto _fail_create_socket; -	} - -	// enable address/port reuse -	{ -		const unsigned int opt = 1; -		if (-1 == setsockopt( -			sockfd, -			SOL_SOCKET, +    // create socket +    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +    if (-1 == sockfd) { +        log(ERROR, "%s", strerror(errno)); +        goto _fail_create_socket; +    } + +    // enable address/port reuse +    { +        const unsigned int opt = 1; +        if (-1 == setsockopt( +            sockfd, +            SOL_SOCKET,  #if defined(__APPLE__) || defined(__FreeBSD__) -			SO_REUSEPORT, +            SO_REUSEPORT,  #else -			SO_REUSEADDR, +            SO_REUSEADDR,  #endif -			&opt, -			sizeof(opt) -		)) { -			log(ERROR, "%s", strerror(errno)); -			goto _fail_enable_addr_reuse; -		} -	} - -	// bind socket to mDNS query port -	{ -		const struct sockaddr_in mgroup = { -			.sin_family = AF_INET, -			.sin_addr.s_addr = htonl(INADDR_ANY), -			.sin_port = htons(MDNS_PORT) -		}; -		if (-1 == bind(sockfd, (struct sockaddr *)(&mgroup), sizeof(mgroup))) { -			log(ERROR, "%s", strerror(errno)); -			goto _fail_bind; -		} -	} - -	// disable loopback -	{ -		const int opt = 0; -		if (-1 == setsockopt( -			sockfd, -			IPPROTO_IP, -			IP_MULTICAST_LOOP, -			&opt, -			sizeof(opt) -		)) { -			log(ERROR, "setsockopt: %s", strerror(errno)); -			goto _fail_disable_loopback; -		} -	} - -	// join multicast group -	{ -		const struct ip_mreqn imr = { -			.imr_multiaddr.s_addr = inet_addr(MDNS_ADDR), -			.imr_address.s_addr = htonl(INADDR_ANY) -		}; -		if (-1 == setsockopt( -			sockfd, -			IPPROTO_IP, -			IP_ADD_MEMBERSHIP, -			&imr, -			sizeof(imr) -		)) { -			log(ERROR, "setsockopt: %s", strerror(errno)); -			goto _fail_join_multicast_group; -		} -	} - -	return sockfd; +            &opt, +            sizeof(opt) +        )) { +            log(ERROR, "%s", strerror(errno)); +            goto _fail_enable_addr_reuse; +        } +    } + +    // bind socket to mDNS query port +    { +        const struct sockaddr_in mgroup = { +            .sin_family = AF_INET, +            .sin_addr.s_addr = htonl(INADDR_ANY), +            .sin_port = htons(MDNS_PORT) +        }; +        if (-1 == bind(sockfd, (struct sockaddr *)(&mgroup), sizeof(mgroup))) { +            log(ERROR, "%s", strerror(errno)); +            goto _fail_bind; +        } +    } + +    // disable loopback +    { +        const int opt = 0; +        if (-1 == setsockopt( +            sockfd, +            IPPROTO_IP, +            IP_MULTICAST_LOOP, +            &opt, +            sizeof(opt) +        )) { +            log(ERROR, "setsockopt: %s", strerror(errno)); +            goto _fail_disable_loopback; +        } +    } + +    // join multicast group +    { +        const struct ip_mreqn imr = { +            .imr_multiaddr.s_addr = inet_addr(MDNS_ADDR), +            .imr_address.s_addr = htonl(INADDR_ANY) +        }; +        if (-1 == setsockopt( +            sockfd, +            IPPROTO_IP, +            IP_ADD_MEMBERSHIP, +            &imr, +            sizeof(imr) +        )) { +            log(ERROR, "setsockopt: %s", strerror(errno)); +            goto _fail_join_multicast_group; +        } +    } + +    return sockfd;  _fail_join_multicast_group:  _fail_disable_loopback:  _fail_bind:  _fail_enable_addr_reuse: -	close(sockfd); +    close(sockfd);  _fail_create_socket: -	return -URTC_ERR; +    return -URTC_ERR;  }  /** @@ -182,12 +185,12 @@ _fail_create_socket:   * \return 0 on success, negative on error.   */  int mdns_unsubscribe(int sockfd) { -	if (-1 == close(sockfd)) { -		log(ERROR, "close: %s", strerror(errno)); -		return -URTC_ERR; -	} +    if (-1 == close(sockfd)) { +        log(ERROR, "close: %s", strerror(errno)); +        return -URTC_ERR; +    } -	return 0; +    return 0;  }  /** @@ -198,52 +201,52 @@ int mdns_unsubscribe(int sockfd) {   * \return 0 on success, negative on error.   */  int mdns_query(const char *name) { -	// create socket -	int msockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); -	if (-1 == msockfd) { -		log(FATAL, "socket: %s", strerror(errno)); -	} - -	uint8_t q[512]; -	size_t qlen = 0; - -	// header -	struct header hdr = { -		.n_question = htons(1) -	}; -	memcpy(&q[qlen], &hdr, sizeof(hdr)); -	qlen += sizeof(hdr); - -	// qname -	q[qlen] = strlen(name); -	memcpy(&q[1 + qlen], name, strlen(name)); -	qlen += 1 + q[qlen]; - -	q[qlen] = strlen("local"); -	memcpy(&q[1 + qlen], "local", strlen("local")); -	qlen += 1 + q[qlen]; - -	q[qlen++] = 0; // root record - -	// qtype: 255 = any -	q[qlen++] = 0; -	q[qlen++] = 255; - -	// qclass: 1 = ipv4 -	q[qlen++] = 0x80; // unicast response please -	q[qlen++] = 1; - -	// send query -	struct sockaddr_in mgroup = { -		.sin_family = AF_INET, -		.sin_addr.s_addr = inet_addr(MDNS_ADDR), -		.sin_port = htons(MDNS_PORT) -	}; -	if (-1 == sendto(msockfd, q, qlen, 0, (struct sockaddr *)(&mgroup), sizeof(mgroup))) { -		log(FATAL, "sendto: %s", strerror(errno)); -	} - -	return 0; +    // create socket +    int msockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +    if (-1 == msockfd) { +        log(FATAL, "socket: %s", strerror(errno)); +    } + +    uint8_t q[512]; +    size_t qlen = 0; + +    // header +    struct header hdr = { +        .n_question = htons(1) +    }; +    memcpy(&q[qlen], &hdr, sizeof(hdr)); +    qlen += sizeof(hdr); + +    // qname +    q[qlen] = strlen(name); +    memcpy(&q[1 + qlen], name, strlen(name)); +    qlen += 1 + q[qlen]; + +    q[qlen] = strlen("local"); +    memcpy(&q[1 + qlen], "local", strlen("local")); +    qlen += 1 + q[qlen]; + +    q[qlen++] = 0; // root record + +    // qtype: 255 = any +    q[qlen++] = 0; +    q[qlen++] = 255; + +    // qclass: 1 = ipv4 +    q[qlen++] = 0x80; // unicast response please +    q[qlen++] = 1; + +    // send query +    struct sockaddr_in mgroup = { +        .sin_family = AF_INET, +        .sin_addr.s_addr = inet_addr(MDNS_ADDR), +        .sin_port = htons(MDNS_PORT) +    }; +    if (-1 == sendto(msockfd, q, qlen, 0, (struct sockaddr *)(&mgroup), sizeof(mgroup))) { +        log(FATAL, "sendto: %s", strerror(errno)); +    } + +    return 0;  }  /** @@ -256,76 +259,76 @@ int mdns_query(const char *name) {   */  int mdns_parse_response(const void *response, size_t len)  { -	// sanity checks -	if (!response) return -URTC_ERR_BAD_ARGUMENT; -	if (len < sizeof(struct header)) return -URTC_ERR_MALFORMED; - -	struct header *hdr = (struct header *)(response); -	response += sizeof(struct header); -	len -= sizeof(struct header); - -	// transaction id must be zero -	if (0 != hdr->id) return -URTC_ERR_MALFORMED; - -	// flags must indicate a response -	if (!(ntohs(hdr->flags) & FLAG_RESPONSE)) return -URTC_ERR_MALFORMED; - -	// sent single question, expecting reponse for single question -	if (1 != ntohs(hdr->n_question)) return -URTC_ERR_MALFORMED; - -	// parse query names -	struct qname *qname; -	do { -		if (len < 1) return -URTC_ERR_MALFORMED; -		qname = (struct qname *)(response); -		if (len < 1 + qname->size) return -URTC_ERR_MALFORMED; -		response += 1 + qname->size; -		len -= 1 + qname->size; -	} while (qname->size); - -	// parse query type (ignore) -	if (len < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; -	response += sizeof(uint16_t); -	len -= sizeof(uint16_t); - -	// parse query class (ignore) -	if (len < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; -	response += sizeof(uint16_t); -	len -= sizeof(uint16_t); - -	// answers -	for (int i = 0; i < ntohs(hdr->n_answer); i++) { -		uint16_t size; -		uint8_t namelen; - -		// parse name (assume matches) -		if (len < 2) return -URTC_ERR_MALFORMED; -		namelen = *(uint8_t *)response; -		switch (namelen) { -			// name compression -			case 0xc0: -				response += 2; -				len -= 2; -				break; -			// no name compression -			default: -				response += 1 + namelen; -				len -= 1 + namelen; -				break; -		} - -		if (len < sizeof(struct answer)) return -URTC_ERR_MALFORMED; -		struct answer *answer = (struct answer *)response; -		response += sizeof(struct answer); -		len -= sizeof(struct answer); - -		size = ntohs(answer->size); -		if (len < size) return -URTC_ERR_MALFORMED; -		response += size; -		len -= size; -	} - -	return 0; +    // sanity checks +    if (!response) return -URTC_ERR_BAD_ARGUMENT; +    if (len < sizeof(struct header)) return -URTC_ERR_MALFORMED; + +    struct header *hdr = (struct header *)(response); +    response += sizeof(struct header); +    len -= sizeof(struct header); + +    // transaction id must be zero +    if (0 != hdr->id) return -URTC_ERR_MALFORMED; + +    // flags must indicate a response +    if (!(ntohs(hdr->flags) & FLAG_RESPONSE)) return -URTC_ERR_MALFORMED; + +    // sent single question, expecting reponse for single question +    if (1 != ntohs(hdr->n_question)) return -URTC_ERR_MALFORMED; + +    // parse query names +    struct qname *qname; +    do { +        if (len < 1) return -URTC_ERR_MALFORMED; +        qname = (struct qname *)(response); +        if (len < 1 + qname->size) return -URTC_ERR_MALFORMED; +        response += 1 + qname->size; +        len -= 1 + qname->size; +    } while (qname->size); + +    // parse query type (ignore) +    if (len < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; +    response += sizeof(uint16_t); +    len -= sizeof(uint16_t); + +    // parse query class (ignore) +    if (len < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; +    response += sizeof(uint16_t); +    len -= sizeof(uint16_t); + +    // answers +    for (int i = 0; i < ntohs(hdr->n_answer); i++) { +        uint16_t size; +        uint8_t namelen; + +        // parse name (assume matches) +        if (len < 2) return -URTC_ERR_MALFORMED; +        namelen = *(uint8_t *)response; +        switch (namelen) { +            // name compression +            case 0xc0: +                response += 2; +                len -= 2; +                break; +            // no name compression +            default: +                response += 1 + namelen; +                len -= 1 + namelen; +                break; +        } + +        if (len < sizeof(struct answer)) return -URTC_ERR_MALFORMED; +        struct answer *answer = (struct answer *)response; +        response += sizeof(struct answer); +        len -= sizeof(struct answer); + +        size = ntohs(answer->size); +        if (len < size) return -URTC_ERR_MALFORMED; +        response += size; +        len -= size; +    } + +    return 0;  }  /** @@ -338,69 +341,69 @@ int mdns_parse_response(const void *response, size_t len)   * \return Positive on match, 0 on no match, negative on malformed query.   */  static int match(const char *expected, const uint8_t *q, int *len) { -	struct qname *qname; -	bool matches; -	int n_records; -	int n; - -	if (!q) return -URTC_ERR_BAD_ARGUMENT; -	if (!expected) return -URTC_ERR_BAD_ARGUMENT; -	if (!len) return -URTC_ERR_BAD_ARGUMENT; - -	n = *len; -	matches = true; - -	n_records = 0; -	do { -		// minimum size check: a single root record (1 byte) -		if (n < 1) return -URTC_ERR_MALFORMED; -		qname = (struct qname *)(q); - -		// minimum size check: length byte plus stated length -		if (n < 1 + qname->size) return -URTC_ERR_MALFORMED; - -		// match records -		switch (n_records) { -			// match hostname record -			case 0: -				if (qname->size == strlen(expected)) { -					if (0 == memcmp(qname->name, expected, qname->size)) { -						break; // matched -					} -				} -				matches = false; -				break; -			// match "local" record -			case 1: -				if (qname->size == sizeof("local")-1) { -					if (0 == memcmp(qname->name, "local", sizeof("local")-1)) { -						break; //matched -					} -				} -				matches = false; -				break; -			// match root record -			case 2: -				if (qname->size == 0) { -					break; -				} -				matches = false; -				break; -			// match ancillary records -			default: -				matches = false; -				break; -		} - -		q += 1 + qname->size; -		n -= 1 + qname->size; -		n_records++; -	} while(qname->size); - -	// update with actual length of run-length encoding -	*len -= n; - -	return matches; +    struct qname *qname; +    bool matches; +    int n_records; +    int n; + +    if (!q) return -URTC_ERR_BAD_ARGUMENT; +    if (!expected) return -URTC_ERR_BAD_ARGUMENT; +    if (!len) return -URTC_ERR_BAD_ARGUMENT; + +    n = *len; +    matches = true; + +    n_records = 0; +    do { +        // minimum size check: a single root record (1 byte) +        if (n < 1) return -URTC_ERR_MALFORMED; +        qname = (struct qname *)(q); + +        // minimum size check: length byte plus stated length +        if (n < 1 + qname->size) return -URTC_ERR_MALFORMED; + +        // match records +        switch (n_records) { +            // match hostname record +            case 0: +                if (qname->size == strlen(expected)) { +                    if (0 == memcmp(qname->name, expected, qname->size)) { +                        break; // matched +                    } +                } +                matches = false; +                break; +            // match "local" record +            case 1: +                if (qname->size == sizeof("local")-1) { +                    if (0 == memcmp(qname->name, "local", sizeof("local")-1)) { +                        break; //matched +                    } +                } +                matches = false; +                break; +            // match root record +            case 2: +                if (qname->size == 0) { +                    break; +                } +                matches = false; +                break; +            // match ancillary records +            default: +                matches = false; +                break; +        } + +        q += 1 + qname->size; +        n -= 1 + qname->size; +        n_records++; +    } while(qname->size); + +    // update with actual length of run-length encoding +    *len -= n; + +    return matches;  }  /** @@ -417,72 +420,72 @@ static int match(const char *expected, const uint8_t *q, int *len) {   */  int mdns_validate_query(const uint8_t *q, size_t n, const char *hostname)  { -	const struct header *hdr = (struct header *)q; -	const uint8_t *qi = q; -	const size_t ni = n; -	int found; - -	found = 0; - -	// sanity checks -	if (!q) return -URTC_ERR_BAD_ARGUMENT; -	if (n < sizeof(struct header)) return -URTC_ERR_MALFORMED; - -	q += sizeof(struct header); -	n -= sizeof(struct header); - -	// transaction id must be zero -	// note: hdr in host byte order (0 is byte order agnostic) -	if (0 != hdr->id) return -URTC_ERR_MALFORMED; - -	// only support standard, non-truncated, non-recursive queries -	// note: hdr in host byte order (non-0 is byte order agnostic) -	if (hdr->flags) return -URTC_ERR_NOT_IMPLEMENTED; - -	// parse questions -	for (int j = 0; j < ntohs(hdr->n_question); j++) { -		bool matched; -		int ret; -		int len; - -		// upper two bits set? "compressed" records -		matched = false; -		if (n > 2 && q[0] >> 6 == 3) { -			// compressed (i.e. offset to previous record) -			const uint16_t offset = ((q[0] & 0x3F) << 8) | q[1]; -			if (offset > ni) return -URTC_ERR_MALFORMED; -			len = ni - offset; -			ret = match(hostname, qi + offset, &len); -			q += 2; -			n -= 2; -		} else { -			// uncompressed -			len = n; -			ret = match(hostname, q, &len); -			q += len; -			n -= len; -		} -		if (ret < 0) return ret; -		if (ret > 0) matched = true; - -		// parse query type for A and AAAA records -		if (n < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; -		if (matched) { -			uint16_t type = ntohs(*(uint16_t *)(q)); -			if (TYPE_A == type || TYPE_AAAA == type) { -				found |= type; -			} -		} -		q += sizeof(uint16_t); -		n -= sizeof(uint16_t); - -		// parse query class (ignore) -		if (n < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; -		q += sizeof(uint16_t); -		n -= sizeof(uint16_t); -	} - -	return found; +    const struct header *hdr = (struct header *)q; +    const uint8_t *qi = q; +    const size_t ni = n; +    int found; + +    found = 0; + +    // sanity checks +    if (!q) return -URTC_ERR_BAD_ARGUMENT; +    if (n < sizeof(struct header)) return -URTC_ERR_MALFORMED; + +    q += sizeof(struct header); +    n -= sizeof(struct header); + +    // transaction id must be zero +    // note: hdr in host byte order (0 is byte order agnostic) +    if (0 != hdr->id) return -URTC_ERR_MALFORMED; + +    // only support standard, non-truncated, non-recursive queries +    // note: hdr in host byte order (non-0 is byte order agnostic) +    if (hdr->flags) return -URTC_ERR_NOT_IMPLEMENTED; + +    // parse questions +    for (int j = 0; j < ntohs(hdr->n_question); j++) { +        bool matched; +        int ret; +        int len; + +        // upper two bits set? "compressed" records +        matched = false; +        if (n > 2 && q[0] >> 6 == 3) { +            // compressed (i.e. offset to previous record) +            const uint16_t offset = ((q[0] & 0x3F) << 8) | q[1]; +            if (offset > ni) return -URTC_ERR_MALFORMED; +            len = ni - offset; +            ret = match(hostname, qi + offset, &len); +            q += 2; +            n -= 2; +        } else { +            // uncompressed +            len = n; +            ret = match(hostname, q, &len); +            q += len; +            n -= len; +        } +        if (ret < 0) return ret; +        if (ret > 0) matched = true; + +        // parse query type for A and AAAA records +        if (n < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; +        if (matched) { +            uint16_t type = ntohs(*(uint16_t *)(q)); +            if (TYPE_A == type || TYPE_AAAA == type) { +                found |= type; +            } +        } +        q += sizeof(uint16_t); +        n -= sizeof(uint16_t); + +        // parse query class (ignore) +        if (n < sizeof(uint16_t)) return -URTC_ERR_MALFORMED; +        q += sizeof(uint16_t); +        n -= sizeof(uint16_t); +    } + +    return found;  }  /** @@ -493,115 +496,117 @@ int mdns_validate_query(const uint8_t *q, size_t n, const char *hostname)   * \return 0 on success, negative on error   */  int mdns_send_response(int sockfd, const char *hostname) { -	struct ifaddrs *ifaddrs; -	struct header *hdr; -	uint8_t *wr;						// writer (convenience pointer) -	uint8_t response[ -		sizeof(struct header) + -		1 + HOST_NAME_MAX + 1 +			// max size of length and host record -		1 + sizeof(".local") +			// size of length and local record -		1 +								// size of root record -		sizeof(struct answer) + -		16								// size of AAAA record (largest record) -	]; -	hdr = (struct header *)(response); -	wr  = response; - -	// write header -	*hdr = (struct header){ -		.id           = 0, -		.flags        = htons(FLAG_RESPONSE), -		.n_question   = 0, -		.n_answer     = 0,  -		.n_authority  = 0, -		.n_additional = 0 -	}; -	wr += sizeof(struct header); - -	// get linked list of network interfaces -	if (-1 == getifaddrs(&ifaddrs)) { -		log(ERROR, "%s", strerror(errno)); -		goto _fail_getifaddrs; -	} - -	// for each network interface... -	for (struct ifaddrs *ifaddr = ifaddrs; ifaddr; ifaddr = ifaddr->ifa_next) { -		// skip loopback interfaces -		if (ifaddr->ifa_flags & IFF_LOOPBACK) continue; - -		// for an AF_INET* interface address, display the address -		if (ifaddr->ifa_addr && ifaddr->ifa_addr->sa_family == AF_INET) { - -			// write host record -			{ -				strncpy((char *)(wr + 1), hostname, HOST_NAME_MAX); -				wr[1 + HOST_NAME_MAX - 1] = '\0'; -				*wr = strlen((char *)(wr + 1)); -				wr += 1 + strlen((char *)(wr + 1)); -			} - -			// write local record -			{ -				const char local[] = "local"; -				*wr++ = sizeof(local) - 1; -				memcpy(wr, local, sizeof(local) - 1); -				wr += sizeof(local) - 1; -			} - -			// write root record -			*wr++ = 0; - -			// write answer -			{ -				struct answer ans = { -					.type  = htons(TYPE_A), -					.class = htons(CACHE_FLUSH | CLASS_INTERNET), -					.ttl   = htonl(DEFAULT_TTL), -					.size  = htons(sizeof(struct in_addr)), -				}; -				memcpy(wr, &ans, sizeof(ans)); -				wr += sizeof(ans); - -				memcpy(wr, -					&(((struct sockaddr_in *)(ifaddr->ifa_addr))->sin_addr), -					sizeof(struct in_addr)); -				wr += sizeof(struct in_addr); -			} - -			// increment number of answers -			hdr->n_answer++; - -			if (hdr->n_answer == 1) { -				break; -			} -		} -	} - -	// free linked list of network interfaces -	freeifaddrs(ifaddrs); - -	// convert to network byte order -	hdr->n_answer = htons(hdr->n_answer); - -	// send response -	struct sockaddr_in mgroup = { -		.sin_family = AF_INET, -		.sin_addr.s_addr = inet_addr(MDNS_ADDR), -		.sin_port = htons(MDNS_PORT) -	}; -	if (-1 == sendto( -		sockfd, -		response, -		wr - response, -		0, -		(struct sockaddr *)(&mgroup), -		sizeof(mgroup) -	)) { -		log(FATAL, "sendto: %s", strerror(errno)); -	} - -	return 0; +    struct ifaddrs *ifaddrs; +    struct header *hdr; +    uint8_t *wr;                        // writer (convenience pointer) +    uint8_t response[ +        sizeof(struct header) + +        1 + HOST_NAME_MAX + 1 +         // max size of length and host record +        1 + sizeof(".local") +          // size of length and local record +        1 +                             // size of root record +        sizeof(struct answer) + +        16                              // size of AAAA record (largest record) +    ]; +    hdr = (struct header *)(response); +    wr  = response; + +    // write header +    *hdr = (struct header){ +        .id           = 0, +        .flags        = htons(FLAG_RESPONSE), +        .n_question   = 0, +        .n_answer     = 0,  +        .n_authority  = 0, +        .n_additional = 0 +    }; +    wr += sizeof(struct header); + +    // get linked list of network interfaces +    if (-1 == getifaddrs(&ifaddrs)) { +        log(ERROR, "%s", strerror(errno)); +        goto _fail_getifaddrs; +    } + +    // for each network interface... +    for (struct ifaddrs *ifaddr = ifaddrs; ifaddr; ifaddr = ifaddr->ifa_next) { +        // skip loopback interfaces +        if (ifaddr->ifa_flags & IFF_LOOPBACK) continue; + +        // for an AF_INET* interface address, display the address +        if (ifaddr->ifa_addr && ifaddr->ifa_addr->sa_family == AF_INET) { + +            // write host record +            { +                strncpy((char *)(wr + 1), hostname, HOST_NAME_MAX); +                wr[1 + HOST_NAME_MAX - 1] = '\0'; +                *wr = strlen((char *)(wr + 1)); +                wr += 1 + strlen((char *)(wr + 1)); +            } + +            // write local record +            { +                const char local[] = "local"; +                *wr++ = sizeof(local) - 1; +                memcpy(wr, local, sizeof(local) - 1); +                wr += sizeof(local) - 1; +            } + +            // write root record +            *wr++ = 0; + +            // write answer +            { +                struct answer ans = { +                    .type  = htons(TYPE_A), +                    .class = htons(CACHE_FLUSH | CLASS_INTERNET), +                    .ttl   = htonl(DEFAULT_TTL), +                    .size  = htons(sizeof(struct in_addr)), +                }; +                memcpy(wr, &ans, sizeof(ans)); +                wr += sizeof(ans); + +                memcpy(wr, +                    &(((struct sockaddr_in *)(ifaddr->ifa_addr))->sin_addr), +                    sizeof(struct in_addr)); +                wr += sizeof(struct in_addr); +            } + +            // increment number of answers +            hdr->n_answer++; + +            if (hdr->n_answer == 1) { +                break; +            } +        } +    } + +    // free linked list of network interfaces +    freeifaddrs(ifaddrs); + +    // convert to network byte order +    hdr->n_answer = htons(hdr->n_answer); + +    // send response +    struct sockaddr_in mgroup = { +        .sin_family = AF_INET, +        .sin_addr.s_addr = inet_addr(MDNS_ADDR), +        .sin_port = htons(MDNS_PORT) +    }; +    if (-1 == sendto( +        sockfd, +        response, +        wr - response, +        0, +        (struct sockaddr *)(&mgroup), +        sizeof(mgroup) +    )) { +        log(FATAL, "sendto: %s", strerror(errno)); +    } + +    return 0;  _fail_getifaddrs: -	return -URTC_ERR; +    return -URTC_ERR;  } + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef _URTC_MDNS_H @@ -41,3 +44,5 @@ int mdns_parse_response(const void *response, size_t len);  int mdns_query(const char *name);  #endif // _URTC_MDNS_H + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #include <stdint.h> @@ -31,7 +34,7 @@   * Initialize pseudo-random number generator   */  void prng_init() { -	srand(time(NULL)); +    srand(time(NULL));  }  /** @@ -41,7 +44,9 @@ void prng_init() {   * \param sz Size (in bytes) of destination memory   */  void prng(void *dst, size_t sz) { -	for (; sz; sz--) { -		*(uint8_t *)dst++ = rand() & 0xFF; -	} +    for (; sz; sz--) { +        *(uint8_t *)dst++ = rand() & 0xFF; +    }  } + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef _URTC_PRNG_H @@ -29,3 +32,5 @@ void prng_init();  void prng(void *dst, size_t sz);  #endif // _URTC_PRNG_H + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #include <inttypes.h> @@ -48,47 +51,47 @@   * \return 0 on success. Negative on error.   */  static int sdp_parse_attr_group(struct sdp *sdp, char *val) { -	char *id = val; +    char *id = val; -	val = strsep(&id, " "); +    val = strsep(&id, " "); -	if (0 == strcmp("BUNDLE", val)) { -		for (int i = 0; id && i < SDP_MAX_BUNDLE_IDS; i++) { -			strncpy(sdp->mid[i], strsep(&id, " "), SDP_MAX_BUNDLE_ID_SIZE); -		} -	} -	return 0; +    if (0 == strcmp("BUNDLE", val)) { +        for (int i = 0; id && i < SDP_MAX_BUNDLE_IDS; i++) { +            strncpy(sdp->mid[i], strsep(&id, " "), SDP_MAX_BUNDLE_ID_SIZE); +        } +    } +    return 0;  }  static int sdp_parse_attr_msid_semantic(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  static int sdp_parse_attr_rtcp(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  static int sdp_parse_attr_ice_ufrag(struct sdp *sdp, const char *val) { -	if (sdp->ufrag != strncpy(sdp->ufrag, val, sizeof(sdp->ufrag))) { -		return -1; -	} -	return 0; +    if (sdp->ufrag != strncpy(sdp->ufrag, val, sizeof(sdp->ufrag))) { +        return -1; +    } +    return 0;  }  static int sdp_parse_attr_ice_password(struct sdp *sdp, const char *val) { -	if (sdp->pwd != strncpy(sdp->pwd, val, sizeof(sdp->pwd))) { -		return -1; -	} -	return 0; +    if (sdp->pwd != strncpy(sdp->pwd, val, sizeof(sdp->pwd))) { +        return -1; +    } +    return 0;  }  static int sdp_parse_attr_ice_options(struct sdp *sdp, const char *val) { -	if (0 == strcmp("trickle", val)) { -		sdp->ice_options.trickle = true; -	} -	return 0; +    if (0 == strcmp("trickle", val)) { +        sdp->ice_options.trickle = true; +    } +    return 0;  }  /** @@ -102,59 +105,59 @@ static int sdp_parse_attr_ice_options(struct sdp *sdp, const char *val) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_attr_fingerprint(struct sdp *sdp, char *val) { -	char *fingerprint = val; - -	val = strsep(&fingerprint, " "); - -	if (fingerprint) { -		if (0 == strcmp("sha-256", val)) { -			if (32 != sscanf(fingerprint, -				"%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:" -				"%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:" -				"%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:" -				"%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX", -				&sdp->fingerprint.sha256[0],  &sdp->fingerprint.sha256[1], -				&sdp->fingerprint.sha256[2],  &sdp->fingerprint.sha256[3], -				&sdp->fingerprint.sha256[4],  &sdp->fingerprint.sha256[5], -				&sdp->fingerprint.sha256[6],  &sdp->fingerprint.sha256[7], -				&sdp->fingerprint.sha256[8],  &sdp->fingerprint.sha256[9], -				&sdp->fingerprint.sha256[10], &sdp->fingerprint.sha256[11], -				&sdp->fingerprint.sha256[12], &sdp->fingerprint.sha256[13], -				&sdp->fingerprint.sha256[14], &sdp->fingerprint.sha256[15], -				&sdp->fingerprint.sha256[16], &sdp->fingerprint.sha256[17], -				&sdp->fingerprint.sha256[18], &sdp->fingerprint.sha256[19], -				&sdp->fingerprint.sha256[20], &sdp->fingerprint.sha256[21], -				&sdp->fingerprint.sha256[22], &sdp->fingerprint.sha256[23], -				&sdp->fingerprint.sha256[24], &sdp->fingerprint.sha256[25], -				&sdp->fingerprint.sha256[26], &sdp->fingerprint.sha256[27], -				&sdp->fingerprint.sha256[28], &sdp->fingerprint.sha256[29], -				&sdp->fingerprint.sha256[30], &sdp->fingerprint.sha256[31] -			)) { -				return -URTC_ERR_SDP_MALFORMED; -			} -		} else { -			return -URTC_ERR_SDP_UNSUPPORTED_FINGERPRINT_ALGO; -		} -	} else { -		return -URTC_ERR_SDP_MALFORMED; -	} - -	return 0; +    char *fingerprint = val; + +    val = strsep(&fingerprint, " "); + +    if (fingerprint) { +        if (0 == strcmp("sha-256", val)) { +            if (32 != sscanf(fingerprint, +                "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:" +                "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:" +                "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:" +                "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX", +                &sdp->fingerprint.sha256[0],  &sdp->fingerprint.sha256[1], +                &sdp->fingerprint.sha256[2],  &sdp->fingerprint.sha256[3], +                &sdp->fingerprint.sha256[4],  &sdp->fingerprint.sha256[5], +                &sdp->fingerprint.sha256[6],  &sdp->fingerprint.sha256[7], +                &sdp->fingerprint.sha256[8],  &sdp->fingerprint.sha256[9], +                &sdp->fingerprint.sha256[10], &sdp->fingerprint.sha256[11], +                &sdp->fingerprint.sha256[12], &sdp->fingerprint.sha256[13], +                &sdp->fingerprint.sha256[14], &sdp->fingerprint.sha256[15], +                &sdp->fingerprint.sha256[16], &sdp->fingerprint.sha256[17], +                &sdp->fingerprint.sha256[18], &sdp->fingerprint.sha256[19], +                &sdp->fingerprint.sha256[20], &sdp->fingerprint.sha256[21], +                &sdp->fingerprint.sha256[22], &sdp->fingerprint.sha256[23], +                &sdp->fingerprint.sha256[24], &sdp->fingerprint.sha256[25], +                &sdp->fingerprint.sha256[26], &sdp->fingerprint.sha256[27], +                &sdp->fingerprint.sha256[28], &sdp->fingerprint.sha256[29], +                &sdp->fingerprint.sha256[30], &sdp->fingerprint.sha256[31] +            )) { +                return -URTC_ERR_SDP_MALFORMED; +            } +        } else { +            return -URTC_ERR_SDP_UNSUPPORTED_FINGERPRINT_ALGO; +        } +    } else { +        return -URTC_ERR_SDP_MALFORMED; +    } + +    return 0;  }  static int sdp_parse_attr_setup(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  static int sdp_parse_attr_mid(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  static int sdp_parse_attr_extmap(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  /** @@ -170,36 +173,36 @@ static int sdp_parse_attr_extmap(struct sdp *sdp, const char *val) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_attr_rtpmap(struct sdp *sdp, char *val) { -	if (!val) return -URTC_ERR_SDP_MALFORMED; - -	unsigned int pt;                    // payload type -	char         en[7];                 // encoding name -	unsigned int cr;                    // clock rate -	 -	if (3 != sscanf(val, "%3d %6[a-zA-Z0-9]%*c%5d", &pt, en, &cr)) { -		return -URTC_ERR_SDP_MALFORMED_ATTRIBUTE; -	} - -	if (0 == strcmp("H264", en)) { -		for (int i = 0; i < sdp->video.count; i++) { -			if (sdp->video.params[i].type == pt) { -				sdp->video.params[i].clock = cr; -				sdp->video.params[i].codec = SDP_CODEC_H264; -			} -		} -	} - -	return 0; +    if (!val) return -URTC_ERR_SDP_MALFORMED; + +    unsigned int pt;                    // payload type +    char         en[7];                 // encoding name +    unsigned int cr;                    // clock rate +     +    if (3 != sscanf(val, "%3d %6[a-zA-Z0-9]%*c%5d", &pt, en, &cr)) { +        return -URTC_ERR_SDP_MALFORMED_ATTRIBUTE; +    } + +    if (0 == strcmp("H264", en)) { +        for (int i = 0; i < sdp->video.count; i++) { +            if (sdp->video.params[i].type == pt) { +                sdp->video.params[i].clock = cr; +                sdp->video.params[i].codec = SDP_CODEC_H264; +            } +        } +    } + +    return 0;  }  static int sdp_parse_attr_rtcp_feedback(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  static int sdp_parse_attr_fmtp(struct sdp *sdp, const char *val) { -	/* not implemented */ -	return 0; +    /* not implemented */ +    return 0;  }  /** @@ -211,54 +214,54 @@ static int sdp_parse_attr_fmtp(struct sdp *sdp, const char *val) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_attribute(struct sdp *sdp, char *attr) { -	char *value = attr; - -	// Find colon separating attribute from value -	attr = strsep(&value, ":"); - -	if (value) { -		if (0 == strcmp("group", attr)) { -			return sdp_parse_attr_group(sdp, value); -		} else if (0 == strcmp("msid-semantic", attr)) { -			return sdp_parse_attr_msid_semantic(sdp, value); -		} else if (0 == strcmp("rtcp", attr)) { -			return sdp_parse_attr_rtcp(sdp, value); -		} else if (0 == strcmp("ice-ufrag", attr)) { -			return sdp_parse_attr_ice_ufrag(sdp, value); -		} else if (0 == strcmp("ice-pwd", attr)) { -			return sdp_parse_attr_ice_password(sdp, value); -		} else if (0 == strcmp("ice-options", attr)) { -			return sdp_parse_attr_ice_options(sdp, value); -		} else if (0 == strcmp("fingerprint", attr)) { -			return sdp_parse_attr_fingerprint(sdp, value); -		} else if (0 == strcmp("setup", attr)) { -			return sdp_parse_attr_setup(sdp, value); -		} else if (0 == strcmp("mid", attr)) { -			return sdp_parse_attr_mid(sdp, value); -		} else if (0 == strcmp("extmap", attr)) { -			return sdp_parse_attr_extmap(sdp, value); -		} else if (0 == strcmp("rtpmap", attr)) { -			return sdp_parse_attr_rtpmap(sdp, value); -		} else if (0 == strcmp("rtcp-fb", attr)) { -			return sdp_parse_attr_rtcp_feedback(sdp, value); -		} else if (0 == strcmp("fmtp", attr)) { -			return sdp_parse_attr_fmtp(sdp, value); -		} -	} else /* flag */ { -		if (0 == strcmp("recvonly", attr)) { -			sdp->mode = SDP_MODE_RECEIVE_ONLY; -		} else if (0 == strcmp("sendonly", attr)) { -			sdp->mode = SDP_MODE_SEND_ONLY; -		} else if (0 == strcmp("sendrecv", attr)) { -			sdp->mode = SDP_MODE_SEND_AND_RECEIVE; -		} else if (0 == strcmp("rtcp-mux", attr)) { -			sdp->rtcp_mux = true; -		} else if (0 == strcmp("rtcp-rsize", attr)) { -			sdp->rtcp_rsize = true; -		} -	} - -	return 0; +    char *value = attr; + +    // Find colon separating attribute from value +    attr = strsep(&value, ":"); + +    if (value) { +        if (0 == strcmp("group", attr)) { +            return sdp_parse_attr_group(sdp, value); +        } else if (0 == strcmp("msid-semantic", attr)) { +            return sdp_parse_attr_msid_semantic(sdp, value); +        } else if (0 == strcmp("rtcp", attr)) { +            return sdp_parse_attr_rtcp(sdp, value); +        } else if (0 == strcmp("ice-ufrag", attr)) { +            return sdp_parse_attr_ice_ufrag(sdp, value); +        } else if (0 == strcmp("ice-pwd", attr)) { +            return sdp_parse_attr_ice_password(sdp, value); +        } else if (0 == strcmp("ice-options", attr)) { +            return sdp_parse_attr_ice_options(sdp, value); +        } else if (0 == strcmp("fingerprint", attr)) { +            return sdp_parse_attr_fingerprint(sdp, value); +        } else if (0 == strcmp("setup", attr)) { +            return sdp_parse_attr_setup(sdp, value); +        } else if (0 == strcmp("mid", attr)) { +            return sdp_parse_attr_mid(sdp, value); +        } else if (0 == strcmp("extmap", attr)) { +            return sdp_parse_attr_extmap(sdp, value); +        } else if (0 == strcmp("rtpmap", attr)) { +            return sdp_parse_attr_rtpmap(sdp, value); +        } else if (0 == strcmp("rtcp-fb", attr)) { +            return sdp_parse_attr_rtcp_feedback(sdp, value); +        } else if (0 == strcmp("fmtp", attr)) { +            return sdp_parse_attr_fmtp(sdp, value); +        } +    } else /* flag */ { +        if (0 == strcmp("recvonly", attr)) { +            sdp->mode = SDP_MODE_RECEIVE_ONLY; +        } else if (0 == strcmp("sendonly", attr)) { +            sdp->mode = SDP_MODE_SEND_ONLY; +        } else if (0 == strcmp("sendrecv", attr)) { +            sdp->mode = SDP_MODE_SEND_AND_RECEIVE; +        } else if (0 == strcmp("rtcp-mux", attr)) { +            sdp->rtcp_mux = true; +        } else if (0 == strcmp("rtcp-rsize", attr)) { +            sdp->rtcp_rsize = true; +        } +    } + +    return 0;  }  /** @@ -277,58 +280,58 @@ static int sdp_parse_attribute(struct sdp *sdp, char *attr) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_media_description(struct sdp *sdp, char *value) { -	char *next = value; - -	value = strsep(&next, " "); - -	if (0 == strcmp("audio", value)) { -		/* not implemented */ -	} else if (0 == strcmp("video", value)) { -		if (!next) return -URTC_ERR_SDP_MALFORMED_MEDIA; - -		/* get port */ -		value = strsep(&next, " "); -		if (1 != sscanf(value, "%5hd", &sdp->video.port)) { -			return -URTC_ERR_SDP_MALFORMED_MEDIA; -		} -		if (!next) return -URTC_ERR_SDP_MALFORMED_MEDIA; - -		/* get protocol: only "UDP/TLS/RTP/SAVPF" supported */ -		value = strsep(&next, " "); -		if (0 != strcmp("UDP/TLS/RTP/SAVPF", value)) { -			return -URTC_ERR_SDP_UNSUPPORTED_MEDIA_PROTOCOL; -		} -		if (!next) return -URTC_ERR_SDP_MALFORMED_MEDIA; - -		/* get RTP payload types */ -		sdp->video.count = 0; -		for ( -			value = strsep(&next, " "); -			value && sdp->video.count < SDP_MAX_RTP_PAYLOAD_TYPES; -			value = strsep(&next, " ") -		) { -			unsigned int *v = &sdp->video.params[sdp->video.count].type; -			if (1 != sscanf(value, "%3d", v)) { -				return -URTC_ERR_SDP_MALFORMED_MEDIA; -			} -			sdp->video.count++; -		} - -	} else if (0 == strcmp("text", value)) { -		/* ignore */ -	} else if (0 == strcmp("message", value)) { -		/* ignore */ -	} else if (0 == strcmp("application", value)) { -		/* ignore */ -	} else { -		return -URTC_ERR_SDP_UNSUPPORTED_MEDIA_TYPE; -	} - -	return 0; +    char *next = value; + +    value = strsep(&next, " "); + +    if (0 == strcmp("audio", value)) { +        /* not implemented */ +    } else if (0 == strcmp("video", value)) { +        if (!next) return -URTC_ERR_SDP_MALFORMED_MEDIA; + +        /* get port */ +        value = strsep(&next, " "); +        if (1 != sscanf(value, "%5hd", &sdp->video.port)) { +            return -URTC_ERR_SDP_MALFORMED_MEDIA; +        } +        if (!next) return -URTC_ERR_SDP_MALFORMED_MEDIA; + +        /* get protocol: only "UDP/TLS/RTP/SAVPF" supported */ +        value = strsep(&next, " "); +        if (0 != strcmp("UDP/TLS/RTP/SAVPF", value)) { +            return -URTC_ERR_SDP_UNSUPPORTED_MEDIA_PROTOCOL; +        } +        if (!next) return -URTC_ERR_SDP_MALFORMED_MEDIA; + +        /* get RTP payload types */ +        sdp->video.count = 0; +        for ( +            value = strsep(&next, " "); +            value && sdp->video.count < SDP_MAX_RTP_PAYLOAD_TYPES; +            value = strsep(&next, " ") +        ) { +            unsigned int *v = &sdp->video.params[sdp->video.count].type; +            if (1 != sscanf(value, "%3d", v)) { +                return -URTC_ERR_SDP_MALFORMED_MEDIA; +            } +            sdp->video.count++; +        } + +    } else if (0 == strcmp("text", value)) { +        /* ignore */ +    } else if (0 == strcmp("message", value)) { +        /* ignore */ +    } else if (0 == strcmp("application", value)) { +        /* ignore */ +    } else { +        return -URTC_ERR_SDP_UNSUPPORTED_MEDIA_TYPE; +    } + +    return 0;  }  static int sdp_parse_connection_data(struct sdp *sdp, const char *value) { -	return 0; +    return 0;  }  /** @@ -345,12 +348,12 @@ static int sdp_parse_connection_data(struct sdp *sdp, const char *value) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_version(struct sdp *sdp, const char *value) { -	if (0 != strcmp("0", value)) { -		return -URTC_ERR_SDP_MALFORMED_VERSION; -	} -	sdp->version = 0; +    if (0 != strcmp("0", value)) { +        return -URTC_ERR_SDP_MALFORMED_VERSION; +    } +    sdp->version = 0; -	return 0; +    return 0;  }  /** @@ -370,23 +373,23 @@ static int sdp_parse_version(struct sdp *sdp, const char *value) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_origin(struct sdp *sdp, const char *value) { -	if (3 != sscanf(value, -		"%" TOSTRING(SDP_MAX_USERNAME_SIZE) "s " -		"%" TOSTRING(SDP_MAX_SESSION_ID_SIZE) "[0-9] " -		"%" TOSTRING(SDP_MAX_SESSION_VERSION_SIZE) "[0-9] " -		"IN IP4 127.0.0.1", -		sdp->username, -		sdp->session_id, -		sdp->session_version -	)) { -		return -URTC_ERR_SDP_MALFORMED_ORIGIN; -	} - -	return 0; +    if (3 != sscanf(value, +        "%" TOSTRING(SDP_MAX_USERNAME_SIZE) "s " +        "%" TOSTRING(SDP_MAX_SESSION_ID_SIZE) "[0-9] " +        "%" TOSTRING(SDP_MAX_SESSION_VERSION_SIZE) "[0-9] " +        "IN IP4 127.0.0.1", +        sdp->username, +        sdp->session_id, +        sdp->session_version +    )) { +        return -URTC_ERR_SDP_MALFORMED_ORIGIN; +    } + +    return 0;  }  static int sdp_parse_session_name(struct sdp *sdp, const char *value) { -	return 0; +    return 0;  }  /** @@ -402,14 +405,14 @@ static int sdp_parse_session_name(struct sdp *sdp, const char *value) {   * \return 0 on success. Negative on error.   */  static int sdp_parse_timing(struct sdp *sdp, const char *value) { -	if (2 != sscanf(value, "%10lli %10lli", -		(unsigned long long *)&sdp->start_time, -		(unsigned long long *)&sdp->stop_time -	)) { -		return -URTC_ERR_SDP_MALFORMED_TIMING; -	} - -	return 0; +    if (2 != sscanf(value, "%10lli %10lli", +        (unsigned long long *)&sdp->start_time, +        (unsigned long long *)&sdp->stop_time +    )) { +        return -URTC_ERR_SDP_MALFORMED_TIMING; +    } + +    return 0;  }  /** @@ -421,279 +424,281 @@ static int sdp_parse_timing(struct sdp *sdp, const char *value) {   * \return 0 on success, negative on error.   */  static int sdp_parse_line(struct sdp *sdp, char *line) { -	if (!line) return -URTC_ERR_BAD_ARGUMENT; -	if (0 == strlen(line)) return 0; -	if (strlen(line) < 3) return -URTC_ERR_SDP_MALFORMED; -	if ('=' != line[1]) return -URTC_ERR_SDP_MALFORMED; - -	char type = line[0]; -	char *value = line + 2; - -	switch (type) { -	case 'a': -		return sdp_parse_attribute(sdp, value); -	case 'c': -		return sdp_parse_connection_data(sdp, value); -	case 'o': -		return sdp_parse_origin(sdp, value); -	case 'm': -		return sdp_parse_media_description(sdp, value); -	case 's': -		return sdp_parse_session_name(sdp, value); -	case 't': -		return sdp_parse_timing(sdp, value); -	case 'v': -		return sdp_parse_version(sdp, value); -	default: -		/* ignore unsupported types */ -		return 0; -	} +    if (!line) return -URTC_ERR_BAD_ARGUMENT; +    if (0 == strlen(line)) return 0; +    if (strlen(line) < 3) return -URTC_ERR_SDP_MALFORMED; +    if ('=' != line[1]) return -URTC_ERR_SDP_MALFORMED; + +    char type = line[0]; +    char *value = line + 2; + +    switch (type) { +    case 'a': +        return sdp_parse_attribute(sdp, value); +    case 'c': +        return sdp_parse_connection_data(sdp, value); +    case 'o': +        return sdp_parse_origin(sdp, value); +    case 'm': +        return sdp_parse_media_description(sdp, value); +    case 's': +        return sdp_parse_session_name(sdp, value); +    case 't': +        return sdp_parse_timing(sdp, value); +    case 'v': +        return sdp_parse_version(sdp, value); +    default: +        /* ignore unsupported types */ +        return 0; +    }  }  int sdp_parse(struct sdp *dst, const char *str) { -	if (!str) return -URTC_ERR_BAD_ARGUMENT; -	if (!dst) return -URTC_ERR_BAD_ARGUMENT; - -	err_t retval = 0; - -	/* make a malleable copy of string for parser */ -	char *copy = malloc(strlen(str)); -	if (copy) { -		strcpy(copy, str); - -		for (char *in = copy, *line = strsep(&in, "\r\n"); in; line = strsep(&in, "\r\n")) { -			retval = sdp_parse_line(dst, line); -			if (retval != 0) { -				log(ERROR, "sdp_parse_line returned %i for %s", retval, line); -				break; -			} -		} - -		free(copy); -	} else { -		return -URTC_ERR_INSUFFICIENT_MEMORY; -	} - -	return retval; +    if (!str) return -URTC_ERR_BAD_ARGUMENT; +    if (!dst) return -URTC_ERR_BAD_ARGUMENT; + +    err_t retval = 0; + +    /* make a malleable copy of string for parser */ +    char *copy = malloc(strlen(str)); +    if (copy) { +        strcpy(copy, str); + +        for (char *in = copy, *line = strsep(&in, "\r\n"); in; line = strsep(&in, "\r\n")) { +            retval = sdp_parse_line(dst, line); +            if (retval != 0) { +                log(ERROR, "sdp_parse_line returned %i for %s", retval, line); +                break; +            } +        } + +        free(copy); +    } else { +        return -URTC_ERR_INSUFFICIENT_MEMORY; +    } + +    return retval;  }  int sdp_serialize(char *dst, size_t len, const struct sdp *src) { -	int n; - -	// sanity check -	if (!dst) return -URTC_ERR_BAD_ARGUMENT; -	if (!src) return -URTC_ERR_BAD_ARGUMENT; - -	// write version -	n = snprintf(dst, len, "v=%u\n", src->version); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write originator and session identifier -	n = snprintf(dst, len, -		"o=liburtc/0.0.0 %s %s IN IP4 127.0.0.1\n", -		src->session_id, -		src->session_version -	); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write session name -	n = snprintf(dst, len, "s=%s\n", -		0 == strlen(src->session_name) ? " " : src->session_name); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write uri -	n = snprintf(dst, len, "u=http://www.liburtc.org\n"); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write time descriptor -	n = snprintf(dst, len, "t=%" PRIu64 " %" PRIu64 "\n", -		src->start_time, src->stop_time); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write session attribute -	n = snprintf(dst, len, "a=group:BUNDLE"); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; -	for (int i = 0; i < SDP_MAX_BUNDLE_IDS; i++) { -		if (strlen(src->mid[i]) > 0) { -			n = snprintf(dst, len, " %s", src->mid[i]); -			if (n < 0) return -URTC_ERR_SDP_MALFORMED; -			if (n >= len) return -URTC_ERR_SDP_MALFORMED; -			dst += n; -			len -= n; -		} -	} -	n = snprintf(dst, len, "\n"); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write video media description -	if (src->video.count > 0) { -		n = snprintf( -			dst, len, "m=video %hd UDP/TLS/RTP/SAVPF", src->video.port -		); -		if (n < 0) return -URTC_ERR_SDP_MALFORMED; -		if (n >= len) return -URTC_ERR_SDP_MALFORMED; -		dst += n; -		len -= n; -		for (int i = 0; i < src->video.count; i++) { -			if (src->video.params[i].codec == SDP_CODEC_H264) { -				n = snprintf(dst, len, " %d", src->video.params[i].type); -				if (n < 0) return -URTC_ERR_SDP_MALFORMED; -				if (n > len) return -URTC_ERR_SDP_MALFORMED; -				dst += n; -				len -= n; -			} -		} -		n = snprintf(dst, len, "\n"); -		if (n < 0) return -URTC_ERR_SDP_MALFORMED; -		if (n >= len) return -URTC_ERR_SDP_MALFORMED; -		dst += n; -		len -= n; -	} - -	// TODO write rtcp attribute - -	// write connection information (TODO IPv6) -	n = snprintf(dst, len, "c=IN IP4 0.0.0.0\n"); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write media attribute: ice ufrag -	n = snprintf(dst, len, "a=ice-ufrag:%s\n", src->ufrag); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write media attribute: ice pwd -	n = snprintf(dst, len, "a=ice-pwd:%s\n", src->pwd); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write media attribute: trickle ICE -	if (src->ice_options.trickle) { -		n = snprintf(dst, len, "a=ice-options:trickle\n"); -		if (n < 0) return -URTC_ERR_SDP_MALFORMED; -		if (n >= len) return -URTC_ERR_SDP_MALFORMED; -		dst += n; -		len -= n; -	} - -	// write media attribute: fingerprint -	n = snprintf(dst, len, -		"a=fingerprint:sha-256 " -		"%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:" -		"%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:" -		"%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:" -		"%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX\n", -		src->fingerprint.sha256[0], src->fingerprint.sha256[1], -		src->fingerprint.sha256[2], src->fingerprint.sha256[3], -		src->fingerprint.sha256[4], src->fingerprint.sha256[5], -		src->fingerprint.sha256[6], src->fingerprint.sha256[7], -		src->fingerprint.sha256[8], src->fingerprint.sha256[9], -		src->fingerprint.sha256[10], src->fingerprint.sha256[11], -		src->fingerprint.sha256[12], src->fingerprint.sha256[13], -		src->fingerprint.sha256[14], src->fingerprint.sha256[15], -		src->fingerprint.sha256[16], src->fingerprint.sha256[17], -		src->fingerprint.sha256[18], src->fingerprint.sha256[19], -		src->fingerprint.sha256[20], src->fingerprint.sha256[21], -		src->fingerprint.sha256[22], src->fingerprint.sha256[23], -		src->fingerprint.sha256[24], src->fingerprint.sha256[25], -		src->fingerprint.sha256[26], src->fingerprint.sha256[27], -		src->fingerprint.sha256[28], src->fingerprint.sha256[29], -		src->fingerprint.sha256[30], src->fingerprint.sha256[31] -	); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// TODO write setup, mid - -	// write media attribute: mode -	switch (src->mode) { -		case SDP_MODE_RECEIVE_ONLY: -			n = snprintf(dst, len, "a=recvonly\n"); -			break; -		case SDP_MODE_SEND_ONLY: -			n = snprintf(dst, len, "a=sendonly\n"); -			break; -		case SDP_MODE_SEND_AND_RECEIVE: -			n = snprintf(dst, len, "a=sendrecv\n"); -			break; -		default: -			return -URTC_ERR_SDP_MALFORMED; -			break; -	} -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	// write media attribute: rtcp mux -	if (src->rtcp_mux) { -		n = snprintf(dst, len, "a=rtcp-mux\n"); -		if (n < 0) return -URTC_ERR_SDP_MALFORMED; -		if (n >= len) return -URTC_ERR_SDP_MALFORMED; -		dst += n; -		len -= n; -	} - -	// write media attribute: rtcp rsize -	if (src->rtcp_rsize) { -		n = snprintf(dst, len, "a=rtcp-rsize\n"); -		if (n < 0) return -URTC_ERR_SDP_MALFORMED; -		if (n >= len) return -URTC_ERR_SDP_MALFORMED; -		dst += n; -		n -= n; -	} - -	// write dynamic profiles -	for (int i = 0; i < src->video.count; i++) { -		if (src->video.params[i].codec == SDP_CODEC_H264) { -			n = snprintf(dst, len, "a=rtpmap:%d H264/%d\n", -				src->video.params[i].type, -				src->video.params[i].clock -			); -			if (n < 0) return -URTC_ERR_SDP_MALFORMED; -			if (n >= len) return -URTC_ERR_SDP_MALFORMED; -			dst += n; -			len -= n; -		} -	} - -	// write media attribute: media id -	// TODO fix hardcoded media id -	n = snprintf(dst, len, "a=mid:0\n"); -	if (n < 0) return -URTC_ERR_SDP_MALFORMED; -	if (n >= len) return -URTC_ERR_SDP_MALFORMED; -	dst += n; -	len -= n; - -	return 0; +    int n; + +    // sanity check +    if (!dst) return -URTC_ERR_BAD_ARGUMENT; +    if (!src) return -URTC_ERR_BAD_ARGUMENT; + +    // write version +    n = snprintf(dst, len, "v=%u\n", src->version); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write originator and session identifier +    n = snprintf(dst, len, +        "o=liburtc/0.0.0 %s %s IN IP4 127.0.0.1\n", +        src->session_id, +        src->session_version +    ); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write session name +    n = snprintf(dst, len, "s=%s\n", +        0 == strlen(src->session_name) ? " " : src->session_name); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write uri +    n = snprintf(dst, len, "u=http://www.liburtc.org\n"); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write time descriptor +    n = snprintf(dst, len, "t=%" PRIu64 " %" PRIu64 "\n", +        src->start_time, src->stop_time); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write session attribute +    n = snprintf(dst, len, "a=group:BUNDLE"); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; +    for (int i = 0; i < SDP_MAX_BUNDLE_IDS; i++) { +        if (strlen(src->mid[i]) > 0) { +            n = snprintf(dst, len, " %s", src->mid[i]); +            if (n < 0) return -URTC_ERR_SDP_MALFORMED; +            if (n >= len) return -URTC_ERR_SDP_MALFORMED; +            dst += n; +            len -= n; +        } +    } +    n = snprintf(dst, len, "\n"); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write video media description +    if (src->video.count > 0) { +        n = snprintf( +            dst, len, "m=video %hd UDP/TLS/RTP/SAVPF", src->video.port +        ); +        if (n < 0) return -URTC_ERR_SDP_MALFORMED; +        if (n >= len) return -URTC_ERR_SDP_MALFORMED; +        dst += n; +        len -= n; +        for (int i = 0; i < src->video.count; i++) { +            if (src->video.params[i].codec == SDP_CODEC_H264) { +                n = snprintf(dst, len, " %d", src->video.params[i].type); +                if (n < 0) return -URTC_ERR_SDP_MALFORMED; +                if (n > len) return -URTC_ERR_SDP_MALFORMED; +                dst += n; +                len -= n; +            } +        } +        n = snprintf(dst, len, "\n"); +        if (n < 0) return -URTC_ERR_SDP_MALFORMED; +        if (n >= len) return -URTC_ERR_SDP_MALFORMED; +        dst += n; +        len -= n; +    } + +    // TODO write rtcp attribute + +    // write connection information (TODO IPv6) +    n = snprintf(dst, len, "c=IN IP4 0.0.0.0\n"); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write media attribute: ice ufrag +    n = snprintf(dst, len, "a=ice-ufrag:%s\n", src->ufrag); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write media attribute: ice pwd +    n = snprintf(dst, len, "a=ice-pwd:%s\n", src->pwd); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write media attribute: trickle ICE +    if (src->ice_options.trickle) { +        n = snprintf(dst, len, "a=ice-options:trickle\n"); +        if (n < 0) return -URTC_ERR_SDP_MALFORMED; +        if (n >= len) return -URTC_ERR_SDP_MALFORMED; +        dst += n; +        len -= n; +    } + +    // write media attribute: fingerprint +    n = snprintf(dst, len, +        "a=fingerprint:sha-256 " +        "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:" +        "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:" +        "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:" +        "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX\n", +        src->fingerprint.sha256[0], src->fingerprint.sha256[1], +        src->fingerprint.sha256[2], src->fingerprint.sha256[3], +        src->fingerprint.sha256[4], src->fingerprint.sha256[5], +        src->fingerprint.sha256[6], src->fingerprint.sha256[7], +        src->fingerprint.sha256[8], src->fingerprint.sha256[9], +        src->fingerprint.sha256[10], src->fingerprint.sha256[11], +        src->fingerprint.sha256[12], src->fingerprint.sha256[13], +        src->fingerprint.sha256[14], src->fingerprint.sha256[15], +        src->fingerprint.sha256[16], src->fingerprint.sha256[17], +        src->fingerprint.sha256[18], src->fingerprint.sha256[19], +        src->fingerprint.sha256[20], src->fingerprint.sha256[21], +        src->fingerprint.sha256[22], src->fingerprint.sha256[23], +        src->fingerprint.sha256[24], src->fingerprint.sha256[25], +        src->fingerprint.sha256[26], src->fingerprint.sha256[27], +        src->fingerprint.sha256[28], src->fingerprint.sha256[29], +        src->fingerprint.sha256[30], src->fingerprint.sha256[31] +    ); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // TODO write setup, mid + +    // write media attribute: mode +    switch (src->mode) { +        case SDP_MODE_RECEIVE_ONLY: +            n = snprintf(dst, len, "a=recvonly\n"); +            break; +        case SDP_MODE_SEND_ONLY: +            n = snprintf(dst, len, "a=sendonly\n"); +            break; +        case SDP_MODE_SEND_AND_RECEIVE: +            n = snprintf(dst, len, "a=sendrecv\n"); +            break; +        default: +            return -URTC_ERR_SDP_MALFORMED; +            break; +    } +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    // write media attribute: rtcp mux +    if (src->rtcp_mux) { +        n = snprintf(dst, len, "a=rtcp-mux\n"); +        if (n < 0) return -URTC_ERR_SDP_MALFORMED; +        if (n >= len) return -URTC_ERR_SDP_MALFORMED; +        dst += n; +        len -= n; +    } + +    // write media attribute: rtcp rsize +    if (src->rtcp_rsize) { +        n = snprintf(dst, len, "a=rtcp-rsize\n"); +        if (n < 0) return -URTC_ERR_SDP_MALFORMED; +        if (n >= len) return -URTC_ERR_SDP_MALFORMED; +        dst += n; +        n -= n; +    } + +    // write dynamic profiles +    for (int i = 0; i < src->video.count; i++) { +        if (src->video.params[i].codec == SDP_CODEC_H264) { +            n = snprintf(dst, len, "a=rtpmap:%d H264/%d\n", +                src->video.params[i].type, +                src->video.params[i].clock +            ); +            if (n < 0) return -URTC_ERR_SDP_MALFORMED; +            if (n >= len) return -URTC_ERR_SDP_MALFORMED; +            dst += n; +            len -= n; +        } +    } + +    // write media attribute: media id +    // TODO fix hardcoded media id +    n = snprintf(dst, len, "a=mid:0\n"); +    if (n < 0) return -URTC_ERR_SDP_MALFORMED; +    if (n >= len) return -URTC_ERR_SDP_MALFORMED; +    dst += n; +    len -= n; + +    return 0;  } + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef _URTC_SDP_H @@ -33,91 +36,91 @@ extern "C" {  // Maximum size of SDP string (in bytes) -#define SDP_MAX_SIZE					2048 +#define SDP_MAX_SIZE                    2048 -#define SDP_MAX_USERNAME_SIZE			32 -#define SDP_MAX_SESSION_ID_SIZE			32 -#define SDP_MAX_SESSION_VERSION_SIZE	32 -#define SDP_MAX_SESSION_NAME_SIZE		32 +#define SDP_MAX_USERNAME_SIZE           32 +#define SDP_MAX_SESSION_ID_SIZE         32 +#define SDP_MAX_SESSION_VERSION_SIZE    32 +#define SDP_MAX_SESSION_NAME_SIZE       32 -#define SDP_MAX_BUNDLE_IDS				5 -#define SDP_MAX_BUNDLE_ID_SIZE			32 -#define SDP_MAX_RTP_PAYLOAD_TYPES		32 +#define SDP_MAX_BUNDLE_IDS              5 +#define SDP_MAX_BUNDLE_ID_SIZE          32 +#define SDP_MAX_RTP_PAYLOAD_TYPES       32  typedef enum sdp_mode { -	SDP_MODE_SEND_AND_RECEIVE = 0, -	SDP_MODE_RECEIVE_ONLY, -	SDP_MODE_SEND_ONLY +    SDP_MODE_SEND_AND_RECEIVE = 0, +    SDP_MODE_RECEIVE_ONLY, +    SDP_MODE_SEND_ONLY  } sdp_mode_t;  typedef enum sdp_media { -	SDP_MEDIA_TYPE_NULL = 0, -	SDP_MEDIA_TYPE_AUDIO, -	SDP_MEDIA_TYPE_VIDEO, -	SDP_MEDIA_TYPE_TEXT, -	SDP_MEDIA_TYPE_APPLICATION, -	SDP_MEDIA_TYPE_MESSAGE +    SDP_MEDIA_TYPE_NULL = 0, +    SDP_MEDIA_TYPE_AUDIO, +    SDP_MEDIA_TYPE_VIDEO, +    SDP_MEDIA_TYPE_TEXT, +    SDP_MEDIA_TYPE_APPLICATION, +    SDP_MEDIA_TYPE_MESSAGE  } sdp_media_type_t;  // Codecs recognized by SDP parser  typedef enum sdp_codec { -	SDP_CODEC_NULL = 0, -	SDP_CODEC_H264, -	SDP_CODEC_VP9 +    SDP_CODEC_NULL = 0, +    SDP_CODEC_H264, +    SDP_CODEC_VP9  } sdp_codec_t;  // Dynamic payload type  typedef struct sdp_rtpmap { -	unsigned int      type;             // Dynamic RTP payload type (e.g. 96) -	enum sdp_codec    codec;            // H264, VP9, etc. -	unsigned int      clock;            // Typically 90kHz for video -	unsigned int      flags; +    unsigned int      type;             // Dynamic RTP payload type (e.g. 96) +    enum sdp_codec    codec;            // H264, VP9, etc. +    unsigned int      clock;            // Typically 90kHz for video +    unsigned int      flags;  } sdp_rtpmap_t;  typedef struct sdp { -	// protocol version -	uint8_t version; - -	// originator and session identifier -	char username[SDP_MAX_USERNAME_SIZE+1]; -	char session_id[SDP_MAX_SESSION_ID_SIZE+1]; -	char session_version[SDP_MAX_SESSION_VERSION_SIZE+1]; - -	// session name -	char session_name[SDP_MAX_SESSION_NAME_SIZE+1]; - -	// time description (mandatory) -	uint64_t start_time; -	uint64_t stop_time; - -	// session attributes -	 -	// bundle media identification tags -	char mid[SDP_MAX_BUNDLE_IDS][SDP_MAX_BUNDLE_ID_SIZE+1]; -	 -	// ice -	char ufrag[4*256];					// ice-ufrag (256 unicode chars max.) -	char pwd[4*256];					// ice-pwd (256 unicode chars max.) -	struct { -		bool trickle; -	} ice_options; - -	// video media -	struct { -		uint16_t port; -		struct sdp_rtpmap params[SDP_MAX_RTP_PAYLOAD_TYPES]; -		int count; -	} video; - -	sdp_mode_t mode;					// send, receive, and send-and-receive - -	bool rtcp_mux;						// is rtcp multiplexed on same socket -	bool rtcp_rsize; - -	union { -		uint8_t sha256[32];				// certificate fingerprint -	} fingerprint; +    // protocol version +    uint8_t version; + +    // originator and session identifier +    char username[SDP_MAX_USERNAME_SIZE+1]; +    char session_id[SDP_MAX_SESSION_ID_SIZE+1]; +    char session_version[SDP_MAX_SESSION_VERSION_SIZE+1]; + +    // session name +    char session_name[SDP_MAX_SESSION_NAME_SIZE+1]; + +    // time description (mandatory) +    uint64_t start_time; +    uint64_t stop_time; + +    // session attributes +     +    // bundle media identification tags +    char mid[SDP_MAX_BUNDLE_IDS][SDP_MAX_BUNDLE_ID_SIZE+1]; +     +    // ice +    char ufrag[4*256];                  // ice-ufrag (256 unicode chars max.) +    char pwd[4*256];                    // ice-pwd (256 unicode chars max.) +    struct { +        bool trickle; +    } ice_options; + +    // video media +    struct { +        uint16_t port; +        struct sdp_rtpmap params[SDP_MAX_RTP_PAYLOAD_TYPES]; +        int count; +    } video; + +    sdp_mode_t mode;                    // send, receive, and send-and-receive + +    bool rtcp_mux;                      // is rtcp multiplexed on same socket +    bool rtcp_rsize; + +    union { +        uint8_t sha256[32];             // certificate fingerprint +    } fingerprint;  } sdp_t; @@ -148,3 +151,5 @@ int sdp_serialize(char *dst, size_t len, const struct sdp *src);  #endif  #endif /* _URTC_SDP_H */ + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,131 +1,139 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */ -#include <assert.h>						// assert -#include <errno.h>						// errno -#include <poll.h>						// poll -#include <pthread.h>					// pthread_create -#include <stdbool.h>					// true -#include <stdio.h>						// fprintf -#include <stdlib.h>						// calloc, free -#include <string.h>						// strerror -#include <unistd.h>						// close - -#include <arpa/inet.h>					// inet_ntoa -#include <netinet/in.h>					// IPPROTO_UDP -#include <sys/socket.h>					// socket +#include <assert.h>                     // assert +#include <errno.h>                      // errno +#include <poll.h>                       // poll +#include <pthread.h>                    // pthread_create +#include <stdbool.h>                    // true +#include <stdio.h>                      // fprintf +#include <stdlib.h>                     // calloc, free +#include <string.h>                     // strerror +#include <unistd.h>                     // close + +#include <arpa/inet.h>                  // inet_ntoa +#include <netinet/in.h>                 // IPPROTO_UDP +#include <sys/socket.h>                 // socket  #include <sys/types.h>  #include "err.h"  #include "log.h" -#include "mdns.h"						// mdns_subscribe, mdns_unsubscribe -#include "prng.h"						// prng_init +#include "mdns.h"                       // mdns_subscribe, mdns_unsubscribe +#include "prng.h"                       // prng_init  #include "sdp.h"  #include "urtc.h" -#include "uuid.h"						// uuid_create_str +#include "uuid.h"                       // uuid_create_str -#define  RX_BUF_CAP               2048  // receive buffer capacity +#define RX_BUF_CAP               2048   // receive buffer capacity -#define  POLL_TIMEOUT_MS            50  // poll() timeout (in milliseconds) +#define POLL_TIMEOUT_MS            50   // poll() timeout (in milliseconds) + +const static char *default_stun_servers[] = { +    "stun.liburtc.org", +    NULL +};  enum signaling_state { -	SIGNALING_STATE_STABLE = 0, -	SIGNALING_STATE_HAVE_LOCAL_OFFER, -	SIGNALING_STATE_HAVE_REMOTE_OFFER, -	SIGNALING_STATE_HAVE_LOCAL_PRANSWER, -	SIGNALING_STATE_HAVE_REMOTE_PRANSWER, +    SIGNALING_STATE_STABLE = 0, +    SIGNALING_STATE_HAVE_LOCAL_OFFER, +    SIGNALING_STATE_HAVE_REMOTE_OFFER, +    SIGNALING_STATE_HAVE_LOCAL_PRANSWER, +    SIGNALING_STATE_HAVE_REMOTE_PRANSWER,  };  enum rtc_state { -	STATE_NEW = 0, +    STATE_NEW = 0, -	STATE_ICE_NEW, -	STATE_ICE_GATHERING, -	STATE_ICE_COMPLETE, +    STATE_ICE_NEW, +    STATE_ICE_GATHERING, +    STATE_ICE_COMPLETE, -	STATE_CONNECTING, +    STATE_CONNECTING, -	STATE_CONNECTED, +    STATE_CONNECTED, -	STATE_DISCONNECTED, +    STATE_DISCONNECTED, -	STATE_FAILED, +    STATE_FAILED, -	STATE_CLOSED, +    STATE_CLOSED, -	NUM_STATES // must be last +    NUM_STATES // must be last  };  enum rtc_event { -	EVENT_SOCKET = 0, -	EVENT_TIMER, -	EVENT_MDNS, -	NUM_EVENTS, // must be last +    EVENT_SOCKET = 0, +    EVENT_TIMER, +    EVENT_MDNS, +    NUM_EVENTS, // must be last  };  struct peerconn { -	// socket file descriptor -	int sockfd; +    // socket file descriptor +    int sockfd; -	// execution thread -	pthread_t thread; +    // execution thread +    pthread_t thread; -	// poll file descriptors -	struct pollfd fds[NUM_EVENTS]; +    // poll file descriptors +    struct pollfd fds[NUM_EVENTS]; -	// callbacks -	urtc_on_ice_candidate *on_ice_candidate; -	urtc_force_idr *force_idr; +    // callbacks +    urtc_on_ice_candidate *on_ice_candidate; +    urtc_force_idr *force_idr; -	// stun servers -	const char **stun; +    // stun servers +    const char **stun; -	// state machine -	enum signaling_state ss; +    // state machine +    enum signaling_state ss; -	// local and remote descriptions -	struct sdp ldesc, rdesc; +    // local and remote descriptions +    struct sdp ldesc, rdesc; -	// mDNS related state -	struct { -		char hostname[UUID_STR_LEN];	// .local hostname -		int  sockfd;					// port 5353 listener -	} mdns; +    // mDNS related state +    struct { +        char hostname[UUID_STR_LEN];    // .local hostname +        int  sockfd;                    // port 5353 listener +    } mdns;  };  typedef int (*event_handler)(struct peerconn *pc);  const enum rtc_state state_table[NUM_STATES][NUM_EVENTS] = { -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW }, -	{ STATE_NEW, STATE_NEW } +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }, +    { STATE_NEW, STATE_NEW }  };  /** @@ -136,11 +144,11 @@ const enum rtc_state state_table[NUM_STATES][NUM_EVENTS] = {   * \return 0 on success, negative on error.   */  static int stun_handler( -	struct peerconn *pc, -	const uint8_t *pkt, -	size_t n +    struct peerconn *pc, +    const uint8_t *pkt, +    size_t n  ) { -	return 0; +    return 0;  }  /** @@ -151,11 +159,11 @@ static int stun_handler(   * \return 0 on success, negative on error.   */  static int dtls_handler( -	struct peerconn *pc, -	const uint8_t *pkt, -	size_t n +    struct peerconn *pc, +    const uint8_t *pkt, +    size_t n  ) { -	return 0; +    return 0;  }  /** @@ -166,11 +174,11 @@ static int dtls_handler(   * \return 0 on success, negative on error.   */  static int rtp_handler( -	struct peerconn *pc, -	const uint8_t *pkt, -	size_t n +    struct peerconn *pc, +    const uint8_t *pkt, +    size_t n  ) { -	return 0; +    return 0;  }  /** @@ -184,39 +192,39 @@ static int rtp_handler(   * \return 0 on success, negative on error.   */  static int socket_event_handler(struct peerconn *pc) { -	uint8_t buffer[RX_BUF_CAP]; -	struct sockaddr_in ra; -	socklen_t ralen; -	ssize_t n; - -	// read packet -	ralen = sizeof(ra); -	n = recvfrom( -		pc->sockfd, -		buffer, -		sizeof(buffer), -		0, -		(struct sockaddr *)(&ra), -		&ralen -	); - -	// rtp -	if ((127 < buffer[0]) && (buffer[0] < 192)) { -		log(INFO, "[rtp] %s", inet_ntoa(ra.sin_addr)); -		rtp_handler(pc, buffer, n); -	} else -	// dtls -	if ((19 < buffer[0]) && (buffer[0] < 64)) { -		log(INFO, "[dtls] %s", inet_ntoa(ra.sin_addr)); -		dtls_handler(pc, buffer, n); -	} else -	// stun -	if (buffer[0] < 2) { -		log(INFO, "[stun] %s", inet_ntoa(ra.sin_addr)); -		stun_handler(pc, buffer, n); -	} - -	return 0; +    uint8_t buffer[RX_BUF_CAP]; +    struct sockaddr_in ra; +    socklen_t ralen; +    ssize_t n; + +    // read packet +    ralen = sizeof(ra); +    n = recvfrom( +        pc->sockfd, +        buffer, +        sizeof(buffer), +        0, +        (struct sockaddr *)(&ra), +        &ralen +    ); + +    // rtp +    if ((127 < buffer[0]) && (buffer[0] < 192)) { +        log(INFO, "[rtp] %s", inet_ntoa(ra.sin_addr)); +        rtp_handler(pc, buffer, n); +    } else +    // dtls +    if ((19 < buffer[0]) && (buffer[0] < 64)) { +        log(INFO, "[dtls] %s", inet_ntoa(ra.sin_addr)); +        dtls_handler(pc, buffer, n); +    } else +    // stun +    if (buffer[0] < 2) { +        log(INFO, "[stun] %s", inet_ntoa(ra.sin_addr)); +        stun_handler(pc, buffer, n); +    } + +    return 0;  }  /** @@ -232,7 +240,7 @@ static int socket_event_handler(struct peerconn *pc) {   * \return 0 on success, negative on error.   */  static int timer_event_handler(struct peerconn *pc) { -	return 0; +    return 0;  }  /** @@ -243,51 +251,51 @@ static int timer_event_handler(struct peerconn *pc) {   * \return 0 on success, negative on error.   */  static int mdns_handler(struct peerconn *pc) { -	uint8_t buffer[RX_BUF_CAP]; -	ssize_t n; - -	// read packet -	if (n = recvfrom( -		pc->mdns.sockfd, -		buffer, -		sizeof(buffer), -		0, -		NULL, -		NULL -	), -1 == n) { -		log(ERROR, "%s", strerror(errno)); -		goto _fail_recvfrom; -	} - -	// if valid query for peer connection's ephemeral hostname... -	int type = mdns_validate_query(buffer, n, pc->mdns.hostname); -	if (type > 0) { -		if (type | TYPE_A) { -			log(DEBUG, "[mdns] received A query"); -			// ...respond to query with interface addresses -			mdns_send_response(pc->mdns.sockfd, pc->mdns.hostname); -		} -		if (type | TYPE_AAAA) { -			log(DEBUG, "[mdns] received AAAA query"); -		} -	} - -	return 0; +    uint8_t buffer[RX_BUF_CAP]; +    ssize_t n; + +    // read packet +    if (n = recvfrom( +        pc->mdns.sockfd, +        buffer, +        sizeof(buffer), +        0, +        NULL, +        NULL +    ), -1 == n) { +        log(ERROR, "%s", strerror(errno)); +        goto _fail_recvfrom; +    } + +    // if valid query for peer connection's ephemeral hostname... +    int type = mdns_validate_query(buffer, n, pc->mdns.hostname); +    if (type > 0) { +        if (type | TYPE_A) { +            log(DEBUG, "[mdns] received A query"); +            // ...respond to query with interface addresses +            mdns_send_response(pc->mdns.sockfd, pc->mdns.hostname); +        } +        if (type | TYPE_AAAA) { +            log(DEBUG, "[mdns] received AAAA query"); +        } +    } + +    return 0;  _fail_recvfrom: -	return -URTC_ERR; +    return -URTC_ERR;  }  const event_handler action_table[NUM_STATES][NUM_EVENTS] = { -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL }, -	{ NULL, NULL, NULL } +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }, +    { NULL, NULL, NULL }  };  /** @@ -296,18 +304,18 @@ const event_handler action_table[NUM_STATES][NUM_EVENTS] = {  // send stun request  // wait for stun reply -// 		timeout -> resend request +//      timeout -> resend request -// called							dir			caller -// ------							---			------ -// setRemoteDescription(offer)		<--			offer = createOffer() -// 												setLocalDescription(offer) -// answer = createAnswer()			-->			setRemoteDescription(answer) +// called                           dir         caller +// ------                           ---         ------ +// setRemoteDescription(offer)      <--         offer = createOffer() +//                                              setLocalDescription(offer) +// answer = createAnswer()          -->         setRemoteDescription(answer)  // setLocalDescription(answer)  // -// cand = onIceCandidate			-->			addIceCandidate(cand) -// addIceCandidate(cand)			<--			cand = onIceCandidate -// 									... +// cand = onIceCandidate            -->         addIceCandidate(cand) +// addIceCandidate(cand)            <--         cand = onIceCandidate +//                                  ...  //  //                       (connection established)  // @@ -324,118 +332,124 @@ const event_handler action_table[NUM_STATES][NUM_EVENTS] = {   * \return Unused.   */  static void * runloop(void *arg) { -	struct peerconn *pc; -	enum rtc_event event; -	int n; +    struct peerconn *pc; +    enum rtc_event event; +    int n; -	pc = (struct peerconn *)arg; -	assert(pc); +    pc = (struct peerconn *)arg; +    assert(pc);  _loop: -	// block indefinitely (-1 timeout) until i/o event -	n = poll(pc->fds, NUM_EVENTS, -1); -	assert(n > 0); +    // block indefinitely (-1 timeout) until i/o event +    n = poll(pc->fds, NUM_EVENTS, -1); +    assert(n > 0); -	// which event(s) occurred? -	if (pc->fds[EVENT_SOCKET].revents & POLLIN) { -		event = EVENT_SOCKET; -	} else -	if (pc->fds[EVENT_MDNS].revents & POLLIN) { -		mdns_handler(pc); -	} else -	if (pc->fds[EVENT_TIMER].revents & POLLIN) { -		event = EVENT_TIMER; -	} +    // which event(s) occurred? +    if (pc->fds[EVENT_SOCKET].revents & POLLIN) { +        event = EVENT_SOCKET; +    } else +    if (pc->fds[EVENT_MDNS].revents & POLLIN) { +        mdns_handler(pc); +    } else +    if (pc->fds[EVENT_TIMER].revents & POLLIN) { +        event = EVENT_TIMER; +    } -	goto _loop; +    goto _loop; -	return NULL; +    return NULL;  };  urtc_peerconn_t * urtc_peerconn_create(const char *stun[]) { -	// seend pseudorandom number generator -	prng_init(); - -	// allocate peer connection -	struct peerconn *pc = (struct peerconn *)calloc(1, sizeof(struct peerconn)); -	if (!pc) return pc; - -	// copy pointer to stun servers -	pc->stun = stun; - -	// open udp socket (for all dtls/srtp/srtcp/stun/turn communication) -	pc->sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); -	if (-1 == pc->sockfd) goto _fail_socket; -	pc->fds[EVENT_SOCKET] = (struct pollfd){ pc->sockfd, POLLIN }; - -	// generate a unique local mDNS hostname -	uuid_create_str(pc->mdns.hostname); -	log(INFO, "mDNS hostname is %s.local", pc->mdns.hostname); - -	// open multicast udp socket for replying to mDNS queries -	pc->mdns.sockfd = mdns_subscribe(); -	if (-1 == pc->mdns.sockfd) goto _fail_mdns_subscribe; -	pc->fds[EVENT_MDNS] = (struct pollfd){ -		pc->mdns.sockfd, -		POLLIN -	}; - -	// start new thread per peer connection -	if (0 != pthread_create( -		&(pc->thread),  -		NULL, -		runloop, -		pc -	)) goto _fail_pthread_create; - -	return pc; +    // seed pseudorandom number generator +    prng_init(); + +    // allocate peer connection +    struct peerconn *pc = (struct peerconn *)calloc(1, sizeof(struct peerconn)); +    if (!pc) return pc; + +    // copy pointer to stun servers +    if (!stun) { +        pc->stun = default_stun_servers; +    } else { +        pc->stun = stun; +    } + +    // open udp socket (for all dtls/srtp/srtcp/stun/turn communication) +    pc->sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); +    if (-1 == pc->sockfd) goto _fail_socket; +    pc->fds[EVENT_SOCKET] = (struct pollfd){ pc->sockfd, POLLIN }; + +    // generate a unique local mDNS hostname +    uuid_create_str(pc->mdns.hostname); +    log(INFO, "mDNS hostname is %s.local", pc->mdns.hostname); + +    // open multicast udp socket for replying to mDNS queries +    pc->mdns.sockfd = mdns_subscribe(); +    if (-1 == pc->mdns.sockfd) goto _fail_mdns_subscribe; +    pc->fds[EVENT_MDNS] = (struct pollfd){ +        pc->mdns.sockfd, +        POLLIN +    }; + +    // start new thread per peer connection +    if (0 != pthread_create( +        &(pc->thread),  +        NULL, +        runloop, +        pc +    )) goto _fail_pthread_create; + +    return pc;  _fail_pthread_create: -	mdns_unsubscribe(pc->mdns.sockfd); +    mdns_unsubscribe(pc->mdns.sockfd);  _fail_mdns_subscribe: -	close(pc->sockfd); +    close(pc->sockfd);  _fail_socket: -	free(pc); +    free(pc); -	return NULL; +    return NULL;  }  int urtc_set_on_ice_candidate(struct peerconn *pc, urtc_on_ice_candidate *cb) { -	if (!pc) return -1; -	if (!cb) return -1; -	pc->on_ice_candidate = cb; +    if (!pc) return -1; +    if (!cb) return -1; +    pc->on_ice_candidate = cb; -	return -URTC_ERR_NOT_IMPLEMENTED; +    return -URTC_ERR_NOT_IMPLEMENTED;  }  int urtc_add_ice_candidate(struct peerconn *pc, const char *cand) { -	return -URTC_ERR_NOT_IMPLEMENTED; +    return -URTC_ERR_NOT_IMPLEMENTED;  }  int urtc_create_answer(struct peerconn *pc, char **answer) { -	return -URTC_ERR_NOT_IMPLEMENTED; +    return -URTC_ERR_NOT_IMPLEMENTED;  }  int urtc_create_offer(struct peerconn *pc, char **offer) { -	return -URTC_ERR_NOT_IMPLEMENTED; +    return -URTC_ERR_NOT_IMPLEMENTED;  }  int urtc_set_remote_description(struct peerconn *pc, const char *desc) { -	return -URTC_ERR_NOT_IMPLEMENTED; +    return -URTC_ERR_NOT_IMPLEMENTED;  }  int urtc_set_local_description(struct peerconn *pc, const char *desc) { -	return -URTC_ERR_NOT_IMPLEMENTED; +    return -URTC_ERR_NOT_IMPLEMENTED;  }  void urtc_peerconn_destroy(struct peerconn *pc) { -	if (pc) { -		pthread_cancel(pc->thread); -		pthread_join(pc->thread, NULL); -		mdns_unsubscribe(pc->mdns.sockfd); -		shutdown(pc->sockfd, SHUT_RDWR); -		close(pc->sockfd); -		free(pc); -	} +    if (pc) { +        pthread_cancel(pc->thread); +        pthread_join(pc->thread, NULL); +        mdns_unsubscribe(pc->mdns.sockfd); +        shutdown(pc->sockfd, SHUT_RDWR); +        close(pc->sockfd); +        free(pc); +    }  } + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -3,25 +3,29 @@   *   * \brief liburtc header file.   * - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  /** @@ -105,8 +109,8 @@ typedef void (urtc_force_idr)();   *             local area network peers will be discoverable.   *   * \return On success, a pointer to new peer connection object is returned. - *		The peer connection must be destroyed with urtc_peerconn_destroy() - *		when no longer needed. On error, NULL is returned. + *      The peer connection must be destroyed with urtc_peerconn_destroy() + *      when no longer needed. On error, NULL is returned.   */  urtc_peerconn_t * urtc_peerconn_create(const char *stun[]); @@ -221,3 +225,5 @@ void urtc_peerconn_destroy(urtc_peerconn_t *pc);  #endif  #endif /* _URTC_H */ + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  /** @@ -39,16 +42,16 @@   * \return Populated UUID.   */  struct uuid uuid_create() { -	struct uuid u; +    struct uuid u; -	// fill with randomness -	prng(&u, sizeof(u)); +    // fill with randomness +    prng(&u, sizeof(u)); -	// set reserved and version bits -	u.clk_seq_hi_and_reserved = (u.clk_seq_hi_and_reserved & 0x3F) | 0x80; -	u.time_hi_and_version = (u.time_hi_and_version & 0x0FFF) | 0x4000; +    // set reserved and version bits +    u.clk_seq_hi_and_reserved = (u.clk_seq_hi_and_reserved & 0x3F) | 0x80; +    u.time_hi_and_version = (u.time_hi_and_version & 0x0FFF) | 0x4000; -	return u; +    return u;  }  /** @@ -58,19 +61,21 @@ struct uuid uuid_create() {   *   */  void uuid_create_str(char s[UUID_STR_LEN]) { -	struct uuid u = uuid_create(); +    struct uuid u = uuid_create(); -	sprintf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", -		u.time_low, -		u.time_mid, -		u.time_hi_and_version, -		u.clk_seq_hi_and_reserved, -		u.clk_seq_low, -		u.node[0], -		u.node[1], -		u.node[2], -		u.node[3], -		u.node[4], -		u.node[5] -	); +    sprintf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", +        u.time_low, +        u.time_mid, +        u.time_hi_and_version, +        u.clk_seq_hi_and_reserved, +        u.clk_seq_low, +        u.node[0], +        u.node[1], +        u.node[2], +        u.node[3], +        u.node[4], +        u.node[5] +    );  } + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ @@ -1,24 +1,27 @@  /** - * liburtc - * Copyright 2020 Chris Hiszpanski - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. + * Copyright (c) 2019-2021 Chris Hiszpanski. All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + *  + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE.   */  #ifndef _URTC_UUID_H @@ -35,12 +38,12 @@ extern "C" {  #define UUID_STR_LEN (32 + 4 + 1) // 16 hex octets, 4 dashes, 1 null terminator  struct __attribute__((__packed__)) uuid { -	uint32_t time_low; -	uint16_t time_mid; -	uint16_t time_hi_and_version; -	uint8_t clk_seq_hi_and_reserved; -	uint8_t clk_seq_low; -	uint8_t node[6]; +    uint32_t time_low; +    uint16_t time_mid; +    uint16_t time_hi_and_version; +    uint8_t clk_seq_hi_and_reserved; +    uint8_t clk_seq_low; +    uint8_t node[6];  };  struct uuid uuid_create(); @@ -52,3 +55,5 @@ void uuid_create_str(char uuid[UUID_STR_LEN]);  #endif  #endif // _URTC_UUID_H + +/* vim: set expandtab ts=8 sw=4 tw=0 : */ | 
