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
QUECTEL_BG96_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 <stdio.h> 00019 #include <string.h> 00020 #include "QUECTEL/BG96/QUECTEL_BG96_CellularStack.h" 00021 #include "CellularLog.h" 00022 #include "netsocket/TLSSocket.h" 00023 00024 // Ref: Quectel_BG96_SSL_AT_Commands_Manual, ch 2.1.1 AT+QSSLCFG 00025 static const int BG96_SUPPORTED_SSL_VERSION = 4; // All 00026 static const char BG96_SUPPORTED_CIPHER_SUITE[] = "0xFFFF"; // Support all 00027 00028 // TODO: At the moment we support only one active SSL context 00029 // Later can be expanded to support multiple contexts. Modem supports IDs 0-5. 00030 static const int sslctxID = 0; 00031 00032 using namespace mbed; 00033 00034 QUECTEL_BG96_CellularStack::QUECTEL_BG96_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) : 00035 AT_CellularStack(atHandler, cid, stack_type, device) 00036 #ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES 00037 #if (MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES != 1) 00038 #error Define cellular.offload-dns-queries to null or 1. 00039 #endif 00040 , _dns_callback(NULL), _dns_version(NSAPI_UNSPEC ) 00041 #endif 00042 , _tls_sec_level(0) 00043 { 00044 _at.set_urc_handler("+QIURC: \"recv", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_recv)); 00045 _at.set_urc_handler("+QIURC: \"close", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_closed)); 00046 #ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES 00047 _at.set_urc_handler("+QIURC: \"dnsgip\",", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_dnsgip)); 00048 #endif 00049 00050 _at.set_urc_handler("+QSSLURC: \"recv", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_recv)); 00051 _at.set_urc_handler("+QSSLURC: \"close", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_closed)); 00052 00053 // TODO: this needs to be handled properly, but now making just a quick hack 00054 // Close all SSL sockets if open. This can happen for example if application processor 00055 // was reset but modem not. Old sockets are still up and running and it prevents 00056 // new SSL configurations and creating new sockets. 00057 for (int i = 0; i < 12; i++) { 00058 _at.clear_error(); 00059 tr_debug("Closing SSL socket %d...", i); 00060 _at.at_cmd_discard("+QSSLCLOSE", "=", "%d", i); 00061 } 00062 _at.clear_error(); 00063 } 00064 00065 QUECTEL_BG96_CellularStack::~QUECTEL_BG96_CellularStack() 00066 { 00067 } 00068 00069 nsapi_error_t QUECTEL_BG96_CellularStack::socket_listen(nsapi_socket_t handle, int backlog) 00070 { 00071 return NSAPI_ERROR_UNSUPPORTED ; 00072 } 00073 00074 nsapi_error_t QUECTEL_BG96_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr) 00075 { 00076 return NSAPI_ERROR_UNSUPPORTED ; 00077 } 00078 00079 nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address) 00080 { 00081 CellularSocket *socket = (CellularSocket *)handle; 00082 00083 int modem_connect_id = -1; 00084 int err = NSAPI_ERROR_NO_CONNECTION ; 00085 00086 int request_connect_id = find_socket_index(socket); 00087 // assert here as its a programming error if the socket container doesn't contain 00088 // specified handle 00089 MBED_ASSERT(request_connect_id != -1); 00090 00091 _at.lock(); 00092 if (socket->proto == NSAPI_TCP ) { 00093 if (socket->tls_socket) { 00094 if (_tls_sec_level == 0) { 00095 _at.unlock(); 00096 return NSAPI_ERROR_AUTH_FAILURE ; 00097 } 00098 00099 _at.at_cmd_discard("+QSSLOPEN", "=", "%d%d%d%s%d%d", _cid, sslctxID, request_connect_id, 00100 address.get_ip_address(), address.get_port(), 0); 00101 handle_open_socket_response(modem_connect_id, err, true); 00102 00103 if ((_at.get_last_error() == NSAPI_ERROR_OK ) && err) { 00104 if (err == BG96_SOCKET_BIND_FAIL) { 00105 socket->id = -1; 00106 _at.unlock(); 00107 return NSAPI_ERROR_PARAMETER ; 00108 } 00109 socket_close_impl(modem_connect_id); 00110 00111 _at.at_cmd_discard("+QSSLOPEN", "=", "%d%d%d%s%d%d", _cid, sslctxID, request_connect_id, 00112 address.get_ip_address(), address.get_port(), 0); 00113 handle_open_socket_response(modem_connect_id, err, true); 00114 } 00115 } else { 00116 char ipdot[NSAPI_IP_SIZE]; 00117 ip2dot(address, ipdot); 00118 _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP", 00119 ipdot, address.get_port(), socket->localAddress.get_port(), 0); 00120 00121 handle_open_socket_response(modem_connect_id, err, false); 00122 00123 if ((_at.get_last_error() == NSAPI_ERROR_OK ) && err) { 00124 if (err == BG96_SOCKET_BIND_FAIL) { 00125 socket->id = -1; 00126 _at.unlock(); 00127 return NSAPI_ERROR_PARAMETER ; 00128 } 00129 socket_close_impl(modem_connect_id); 00130 00131 _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP", 00132 ipdot, address.get_port(), socket->localAddress.get_port(), 0); 00133 00134 handle_open_socket_response(modem_connect_id, err, false); 00135 } 00136 } 00137 } 00138 00139 // If opened successfully BUT not requested one, close it 00140 if (!err && (modem_connect_id != request_connect_id)) { 00141 _at.at_cmd_discard("+QICLOSE", "=", "%d", modem_connect_id); 00142 } 00143 00144 nsapi_error_t ret_val = _at.get_last_error(); 00145 _at.unlock(); 00146 00147 if ((!err) && (ret_val == NSAPI_ERROR_OK ) && (modem_connect_id == request_connect_id)) { 00148 socket->id = request_connect_id; 00149 socket->remoteAddress = address; 00150 socket->connected = true; 00151 return NSAPI_ERROR_OK ; 00152 } 00153 00154 return err; 00155 } 00156 00157 void QUECTEL_BG96_CellularStack::urc_qiurc_recv() 00158 { 00159 urc_qiurc(URC_RECV); 00160 } 00161 00162 void QUECTEL_BG96_CellularStack::urc_qiurc_closed() 00163 { 00164 urc_qiurc(URC_CLOSED); 00165 } 00166 00167 #ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES 00168 bool QUECTEL_BG96_CellularStack::read_dnsgip(SocketAddress &address, nsapi_version_t _dns_version) 00169 { 00170 if (_at.read_int() == 0) { 00171 int count = _at.read_int(); 00172 _at.skip_param(); 00173 for (; count > 0; count--) { 00174 _at.resp_start("+QIURC: \"dnsgip\","); 00175 char ipAddress[NSAPI_IP_SIZE]; 00176 _at.read_string(ipAddress, sizeof(ipAddress)); 00177 if (address.set_ip_address(ipAddress)) { 00178 if (_dns_version == NSAPI_UNSPEC || _dns_version == address.get_ip_version()) { 00179 return true; 00180 } 00181 } 00182 } 00183 } 00184 return false; 00185 } 00186 00187 void QUECTEL_BG96_CellularStack::urc_qiurc_dnsgip() 00188 { 00189 if (!_dns_callback) { 00190 return; 00191 } 00192 SocketAddress address; 00193 if (read_dnsgip(address, _dns_version)) { 00194 _dns_callback(NSAPI_ERROR_OK , &address); 00195 } else { 00196 _dns_callback(NSAPI_ERROR_DNS_FAILURE , NULL); 00197 } 00198 _dns_callback = NULL; 00199 } 00200 #endif 00201 00202 void QUECTEL_BG96_CellularStack::urc_qiurc(urc_type_t urc_type) 00203 { 00204 _at.lock(); 00205 _at.skip_param(); 00206 const int sock_id = _at.read_int(); 00207 const nsapi_error_t err = _at.unlock_return_error(); 00208 00209 if (err != NSAPI_ERROR_OK ) { 00210 return; 00211 } 00212 00213 CellularSocket *sock = find_socket(sock_id); 00214 if (sock) { 00215 if (urc_type == URC_CLOSED) { 00216 tr_info("Socket closed %d", sock_id); 00217 sock->closed = true; 00218 } 00219 if (sock->_cb) { 00220 sock->_cb(sock->_data); 00221 } 00222 } 00223 } 00224 00225 int QUECTEL_BG96_CellularStack::get_max_socket_count() 00226 { 00227 return BG96_SOCKET_MAX; 00228 } 00229 00230 bool QUECTEL_BG96_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) 00231 { 00232 return (protocol == NSAPI_UDP || protocol == NSAPI_TCP ); 00233 } 00234 00235 nsapi_error_t QUECTEL_BG96_CellularStack::socket_close_impl(int sock_id) 00236 { 00237 _at.set_at_timeout(BG96_CLOSE_SOCKET_TIMEOUT); 00238 nsapi_error_t err; 00239 CellularSocket *socket = find_socket(sock_id); 00240 if (socket && socket->tls_socket) { 00241 err = _at.at_cmd_discard("+QSSLCLOSE", "=", "%d", sock_id); 00242 if (err == NSAPI_ERROR_OK ) { 00243 // Disable TLSSocket settings to prevent reuse on next socket without setting the values 00244 _tls_sec_level = 0; 00245 err = _at.at_cmd_discard("+QSSLCFG", "=\"seclevel\",", "%d%d", sslctxID, _tls_sec_level); 00246 } 00247 } else { 00248 err = _at.at_cmd_discard("+QICLOSE", "=", "%d", sock_id); 00249 } 00250 _at.restore_at_timeout(); 00251 00252 return err; 00253 } 00254 00255 void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_id, int &err, bool tlssocket) 00256 { 00257 // OK 00258 // QIOPEN -> should be handled as URC? 00259 _at.set_at_timeout(BG96_CREATE_SOCKET_TIMEOUT); 00260 00261 if (tlssocket) { 00262 _at.resp_start("+QSSLOPEN:"); 00263 } else { 00264 _at.resp_start("+QIOPEN:"); 00265 } 00266 00267 _at.restore_at_timeout(); 00268 modem_connect_id = _at.read_int(); 00269 err = _at.read_int(); 00270 if (tlssocket && err != 0) { 00271 err = NSAPI_ERROR_AUTH_FAILURE ; 00272 } 00273 } 00274 00275 nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *socket) 00276 { 00277 int modem_connect_id = -1; 00278 int remote_port = 0; 00279 int err = -1; 00280 00281 int request_connect_id = find_socket_index(socket); 00282 // assert here as its a programming error if the socket container doesn't contain 00283 // specified handle 00284 MBED_ASSERT(request_connect_id != -1); 00285 00286 if (socket->proto == NSAPI_UDP && !socket->connected) { 00287 _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "UDP SERVICE", 00288 (_ip_ver_sendto == NSAPI_IPv4 ) ? "127.0.0.1" : "0:0:0:0:0:0:0:1", 00289 remote_port, socket->localAddress.get_port(), 0); 00290 00291 handle_open_socket_response(modem_connect_id, err, false); 00292 00293 if ((_at.get_last_error() == NSAPI_ERROR_OK ) && err) { 00294 if (err == BG96_SOCKET_BIND_FAIL) { 00295 socket->id = -1; 00296 return NSAPI_ERROR_PARAMETER ; 00297 } 00298 socket_close_impl(modem_connect_id); 00299 00300 _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "UDP SERVICE", 00301 (_ip_ver_sendto == NSAPI_IPv4 ) ? "127.0.0.1" : "0:0:0:0:0:0:0:1", 00302 remote_port, socket->localAddress.get_port(), 0); 00303 00304 handle_open_socket_response(modem_connect_id, err, false); 00305 } 00306 } else if (socket->proto == NSAPI_UDP && socket->connected) { 00307 char ipdot[NSAPI_IP_SIZE]; 00308 ip2dot(socket->remoteAddress, ipdot); 00309 _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d", _cid, request_connect_id, "UDP", 00310 ipdot, socket->remoteAddress.get_port()); 00311 00312 handle_open_socket_response(modem_connect_id, err, false); 00313 00314 if ((_at.get_last_error() == NSAPI_ERROR_OK ) && err) { 00315 if (err == BG96_SOCKET_BIND_FAIL) { 00316 socket->id = -1; 00317 return NSAPI_ERROR_PARAMETER ; 00318 } 00319 socket_close_impl(modem_connect_id); 00320 00321 _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d", _cid, request_connect_id, "UDP", 00322 ipdot, socket->remoteAddress.get_port()); 00323 00324 handle_open_socket_response(modem_connect_id, err, false); 00325 } 00326 } 00327 00328 // If opened successfully BUT not requested one, close it 00329 if (!err && (modem_connect_id != request_connect_id)) { 00330 socket_close_impl(modem_connect_id); 00331 } 00332 00333 nsapi_error_t ret_val = _at.get_last_error(); 00334 00335 if (ret_val == NSAPI_ERROR_OK && (modem_connect_id == request_connect_id)) { 00336 socket->id = request_connect_id; 00337 } 00338 00339 return ret_val; 00340 } 00341 00342 nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, 00343 const void *data, nsapi_size_t size) 00344 { 00345 if (size > BG96_MAX_SEND_SIZE) { 00346 return NSAPI_ERROR_PARAMETER ; 00347 } 00348 00349 if (_ip_ver_sendto != address.get_ip_version()) { 00350 _ip_ver_sendto = address.get_ip_version(); 00351 socket_close_impl(socket->id); 00352 create_socket_impl(socket); 00353 } 00354 00355 int sent_len = 0; 00356 int sent_len_before = 0; 00357 int sent_len_after = 0; 00358 00359 if (socket->tls_socket) { 00360 sent_len_after = size; 00361 } else { 00362 // Get the sent count before sending 00363 _at.at_cmd_int("+QISEND", "=", sent_len_before, "%d%d", socket->id, 0); 00364 } 00365 00366 // Send 00367 if (socket->proto == NSAPI_UDP ) { 00368 char ipdot[NSAPI_IP_SIZE]; 00369 ip2dot(address, ipdot); 00370 _at.cmd_start_stop("+QISEND", "=", "%d%d%s%d", socket->id, size, 00371 ipdot, address.get_port()); 00372 } else { 00373 if (socket->tls_socket) { 00374 _at.cmd_start_stop("+QSSLSEND", "=", "%d%d", socket->id, size); 00375 } else { 00376 _at.cmd_start_stop("+QISEND", "=", "%d%d", socket->id, size); 00377 } 00378 } 00379 00380 _at.resp_start(">"); 00381 _at.write_bytes((uint8_t *)data, size); 00382 _at.resp_start(); 00383 _at.set_stop_tag("\r\n"); 00384 // Possible responses are SEND OK, SEND FAIL or ERROR. 00385 char response[16]; 00386 response[0] = '\0'; 00387 _at.read_string(response, sizeof(response)); 00388 _at.resp_stop(); 00389 if (strcmp(response, "SEND OK") != 0) { 00390 return NSAPI_ERROR_DEVICE_ERROR ; 00391 } 00392 00393 // Get the sent count after sending 00394 nsapi_size_or_error_t err = NSAPI_ERROR_OK ; 00395 00396 if (!socket->tls_socket) { 00397 err = _at.at_cmd_int("+QISEND", "=", sent_len_after, "%d%d", socket->id, 0); 00398 } 00399 00400 if (err == NSAPI_ERROR_OK ) { 00401 sent_len = sent_len_after - sent_len_before; 00402 return sent_len; 00403 } 00404 00405 return err; 00406 } 00407 00408 nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, 00409 void *buffer, nsapi_size_t size) 00410 { 00411 nsapi_size_or_error_t recv_len = 0; 00412 int port = -1; 00413 char ip_address[NSAPI_IP_SIZE + 1]; 00414 00415 if (socket->proto == NSAPI_TCP ) { 00416 // do not read more than max size 00417 size = size > BG96_MAX_RECV_SIZE ? BG96_MAX_RECV_SIZE : size; 00418 if (socket->tls_socket) { 00419 _at.cmd_start_stop("+QSSLRECV", "=", "%d%d", socket->id, size); 00420 } else { 00421 _at.cmd_start_stop("+QIRD", "=", "%d%d", socket->id, size); 00422 } 00423 } else { 00424 _at.cmd_start_stop("+QIRD", "=", "%d", socket->id); 00425 } 00426 00427 if (socket->tls_socket) { 00428 _at.resp_start("+QSSLRECV:"); 00429 } else { 00430 _at.resp_start("+QIRD:"); 00431 } 00432 00433 recv_len = _at.read_int(); 00434 if (recv_len > 0) { 00435 // UDP has remote_IP and remote_port parameters 00436 if (socket->proto == NSAPI_UDP ) { 00437 _at.read_string(ip_address, sizeof(ip_address)); 00438 port = _at.read_int(); 00439 } 00440 // do not read more than buffer size 00441 recv_len = recv_len > (nsapi_size_or_error_t)size ? size : recv_len; 00442 _at.read_bytes((uint8_t *)buffer, recv_len); 00443 } 00444 _at.resp_stop(); 00445 00446 // We block only if 0 recv length really means no data. 00447 // If 0 is followed by ip address and port can be an UDP 0 length packet 00448 if (!recv_len && port < 0) { 00449 return NSAPI_ERROR_WOULD_BLOCK ; 00450 } 00451 00452 if (address) { 00453 address->set_ip_address(ip_address); 00454 address->set_port(port); 00455 } 00456 00457 return recv_len; 00458 } 00459 00460 #ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES 00461 nsapi_error_t QUECTEL_BG96_CellularStack::gethostbyname(const char *host, SocketAddress *address, 00462 nsapi_version_t version, const char *interface_name) 00463 { 00464 (void) interface_name; 00465 MBED_ASSERT(host); 00466 MBED_ASSERT(address); 00467 00468 _at.lock(); 00469 00470 if (_dns_callback) { 00471 _at.unlock(); 00472 return NSAPI_ERROR_BUSY ; 00473 } 00474 00475 if (!address->set_ip_address(host)) { 00476 _at.set_at_timeout(60 * 1000); // from BG96_TCP/IP_AT_Commands_Manual_V1.0 00477 _at.at_cmd_discard("+QIDNSGIP", "=", "%d%s", _cid, host); 00478 _at.resp_start("+QIURC: \"dnsgip\","); 00479 _at.restore_at_timeout(); 00480 if (!read_dnsgip(*address, version)) { 00481 _at.unlock(); 00482 return NSAPI_ERROR_DNS_FAILURE ; 00483 } 00484 } 00485 00486 return _at.unlock_return_error(); 00487 } 00488 00489 nsapi_value_or_error_t QUECTEL_BG96_CellularStack::gethostbyname_async(const char *host, hostbyname_cb_t callback, 00490 nsapi_version_t version, const char *interface_name) 00491 { 00492 (void) interface_name; 00493 MBED_ASSERT(host); 00494 MBED_ASSERT(callback); 00495 00496 _at.lock(); 00497 00498 if (_dns_callback) { 00499 _at.unlock(); 00500 return NSAPI_ERROR_BUSY ; 00501 } 00502 00503 _at.at_cmd_discard("+QIDNSGIP", "=", "%d%s", _cid, host); 00504 if (!_at.get_last_error()) { 00505 _dns_callback = callback; 00506 _dns_version = version; 00507 } 00508 00509 return _at.unlock_return_error() ? NSAPI_ERROR_DNS_FAILURE : NSAPI_ERROR_OK ; 00510 } 00511 00512 nsapi_error_t QUECTEL_BG96_CellularStack::gethostbyname_async_cancel(int id) 00513 { 00514 _at.lock(); 00515 _dns_callback = NULL; 00516 _at.unlock(); 00517 return NSAPI_ERROR_OK ; 00518 } 00519 #endif 00520 00521 void QUECTEL_BG96_CellularStack::ip2dot(const SocketAddress &ip, char *dot) 00522 { 00523 if (ip.get_ip_version() == NSAPI_IPv6 ) { 00524 const uint8_t *bytes = (uint8_t *)ip.get_ip_bytes(); 00525 for (int i = 0; i < NSAPI_IPv6_BYTES; i += 2) { 00526 if (i != 0) { 00527 *dot++ = ':'; 00528 } 00529 dot += sprintf(dot, "%x", (*(bytes + i) << 8 | *(bytes + i + 1))); 00530 } 00531 } else if (ip.get_ip_version() == NSAPI_IPv4 ) { 00532 strcpy(dot, ip.get_ip_address()); 00533 } else { 00534 *dot = '\0'; 00535 } 00536 } 00537 00538 nsapi_error_t QUECTEL_BG96_CellularStack::set_to_modem_impl(const char *filename, const char *config, const char *data, size_t size) 00539 { 00540 // Delete old file from the modem. 00541 _at.at_cmd_discard("+QFDEL", "=", "%s", filename); 00542 _at.clear_error(); // Ignore error if file didn't exist 00543 00544 // Upload new file to modem 00545 _at.cmd_start_stop("+QFUPL", "=", "%s%d", filename, size); 00546 _at.resp_start("CONNECT"); 00547 _at.write_bytes((uint8_t *)data, size); 00548 _at.resp_start("+QFUPL:"); 00549 size_t upload_size = _at.read_int(); 00550 _at.resp_stop(); 00551 if (upload_size != size) { 00552 tr_error("Upload error! orig = %d, uploaded = %d", size, upload_size); 00553 return NSAPI_ERROR_DEVICE_ERROR ; 00554 } 00555 00556 // Configure into use 00557 _at.at_cmd_discard("+QSSLCFG", "=", "%s%d%s", config, sslctxID, filename); 00558 00559 return _at.get_last_error(); 00560 } 00561 00562 00563 nsapi_error_t QUECTEL_BG96_CellularStack::setsockopt(nsapi_socket_t handle, int level, 00564 int optname, const void *optval, unsigned optlen) 00565 { 00566 CellularSocket *socket = (CellularSocket *)handle; 00567 nsapi_error_t ret = NSAPI_ERROR_OK ; 00568 00569 if (level == NSAPI_TLSSOCKET_LEVEL ) { 00570 if (optval) { 00571 _at.lock(); 00572 switch (optname) { 00573 case NSAPI_TLSSOCKET_ENABLE : { 00574 MBED_ASSERT(optlen == sizeof(bool)); 00575 bool *enabled = (bool *)optval; 00576 if (socket->proto == NSAPI_TCP ) { 00577 socket->tls_socket = enabled; 00578 00579 if (enabled) { 00580 _at.at_cmd_discard("+QSSLCFG", "=\"seclevel\",", "%d%d", sslctxID, _tls_sec_level); 00581 00582 _at.at_cmd_discard("+QSSLCFG", "=\"sslversion\",", "%d%d", sslctxID, BG96_SUPPORTED_SSL_VERSION); 00583 00584 _at.cmd_start("AT+QSSLCFG=\"ciphersuite\","); 00585 _at.write_int(sslctxID); 00586 _at.write_string(BG96_SUPPORTED_CIPHER_SUITE, false); 00587 _at.cmd_stop_read_resp(); 00588 00589 ret = _at.get_last_error(); 00590 } 00591 } else { 00592 tr_error("Trying to set non-TCPSocket as TLSSocket"); 00593 ret = NSAPI_ERROR_PARAMETER ; 00594 } 00595 } 00596 break; 00597 00598 case NSAPI_TLSSOCKET_SET_HOSTNAME : { 00599 const char *hostname = (const char *)optval; 00600 _at.at_cmd_discard("+QSSLCFG", "=\"checkhost\",", "%d%s", sslctxID, hostname); 00601 ret = _at.get_last_error(); 00602 } 00603 break; 00604 00605 case NSAPI_TLSSOCKET_SET_CACERT : { 00606 const char *cacert = (const char *)optval; 00607 ret = set_to_modem_impl("cacert.pem", "cacert", cacert, optlen); 00608 00609 // Set sec level to "Manage server authentication" if only cacert is in use 00610 if (ret == NSAPI_ERROR_OK && _tls_sec_level == 0) { 00611 _tls_sec_level = 1; 00612 } 00613 } 00614 break; 00615 00616 case NSAPI_TLSSOCKET_SET_CLCERT : { 00617 const char *clcert = (const char *)optval; 00618 ret = set_to_modem_impl("clcert.pem", "clientcert", clcert, optlen); 00619 00620 // Set sec level to "Manage server and client authentication if requested by the remote server" 00621 if (ret == NSAPI_ERROR_OK ) { 00622 _tls_sec_level = 2; 00623 } 00624 } 00625 break; 00626 00627 case NSAPI_TLSSOCKET_SET_CLKEY : { 00628 const char *clkey = (const char *)optval; 00629 ret = set_to_modem_impl("client.key", "clientkey", clkey, optlen); 00630 00631 // Set sec level to "Manage server and client authentication if requested by the remote server" 00632 if (ret == NSAPI_ERROR_OK ) { 00633 _tls_sec_level = 2; 00634 } 00635 } 00636 break; 00637 00638 default: 00639 tr_error("Unsupported sockopt (%d)", optname); 00640 ret = NSAPI_ERROR_UNSUPPORTED ; 00641 } 00642 _at.unlock(); 00643 } else { 00644 tr_error("No optval!"); 00645 ret = NSAPI_ERROR_PARAMETER ; 00646 } 00647 } else { 00648 tr_warning("Unsupported level (%d)", level); 00649 ret = NSAPI_ERROR_UNSUPPORTED ; 00650 } 00651 00652 return ret; 00653 }
Generated on Tue Jul 12 2022 13:54:46 by
