Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TCPServer.cpp Source File

TCPServer.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 "TCPServer.h"
00018 #include "mbed.h"
00019 
00020 TCPServer::TCPServer()
00021     : _pending(0), _accept_sem(0)
00022 {
00023 }
00024 
00025 TCPServer::~TCPServer()
00026 {
00027     close();
00028 }
00029 
00030 nsapi_protocol_t TCPServer::get_proto()
00031 {
00032     return NSAPI_TCP ;
00033 }
00034 
00035 nsapi_error_t TCPServer::listen(int backlog)
00036 {
00037     _lock.lock();
00038     nsapi_error_t ret;
00039 
00040     if (!_socket) {
00041         ret = NSAPI_ERROR_NO_SOCKET ;
00042     } else {
00043         ret = _stack->socket_listen(_socket, backlog);
00044     }
00045 
00046     _lock.unlock();
00047     return ret;
00048 }
00049 
00050 nsapi_error_t TCPServer::accept(TCPSocket *connection, SocketAddress *address)
00051 {
00052     _lock.lock();
00053     nsapi_error_t ret;
00054 
00055     while (true) {
00056         if (!_socket) {
00057             ret = NSAPI_ERROR_NO_SOCKET ;
00058             break;
00059         } 
00060 
00061         _pending = 0;
00062         void *socket;
00063         ret = _stack->socket_accept(_socket, &socket, address);
00064 
00065         if (0 == ret) {
00066             connection->_lock.lock();
00067 
00068             if (connection->_socket) {
00069                 connection->close();
00070             }
00071 
00072             connection->_stack = _stack;
00073             connection->_socket = socket;
00074             connection->_event = Callback<void()>(connection, &TCPSocket::event);
00075             _stack->socket_attach(socket, &Callback<void()>::thunk, &connection->_event);
00076 
00077             connection->_lock.unlock();
00078             break;
00079         } else if (NSAPI_ERROR_WOULD_BLOCK  != ret) {
00080             break;
00081         } else {
00082             int32_t count;
00083 
00084             // Release lock before blocking so other threads
00085             // accessing this object aren't blocked
00086             _lock.unlock();
00087             count = _accept_sem.wait(_timeout);
00088             _lock.lock();
00089 
00090             if (count < 1) {
00091                 // Semaphore wait timed out so break out and return
00092                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00093                 break;
00094             }
00095         }
00096     }
00097 
00098     _lock.unlock();
00099     return ret;
00100 }
00101 
00102 void TCPServer::event()
00103 {
00104     int32_t acount = _accept_sem.wait(0);
00105     if (acount <= 1) {
00106         _accept_sem.release();
00107     }
00108 
00109     _pending += 1;
00110     if (_callback && _pending == 1) {
00111         _callback();
00112     }
00113 }