Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 /* Socket
marcozecchini 0:9fca2b23d0ba 2 * Copyright (c) 2015 ARM Limited
marcozecchini 0:9fca2b23d0ba 3 *
marcozecchini 0:9fca2b23d0ba 4 * Licensed under the Apache License, Version 2.0 (the "License");
marcozecchini 0:9fca2b23d0ba 5 * you may not use this file except in compliance with the License.
marcozecchini 0:9fca2b23d0ba 6 * You may obtain a copy of the License at
marcozecchini 0:9fca2b23d0ba 7 *
marcozecchini 0:9fca2b23d0ba 8 * http://www.apache.org/licenses/LICENSE-2.0
marcozecchini 0:9fca2b23d0ba 9 *
marcozecchini 0:9fca2b23d0ba 10 * Unless required by applicable law or agreed to in writing, software
marcozecchini 0:9fca2b23d0ba 11 * distributed under the License is distributed on an "AS IS" BASIS,
marcozecchini 0:9fca2b23d0ba 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
marcozecchini 0:9fca2b23d0ba 13 * See the License for the specific language governing permissions and
marcozecchini 0:9fca2b23d0ba 14 * limitations under the License.
marcozecchini 0:9fca2b23d0ba 15 */
marcozecchini 0:9fca2b23d0ba 16
marcozecchini 0:9fca2b23d0ba 17 #include "UDPSocket.h"
marcozecchini 0:9fca2b23d0ba 18 #include "Timer.h"
marcozecchini 0:9fca2b23d0ba 19 #include "mbed_assert.h"
marcozecchini 0:9fca2b23d0ba 20
marcozecchini 0:9fca2b23d0ba 21 #define TCP_EVENT "UDP_Events"
marcozecchini 0:9fca2b23d0ba 22 #define READ_FLAG 0x1u
marcozecchini 0:9fca2b23d0ba 23 #define WRITE_FLAG 0x2u
marcozecchini 0:9fca2b23d0ba 24
marcozecchini 0:9fca2b23d0ba 25 UDPSocket::UDPSocket()
marcozecchini 0:9fca2b23d0ba 26 : _pending(0), _event_flag()
marcozecchini 0:9fca2b23d0ba 27 {
marcozecchini 0:9fca2b23d0ba 28 }
marcozecchini 0:9fca2b23d0ba 29
marcozecchini 0:9fca2b23d0ba 30 UDPSocket::~UDPSocket()
marcozecchini 0:9fca2b23d0ba 31 {
marcozecchini 0:9fca2b23d0ba 32 close();
marcozecchini 0:9fca2b23d0ba 33 }
marcozecchini 0:9fca2b23d0ba 34
marcozecchini 0:9fca2b23d0ba 35 nsapi_protocol_t UDPSocket::get_proto()
marcozecchini 0:9fca2b23d0ba 36 {
marcozecchini 0:9fca2b23d0ba 37 return NSAPI_UDP;
marcozecchini 0:9fca2b23d0ba 38 }
marcozecchini 0:9fca2b23d0ba 39
marcozecchini 0:9fca2b23d0ba 40
marcozecchini 0:9fca2b23d0ba 41 nsapi_size_or_error_t UDPSocket::sendto(const char *host, uint16_t port, const void *data, nsapi_size_t size)
marcozecchini 0:9fca2b23d0ba 42 {
marcozecchini 0:9fca2b23d0ba 43 SocketAddress address;
marcozecchini 0:9fca2b23d0ba 44 nsapi_size_or_error_t err = _stack->gethostbyname(host, &address);
marcozecchini 0:9fca2b23d0ba 45 if (err) {
marcozecchini 0:9fca2b23d0ba 46 return NSAPI_ERROR_DNS_FAILURE;
marcozecchini 0:9fca2b23d0ba 47 }
marcozecchini 0:9fca2b23d0ba 48
marcozecchini 0:9fca2b23d0ba 49 address.set_port(port);
marcozecchini 0:9fca2b23d0ba 50
marcozecchini 0:9fca2b23d0ba 51 // sendto is thread safe
marcozecchini 0:9fca2b23d0ba 52 return sendto(address, data, size);
marcozecchini 0:9fca2b23d0ba 53 }
marcozecchini 0:9fca2b23d0ba 54
marcozecchini 0:9fca2b23d0ba 55 nsapi_size_or_error_t UDPSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
marcozecchini 0:9fca2b23d0ba 56 {
marcozecchini 0:9fca2b23d0ba 57 _lock.lock();
marcozecchini 0:9fca2b23d0ba 58 nsapi_size_or_error_t ret;
marcozecchini 0:9fca2b23d0ba 59
marcozecchini 0:9fca2b23d0ba 60 while (true) {
marcozecchini 0:9fca2b23d0ba 61 if (!_socket) {
marcozecchini 0:9fca2b23d0ba 62 ret = NSAPI_ERROR_NO_SOCKET;
marcozecchini 0:9fca2b23d0ba 63 break;
marcozecchini 0:9fca2b23d0ba 64 }
marcozecchini 0:9fca2b23d0ba 65
marcozecchini 0:9fca2b23d0ba 66 _pending = 0;
marcozecchini 0:9fca2b23d0ba 67 nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size);
marcozecchini 0:9fca2b23d0ba 68 if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
marcozecchini 0:9fca2b23d0ba 69 ret = sent;
marcozecchini 0:9fca2b23d0ba 70 break;
marcozecchini 0:9fca2b23d0ba 71 } else {
marcozecchini 0:9fca2b23d0ba 72 uint32_t flag;
marcozecchini 0:9fca2b23d0ba 73
marcozecchini 0:9fca2b23d0ba 74 // Release lock before blocking so other threads
marcozecchini 0:9fca2b23d0ba 75 // accessing this object aren't blocked
marcozecchini 0:9fca2b23d0ba 76 _lock.unlock();
marcozecchini 0:9fca2b23d0ba 77 flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
marcozecchini 0:9fca2b23d0ba 78 _lock.lock();
marcozecchini 0:9fca2b23d0ba 79
marcozecchini 0:9fca2b23d0ba 80 if (flag & osFlagsError) {
marcozecchini 0:9fca2b23d0ba 81 // Timeout break
marcozecchini 0:9fca2b23d0ba 82 ret = NSAPI_ERROR_WOULD_BLOCK;
marcozecchini 0:9fca2b23d0ba 83 break;
marcozecchini 0:9fca2b23d0ba 84 }
marcozecchini 0:9fca2b23d0ba 85 }
marcozecchini 0:9fca2b23d0ba 86 }
marcozecchini 0:9fca2b23d0ba 87
marcozecchini 0:9fca2b23d0ba 88 _lock.unlock();
marcozecchini 0:9fca2b23d0ba 89 return ret;
marcozecchini 0:9fca2b23d0ba 90 }
marcozecchini 0:9fca2b23d0ba 91
marcozecchini 0:9fca2b23d0ba 92 nsapi_size_or_error_t UDPSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size)
marcozecchini 0:9fca2b23d0ba 93 {
marcozecchini 0:9fca2b23d0ba 94 _lock.lock();
marcozecchini 0:9fca2b23d0ba 95 nsapi_size_or_error_t ret;
marcozecchini 0:9fca2b23d0ba 96
marcozecchini 0:9fca2b23d0ba 97 while (true) {
marcozecchini 0:9fca2b23d0ba 98 if (!_socket) {
marcozecchini 0:9fca2b23d0ba 99 ret = NSAPI_ERROR_NO_SOCKET;
marcozecchini 0:9fca2b23d0ba 100 break;
marcozecchini 0:9fca2b23d0ba 101 }
marcozecchini 0:9fca2b23d0ba 102
marcozecchini 0:9fca2b23d0ba 103 _pending = 0;
marcozecchini 0:9fca2b23d0ba 104 nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size);
marcozecchini 0:9fca2b23d0ba 105 if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
marcozecchini 0:9fca2b23d0ba 106 ret = recv;
marcozecchini 0:9fca2b23d0ba 107 break;
marcozecchini 0:9fca2b23d0ba 108 } else {
marcozecchini 0:9fca2b23d0ba 109 uint32_t flag;
marcozecchini 0:9fca2b23d0ba 110
marcozecchini 0:9fca2b23d0ba 111 // Release lock before blocking so other threads
marcozecchini 0:9fca2b23d0ba 112 // accessing this object aren't blocked
marcozecchini 0:9fca2b23d0ba 113 _lock.unlock();
marcozecchini 0:9fca2b23d0ba 114 flag = _event_flag.wait_any(READ_FLAG, _timeout);
marcozecchini 0:9fca2b23d0ba 115 _lock.lock();
marcozecchini 0:9fca2b23d0ba 116
marcozecchini 0:9fca2b23d0ba 117 if (flag & osFlagsError) {
marcozecchini 0:9fca2b23d0ba 118 // Timeout break
marcozecchini 0:9fca2b23d0ba 119 ret = NSAPI_ERROR_WOULD_BLOCK;
marcozecchini 0:9fca2b23d0ba 120 break;
marcozecchini 0:9fca2b23d0ba 121 }
marcozecchini 0:9fca2b23d0ba 122 }
marcozecchini 0:9fca2b23d0ba 123 }
marcozecchini 0:9fca2b23d0ba 124
marcozecchini 0:9fca2b23d0ba 125 _lock.unlock();
marcozecchini 0:9fca2b23d0ba 126 return ret;
marcozecchini 0:9fca2b23d0ba 127 }
marcozecchini 0:9fca2b23d0ba 128
marcozecchini 0:9fca2b23d0ba 129 void UDPSocket::event()
marcozecchini 0:9fca2b23d0ba 130 {
marcozecchini 0:9fca2b23d0ba 131 _event_flag.set(READ_FLAG|WRITE_FLAG);
marcozecchini 0:9fca2b23d0ba 132
marcozecchini 0:9fca2b23d0ba 133 _pending += 1;
marcozecchini 0:9fca2b23d0ba 134 if (_callback && _pending == 1) {
marcozecchini 0:9fca2b23d0ba 135 _callback();
marcozecchini 0:9fca2b23d0ba 136 }
marcozecchini 0:9fca2b23d0ba 137 }