Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
AT_CellularStack.cpp
00001 /* 00002 * Copyright (c) 2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "AT_CellularStack.h" 00019 #include "CellularUtil.h" 00020 #include "CellularLog.h" 00021 #include "ThisThread.h" 00022 #include "AT_CellularDevice.h" 00023 00024 using namespace mbed_cellular_util; 00025 using namespace mbed; 00026 00027 AT_CellularStack::AT_CellularStack(ATHandler &at, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) : 00028 _socket(NULL), _socket_count(0), _cid(cid), 00029 _stack_type(stack_type), _ip_ver_sendto(NSAPI_UNSPEC ), _at(at), _device(device) 00030 { 00031 memset(_ip, 0, PDP_IPV6_SIZE); 00032 } 00033 00034 AT_CellularStack::~AT_CellularStack() 00035 { 00036 for (int i = 0; i < _socket_count; i++) { 00037 if (_socket[i]) { 00038 delete _socket[i]; 00039 _socket[i] = NULL; 00040 } 00041 } 00042 _socket_count = 0; 00043 00044 delete [] _socket; 00045 _socket = NULL; 00046 } 00047 00048 int AT_CellularStack::find_socket_index(nsapi_socket_t handle) 00049 { 00050 int max_socket_count = get_max_socket_count(); 00051 for (int i = 0; i < max_socket_count; i++) { 00052 if (_socket[i] == handle) { 00053 return i; 00054 } 00055 } 00056 return -1; 00057 } 00058 00059 /** NetworkStack 00060 */ 00061 nsapi_error_t AT_CellularStack::get_ip_address(SocketAddress *address) 00062 { 00063 if (!address) { 00064 return NSAPI_ERROR_PARAMETER ; 00065 } 00066 _at.lock(); 00067 00068 bool ipv4 = false, ipv6 = false; 00069 00070 _at.cmd_start_stop("+CGPADDR", "=", "%d", _cid); 00071 _at.resp_start("+CGPADDR:"); 00072 00073 if (_at.info_resp()) { 00074 _at.skip_param(); 00075 00076 if (_at.read_string(_ip, PDP_IPV6_SIZE) != -1) { 00077 convert_ipv6(_ip); 00078 address->set_ip_address(_ip); 00079 00080 ipv4 = (address->get_ip_version() == NSAPI_IPv4 ); 00081 ipv6 = (address->get_ip_version() == NSAPI_IPv6 ); 00082 00083 // Try to look for second address ONLY if modem has support for dual stack(can handle both IPv4 and IPv6 simultaneously). 00084 // Otherwise assumption is that second address is not reliable, even if network provides one. 00085 if ((_device.get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) && (_at.read_string(_ip, PDP_IPV6_SIZE) != -1))) { 00086 convert_ipv6(_ip); 00087 address->set_ip_address(_ip); 00088 ipv6 = (address->get_ip_version() == NSAPI_IPv6 ); 00089 } 00090 } 00091 } 00092 _at.resp_stop(); 00093 _at.unlock(); 00094 00095 if (ipv4 && ipv6) { 00096 _stack_type = IPV4V6_STACK; 00097 } else if (ipv4) { 00098 _stack_type = IPV4_STACK; 00099 } else if (ipv6) { 00100 _stack_type = IPV6_STACK; 00101 } 00102 00103 return (ipv4 || ipv6) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_ADDRESS ; 00104 } 00105 00106 const char *AT_CellularStack::get_ip_address() 00107 { 00108 _at.lock(); 00109 00110 bool ipv4 = false, ipv6 = false; 00111 00112 _at.cmd_start_stop("+CGPADDR", "=", "%d", _cid); 00113 _at.resp_start("+CGPADDR:"); 00114 00115 if (_at.info_resp()) { 00116 _at.skip_param(); 00117 00118 if (_at.read_string(_ip, PDP_IPV6_SIZE) != -1) { 00119 convert_ipv6(_ip); 00120 SocketAddress address; 00121 address.set_ip_address(_ip); 00122 00123 ipv4 = (address.get_ip_version() == NSAPI_IPv4 ); 00124 ipv6 = (address.get_ip_version() == NSAPI_IPv6 ); 00125 00126 // Try to look for second address ONLY if modem has support for dual stack(can handle both IPv4 and IPv6 simultaneously). 00127 // Otherwise assumption is that second address is not reliable, even if network provides one. 00128 if ((_device.get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) && (_at.read_string(_ip, PDP_IPV6_SIZE) != -1))) { 00129 convert_ipv6(_ip); 00130 address.set_ip_address(_ip); 00131 ipv6 = (address.get_ip_version() == NSAPI_IPv6 ); 00132 } 00133 } 00134 } 00135 _at.resp_stop(); 00136 _at.unlock(); 00137 00138 if (ipv4 && ipv6) { 00139 _stack_type = IPV4V6_STACK; 00140 } else if (ipv4) { 00141 _stack_type = IPV4_STACK; 00142 } else if (ipv6) { 00143 _stack_type = IPV6_STACK; 00144 } 00145 00146 return (ipv4 || ipv6) ? _ip : NULL; 00147 } 00148 00149 void AT_CellularStack::set_cid(int cid) 00150 { 00151 _cid = cid; 00152 } 00153 00154 nsapi_error_t AT_CellularStack::socket_stack_init() 00155 { 00156 return NSAPI_ERROR_OK ; 00157 } 00158 00159 nsapi_error_t AT_CellularStack::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) 00160 { 00161 if (!is_protocol_supported(proto) || !handle) { 00162 return NSAPI_ERROR_UNSUPPORTED ; 00163 } 00164 00165 int max_socket_count = get_max_socket_count(); 00166 00167 _socket_mutex.lock(); 00168 00169 if (!_socket) { 00170 if (socket_stack_init() != NSAPI_ERROR_OK ) { 00171 _socket_mutex.unlock(); 00172 return NSAPI_ERROR_NO_SOCKET ; 00173 } 00174 00175 _socket = new CellularSocket*[max_socket_count]; 00176 _socket_count = max_socket_count; 00177 for (int i = 0; i < max_socket_count; i++) { 00178 _socket[i] = 0; 00179 } 00180 } 00181 00182 int index = find_socket_index(0); 00183 if (index == -1) { 00184 tr_error("No free sockets!"); 00185 _socket_mutex.unlock(); 00186 return NSAPI_ERROR_NO_SOCKET ; 00187 } 00188 00189 tr_info("Socket %d open", index); 00190 // create local socket structure, socket on modem is created when app calls sendto/recvfrom 00191 // Do not assign a socket ID yet. Socket is not created at the Modem yet. 00192 // create_socket_impl(handle) will assign the correct socket ID. 00193 _socket[index] = new CellularSocket; 00194 CellularSocket *psock = _socket[index]; 00195 SocketAddress addr(0, get_dynamic_ip_port()); 00196 00197 psock->localAddress = addr; 00198 psock->proto = proto; 00199 *handle = psock; 00200 00201 _socket_mutex.unlock(); 00202 00203 return NSAPI_ERROR_OK ; 00204 } 00205 00206 nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle) 00207 { 00208 int err = NSAPI_ERROR_DEVICE_ERROR ; 00209 00210 struct CellularSocket *socket = (struct CellularSocket *)handle; 00211 if (!socket) { 00212 return NSAPI_ERROR_NO_SOCKET ; 00213 } 00214 int sock_id = socket->id; 00215 00216 int index = find_socket_index(handle); 00217 if (index == -1) { 00218 tr_error("No socket found to be closed"); 00219 return err; 00220 } 00221 00222 err = NSAPI_ERROR_OK ; 00223 00224 // Close the socket on the modem if it was created 00225 _at.lock(); 00226 if (sock_id > -1) { 00227 err = socket_close_impl(sock_id); 00228 } 00229 00230 if (!err) { 00231 tr_info("Socket %d closed", index); 00232 } else { 00233 tr_info("Socket %d close (id %d, started %d, error %d)", index, sock_id, socket->started, err); 00234 } 00235 00236 _socket_mutex.lock(); 00237 _socket[index] = NULL; 00238 delete socket; 00239 _socket_mutex.unlock(); 00240 00241 _at.unlock(); 00242 00243 return err; 00244 } 00245 00246 nsapi_error_t AT_CellularStack::socket_bind(nsapi_socket_t handle, const SocketAddress &addr) 00247 { 00248 struct CellularSocket *socket = (CellularSocket *)handle; 00249 if (!socket) { 00250 return NSAPI_ERROR_NO_SOCKET ; 00251 } 00252 00253 if (addr) { 00254 return NSAPI_ERROR_UNSUPPORTED ; 00255 } 00256 00257 _at.lock(); 00258 00259 uint16_t port = addr.get_port(); 00260 if (port != socket->localAddress.get_port()) { 00261 if (port && (get_socket_index_by_port(port) == -1)) { 00262 socket->localAddress.set_port(port); 00263 } else { 00264 _at.unlock(); 00265 return NSAPI_ERROR_PARAMETER ; 00266 } 00267 } 00268 00269 if (socket->id == -1) { 00270 create_socket_impl(socket); 00271 } 00272 00273 return _at.unlock_return_error(); 00274 } 00275 00276 nsapi_error_t AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog) 00277 { 00278 return NSAPI_ERROR_UNSUPPORTED ; 00279 } 00280 00281 nsapi_error_t AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr) 00282 { 00283 CellularSocket *socket = (CellularSocket *)handle; 00284 if (!socket) { 00285 return NSAPI_ERROR_NO_SOCKET ; 00286 } 00287 socket->remoteAddress = addr; 00288 socket->connected = true; 00289 00290 return NSAPI_ERROR_OK ; 00291 } 00292 00293 nsapi_error_t AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr) 00294 { 00295 return NSAPI_ERROR_UNSUPPORTED ; 00296 } 00297 00298 nsapi_size_or_error_t AT_CellularStack::socket_send(nsapi_socket_t handle, const void *data, unsigned size) 00299 { 00300 CellularSocket *socket = (CellularSocket *)handle; 00301 if (!socket) { 00302 return NSAPI_ERROR_NO_SOCKET ; 00303 } 00304 if (!socket->connected) { 00305 return NSAPI_ERROR_NO_CONNECTION ; 00306 } 00307 return socket_sendto(handle, socket->remoteAddress, data, size); 00308 } 00309 00310 nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, const SocketAddress &addr, const void *data, unsigned size) 00311 { 00312 CellularSocket *socket = (CellularSocket *)handle; 00313 if (!socket) { 00314 return NSAPI_ERROR_NO_SOCKET ; 00315 } 00316 00317 if (socket->closed && !socket->pending_bytes) { 00318 tr_info("sendto socket %d closed", socket->id); 00319 return NSAPI_ERROR_NO_CONNECTION ; 00320 } 00321 00322 if (size == 0) { 00323 if (socket->proto == NSAPI_UDP ) { 00324 return NSAPI_ERROR_UNSUPPORTED ; 00325 } else if (socket->proto == NSAPI_TCP ) { 00326 return 0; 00327 } 00328 } 00329 00330 nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK ; 00331 00332 if (socket->id == -1) { 00333 00334 /* Check that stack type supports sendto address type*/ 00335 if (!is_addr_stack_compatible(addr)) { 00336 return NSAPI_ERROR_PARAMETER ; 00337 } 00338 00339 _ip_ver_sendto = addr.get_ip_version(); 00340 _at.lock(); 00341 00342 ret_val = create_socket_impl(socket); 00343 00344 _at.unlock(); 00345 if (ret_val != NSAPI_ERROR_OK ) { 00346 tr_error("Socket %d create %s error %d", find_socket_index(socket), addr.get_ip_address(), ret_val); 00347 return ret_val; 00348 } 00349 } 00350 00351 /* Check parameters - sendto address is valid and stack type supports sending to that address type*/ 00352 if (!is_addr_stack_compatible(addr)) { 00353 return NSAPI_ERROR_PARAMETER ; 00354 } 00355 00356 _at.lock(); 00357 00358 ret_val = socket_sendto_impl(socket, addr, data, size); 00359 00360 _at.unlock(); 00361 00362 if (ret_val >= 0) { 00363 tr_info("Socket %d sent %d bytes to %s port %d", find_socket_index(socket), ret_val, addr.get_ip_address(), addr.get_port()); 00364 } else if (ret_val != NSAPI_ERROR_WOULD_BLOCK ) { 00365 tr_error("Socket %d sendto %s error %d", find_socket_index(socket), addr.get_ip_address(), ret_val); 00366 } 00367 00368 return ret_val; 00369 } 00370 00371 nsapi_size_or_error_t AT_CellularStack::socket_recv(nsapi_socket_t handle, void *data, unsigned size) 00372 { 00373 return socket_recvfrom(handle, NULL, data, size); 00374 } 00375 00376 nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, SocketAddress *addr, void *buffer, unsigned size) 00377 { 00378 CellularSocket *socket = (CellularSocket *)handle; 00379 if (!socket) { 00380 return NSAPI_ERROR_NO_SOCKET ; 00381 } 00382 00383 if (socket->closed) { 00384 tr_info("recvfrom socket %d closed", socket->id); 00385 return 0; 00386 } 00387 00388 nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK ; 00389 00390 if (socket->id == -1) { 00391 _at.lock(); 00392 00393 ret_val = create_socket_impl(socket); 00394 00395 _at.unlock(); 00396 if (ret_val != NSAPI_ERROR_OK ) { 00397 tr_error("Socket %d create error %d", find_socket_index(socket), ret_val); 00398 return ret_val; 00399 } 00400 } 00401 00402 _at.lock(); 00403 00404 ret_val = socket_recvfrom_impl(socket, addr, buffer, size); 00405 00406 _at.unlock(); 00407 00408 if (socket->closed) { 00409 tr_info("recvfrom socket %d closed", socket->id); 00410 return 0; 00411 } 00412 00413 if (ret_val >= 0) { 00414 if (addr) { 00415 tr_info("Socket %d recv %d bytes from %s port %d", find_socket_index(socket), ret_val, addr->get_ip_address(), addr->get_port()); 00416 } else { 00417 tr_info("Socket %d recv %d bytes", find_socket_index(socket), ret_val); 00418 } 00419 } else if (ret_val != NSAPI_ERROR_WOULD_BLOCK ) { 00420 tr_error("Socket %d recv error %d", find_socket_index(socket), ret_val); 00421 } 00422 00423 return ret_val; 00424 } 00425 00426 void AT_CellularStack::socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) 00427 { 00428 CellularSocket *socket = (CellularSocket *)handle; 00429 if (!socket) { 00430 return; 00431 } 00432 socket->_cb = callback; 00433 socket->_data = data; 00434 } 00435 00436 int AT_CellularStack::get_socket_index_by_port(uint16_t port) 00437 { 00438 int max_socket_count = get_max_socket_count(); 00439 for (int i = 0; i < max_socket_count; i++) { 00440 if (_socket[i]->localAddress.get_port() == port) { 00441 return i; 00442 } 00443 } 00444 return -1; 00445 } 00446 00447 AT_CellularStack::CellularSocket *AT_CellularStack::find_socket(int sock_id) 00448 { 00449 CellularSocket *sock = NULL; 00450 for (int i = 0; i < _socket_count; i++) { 00451 if (_socket[i] && _socket[i]->id == sock_id) { 00452 sock = _socket[i]; 00453 break; 00454 } 00455 } 00456 if (!sock) { 00457 tr_error("Socket not found %d", sock_id); 00458 } 00459 return sock; 00460 } 00461 00462 bool AT_CellularStack::is_addr_stack_compatible(const SocketAddress &addr) 00463 { 00464 if ((addr.get_ip_version() == NSAPI_UNSPEC ) || 00465 (addr.get_ip_version() == NSAPI_IPv4 && _stack_type == IPV6_STACK) || 00466 (addr.get_ip_version() == NSAPI_IPv6 && _stack_type == IPV4_STACK)) { 00467 return false; 00468 } 00469 return true; 00470 } 00471
Generated on Tue Jul 12 2022 13:54:02 by
