Klika Tech / Mbed 2 deprecated Nucleo-AWS-IoT-mbed

Dependencies:   X_NUCLEO_IKS01A1 mbed FP MQTTPacket DnsQuery ATParser

Committer:
PavelSavyhin
Date:
Wed Sep 27 14:40:52 2017 +0300
Revision:
0:4cdaf9b1e7d0
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
PavelSavyhin 0:4cdaf9b1e7d0 1 /* Socket
PavelSavyhin 0:4cdaf9b1e7d0 2 * Copyright (c) 2015 ARM Limited
PavelSavyhin 0:4cdaf9b1e7d0 3 *
PavelSavyhin 0:4cdaf9b1e7d0 4 * Licensed under the Apache License, Version 2.0 (the "License");
PavelSavyhin 0:4cdaf9b1e7d0 5 * you may not use this file except in compliance with the License.
PavelSavyhin 0:4cdaf9b1e7d0 6 * You may obtain a copy of the License at
PavelSavyhin 0:4cdaf9b1e7d0 7 *
PavelSavyhin 0:4cdaf9b1e7d0 8 * http://www.apache.org/licenses/LICENSE-2.0
PavelSavyhin 0:4cdaf9b1e7d0 9 *
PavelSavyhin 0:4cdaf9b1e7d0 10 * Unless required by applicable law or agreed to in writing, software
PavelSavyhin 0:4cdaf9b1e7d0 11 * distributed under the License is distributed on an "AS IS" BASIS,
PavelSavyhin 0:4cdaf9b1e7d0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
PavelSavyhin 0:4cdaf9b1e7d0 13 * See the License for the specific language governing permissions and
PavelSavyhin 0:4cdaf9b1e7d0 14 * limitations under the License.
PavelSavyhin 0:4cdaf9b1e7d0 15 */
PavelSavyhin 0:4cdaf9b1e7d0 16
PavelSavyhin 0:4cdaf9b1e7d0 17 #include "SocketAddress.h"
PavelSavyhin 0:4cdaf9b1e7d0 18 #include "NetworkStack.h"
PavelSavyhin 0:4cdaf9b1e7d0 19 #include <string.h>
PavelSavyhin 0:4cdaf9b1e7d0 20 #include "mbed.h"
PavelSavyhin 0:4cdaf9b1e7d0 21
PavelSavyhin 0:4cdaf9b1e7d0 22
PavelSavyhin 0:4cdaf9b1e7d0 23 static bool ipv4_is_valid(const char *addr)
PavelSavyhin 0:4cdaf9b1e7d0 24 {
PavelSavyhin 0:4cdaf9b1e7d0 25 int i = 0;
PavelSavyhin 0:4cdaf9b1e7d0 26
PavelSavyhin 0:4cdaf9b1e7d0 27 // Check each digit for [0-9.]
PavelSavyhin 0:4cdaf9b1e7d0 28 for (; addr[i]; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 29 if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
PavelSavyhin 0:4cdaf9b1e7d0 30 return false;
PavelSavyhin 0:4cdaf9b1e7d0 31 }
PavelSavyhin 0:4cdaf9b1e7d0 32 }
PavelSavyhin 0:4cdaf9b1e7d0 33
PavelSavyhin 0:4cdaf9b1e7d0 34 // Ending with '.' garuntees host
PavelSavyhin 0:4cdaf9b1e7d0 35 if (i > 0 && addr[i-1] == '.') {
PavelSavyhin 0:4cdaf9b1e7d0 36 return false;
PavelSavyhin 0:4cdaf9b1e7d0 37 }
PavelSavyhin 0:4cdaf9b1e7d0 38
PavelSavyhin 0:4cdaf9b1e7d0 39 return true;
PavelSavyhin 0:4cdaf9b1e7d0 40 }
PavelSavyhin 0:4cdaf9b1e7d0 41
PavelSavyhin 0:4cdaf9b1e7d0 42 static bool ipv6_is_valid(const char *addr)
PavelSavyhin 0:4cdaf9b1e7d0 43 {
PavelSavyhin 0:4cdaf9b1e7d0 44 // Check each digit for [0-9a-fA-F:]
PavelSavyhin 0:4cdaf9b1e7d0 45 for (int i = 0; addr[i]; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 46 if (!(addr[i] >= '0' && addr[i] <= '9') &&
PavelSavyhin 0:4cdaf9b1e7d0 47 !(addr[i] >= 'a' && addr[i] <= 'f') &&
PavelSavyhin 0:4cdaf9b1e7d0 48 !(addr[i] >= 'A' && addr[i] <= 'F') &&
PavelSavyhin 0:4cdaf9b1e7d0 49 addr[i] != ':') {
PavelSavyhin 0:4cdaf9b1e7d0 50 return false;
PavelSavyhin 0:4cdaf9b1e7d0 51 }
PavelSavyhin 0:4cdaf9b1e7d0 52 }
PavelSavyhin 0:4cdaf9b1e7d0 53
PavelSavyhin 0:4cdaf9b1e7d0 54 return true;
PavelSavyhin 0:4cdaf9b1e7d0 55 }
PavelSavyhin 0:4cdaf9b1e7d0 56
PavelSavyhin 0:4cdaf9b1e7d0 57 static void ipv4_from_address(uint8_t *bytes, const char *addr)
PavelSavyhin 0:4cdaf9b1e7d0 58 {
PavelSavyhin 0:4cdaf9b1e7d0 59 int count = 0;
PavelSavyhin 0:4cdaf9b1e7d0 60 int i = 0;
PavelSavyhin 0:4cdaf9b1e7d0 61
PavelSavyhin 0:4cdaf9b1e7d0 62 for (; count < NSAPI_IPv4_BYTES; count++) {
PavelSavyhin 0:4cdaf9b1e7d0 63 int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
PavelSavyhin 0:4cdaf9b1e7d0 64 if (scanned < 1) {
PavelSavyhin 0:4cdaf9b1e7d0 65 return;
PavelSavyhin 0:4cdaf9b1e7d0 66 }
PavelSavyhin 0:4cdaf9b1e7d0 67
PavelSavyhin 0:4cdaf9b1e7d0 68 for (; addr[i] != '.'; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 69 if (!addr[i]) {
PavelSavyhin 0:4cdaf9b1e7d0 70 return;
PavelSavyhin 0:4cdaf9b1e7d0 71 }
PavelSavyhin 0:4cdaf9b1e7d0 72 }
PavelSavyhin 0:4cdaf9b1e7d0 73
PavelSavyhin 0:4cdaf9b1e7d0 74 i++;
PavelSavyhin 0:4cdaf9b1e7d0 75 }
PavelSavyhin 0:4cdaf9b1e7d0 76 }
PavelSavyhin 0:4cdaf9b1e7d0 77
PavelSavyhin 0:4cdaf9b1e7d0 78 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
PavelSavyhin 0:4cdaf9b1e7d0 79 int count = 0;
PavelSavyhin 0:4cdaf9b1e7d0 80 int i = 0;
PavelSavyhin 0:4cdaf9b1e7d0 81
PavelSavyhin 0:4cdaf9b1e7d0 82 for (; count < NSAPI_IPv6_BYTES/2; count++) {
PavelSavyhin 0:4cdaf9b1e7d0 83 int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
PavelSavyhin 0:4cdaf9b1e7d0 84 if (scanned < 1) {
PavelSavyhin 0:4cdaf9b1e7d0 85 return count;
PavelSavyhin 0:4cdaf9b1e7d0 86 }
PavelSavyhin 0:4cdaf9b1e7d0 87
PavelSavyhin 0:4cdaf9b1e7d0 88 for (; chunk[i] != ':'; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 89 if (!chunk[i]) {
PavelSavyhin 0:4cdaf9b1e7d0 90 return count+1;
PavelSavyhin 0:4cdaf9b1e7d0 91 }
PavelSavyhin 0:4cdaf9b1e7d0 92 }
PavelSavyhin 0:4cdaf9b1e7d0 93
PavelSavyhin 0:4cdaf9b1e7d0 94 i++;
PavelSavyhin 0:4cdaf9b1e7d0 95 }
PavelSavyhin 0:4cdaf9b1e7d0 96
PavelSavyhin 0:4cdaf9b1e7d0 97 return count;
PavelSavyhin 0:4cdaf9b1e7d0 98 }
PavelSavyhin 0:4cdaf9b1e7d0 99
PavelSavyhin 0:4cdaf9b1e7d0 100 static void ipv6_from_address(uint8_t *bytes, const char *addr)
PavelSavyhin 0:4cdaf9b1e7d0 101 {
PavelSavyhin 0:4cdaf9b1e7d0 102 // Start with zeroed address
PavelSavyhin 0:4cdaf9b1e7d0 103 uint16_t shorts[NSAPI_IPv6_BYTES/2];
PavelSavyhin 0:4cdaf9b1e7d0 104 memset(shorts, 0, sizeof shorts);
PavelSavyhin 0:4cdaf9b1e7d0 105
PavelSavyhin 0:4cdaf9b1e7d0 106 int suffix = 0;
PavelSavyhin 0:4cdaf9b1e7d0 107
PavelSavyhin 0:4cdaf9b1e7d0 108 // Find double colons and scan suffix
PavelSavyhin 0:4cdaf9b1e7d0 109 for (int i = 0; addr[i]; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 110 if (addr[i] == ':' && addr[i+1] == ':') {
PavelSavyhin 0:4cdaf9b1e7d0 111 suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
PavelSavyhin 0:4cdaf9b1e7d0 112 break;
PavelSavyhin 0:4cdaf9b1e7d0 113 }
PavelSavyhin 0:4cdaf9b1e7d0 114 }
PavelSavyhin 0:4cdaf9b1e7d0 115
PavelSavyhin 0:4cdaf9b1e7d0 116 // Move suffix to end
PavelSavyhin 0:4cdaf9b1e7d0 117 memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
PavelSavyhin 0:4cdaf9b1e7d0 118 suffix*sizeof(uint16_t));
PavelSavyhin 0:4cdaf9b1e7d0 119
PavelSavyhin 0:4cdaf9b1e7d0 120 // Scan prefix
PavelSavyhin 0:4cdaf9b1e7d0 121 ipv6_scan_chunk(shorts, &addr[0]);
PavelSavyhin 0:4cdaf9b1e7d0 122
PavelSavyhin 0:4cdaf9b1e7d0 123 // Flip bytes
PavelSavyhin 0:4cdaf9b1e7d0 124 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 125 bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
PavelSavyhin 0:4cdaf9b1e7d0 126 bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
PavelSavyhin 0:4cdaf9b1e7d0 127 }
PavelSavyhin 0:4cdaf9b1e7d0 128 }
PavelSavyhin 0:4cdaf9b1e7d0 129
PavelSavyhin 0:4cdaf9b1e7d0 130 static void ipv4_to_address(char *addr, const uint8_t *bytes)
PavelSavyhin 0:4cdaf9b1e7d0 131 {
PavelSavyhin 0:4cdaf9b1e7d0 132 sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
PavelSavyhin 0:4cdaf9b1e7d0 133 }
PavelSavyhin 0:4cdaf9b1e7d0 134
PavelSavyhin 0:4cdaf9b1e7d0 135 static void ipv6_to_address(char *addr, const uint8_t *bytes)
PavelSavyhin 0:4cdaf9b1e7d0 136 {
PavelSavyhin 0:4cdaf9b1e7d0 137 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 138 sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
PavelSavyhin 0:4cdaf9b1e7d0 139 addr[5*i+4] = ':';
PavelSavyhin 0:4cdaf9b1e7d0 140 }
PavelSavyhin 0:4cdaf9b1e7d0 141 addr[NSAPI_IPv6_SIZE-1] = '\0';
PavelSavyhin 0:4cdaf9b1e7d0 142 }
PavelSavyhin 0:4cdaf9b1e7d0 143
PavelSavyhin 0:4cdaf9b1e7d0 144
PavelSavyhin 0:4cdaf9b1e7d0 145 SocketAddress::SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
PavelSavyhin 0:4cdaf9b1e7d0 146 {
PavelSavyhin 0:4cdaf9b1e7d0 147 memset(&_ip_address, 0, sizeof _ip_address);
PavelSavyhin 0:4cdaf9b1e7d0 148
PavelSavyhin 0:4cdaf9b1e7d0 149 // Check for valid IP addresses
PavelSavyhin 0:4cdaf9b1e7d0 150 if (host && ipv4_is_valid(host)) {
PavelSavyhin 0:4cdaf9b1e7d0 151 _ip_version = NSAPI_IPv4;
PavelSavyhin 0:4cdaf9b1e7d0 152 ipv4_from_address(_ip_bytes, host);
PavelSavyhin 0:4cdaf9b1e7d0 153 set_port(port);
PavelSavyhin 0:4cdaf9b1e7d0 154 } else if (host && ipv6_is_valid(host)) {
PavelSavyhin 0:4cdaf9b1e7d0 155 _ip_version = NSAPI_IPv6;
PavelSavyhin 0:4cdaf9b1e7d0 156 ipv6_from_address(_ip_bytes, host);
PavelSavyhin 0:4cdaf9b1e7d0 157 set_port(port);
PavelSavyhin 0:4cdaf9b1e7d0 158 } else {
PavelSavyhin 0:4cdaf9b1e7d0 159 // DNS lookup
PavelSavyhin 0:4cdaf9b1e7d0 160 int err = iface->gethostbyname(this, host);
PavelSavyhin 0:4cdaf9b1e7d0 161 if (!err) {
PavelSavyhin 0:4cdaf9b1e7d0 162 set_port(port);
PavelSavyhin 0:4cdaf9b1e7d0 163 } else {
PavelSavyhin 0:4cdaf9b1e7d0 164 _ip_version = NSAPI_IPv4;
PavelSavyhin 0:4cdaf9b1e7d0 165 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
PavelSavyhin 0:4cdaf9b1e7d0 166 set_port(0);
PavelSavyhin 0:4cdaf9b1e7d0 167 }
PavelSavyhin 0:4cdaf9b1e7d0 168 }
PavelSavyhin 0:4cdaf9b1e7d0 169 }
PavelSavyhin 0:4cdaf9b1e7d0 170
PavelSavyhin 0:4cdaf9b1e7d0 171 SocketAddress::SocketAddress(const char *addr, uint16_t port)
PavelSavyhin 0:4cdaf9b1e7d0 172 {
PavelSavyhin 0:4cdaf9b1e7d0 173 memset(&_ip_address, 0, sizeof _ip_address);
PavelSavyhin 0:4cdaf9b1e7d0 174 set_ip_address(addr);
PavelSavyhin 0:4cdaf9b1e7d0 175 set_port(port);
PavelSavyhin 0:4cdaf9b1e7d0 176 }
PavelSavyhin 0:4cdaf9b1e7d0 177
PavelSavyhin 0:4cdaf9b1e7d0 178 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
PavelSavyhin 0:4cdaf9b1e7d0 179 {
PavelSavyhin 0:4cdaf9b1e7d0 180 memset(&_ip_address, 0, sizeof _ip_address);
PavelSavyhin 0:4cdaf9b1e7d0 181 set_ip_bytes(bytes, version);
PavelSavyhin 0:4cdaf9b1e7d0 182 set_port(port);
PavelSavyhin 0:4cdaf9b1e7d0 183 }
PavelSavyhin 0:4cdaf9b1e7d0 184
PavelSavyhin 0:4cdaf9b1e7d0 185 SocketAddress::SocketAddress(const SocketAddress &addr)
PavelSavyhin 0:4cdaf9b1e7d0 186 {
PavelSavyhin 0:4cdaf9b1e7d0 187 memset(&_ip_address, 0, sizeof _ip_address);
PavelSavyhin 0:4cdaf9b1e7d0 188 set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
PavelSavyhin 0:4cdaf9b1e7d0 189 set_port(addr.get_port());
PavelSavyhin 0:4cdaf9b1e7d0 190 }
PavelSavyhin 0:4cdaf9b1e7d0 191
PavelSavyhin 0:4cdaf9b1e7d0 192 void SocketAddress::set_ip_address(const char *addr)
PavelSavyhin 0:4cdaf9b1e7d0 193 {
PavelSavyhin 0:4cdaf9b1e7d0 194 _ip_address[0] = '\0';
PavelSavyhin 0:4cdaf9b1e7d0 195
PavelSavyhin 0:4cdaf9b1e7d0 196 if (addr && ipv4_is_valid(addr)) {
PavelSavyhin 0:4cdaf9b1e7d0 197 _ip_version = NSAPI_IPv4;
PavelSavyhin 0:4cdaf9b1e7d0 198 ipv4_from_address(_ip_bytes, addr);
PavelSavyhin 0:4cdaf9b1e7d0 199 } else if (addr && ipv6_is_valid(addr)) {
PavelSavyhin 0:4cdaf9b1e7d0 200 _ip_version = NSAPI_IPv6;
PavelSavyhin 0:4cdaf9b1e7d0 201 ipv6_from_address(_ip_bytes, addr);
PavelSavyhin 0:4cdaf9b1e7d0 202 } else {
PavelSavyhin 0:4cdaf9b1e7d0 203 _ip_version = NSAPI_IPv4;
PavelSavyhin 0:4cdaf9b1e7d0 204 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
PavelSavyhin 0:4cdaf9b1e7d0 205 }
PavelSavyhin 0:4cdaf9b1e7d0 206 }
PavelSavyhin 0:4cdaf9b1e7d0 207
PavelSavyhin 0:4cdaf9b1e7d0 208 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
PavelSavyhin 0:4cdaf9b1e7d0 209 {
PavelSavyhin 0:4cdaf9b1e7d0 210 _ip_address[0] = '\0';
PavelSavyhin 0:4cdaf9b1e7d0 211
PavelSavyhin 0:4cdaf9b1e7d0 212 if (version == NSAPI_IPv4) {
PavelSavyhin 0:4cdaf9b1e7d0 213 _ip_version = NSAPI_IPv4;
PavelSavyhin 0:4cdaf9b1e7d0 214 memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
PavelSavyhin 0:4cdaf9b1e7d0 215 } else if (version == NSAPI_IPv6) {
PavelSavyhin 0:4cdaf9b1e7d0 216 _ip_version = NSAPI_IPv6;
PavelSavyhin 0:4cdaf9b1e7d0 217 memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
PavelSavyhin 0:4cdaf9b1e7d0 218 } else {
PavelSavyhin 0:4cdaf9b1e7d0 219 _ip_version = NSAPI_IPv4;
PavelSavyhin 0:4cdaf9b1e7d0 220 memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
PavelSavyhin 0:4cdaf9b1e7d0 221 }
PavelSavyhin 0:4cdaf9b1e7d0 222 }
PavelSavyhin 0:4cdaf9b1e7d0 223
PavelSavyhin 0:4cdaf9b1e7d0 224 void SocketAddress::set_port(uint16_t port)
PavelSavyhin 0:4cdaf9b1e7d0 225 {
PavelSavyhin 0:4cdaf9b1e7d0 226 _port = port;
PavelSavyhin 0:4cdaf9b1e7d0 227 }
PavelSavyhin 0:4cdaf9b1e7d0 228
PavelSavyhin 0:4cdaf9b1e7d0 229 const char *SocketAddress::get_ip_address() const
PavelSavyhin 0:4cdaf9b1e7d0 230 {
PavelSavyhin 0:4cdaf9b1e7d0 231 char *ip_address = (char *)_ip_address;
PavelSavyhin 0:4cdaf9b1e7d0 232
PavelSavyhin 0:4cdaf9b1e7d0 233 if (!ip_address[0]) {
PavelSavyhin 0:4cdaf9b1e7d0 234 if (_ip_version == NSAPI_IPv4) {
PavelSavyhin 0:4cdaf9b1e7d0 235 ipv4_to_address(ip_address, _ip_bytes);
PavelSavyhin 0:4cdaf9b1e7d0 236 } else if (_ip_version == NSAPI_IPv6) {
PavelSavyhin 0:4cdaf9b1e7d0 237 ipv6_to_address(ip_address, _ip_bytes);
PavelSavyhin 0:4cdaf9b1e7d0 238 }
PavelSavyhin 0:4cdaf9b1e7d0 239 }
PavelSavyhin 0:4cdaf9b1e7d0 240
PavelSavyhin 0:4cdaf9b1e7d0 241 return ip_address;
PavelSavyhin 0:4cdaf9b1e7d0 242 }
PavelSavyhin 0:4cdaf9b1e7d0 243
PavelSavyhin 0:4cdaf9b1e7d0 244 const void *SocketAddress::get_ip_bytes() const
PavelSavyhin 0:4cdaf9b1e7d0 245 {
PavelSavyhin 0:4cdaf9b1e7d0 246 return _ip_bytes;
PavelSavyhin 0:4cdaf9b1e7d0 247 }
PavelSavyhin 0:4cdaf9b1e7d0 248
PavelSavyhin 0:4cdaf9b1e7d0 249 nsapi_version_t SocketAddress::get_ip_version() const
PavelSavyhin 0:4cdaf9b1e7d0 250 {
PavelSavyhin 0:4cdaf9b1e7d0 251 return _ip_version;
PavelSavyhin 0:4cdaf9b1e7d0 252 }
PavelSavyhin 0:4cdaf9b1e7d0 253
PavelSavyhin 0:4cdaf9b1e7d0 254 uint16_t SocketAddress::get_port() const
PavelSavyhin 0:4cdaf9b1e7d0 255 {
PavelSavyhin 0:4cdaf9b1e7d0 256 return _port;
PavelSavyhin 0:4cdaf9b1e7d0 257 }
PavelSavyhin 0:4cdaf9b1e7d0 258
PavelSavyhin 0:4cdaf9b1e7d0 259 SocketAddress::operator bool() const
PavelSavyhin 0:4cdaf9b1e7d0 260 {
PavelSavyhin 0:4cdaf9b1e7d0 261 int count = 0;
PavelSavyhin 0:4cdaf9b1e7d0 262 if (_ip_version == NSAPI_IPv4) {
PavelSavyhin 0:4cdaf9b1e7d0 263 count = NSAPI_IPv4_BYTES;
PavelSavyhin 0:4cdaf9b1e7d0 264 } else if (_ip_version == NSAPI_IPv6) {
PavelSavyhin 0:4cdaf9b1e7d0 265 count = NSAPI_IPv6_BYTES;
PavelSavyhin 0:4cdaf9b1e7d0 266 }
PavelSavyhin 0:4cdaf9b1e7d0 267
PavelSavyhin 0:4cdaf9b1e7d0 268 for (int i = 0; i < count; i++) {
PavelSavyhin 0:4cdaf9b1e7d0 269 if (_ip_bytes[i]) {
PavelSavyhin 0:4cdaf9b1e7d0 270 return true;
PavelSavyhin 0:4cdaf9b1e7d0 271 }
PavelSavyhin 0:4cdaf9b1e7d0 272 }
PavelSavyhin 0:4cdaf9b1e7d0 273
PavelSavyhin 0:4cdaf9b1e7d0 274 return false;
PavelSavyhin 0:4cdaf9b1e7d0 275 }