joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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