Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UDPSocket.cpp Source File

UDPSocket.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 "UDPSocket.h"
00018 #include "Timer.h"
00019 #include "mbed_assert.h"
00020 
00021 UDPSocket::UDPSocket()
00022 {
00023 }
00024 
00025 UDPSocket::~UDPSocket()
00026 {
00027 }
00028 
00029 nsapi_protocol_t UDPSocket::get_proto()
00030 {
00031     return NSAPI_UDP ;
00032 }
00033 
00034 nsapi_error_t UDPSocket::connect(const SocketAddress &address)
00035 {
00036     _remote_peer = address;
00037     return NSAPI_ERROR_OK ;
00038 }
00039 
00040 nsapi_size_or_error_t UDPSocket::sendto(const char *host, uint16_t port, const void *data, nsapi_size_t size)
00041 {
00042     SocketAddress address;
00043     nsapi_size_or_error_t err = _stack->gethostbyname(host, &address);
00044     if (err) {
00045         return NSAPI_ERROR_DNS_FAILURE ;
00046     }
00047 
00048     address.set_port(port);
00049 
00050     // sendto is thread safe
00051     return sendto(address, data, size);
00052 }
00053 
00054 nsapi_size_or_error_t UDPSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
00055 {
00056     _lock.lock();
00057     nsapi_size_or_error_t ret;
00058 
00059     _writers++;
00060 
00061     while (true) {
00062         if (!_socket) {
00063             ret = NSAPI_ERROR_NO_SOCKET ;
00064             break;
00065         }
00066 
00067         _pending = 0;
00068         nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size);
00069         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != sent)) {
00070             ret = sent;
00071             break;
00072         } else {
00073             uint32_t flag;
00074 
00075             // Release lock before blocking so other threads
00076             // accessing this object aren't blocked
00077             _lock.unlock();
00078             flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
00079             _lock.lock();
00080 
00081             if (flag & osFlagsError) {
00082                 // Timeout break
00083                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00084                 break;
00085             }
00086         }
00087     }
00088 
00089     _writers--;
00090     if (!_socket || !_writers) {
00091         _event_flag.set(FINISHED_FLAG);
00092     }
00093     _lock.unlock();
00094     return ret;
00095 }
00096 
00097 nsapi_size_or_error_t UDPSocket::send(const void *data, nsapi_size_t size)
00098 {
00099     if (!_remote_peer) {
00100         return NSAPI_ERROR_NO_ADDRESS ;
00101     }
00102     return sendto(_remote_peer, data, size);
00103 }
00104 
00105 nsapi_size_or_error_t UDPSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size)
00106 {
00107     _lock.lock();
00108     nsapi_size_or_error_t ret;
00109     SocketAddress ignored;
00110 
00111     if (!address) {
00112         address = &ignored;
00113     }
00114 
00115     _readers++;
00116 
00117     while (true) {
00118         if (!_socket) {
00119             ret = NSAPI_ERROR_NO_SOCKET ;
00120             break;
00121         }
00122 
00123         _pending = 0;
00124         nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size);
00125 
00126         // Filter incomming packets using connected peer address
00127         if (recv >= 0 && _remote_peer && _remote_peer != *address) {
00128             continue;
00129         }
00130 
00131         // Non-blocking sockets always return. Blocking only returns when success or errors other than WOULD_BLOCK
00132         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != recv)) {
00133             ret = recv;
00134             break;
00135         } else {
00136             uint32_t flag;
00137 
00138             // Release lock before blocking so other threads
00139             // accessing this object aren't blocked
00140             _lock.unlock();
00141             flag = _event_flag.wait_any(READ_FLAG, _timeout);
00142             _lock.lock();
00143 
00144             if (flag & osFlagsError) {
00145                 // Timeout break
00146                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00147                 break;
00148             }
00149         }
00150     }
00151 
00152     _readers--;
00153     if (!_socket || !_readers) {
00154         _event_flag.set(FINISHED_FLAG);
00155     }
00156 
00157     _lock.unlock();
00158     return ret;
00159 }
00160 
00161 nsapi_size_or_error_t UDPSocket::recv(void *buffer, nsapi_size_t size)
00162 {
00163     return recvfrom(NULL, buffer, size);
00164 }
00165 
00166 Socket *UDPSocket::accept(nsapi_error_t *error)
00167 {
00168     if (error) {
00169         *error = NSAPI_ERROR_UNSUPPORTED ;
00170     }
00171     return NULL;
00172 }
00173 
00174 nsapi_error_t UDPSocket::listen(int)
00175 {
00176     return NSAPI_ERROR_UNSUPPORTED ;
00177 }