mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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