Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Simon Cooksey 0:fb7af294d5d9 1 /* Socket
Simon Cooksey 0:fb7af294d5d9 2 * Copyright (c) 2015 ARM Limited
Simon Cooksey 0:fb7af294d5d9 3 *
Simon Cooksey 0:fb7af294d5d9 4 * Licensed under the Apache License, Version 2.0 (the "License");
Simon Cooksey 0:fb7af294d5d9 5 * you may not use this file except in compliance with the License.
Simon Cooksey 0:fb7af294d5d9 6 * You may obtain a copy of the License at
Simon Cooksey 0:fb7af294d5d9 7 *
Simon Cooksey 0:fb7af294d5d9 8 * http://www.apache.org/licenses/LICENSE-2.0
Simon Cooksey 0:fb7af294d5d9 9 *
Simon Cooksey 0:fb7af294d5d9 10 * Unless required by applicable law or agreed to in writing, software
Simon Cooksey 0:fb7af294d5d9 11 * distributed under the License is distributed on an "AS IS" BASIS,
Simon Cooksey 0:fb7af294d5d9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Simon Cooksey 0:fb7af294d5d9 13 * See the License for the specific language governing permissions and
Simon Cooksey 0:fb7af294d5d9 14 * limitations under the License.
Simon Cooksey 0:fb7af294d5d9 15 */
Simon Cooksey 0:fb7af294d5d9 16
Simon Cooksey 0:fb7af294d5d9 17 #include "TCPServer.h"
Simon Cooksey 0:fb7af294d5d9 18 #include "mbed.h"
Simon Cooksey 0:fb7af294d5d9 19
Simon Cooksey 0:fb7af294d5d9 20 TCPServer::TCPServer()
Simon Cooksey 0:fb7af294d5d9 21 : _pending(0), _accept_sem(0)
Simon Cooksey 0:fb7af294d5d9 22 {
Simon Cooksey 0:fb7af294d5d9 23 }
Simon Cooksey 0:fb7af294d5d9 24
Simon Cooksey 0:fb7af294d5d9 25 TCPServer::~TCPServer()
Simon Cooksey 0:fb7af294d5d9 26 {
Simon Cooksey 0:fb7af294d5d9 27 close();
Simon Cooksey 0:fb7af294d5d9 28 }
Simon Cooksey 0:fb7af294d5d9 29
Simon Cooksey 0:fb7af294d5d9 30 nsapi_protocol_t TCPServer::get_proto()
Simon Cooksey 0:fb7af294d5d9 31 {
Simon Cooksey 0:fb7af294d5d9 32 return NSAPI_TCP;
Simon Cooksey 0:fb7af294d5d9 33 }
Simon Cooksey 0:fb7af294d5d9 34
Simon Cooksey 0:fb7af294d5d9 35 int TCPServer::listen(int backlog)
Simon Cooksey 0:fb7af294d5d9 36 {
Simon Cooksey 0:fb7af294d5d9 37 _lock.lock();
Simon Cooksey 0:fb7af294d5d9 38 int ret;
Simon Cooksey 0:fb7af294d5d9 39
Simon Cooksey 0:fb7af294d5d9 40 if (!_socket) {
Simon Cooksey 0:fb7af294d5d9 41 ret = NSAPI_ERROR_NO_SOCKET;
Simon Cooksey 0:fb7af294d5d9 42 } else {
Simon Cooksey 0:fb7af294d5d9 43 ret = _stack->socket_listen(_socket, backlog);
Simon Cooksey 0:fb7af294d5d9 44 }
Simon Cooksey 0:fb7af294d5d9 45
Simon Cooksey 0:fb7af294d5d9 46 _lock.unlock();
Simon Cooksey 0:fb7af294d5d9 47 return ret;
Simon Cooksey 0:fb7af294d5d9 48 }
Simon Cooksey 0:fb7af294d5d9 49
Simon Cooksey 0:fb7af294d5d9 50 int TCPServer::accept(TCPSocket *connection, SocketAddress *address)
Simon Cooksey 0:fb7af294d5d9 51 {
Simon Cooksey 0:fb7af294d5d9 52 _lock.lock();
Simon Cooksey 0:fb7af294d5d9 53 int ret;
Simon Cooksey 0:fb7af294d5d9 54
Simon Cooksey 0:fb7af294d5d9 55 while (true) {
Simon Cooksey 0:fb7af294d5d9 56 if (!_socket) {
Simon Cooksey 0:fb7af294d5d9 57 ret = NSAPI_ERROR_NO_SOCKET;
Simon Cooksey 0:fb7af294d5d9 58 break;
Simon Cooksey 0:fb7af294d5d9 59 }
Simon Cooksey 0:fb7af294d5d9 60
Simon Cooksey 0:fb7af294d5d9 61 _pending = 0;
Simon Cooksey 0:fb7af294d5d9 62 void *socket;
Simon Cooksey 0:fb7af294d5d9 63 ret = _stack->socket_accept(_socket, &socket, address);
Simon Cooksey 0:fb7af294d5d9 64
Simon Cooksey 0:fb7af294d5d9 65 if (0 == ret) {
Simon Cooksey 0:fb7af294d5d9 66 connection->_lock.lock();
Simon Cooksey 0:fb7af294d5d9 67
Simon Cooksey 0:fb7af294d5d9 68 if (connection->_socket) {
Simon Cooksey 0:fb7af294d5d9 69 connection->close();
Simon Cooksey 0:fb7af294d5d9 70 }
Simon Cooksey 0:fb7af294d5d9 71
Simon Cooksey 0:fb7af294d5d9 72 connection->_stack = _stack;
Simon Cooksey 0:fb7af294d5d9 73 connection->_socket = socket;
Simon Cooksey 0:fb7af294d5d9 74 connection->_event = Callback<void()>(connection, &TCPSocket::event);
Simon Cooksey 0:fb7af294d5d9 75 _stack->socket_attach(socket, &Callback<void()>::thunk, &connection->_event);
Simon Cooksey 0:fb7af294d5d9 76
Simon Cooksey 0:fb7af294d5d9 77 connection->_lock.unlock();
Simon Cooksey 0:fb7af294d5d9 78 break;
Simon Cooksey 0:fb7af294d5d9 79 } else if (NSAPI_ERROR_WOULD_BLOCK != ret) {
Simon Cooksey 0:fb7af294d5d9 80 break;
Simon Cooksey 0:fb7af294d5d9 81 } else {
Simon Cooksey 0:fb7af294d5d9 82 int32_t count;
Simon Cooksey 0:fb7af294d5d9 83
Simon Cooksey 0:fb7af294d5d9 84 // Release lock before blocking so other threads
Simon Cooksey 0:fb7af294d5d9 85 // accessing this object aren't blocked
Simon Cooksey 0:fb7af294d5d9 86 _lock.unlock();
Simon Cooksey 0:fb7af294d5d9 87 count = _accept_sem.wait(_timeout);
Simon Cooksey 0:fb7af294d5d9 88 _lock.lock();
Simon Cooksey 0:fb7af294d5d9 89
Simon Cooksey 0:fb7af294d5d9 90 if (count < 1) {
Simon Cooksey 0:fb7af294d5d9 91 // Semaphore wait timed out so break out and return
Simon Cooksey 0:fb7af294d5d9 92 ret = NSAPI_ERROR_WOULD_BLOCK;
Simon Cooksey 0:fb7af294d5d9 93 break;
Simon Cooksey 0:fb7af294d5d9 94 }
Simon Cooksey 0:fb7af294d5d9 95 }
Simon Cooksey 0:fb7af294d5d9 96 }
Simon Cooksey 0:fb7af294d5d9 97
Simon Cooksey 0:fb7af294d5d9 98 _lock.unlock();
Simon Cooksey 0:fb7af294d5d9 99 return ret;
Simon Cooksey 0:fb7af294d5d9 100 }
Simon Cooksey 0:fb7af294d5d9 101
Simon Cooksey 0:fb7af294d5d9 102 void TCPServer::event()
Simon Cooksey 0:fb7af294d5d9 103 {
Simon Cooksey 0:fb7af294d5d9 104 int32_t acount = _accept_sem.wait(0);
Simon Cooksey 0:fb7af294d5d9 105 if (acount <= 1) {
Simon Cooksey 0:fb7af294d5d9 106 _accept_sem.release();
Simon Cooksey 0:fb7af294d5d9 107 }
Simon Cooksey 0:fb7af294d5d9 108
Simon Cooksey 0:fb7af294d5d9 109 _pending += 1;
Simon Cooksey 0:fb7af294d5d9 110 if (_callback && _pending == 1) {
Simon Cooksey 0:fb7af294d5d9 111 _callback();
Simon Cooksey 0:fb7af294d5d9 112 }
Simon Cooksey 0:fb7af294d5d9 113 }