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: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
TCPSocket.cpp
00001 /* Socket 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "TCPSocket.h" 00018 #include "Timer.h" 00019 #include "mbed_assert.h" 00020 00021 TCPSocket::TCPSocket() 00022 : _pending(1), _read_sem(0), _write_sem(0), 00023 _read_in_progress(false), _write_in_progress(false) 00024 { 00025 } 00026 00027 TCPSocket::~TCPSocket() 00028 { 00029 close(); 00030 } 00031 00032 nsapi_protocol_t TCPSocket::get_proto() 00033 { 00034 return NSAPI_TCP ; 00035 } 00036 00037 nsapi_error_t TCPSocket::connect(const SocketAddress &address) 00038 { 00039 _lock.lock(); 00040 nsapi_error_t ret; 00041 00042 // If this assert is hit then there are two threads 00043 // performing a send at the same time which is undefined 00044 // behavior 00045 MBED_ASSERT(!_write_in_progress); 00046 _write_in_progress = true; 00047 00048 bool blocking_connect_in_progress = false; 00049 00050 while (true) { 00051 if (!_socket) { 00052 ret = NSAPI_ERROR_NO_SOCKET ; 00053 break; 00054 } 00055 00056 _pending = 0; 00057 ret = _stack->socket_connect(_socket, address); 00058 if ((_timeout == 0) || !(ret == NSAPI_ERROR_IN_PROGRESS || ret == NSAPI_ERROR_ALREADY )) { 00059 break; 00060 } else { 00061 blocking_connect_in_progress = true; 00062 00063 int32_t count; 00064 00065 // Release lock before blocking so other threads 00066 // accessing this object aren't blocked 00067 _lock.unlock(); 00068 count = _write_sem.wait(_timeout); 00069 _lock.lock(); 00070 00071 if (count < 1) { 00072 // Semaphore wait timed out so break out and return 00073 break; 00074 } 00075 } 00076 } 00077 00078 _write_in_progress = false; 00079 00080 /* Non-blocking connect gives "EISCONN" once done - convert to OK for blocking mode if we became connected during this call */ 00081 if (ret == NSAPI_ERROR_IS_CONNECTED && blocking_connect_in_progress) { 00082 ret = NSAPI_ERROR_OK ; 00083 } 00084 00085 _lock.unlock(); 00086 return ret; 00087 } 00088 00089 nsapi_error_t TCPSocket::connect(const char *host, uint16_t port) 00090 { 00091 SocketAddress address; 00092 nsapi_error_t err = _stack->gethostbyname(host, &address); 00093 if (err) { 00094 return NSAPI_ERROR_DNS_FAILURE ; 00095 } 00096 00097 address.set_port(port); 00098 00099 // connect is thread safe 00100 return connect(address); 00101 } 00102 00103 nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size) 00104 { 00105 _lock.lock(); 00106 nsapi_size_or_error_t ret; 00107 00108 // If this assert is hit then there are two threads 00109 // performing a send at the same time which is undefined 00110 // behavior 00111 MBED_ASSERT(!_write_in_progress); 00112 _write_in_progress = true; 00113 00114 while (true) { 00115 if (!_socket) { 00116 ret = NSAPI_ERROR_NO_SOCKET ; 00117 break; 00118 } 00119 00120 _pending = 0; 00121 ret = _stack->socket_send(_socket, data, size); 00122 if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK )) { 00123 break; 00124 } else { 00125 int32_t count; 00126 00127 // Release lock before blocking so other threads 00128 // accessing this object aren't blocked 00129 _lock.unlock(); 00130 count = _write_sem.wait(_timeout); 00131 _lock.lock(); 00132 00133 if (count < 1) { 00134 // Semaphore wait timed out so break out and return 00135 ret = NSAPI_ERROR_WOULD_BLOCK ; 00136 break; 00137 } 00138 } 00139 } 00140 00141 _write_in_progress = false; 00142 _lock.unlock(); 00143 return ret; 00144 } 00145 00146 nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size) 00147 { 00148 _lock.lock(); 00149 nsapi_size_or_error_t ret; 00150 00151 // If this assert is hit then there are two threads 00152 // performing a recv at the same time which is undefined 00153 // behavior 00154 MBED_ASSERT(!_read_in_progress); 00155 _read_in_progress = true; 00156 00157 while (true) { 00158 if (!_socket) { 00159 ret = NSAPI_ERROR_NO_SOCKET ; 00160 break; 00161 } 00162 00163 _pending = 0; 00164 ret = _stack->socket_recv(_socket, data, size); 00165 if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK )) { 00166 break; 00167 } else { 00168 int32_t count; 00169 00170 // Release lock before blocking so other threads 00171 // accessing this object aren't blocked 00172 _lock.unlock(); 00173 count = _read_sem.wait(_timeout); 00174 _lock.lock(); 00175 00176 if (count < 1) { 00177 // Semaphore wait timed out so break out and return 00178 ret = NSAPI_ERROR_WOULD_BLOCK ; 00179 break; 00180 } 00181 } 00182 } 00183 00184 _read_in_progress = false; 00185 _lock.unlock(); 00186 return ret; 00187 } 00188 00189 void TCPSocket::event() 00190 { 00191 int32_t wcount = _write_sem.wait(0); 00192 if (wcount <= 1) { 00193 _write_sem.release(); 00194 } 00195 int32_t rcount = _read_sem.wait(0); 00196 if (rcount <= 1) { 00197 _read_sem.release(); 00198 } 00199 00200 _pending += 1; 00201 if (_callback && _pending == 1) { 00202 _callback(); 00203 } 00204 }
Generated on Tue Jul 12 2022 11:02:54 by
