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 "TCPSocket.h"
rahul_dahiya 0:fb8047b156bb 18 #include "Timer.h"
rahul_dahiya 0:fb8047b156bb 19 #include "mbed_assert.h"
rahul_dahiya 0:fb8047b156bb 20
rahul_dahiya 0:fb8047b156bb 21 #define READ_FLAG 0x1u
rahul_dahiya 0:fb8047b156bb 22 #define WRITE_FLAG 0x2u
rahul_dahiya 0:fb8047b156bb 23
rahul_dahiya 0:fb8047b156bb 24 TCPSocket::TCPSocket()
rahul_dahiya 0:fb8047b156bb 25 : _pending(0), _event_flag(),
rahul_dahiya 0:fb8047b156bb 26 _read_in_progress(false), _write_in_progress(false)
rahul_dahiya 0:fb8047b156bb 27 {
rahul_dahiya 0:fb8047b156bb 28 }
rahul_dahiya 0:fb8047b156bb 29
rahul_dahiya 0:fb8047b156bb 30 TCPSocket::~TCPSocket()
rahul_dahiya 0:fb8047b156bb 31 {
rahul_dahiya 0:fb8047b156bb 32 close();
rahul_dahiya 0:fb8047b156bb 33 }
rahul_dahiya 0:fb8047b156bb 34
rahul_dahiya 0:fb8047b156bb 35 nsapi_protocol_t TCPSocket::get_proto()
rahul_dahiya 0:fb8047b156bb 36 {
rahul_dahiya 0:fb8047b156bb 37 return NSAPI_TCP;
rahul_dahiya 0:fb8047b156bb 38 }
rahul_dahiya 0:fb8047b156bb 39
rahul_dahiya 0:fb8047b156bb 40 nsapi_error_t TCPSocket::connect(const SocketAddress &address)
rahul_dahiya 0:fb8047b156bb 41 {
rahul_dahiya 0:fb8047b156bb 42 _lock.lock();
rahul_dahiya 0:fb8047b156bb 43 nsapi_error_t ret;
rahul_dahiya 0:fb8047b156bb 44
rahul_dahiya 0:fb8047b156bb 45 // If this assert is hit then there are two threads
rahul_dahiya 0:fb8047b156bb 46 // performing a send at the same time which is undefined
rahul_dahiya 0:fb8047b156bb 47 // behavior
rahul_dahiya 0:fb8047b156bb 48 MBED_ASSERT(!_write_in_progress);
rahul_dahiya 0:fb8047b156bb 49 _write_in_progress = true;
rahul_dahiya 0:fb8047b156bb 50
rahul_dahiya 0:fb8047b156bb 51 bool blocking_connect_in_progress = false;
rahul_dahiya 0:fb8047b156bb 52
rahul_dahiya 0:fb8047b156bb 53 while (true) {
rahul_dahiya 0:fb8047b156bb 54 if (!_socket) {
rahul_dahiya 0:fb8047b156bb 55 ret = NSAPI_ERROR_NO_SOCKET;
rahul_dahiya 0:fb8047b156bb 56 break;
rahul_dahiya 0:fb8047b156bb 57 }
rahul_dahiya 0:fb8047b156bb 58
rahul_dahiya 0:fb8047b156bb 59 _pending = 0;
rahul_dahiya 0:fb8047b156bb 60 ret = _stack->socket_connect(_socket, address);
rahul_dahiya 0:fb8047b156bb 61 if ((_timeout == 0) || !(ret == NSAPI_ERROR_IN_PROGRESS || ret == NSAPI_ERROR_ALREADY)) {
rahul_dahiya 0:fb8047b156bb 62 break;
rahul_dahiya 0:fb8047b156bb 63 } else {
rahul_dahiya 0:fb8047b156bb 64 blocking_connect_in_progress = true;
rahul_dahiya 0:fb8047b156bb 65
rahul_dahiya 0:fb8047b156bb 66 uint32_t flag;
rahul_dahiya 0:fb8047b156bb 67
rahul_dahiya 0:fb8047b156bb 68 // Release lock before blocking so other threads
rahul_dahiya 0:fb8047b156bb 69 // accessing this object aren't blocked
rahul_dahiya 0:fb8047b156bb 70 _lock.unlock();
rahul_dahiya 0:fb8047b156bb 71 flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
rahul_dahiya 0:fb8047b156bb 72 _lock.lock();
rahul_dahiya 0:fb8047b156bb 73 if (flag & osFlagsError) {
rahul_dahiya 0:fb8047b156bb 74 // Timeout break
rahul_dahiya 0:fb8047b156bb 75 break;
rahul_dahiya 0:fb8047b156bb 76 }
rahul_dahiya 0:fb8047b156bb 77 }
rahul_dahiya 0:fb8047b156bb 78 }
rahul_dahiya 0:fb8047b156bb 79
rahul_dahiya 0:fb8047b156bb 80 _write_in_progress = false;
rahul_dahiya 0:fb8047b156bb 81
rahul_dahiya 0:fb8047b156bb 82 /* Non-blocking connect gives "EISCONN" once done - convert to OK for blocking mode if we became connected during this call */
rahul_dahiya 0:fb8047b156bb 83 if (ret == NSAPI_ERROR_IS_CONNECTED && blocking_connect_in_progress) {
rahul_dahiya 0:fb8047b156bb 84 ret = NSAPI_ERROR_OK;
rahul_dahiya 0:fb8047b156bb 85 }
rahul_dahiya 0:fb8047b156bb 86
rahul_dahiya 0:fb8047b156bb 87 _lock.unlock();
rahul_dahiya 0:fb8047b156bb 88 return ret;
rahul_dahiya 0:fb8047b156bb 89 }
rahul_dahiya 0:fb8047b156bb 90
rahul_dahiya 0:fb8047b156bb 91 nsapi_error_t TCPSocket::connect(const char *host, uint16_t port)
rahul_dahiya 0:fb8047b156bb 92 {
rahul_dahiya 0:fb8047b156bb 93 SocketAddress address;
rahul_dahiya 0:fb8047b156bb 94 nsapi_error_t err = _stack->gethostbyname(host, &address);
rahul_dahiya 0:fb8047b156bb 95 if (err) {
rahul_dahiya 0:fb8047b156bb 96 return NSAPI_ERROR_DNS_FAILURE;
rahul_dahiya 0:fb8047b156bb 97 }
rahul_dahiya 0:fb8047b156bb 98
rahul_dahiya 0:fb8047b156bb 99 address.set_port(port);
rahul_dahiya 0:fb8047b156bb 100
rahul_dahiya 0:fb8047b156bb 101 // connect is thread safe
rahul_dahiya 0:fb8047b156bb 102 return connect(address);
rahul_dahiya 0:fb8047b156bb 103 }
rahul_dahiya 0:fb8047b156bb 104
rahul_dahiya 0:fb8047b156bb 105 nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
rahul_dahiya 0:fb8047b156bb 106 {
rahul_dahiya 0:fb8047b156bb 107 _lock.lock();
rahul_dahiya 0:fb8047b156bb 108 nsapi_size_or_error_t ret;
rahul_dahiya 0:fb8047b156bb 109
rahul_dahiya 0:fb8047b156bb 110 // If this assert is hit then there are two threads
rahul_dahiya 0:fb8047b156bb 111 // performing a send at the same time which is undefined
rahul_dahiya 0:fb8047b156bb 112 // behavior
rahul_dahiya 0:fb8047b156bb 113 MBED_ASSERT(!_write_in_progress);
rahul_dahiya 0:fb8047b156bb 114 _write_in_progress = true;
rahul_dahiya 0:fb8047b156bb 115
rahul_dahiya 0:fb8047b156bb 116 while (true) {
rahul_dahiya 0:fb8047b156bb 117 if (!_socket) {
rahul_dahiya 0:fb8047b156bb 118 ret = NSAPI_ERROR_NO_SOCKET;
rahul_dahiya 0:fb8047b156bb 119 break;
rahul_dahiya 0:fb8047b156bb 120 }
rahul_dahiya 0:fb8047b156bb 121
rahul_dahiya 0:fb8047b156bb 122 _pending = 0;
rahul_dahiya 0:fb8047b156bb 123 ret = _stack->socket_send(_socket, data, size);
rahul_dahiya 0:fb8047b156bb 124 if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
rahul_dahiya 0:fb8047b156bb 125 break;
rahul_dahiya 0:fb8047b156bb 126 } else {
rahul_dahiya 0:fb8047b156bb 127 uint32_t flag;
rahul_dahiya 0:fb8047b156bb 128
rahul_dahiya 0:fb8047b156bb 129 // Release lock before blocking so other threads
rahul_dahiya 0:fb8047b156bb 130 // accessing this object aren't blocked
rahul_dahiya 0:fb8047b156bb 131 _lock.unlock();
rahul_dahiya 0:fb8047b156bb 132 flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
rahul_dahiya 0:fb8047b156bb 133 _lock.lock();
rahul_dahiya 0:fb8047b156bb 134
rahul_dahiya 0:fb8047b156bb 135 if (flag & osFlagsError) {
rahul_dahiya 0:fb8047b156bb 136 // Timeout break
rahul_dahiya 0:fb8047b156bb 137 ret = NSAPI_ERROR_WOULD_BLOCK;
rahul_dahiya 0:fb8047b156bb 138 break;
rahul_dahiya 0:fb8047b156bb 139 }
rahul_dahiya 0:fb8047b156bb 140 }
rahul_dahiya 0:fb8047b156bb 141 }
rahul_dahiya 0:fb8047b156bb 142
rahul_dahiya 0:fb8047b156bb 143 _write_in_progress = false;
rahul_dahiya 0:fb8047b156bb 144 _lock.unlock();
rahul_dahiya 0:fb8047b156bb 145 return ret;
rahul_dahiya 0:fb8047b156bb 146 }
rahul_dahiya 0:fb8047b156bb 147
rahul_dahiya 0:fb8047b156bb 148 nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size)
rahul_dahiya 0:fb8047b156bb 149 {
rahul_dahiya 0:fb8047b156bb 150 _lock.lock();
rahul_dahiya 0:fb8047b156bb 151 nsapi_size_or_error_t ret;
rahul_dahiya 0:fb8047b156bb 152
rahul_dahiya 0:fb8047b156bb 153 // If this assert is hit then there are two threads
rahul_dahiya 0:fb8047b156bb 154 // performing a recv at the same time which is undefined
rahul_dahiya 0:fb8047b156bb 155 // behavior
rahul_dahiya 0:fb8047b156bb 156 MBED_ASSERT(!_read_in_progress);
rahul_dahiya 0:fb8047b156bb 157 _read_in_progress = true;
rahul_dahiya 0:fb8047b156bb 158
rahul_dahiya 0:fb8047b156bb 159 while (true) {
rahul_dahiya 0:fb8047b156bb 160 if (!_socket) {
rahul_dahiya 0:fb8047b156bb 161 ret = NSAPI_ERROR_NO_SOCKET;
rahul_dahiya 0:fb8047b156bb 162 break;
rahul_dahiya 0:fb8047b156bb 163 }
rahul_dahiya 0:fb8047b156bb 164
rahul_dahiya 0:fb8047b156bb 165 _pending = 0;
rahul_dahiya 0:fb8047b156bb 166 ret = _stack->socket_recv(_socket, data, size);
rahul_dahiya 0:fb8047b156bb 167 if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
rahul_dahiya 0:fb8047b156bb 168 break;
rahul_dahiya 0:fb8047b156bb 169 } else {
rahul_dahiya 0:fb8047b156bb 170 uint32_t flag;
rahul_dahiya 0:fb8047b156bb 171
rahul_dahiya 0:fb8047b156bb 172 // Release lock before blocking so other threads
rahul_dahiya 0:fb8047b156bb 173 // accessing this object aren't blocked
rahul_dahiya 0:fb8047b156bb 174 _lock.unlock();
rahul_dahiya 0:fb8047b156bb 175 flag = _event_flag.wait_any(READ_FLAG, _timeout);
rahul_dahiya 0:fb8047b156bb 176 _lock.lock();
rahul_dahiya 0:fb8047b156bb 177
rahul_dahiya 0:fb8047b156bb 178 if (flag & osFlagsError) {
rahul_dahiya 0:fb8047b156bb 179 // Timeout break
rahul_dahiya 0:fb8047b156bb 180 ret = NSAPI_ERROR_WOULD_BLOCK;
rahul_dahiya 0:fb8047b156bb 181 break;
rahul_dahiya 0:fb8047b156bb 182 }
rahul_dahiya 0:fb8047b156bb 183 }
rahul_dahiya 0:fb8047b156bb 184 }
rahul_dahiya 0:fb8047b156bb 185
rahul_dahiya 0:fb8047b156bb 186 _read_in_progress = false;
rahul_dahiya 0:fb8047b156bb 187 _lock.unlock();
rahul_dahiya 0:fb8047b156bb 188 return ret;
rahul_dahiya 0:fb8047b156bb 189 }
rahul_dahiya 0:fb8047b156bb 190
rahul_dahiya 0:fb8047b156bb 191 void TCPSocket::event()
rahul_dahiya 0:fb8047b156bb 192 {
rahul_dahiya 0:fb8047b156bb 193 _event_flag.set(READ_FLAG|WRITE_FLAG);
rahul_dahiya 0:fb8047b156bb 194
rahul_dahiya 0:fb8047b156bb 195 _pending += 1;
rahul_dahiya 0:fb8047b156bb 196 if (_callback && _pending == 1) {
rahul_dahiya 0:fb8047b156bb 197 _callback();
rahul_dahiya 0:fb8047b156bb 198 }
rahul_dahiya 0:fb8047b156bb 199 }