Rahul Dahiya / Mbed OS STM32F7 Ethernet
Committer:
rahul_dahiya
Date:
Wed Jan 15 15:57:15 2020 +0530
Revision:
0:fb8047b156bb
STM32F7 LWIP

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rahul_dahiya 0:fb8047b156bb 1 /* Socket
rahul_dahiya 0:fb8047b156bb 2 * Copyright (c) 2015 ARM Limited
rahul_dahiya 0:fb8047b156bb 3 *
rahul_dahiya 0:fb8047b156bb 4 * Licensed under the Apache License, Version 2.0 (the "License");
rahul_dahiya 0:fb8047b156bb 5 * you may not use this file except in compliance with the License.
rahul_dahiya 0:fb8047b156bb 6 * You may obtain a copy of the License at
rahul_dahiya 0:fb8047b156bb 7 *
rahul_dahiya 0:fb8047b156bb 8 * http://www.apache.org/licenses/LICENSE-2.0
rahul_dahiya 0:fb8047b156bb 9 *
rahul_dahiya 0:fb8047b156bb 10 * Unless required by applicable law or agreed to in writing, software
rahul_dahiya 0:fb8047b156bb 11 * distributed under the License is distributed on an "AS IS" BASIS,
rahul_dahiya 0:fb8047b156bb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rahul_dahiya 0:fb8047b156bb 13 * See the License for the specific language governing permissions and
rahul_dahiya 0:fb8047b156bb 14 * limitations under the License.
rahul_dahiya 0:fb8047b156bb 15 */
rahul_dahiya 0:fb8047b156bb 16
rahul_dahiya 0:fb8047b156bb 17 #include "NetworkStack.h"
rahul_dahiya 0:fb8047b156bb 18 #include "nsapi_dns.h"
rahul_dahiya 0:fb8047b156bb 19 #include "mbed.h"
rahul_dahiya 0:fb8047b156bb 20 #include "stddef.h"
rahul_dahiya 0:fb8047b156bb 21 #include <new>
rahul_dahiya 0:fb8047b156bb 22
rahul_dahiya 0:fb8047b156bb 23
rahul_dahiya 0:fb8047b156bb 24 // Default NetworkStack operations
rahul_dahiya 0:fb8047b156bb 25 nsapi_error_t NetworkStack::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
rahul_dahiya 0:fb8047b156bb 26 {
rahul_dahiya 0:fb8047b156bb 27 // check for simple ip addresses
rahul_dahiya 0:fb8047b156bb 28 if (address->set_ip_address(name)) {
rahul_dahiya 0:fb8047b156bb 29 if (version != NSAPI_UNSPEC && address->get_ip_version() != version) {
rahul_dahiya 0:fb8047b156bb 30 return NSAPI_ERROR_DNS_FAILURE;
rahul_dahiya 0:fb8047b156bb 31 }
rahul_dahiya 0:fb8047b156bb 32
rahul_dahiya 0:fb8047b156bb 33 return NSAPI_ERROR_OK;
rahul_dahiya 0:fb8047b156bb 34 }
rahul_dahiya 0:fb8047b156bb 35
rahul_dahiya 0:fb8047b156bb 36 // if the version is unspecified, try to guess the version from the
rahul_dahiya 0:fb8047b156bb 37 // ip address of the underlying stack
rahul_dahiya 0:fb8047b156bb 38 if (version == NSAPI_UNSPEC) {
rahul_dahiya 0:fb8047b156bb 39 SocketAddress testaddress;
rahul_dahiya 0:fb8047b156bb 40 if (testaddress.set_ip_address(this->get_ip_address())) {
rahul_dahiya 0:fb8047b156bb 41 version = testaddress.get_ip_version();
rahul_dahiya 0:fb8047b156bb 42 }
rahul_dahiya 0:fb8047b156bb 43 }
rahul_dahiya 0:fb8047b156bb 44
rahul_dahiya 0:fb8047b156bb 45 return nsapi_dns_query(this, name, address, version);
rahul_dahiya 0:fb8047b156bb 46 }
rahul_dahiya 0:fb8047b156bb 47
rahul_dahiya 0:fb8047b156bb 48 nsapi_error_t NetworkStack::add_dns_server(const SocketAddress &address)
rahul_dahiya 0:fb8047b156bb 49 {
rahul_dahiya 0:fb8047b156bb 50 return nsapi_dns_add_server(address);
rahul_dahiya 0:fb8047b156bb 51 }
rahul_dahiya 0:fb8047b156bb 52
rahul_dahiya 0:fb8047b156bb 53 nsapi_error_t NetworkStack::setstackopt(int level, int optname, const void *optval, unsigned optlen)
rahul_dahiya 0:fb8047b156bb 54 {
rahul_dahiya 0:fb8047b156bb 55 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 56 }
rahul_dahiya 0:fb8047b156bb 57
rahul_dahiya 0:fb8047b156bb 58 nsapi_error_t NetworkStack::getstackopt(int level, int optname, void *optval, unsigned *optlen)
rahul_dahiya 0:fb8047b156bb 59 {
rahul_dahiya 0:fb8047b156bb 60 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 61 }
rahul_dahiya 0:fb8047b156bb 62
rahul_dahiya 0:fb8047b156bb 63 nsapi_error_t NetworkStack::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
rahul_dahiya 0:fb8047b156bb 64 {
rahul_dahiya 0:fb8047b156bb 65 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 66 }
rahul_dahiya 0:fb8047b156bb 67
rahul_dahiya 0:fb8047b156bb 68 nsapi_error_t NetworkStack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
rahul_dahiya 0:fb8047b156bb 69 {
rahul_dahiya 0:fb8047b156bb 70 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 71 }
rahul_dahiya 0:fb8047b156bb 72
rahul_dahiya 0:fb8047b156bb 73
rahul_dahiya 0:fb8047b156bb 74 // NetworkStackWrapper class for encapsulating the raw nsapi_stack structure
rahul_dahiya 0:fb8047b156bb 75 class NetworkStackWrapper : public NetworkStack
rahul_dahiya 0:fb8047b156bb 76 {
rahul_dahiya 0:fb8047b156bb 77 private:
rahul_dahiya 0:fb8047b156bb 78 inline nsapi_stack_t *_stack()
rahul_dahiya 0:fb8047b156bb 79 {
rahul_dahiya 0:fb8047b156bb 80 return reinterpret_cast<nsapi_stack_t *>(
rahul_dahiya 0:fb8047b156bb 81 reinterpret_cast<uint8_t *>(this)
rahul_dahiya 0:fb8047b156bb 82 - offsetof(nsapi_stack_t, _stack_buffer));
rahul_dahiya 0:fb8047b156bb 83 }
rahul_dahiya 0:fb8047b156bb 84
rahul_dahiya 0:fb8047b156bb 85 inline const nsapi_stack_api_t *_stack_api()
rahul_dahiya 0:fb8047b156bb 86 {
rahul_dahiya 0:fb8047b156bb 87 return _stack()->stack_api;
rahul_dahiya 0:fb8047b156bb 88 }
rahul_dahiya 0:fb8047b156bb 89
rahul_dahiya 0:fb8047b156bb 90 public:
rahul_dahiya 0:fb8047b156bb 91 virtual const char *get_ip_address()
rahul_dahiya 0:fb8047b156bb 92 {
rahul_dahiya 0:fb8047b156bb 93 if (!_stack_api()->get_ip_address) {
rahul_dahiya 0:fb8047b156bb 94 return 0;
rahul_dahiya 0:fb8047b156bb 95 }
rahul_dahiya 0:fb8047b156bb 96
rahul_dahiya 0:fb8047b156bb 97 static uint8_t buffer[sizeof(SocketAddress)];
rahul_dahiya 0:fb8047b156bb 98 SocketAddress *address = new (buffer) SocketAddress(_stack_api()->get_ip_address(_stack()));
rahul_dahiya 0:fb8047b156bb 99 return address->get_ip_address();
rahul_dahiya 0:fb8047b156bb 100 }
rahul_dahiya 0:fb8047b156bb 101
rahul_dahiya 0:fb8047b156bb 102 virtual nsapi_error_t gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
rahul_dahiya 0:fb8047b156bb 103 {
rahul_dahiya 0:fb8047b156bb 104 if (!_stack_api()->gethostbyname) {
rahul_dahiya 0:fb8047b156bb 105 return NetworkStack::gethostbyname(name, address, version);
rahul_dahiya 0:fb8047b156bb 106 }
rahul_dahiya 0:fb8047b156bb 107
rahul_dahiya 0:fb8047b156bb 108 nsapi_addr_t addr = {NSAPI_UNSPEC, 0};
rahul_dahiya 0:fb8047b156bb 109 nsapi_error_t err = _stack_api()->gethostbyname(_stack(), name, &addr, version);
rahul_dahiya 0:fb8047b156bb 110 address->set_addr(addr);
rahul_dahiya 0:fb8047b156bb 111 return err;
rahul_dahiya 0:fb8047b156bb 112 }
rahul_dahiya 0:fb8047b156bb 113
rahul_dahiya 0:fb8047b156bb 114 virtual nsapi_error_t add_dns_server(const SocketAddress &address)
rahul_dahiya 0:fb8047b156bb 115 {
rahul_dahiya 0:fb8047b156bb 116 if (!_stack_api()->add_dns_server) {
rahul_dahiya 0:fb8047b156bb 117 return NetworkStack::add_dns_server(address);
rahul_dahiya 0:fb8047b156bb 118 }
rahul_dahiya 0:fb8047b156bb 119
rahul_dahiya 0:fb8047b156bb 120 return _stack_api()->add_dns_server(_stack(), address.get_addr());
rahul_dahiya 0:fb8047b156bb 121 }
rahul_dahiya 0:fb8047b156bb 122
rahul_dahiya 0:fb8047b156bb 123 virtual nsapi_error_t setstackopt(int level, int optname, const void *optval, unsigned optlen)
rahul_dahiya 0:fb8047b156bb 124 {
rahul_dahiya 0:fb8047b156bb 125 if (!_stack_api()->setstackopt) {
rahul_dahiya 0:fb8047b156bb 126 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 127 }
rahul_dahiya 0:fb8047b156bb 128
rahul_dahiya 0:fb8047b156bb 129 return _stack_api()->setstackopt(_stack(), level, optname, optval, optlen);
rahul_dahiya 0:fb8047b156bb 130 }
rahul_dahiya 0:fb8047b156bb 131
rahul_dahiya 0:fb8047b156bb 132 virtual nsapi_error_t getstackopt(int level, int optname, void *optval, unsigned *optlen)
rahul_dahiya 0:fb8047b156bb 133 {
rahul_dahiya 0:fb8047b156bb 134 if (!_stack_api()->getstackopt) {
rahul_dahiya 0:fb8047b156bb 135 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 136 }
rahul_dahiya 0:fb8047b156bb 137
rahul_dahiya 0:fb8047b156bb 138 return _stack_api()->getstackopt(_stack(), level, optname, optval, optlen);
rahul_dahiya 0:fb8047b156bb 139 }
rahul_dahiya 0:fb8047b156bb 140
rahul_dahiya 0:fb8047b156bb 141 protected:
rahul_dahiya 0:fb8047b156bb 142 virtual nsapi_error_t socket_open(nsapi_socket_t *socket, nsapi_protocol_t proto)
rahul_dahiya 0:fb8047b156bb 143 {
rahul_dahiya 0:fb8047b156bb 144 if (!_stack_api()->socket_open) {
rahul_dahiya 0:fb8047b156bb 145 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 146 }
rahul_dahiya 0:fb8047b156bb 147
rahul_dahiya 0:fb8047b156bb 148 return _stack_api()->socket_open(_stack(), socket, proto);
rahul_dahiya 0:fb8047b156bb 149 }
rahul_dahiya 0:fb8047b156bb 150
rahul_dahiya 0:fb8047b156bb 151 virtual nsapi_error_t socket_close(nsapi_socket_t socket)
rahul_dahiya 0:fb8047b156bb 152 {
rahul_dahiya 0:fb8047b156bb 153 if (!_stack_api()->socket_close) {
rahul_dahiya 0:fb8047b156bb 154 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 155 }
rahul_dahiya 0:fb8047b156bb 156
rahul_dahiya 0:fb8047b156bb 157 return _stack_api()->socket_close(_stack(), socket);
rahul_dahiya 0:fb8047b156bb 158 }
rahul_dahiya 0:fb8047b156bb 159
rahul_dahiya 0:fb8047b156bb 160 virtual nsapi_error_t socket_bind(nsapi_socket_t socket, const SocketAddress &address)
rahul_dahiya 0:fb8047b156bb 161 {
rahul_dahiya 0:fb8047b156bb 162 if (!_stack_api()->socket_bind) {
rahul_dahiya 0:fb8047b156bb 163 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 164 }
rahul_dahiya 0:fb8047b156bb 165
rahul_dahiya 0:fb8047b156bb 166 return _stack_api()->socket_bind(_stack(), socket, address.get_addr(), address.get_port());
rahul_dahiya 0:fb8047b156bb 167 }
rahul_dahiya 0:fb8047b156bb 168
rahul_dahiya 0:fb8047b156bb 169 virtual nsapi_error_t socket_listen(nsapi_socket_t socket, int backlog)
rahul_dahiya 0:fb8047b156bb 170 {
rahul_dahiya 0:fb8047b156bb 171 if (!_stack_api()->socket_listen) {
rahul_dahiya 0:fb8047b156bb 172 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 173 }
rahul_dahiya 0:fb8047b156bb 174
rahul_dahiya 0:fb8047b156bb 175 return _stack_api()->socket_listen(_stack(), socket, backlog);
rahul_dahiya 0:fb8047b156bb 176 }
rahul_dahiya 0:fb8047b156bb 177
rahul_dahiya 0:fb8047b156bb 178 virtual nsapi_error_t socket_connect(nsapi_socket_t socket, const SocketAddress &address)
rahul_dahiya 0:fb8047b156bb 179 {
rahul_dahiya 0:fb8047b156bb 180 if (!_stack_api()->socket_connect) {
rahul_dahiya 0:fb8047b156bb 181 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 182 }
rahul_dahiya 0:fb8047b156bb 183
rahul_dahiya 0:fb8047b156bb 184 return _stack_api()->socket_connect(_stack(), socket, address.get_addr(), address.get_port());
rahul_dahiya 0:fb8047b156bb 185 }
rahul_dahiya 0:fb8047b156bb 186
rahul_dahiya 0:fb8047b156bb 187 virtual nsapi_error_t socket_accept(nsapi_socket_t server, nsapi_socket_t *socket, SocketAddress *address)
rahul_dahiya 0:fb8047b156bb 188 {
rahul_dahiya 0:fb8047b156bb 189 if (!_stack_api()->socket_accept) {
rahul_dahiya 0:fb8047b156bb 190 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 191 }
rahul_dahiya 0:fb8047b156bb 192
rahul_dahiya 0:fb8047b156bb 193 nsapi_addr_t addr = {NSAPI_IPv4, 0};
rahul_dahiya 0:fb8047b156bb 194 uint16_t port = 0;
rahul_dahiya 0:fb8047b156bb 195
rahul_dahiya 0:fb8047b156bb 196 nsapi_error_t err = _stack_api()->socket_accept(_stack(), server, socket, &addr, &port);
rahul_dahiya 0:fb8047b156bb 197
rahul_dahiya 0:fb8047b156bb 198 if (address) {
rahul_dahiya 0:fb8047b156bb 199 address->set_addr(addr);
rahul_dahiya 0:fb8047b156bb 200 address->set_port(port);
rahul_dahiya 0:fb8047b156bb 201 }
rahul_dahiya 0:fb8047b156bb 202
rahul_dahiya 0:fb8047b156bb 203 return err;
rahul_dahiya 0:fb8047b156bb 204 }
rahul_dahiya 0:fb8047b156bb 205
rahul_dahiya 0:fb8047b156bb 206 virtual nsapi_size_or_error_t socket_send(nsapi_socket_t socket, const void *data, nsapi_size_t size)
rahul_dahiya 0:fb8047b156bb 207 {
rahul_dahiya 0:fb8047b156bb 208 if (!_stack_api()->socket_send) {
rahul_dahiya 0:fb8047b156bb 209 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 210 }
rahul_dahiya 0:fb8047b156bb 211
rahul_dahiya 0:fb8047b156bb 212 return _stack_api()->socket_send(_stack(), socket, data, size);
rahul_dahiya 0:fb8047b156bb 213 }
rahul_dahiya 0:fb8047b156bb 214
rahul_dahiya 0:fb8047b156bb 215 virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t socket, void *data, nsapi_size_t size)
rahul_dahiya 0:fb8047b156bb 216 {
rahul_dahiya 0:fb8047b156bb 217 if (!_stack_api()->socket_recv) {
rahul_dahiya 0:fb8047b156bb 218 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 219 }
rahul_dahiya 0:fb8047b156bb 220
rahul_dahiya 0:fb8047b156bb 221 return _stack_api()->socket_recv(_stack(), socket, data, size);
rahul_dahiya 0:fb8047b156bb 222 }
rahul_dahiya 0:fb8047b156bb 223
rahul_dahiya 0:fb8047b156bb 224 virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t socket, const SocketAddress &address, const void *data, nsapi_size_t size)
rahul_dahiya 0:fb8047b156bb 225 {
rahul_dahiya 0:fb8047b156bb 226 if (!_stack_api()->socket_sendto) {
rahul_dahiya 0:fb8047b156bb 227 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 228 }
rahul_dahiya 0:fb8047b156bb 229
rahul_dahiya 0:fb8047b156bb 230 return _stack_api()->socket_sendto(_stack(), socket, address.get_addr(), address.get_port(), data, size);
rahul_dahiya 0:fb8047b156bb 231 }
rahul_dahiya 0:fb8047b156bb 232
rahul_dahiya 0:fb8047b156bb 233 virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t socket, SocketAddress *address, void *data, nsapi_size_t size)
rahul_dahiya 0:fb8047b156bb 234 {
rahul_dahiya 0:fb8047b156bb 235 if (!_stack_api()->socket_recvfrom) {
rahul_dahiya 0:fb8047b156bb 236 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 237 }
rahul_dahiya 0:fb8047b156bb 238
rahul_dahiya 0:fb8047b156bb 239 nsapi_addr_t addr = {NSAPI_IPv4, 0};
rahul_dahiya 0:fb8047b156bb 240 uint16_t port = 0;
rahul_dahiya 0:fb8047b156bb 241
rahul_dahiya 0:fb8047b156bb 242 nsapi_size_or_error_t err = _stack_api()->socket_recvfrom(_stack(), socket, &addr, &port, data, size);
rahul_dahiya 0:fb8047b156bb 243
rahul_dahiya 0:fb8047b156bb 244 if (address) {
rahul_dahiya 0:fb8047b156bb 245 address->set_addr(addr);
rahul_dahiya 0:fb8047b156bb 246 address->set_port(port);
rahul_dahiya 0:fb8047b156bb 247 }
rahul_dahiya 0:fb8047b156bb 248
rahul_dahiya 0:fb8047b156bb 249 return err;
rahul_dahiya 0:fb8047b156bb 250 }
rahul_dahiya 0:fb8047b156bb 251
rahul_dahiya 0:fb8047b156bb 252 virtual void socket_attach(nsapi_socket_t socket, void (*callback)(void *), void *data)
rahul_dahiya 0:fb8047b156bb 253 {
rahul_dahiya 0:fb8047b156bb 254 if (!_stack_api()->socket_attach) {
rahul_dahiya 0:fb8047b156bb 255 return;
rahul_dahiya 0:fb8047b156bb 256 }
rahul_dahiya 0:fb8047b156bb 257
rahul_dahiya 0:fb8047b156bb 258 return _stack_api()->socket_attach(_stack(), socket, callback, data);
rahul_dahiya 0:fb8047b156bb 259 }
rahul_dahiya 0:fb8047b156bb 260
rahul_dahiya 0:fb8047b156bb 261 virtual nsapi_error_t setsockopt(nsapi_socket_t socket, int level, int optname, const void *optval, unsigned optlen)
rahul_dahiya 0:fb8047b156bb 262 {
rahul_dahiya 0:fb8047b156bb 263 if (!_stack_api()->setsockopt) {
rahul_dahiya 0:fb8047b156bb 264 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 265 }
rahul_dahiya 0:fb8047b156bb 266
rahul_dahiya 0:fb8047b156bb 267 return _stack_api()->setsockopt(_stack(), socket, level, optname, optval, optlen);
rahul_dahiya 0:fb8047b156bb 268 }
rahul_dahiya 0:fb8047b156bb 269
rahul_dahiya 0:fb8047b156bb 270 virtual nsapi_error_t getsockopt(nsapi_socket_t socket, int level, int optname, void *optval, unsigned *optlen)
rahul_dahiya 0:fb8047b156bb 271 {
rahul_dahiya 0:fb8047b156bb 272 if (!_stack_api()->getsockopt) {
rahul_dahiya 0:fb8047b156bb 273 return NSAPI_ERROR_UNSUPPORTED;
rahul_dahiya 0:fb8047b156bb 274 }
rahul_dahiya 0:fb8047b156bb 275
rahul_dahiya 0:fb8047b156bb 276 return _stack_api()->getsockopt(_stack(), socket, level, optname, optval, optlen);
rahul_dahiya 0:fb8047b156bb 277 }
rahul_dahiya 0:fb8047b156bb 278 };
rahul_dahiya 0:fb8047b156bb 279
rahul_dahiya 0:fb8047b156bb 280
rahul_dahiya 0:fb8047b156bb 281 // Conversion function for network stacks
rahul_dahiya 0:fb8047b156bb 282 NetworkStack *nsapi_create_stack(nsapi_stack_t *stack)
rahul_dahiya 0:fb8047b156bb 283 {
rahul_dahiya 0:fb8047b156bb 284 MBED_STATIC_ASSERT(sizeof stack->_stack_buffer >= sizeof(NetworkStackWrapper),
rahul_dahiya 0:fb8047b156bb 285 "The nsapi_stack_t stack buffer must fit a NetworkStackWrapper");
rahul_dahiya 0:fb8047b156bb 286 return new (stack->_stack_buffer) NetworkStackWrapper;
rahul_dahiya 0:fb8047b156bb 287 }
rahul_dahiya 0:fb8047b156bb 288
rahul_dahiya 0:fb8047b156bb 289 NetworkStack *nsapi_create_stack(NetworkStack *stack)
rahul_dahiya 0:fb8047b156bb 290 {
rahul_dahiya 0:fb8047b156bb 291 return stack;
rahul_dahiya 0:fb8047b156bb 292 }
rahul_dahiya 0:fb8047b156bb 293