ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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