Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers InternetSocket.cpp Source File

InternetSocket.cpp

00001 /* InternetSocket
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 "InternetSocket.h"
00018 #include "platform/Callback.h"
00019 
00020 using namespace mbed;
00021 
00022 InternetSocket::InternetSocket()
00023     : _stack(0), _socket(0), _timeout(osWaitForever),
00024       _readers(0), _writers(0), _pending(0),
00025       _factory_allocated(false)
00026 {
00027 }
00028 
00029 InternetSocket::~InternetSocket()
00030 {
00031     close();
00032 }
00033 
00034 nsapi_error_t InternetSocket::open(NetworkStack *stack)
00035 {
00036     _lock.lock();
00037 
00038     if (_stack != NULL || stack == NULL) {
00039         _lock.unlock();
00040         return NSAPI_ERROR_PARAMETER ;
00041     }
00042     _stack = stack;
00043 
00044     nsapi_socket_t socket;
00045     nsapi_error_t err = _stack->socket_open(&socket, get_proto());
00046     if (err) {
00047         _lock.unlock();
00048         return err;
00049     }
00050 
00051     _socket = socket;
00052     _event = callback(this, &InternetSocket::event);
00053     _stack->socket_attach(_socket, Callback<void()>::thunk, &_event);
00054 
00055     _lock.unlock();
00056     return NSAPI_ERROR_OK ;
00057 }
00058 
00059 nsapi_error_t InternetSocket::close()
00060 {
00061     _lock.lock();
00062 
00063     nsapi_error_t ret = NSAPI_ERROR_OK ;
00064     if (!_socket)  {
00065         _lock.unlock();
00066         return NSAPI_ERROR_NO_SOCKET ;
00067     }
00068 
00069     // Just in case - tell the stack not to callback any more, then remove this socket.
00070     _stack->socket_attach(_socket, 0, 0);
00071     nsapi_socket_t socket = _socket;
00072     _socket = 0;
00073     ret = _stack->socket_close(socket);
00074     _stack = 0; // Invalidate the stack pointer - otherwise open() fails.
00075 
00076     // Wakeup anything in a blocking operation
00077     // on this socket
00078     event();
00079 
00080     // Wait until all readers and writers are gone
00081     while (_readers || _writers) {
00082         _lock.unlock();
00083         _event_flag.wait_any(FINISHED_FLAG, osWaitForever);
00084         _lock.lock();
00085     }
00086 
00087     _lock.unlock();
00088 
00089     // When allocated by accept() call, will destroy itself on close();
00090     if (_factory_allocated) {
00091         delete this;
00092     }
00093     return ret;
00094 }
00095 
00096 int InternetSocket::modify_multicast_group(const SocketAddress &address, nsapi_socket_option_t socketopt)
00097 {
00098     nsapi_ip_mreq_t mreq;
00099 
00100     // Set up group address
00101     mreq.imr_multiaddr = address.get_addr();
00102     mreq.imr_interface = nsapi_addr_t();   // Default address, NSAPI_UNSPEC
00103 
00104     return this->setsockopt (NSAPI_SOCKET , socketopt, &mreq, sizeof(mreq));
00105 }
00106 
00107 int InternetSocket::join_multicast_group(const SocketAddress &address)
00108 {
00109     return modify_multicast_group(address, NSAPI_ADD_MEMBERSHIP );
00110 }
00111 
00112 int InternetSocket::leave_multicast_group(const SocketAddress &address)
00113 {
00114     return modify_multicast_group(address, NSAPI_DROP_MEMBERSHIP );
00115 }
00116 
00117 
00118 nsapi_error_t InternetSocket::bind(uint16_t port)
00119 {
00120     // Underlying bind is thread safe
00121     SocketAddress addr(0, port);
00122     return bind(addr);
00123 }
00124 
00125 nsapi_error_t InternetSocket::bind(const char *address, uint16_t port)
00126 {
00127     // Underlying bind is thread safe
00128     SocketAddress addr(address, port);
00129     return bind(addr);
00130 }
00131 
00132 nsapi_error_t InternetSocket::bind(const SocketAddress &address)
00133 {
00134     _lock.lock();
00135     nsapi_error_t ret;
00136 
00137     if (!_socket) {
00138         ret = NSAPI_ERROR_NO_SOCKET ;
00139     } else {
00140         ret = _stack->socket_bind(_socket, address);
00141     }
00142 
00143     _lock.unlock();
00144     return ret;
00145 }
00146 
00147 void InternetSocket::set_blocking (bool blocking)
00148 {
00149     // InternetSocket::set_timeout is thread safe
00150     set_timeout (blocking ? -1 : 0);
00151 }
00152 
00153 void InternetSocket::set_timeout (int timeout)
00154 {
00155     _lock.lock();
00156 
00157     if (timeout >= 0) {
00158         _timeout = (uint32_t)timeout;
00159     } else {
00160         _timeout = osWaitForever;
00161     }
00162 
00163     _lock.unlock();
00164 }
00165 
00166 nsapi_error_t InternetSocket::setsockopt (int level, int optname, const void *optval, unsigned optlen)
00167 {
00168     _lock.lock();
00169     nsapi_error_t ret;
00170 
00171     if (!_socket) {
00172         ret = NSAPI_ERROR_NO_SOCKET ;
00173     } else {
00174         ret = _stack->setsockopt(_socket, level, optname, optval, optlen);
00175     }
00176 
00177     _lock.unlock();
00178     return ret;
00179 }
00180 
00181 nsapi_error_t InternetSocket::getsockopt (int level, int optname, void *optval, unsigned *optlen)
00182 {
00183     _lock.lock();
00184     nsapi_error_t ret;
00185 
00186     if (!_socket) {
00187         ret = NSAPI_ERROR_NO_SOCKET ;
00188     } else {
00189         ret = _stack->getsockopt(_socket, level, optname, optval, optlen);
00190     }
00191 
00192     _lock.unlock();
00193     return ret;
00194 
00195 }
00196 void InternetSocket::event()
00197 {
00198     _event_flag.set(READ_FLAG | WRITE_FLAG);
00199 
00200     _pending += 1;
00201     if (_callback && _pending == 1) {
00202         _callback();
00203     }
00204 }
00205 
00206 void InternetSocket::sigio (Callback<void()> callback)
00207 {
00208     _lock.lock();
00209     _callback = callback;
00210     _lock.unlock();
00211 }
00212 
00213 void InternetSocket::attach(Callback<void()> callback)
00214 {
00215     sigio (callback);
00216 }