Lee Shen / FTHR_USB_serial_qSPI
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 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     while (true) {
00060         if (!_socket) {
00061             ret = NSAPI_ERROR_NO_SOCKET ;
00062             break;
00063         }
00064 
00065         _pending = 0;
00066         nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size);
00067         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != sent)) {
00068             ret = sent;
00069             break;
00070         } else {
00071             uint32_t flag;
00072 
00073             // Release lock before blocking so other threads
00074             // accessing this object aren't blocked
00075             _lock.unlock();
00076             flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
00077             _lock.lock();
00078 
00079             if (flag & osFlagsError) {
00080                 // Timeout break
00081                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00082                 break;
00083             }
00084         }
00085     }
00086 
00087     _lock.unlock();
00088     return ret;
00089 }
00090 
00091 nsapi_size_or_error_t UDPSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size)
00092 {
00093     _lock.lock();
00094     nsapi_size_or_error_t ret;
00095 
00096     while (true) {
00097         if (!_socket) {
00098             ret = NSAPI_ERROR_NO_SOCKET ;
00099             break;
00100         }
00101 
00102         _pending = 0;
00103         nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size);
00104         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != recv)) {
00105             ret = recv;
00106             break;
00107         } else {
00108             uint32_t flag;
00109 
00110             // Release lock before blocking so other threads
00111             // accessing this object aren't blocked
00112             _lock.unlock();
00113             flag = _event_flag.wait_any(READ_FLAG, _timeout);
00114             _lock.lock();
00115 
00116             if (flag & osFlagsError) {
00117                 // Timeout break
00118                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00119                 break;
00120             }
00121         }
00122     }
00123 
00124     _lock.unlock();
00125     return ret;
00126 }
00127 
00128 void UDPSocket::event()
00129 {
00130     _event_flag.set(READ_FLAG|WRITE_FLAG);
00131 
00132     _pending += 1;
00133     if (_callback && _pending == 1) {
00134         _callback();
00135     }
00136 }