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 TCPSocket.cpp Source File

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