Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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