Rtos API example

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 #define TCP_EVENT           "UDP_Events"
00022 #define READ_FLAG           0x1u
00023 #define WRITE_FLAG          0x2u
00024 
00025 UDPSocket::UDPSocket()
00026     : _pending(0), _event_flag()
00027 {
00028 }
00029 
00030 UDPSocket::~UDPSocket()
00031 {
00032     close();
00033 }
00034 
00035 nsapi_protocol_t UDPSocket::get_proto()
00036 {
00037     return NSAPI_UDP ;
00038 }
00039 
00040 
00041 nsapi_size_or_error_t UDPSocket::sendto(const char *host, uint16_t port, const void *data, nsapi_size_t size)
00042 {
00043     SocketAddress address;
00044     nsapi_size_or_error_t err = _stack->gethostbyname(host, &address);
00045     if (err) {
00046         return NSAPI_ERROR_DNS_FAILURE ;
00047     }
00048 
00049     address.set_port(port);
00050 
00051     // sendto is thread safe
00052     return sendto(address, data, size);
00053 }
00054 
00055 nsapi_size_or_error_t UDPSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
00056 {
00057     _lock.lock();
00058     nsapi_size_or_error_t ret;
00059 
00060     while (true) {
00061         if (!_socket) {
00062             ret = NSAPI_ERROR_NO_SOCKET ;
00063             break;
00064         }
00065 
00066         _pending = 0;
00067         nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size);
00068         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != sent)) {
00069             ret = sent;
00070             break;
00071         } else {
00072             uint32_t flag;
00073 
00074             // Release lock before blocking so other threads
00075             // accessing this object aren't blocked
00076             _lock.unlock();
00077             flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
00078             _lock.lock();
00079 
00080             if (flag & osFlagsError) {
00081                 // Timeout break
00082                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00083                 break;
00084             }
00085         }
00086     }
00087 
00088     _lock.unlock();
00089     return ret;
00090 }
00091 
00092 nsapi_size_or_error_t UDPSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size)
00093 {
00094     _lock.lock();
00095     nsapi_size_or_error_t ret;
00096 
00097     while (true) {
00098         if (!_socket) {
00099             ret = NSAPI_ERROR_NO_SOCKET ;
00100             break;
00101         }
00102 
00103         _pending = 0;
00104         nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size);
00105         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != recv)) {
00106             ret = recv;
00107             break;
00108         } else {
00109             uint32_t flag;
00110 
00111             // Release lock before blocking so other threads
00112             // accessing this object aren't blocked
00113             _lock.unlock();
00114             flag = _event_flag.wait_any(READ_FLAG, _timeout);
00115             _lock.lock();
00116 
00117             if (flag & osFlagsError) {
00118                 // Timeout break
00119                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00120                 break;
00121             }
00122         }
00123     }
00124 
00125     _lock.unlock();
00126     return ret;
00127 }
00128 
00129 void UDPSocket::event()
00130 {
00131     _event_flag.set(READ_FLAG|WRITE_FLAG);
00132 
00133     _pending += 1;
00134     if (_callback && _pending == 1) {
00135         _callback();
00136     }
00137 }