takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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