2016-10-04 20:02:44 +00:00
|
|
|
|
|
|
|
/** \addtogroup netsocket */
|
|
|
|
/** @{*/
|
2016-04-19 22:51:51 +00:00
|
|
|
/* TCPSocket
|
2016-04-05 14:30:31 +00:00
|
|
|
* Copyright (c) 2015 ARM Limited
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2016-04-06 13:50:56 +00:00
|
|
|
#ifndef TCPSOCKET_H
|
|
|
|
#define TCPSOCKET_H
|
2016-04-05 14:30:31 +00:00
|
|
|
|
2016-09-30 23:32:06 +00:00
|
|
|
#include "netsocket/Socket.h"
|
|
|
|
#include "netsocket/NetworkStack.h"
|
|
|
|
#include "netsocket/NetworkInterface.h"
|
2017-08-28 15:33:50 +00:00
|
|
|
#include "rtos/EventFlags.h"
|
2016-07-19 22:12:22 +00:00
|
|
|
|
2016-04-05 14:30:31 +00:00
|
|
|
|
2016-04-06 13:50:56 +00:00
|
|
|
/** TCP socket connection
|
2016-04-05 14:30:31 +00:00
|
|
|
*/
|
2016-04-06 13:50:56 +00:00
|
|
|
class TCPSocket : public Socket {
|
2016-04-05 14:30:31 +00:00
|
|
|
public:
|
2016-04-19 21:52:06 +00:00
|
|
|
/** Create an uninitialized socket
|
|
|
|
*
|
|
|
|
* Must call open to initialize the socket on a network stack.
|
2016-04-06 13:50:56 +00:00
|
|
|
*/
|
2016-03-13 12:08:27 +00:00
|
|
|
TCPSocket();
|
2016-04-19 21:52:06 +00:00
|
|
|
|
2016-05-27 04:54:05 +00:00
|
|
|
/** Create a socket on a network interface
|
|
|
|
*
|
|
|
|
* Creates and opens a socket on the network stack of the given
|
|
|
|
* network interface.
|
|
|
|
*
|
2016-07-20 02:50:24 +00:00
|
|
|
* @param stack Network stack as target for socket
|
2016-05-27 04:54:05 +00:00
|
|
|
*/
|
2016-07-20 20:20:03 +00:00
|
|
|
template <typename S>
|
|
|
|
TCPSocket(S *stack)
|
2017-08-28 15:33:50 +00:00
|
|
|
: _pending(0), _event_flag(0),
|
2016-07-20 02:50:24 +00:00
|
|
|
_read_in_progress(false), _write_in_progress(false)
|
|
|
|
{
|
2016-07-20 20:20:03 +00:00
|
|
|
open(stack);
|
2016-07-20 02:50:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Destroy a socket
|
2016-04-19 21:52:06 +00:00
|
|
|
*
|
2016-07-20 02:50:24 +00:00
|
|
|
* Closes socket if the socket is still open
|
2016-03-13 12:08:27 +00:00
|
|
|
*/
|
2016-07-20 02:50:24 +00:00
|
|
|
virtual ~TCPSocket();
|
2016-04-19 21:52:06 +00:00
|
|
|
|
2017-07-21 16:21:27 +00:00
|
|
|
/** Override multicast functions to return error for TCP
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
int join_multicast_group(const SocketAddress &address) { return NSAPI_ERROR_UNSUPPORTED; }
|
|
|
|
|
2016-04-19 21:52:06 +00:00
|
|
|
/** Connects TCP socket to a remote host
|
|
|
|
*
|
|
|
|
* Initiates a connection to a remote server specified by either
|
|
|
|
* a domain name or an IP address and a port.
|
|
|
|
*
|
2016-04-19 22:51:51 +00:00
|
|
|
* @param host Hostname of the remote host
|
2016-04-19 21:52:06 +00:00
|
|
|
* @param port Port of the remote host
|
|
|
|
* @return 0 on success, negative error code on failure
|
2016-04-06 13:50:56 +00:00
|
|
|
*/
|
2016-10-18 19:48:46 +00:00
|
|
|
nsapi_error_t connect(const char *host, uint16_t port);
|
2016-04-06 13:50:56 +00:00
|
|
|
|
2016-04-19 21:52:06 +00:00
|
|
|
/** Connects TCP socket to a remote host
|
|
|
|
*
|
|
|
|
* Initiates a connection to a remote server specified by the
|
|
|
|
* indicated address.
|
|
|
|
*
|
|
|
|
* @param address The SocketAddress of the remote host
|
|
|
|
* @return 0 on success, negative error code on failure
|
2016-04-06 13:50:56 +00:00
|
|
|
*/
|
2016-10-18 19:48:46 +00:00
|
|
|
nsapi_error_t connect(const SocketAddress &address);
|
2016-04-06 13:50:56 +00:00
|
|
|
|
2016-04-19 21:52:06 +00:00
|
|
|
/** Send data over a TCP socket
|
|
|
|
*
|
|
|
|
* The socket must be connected to a remote host. Returns the number of
|
|
|
|
* bytes sent from the buffer.
|
|
|
|
*
|
Make TCPSocket send all data when blocking
Previously, send() was somewhat soft - it only ever made one send
call to the underlying stack, so it would typically take as much data
as would fit in the buffer, and only block if it was unable to write
anything.
This is not the intent of a POSIX socket/filehandle write. It should try
to send everything if blocking, and only send less if interrupted by a
signal:
- If the O_NONBLOCK flag is clear, write() shall block the calling
thread until the data can be accepted.
- If the O_NONBLOCK flag is set, write() shall not block the thread.
If some data can be written without blocking the thread, write()
shall write what it can and return the number of bytes written.
Otherwise, it shall return -1 and set errno to [EAGAIN].
This "send all" behaviour is of slightly limited usefulness in POSIX, as
you still usually have to worry about the interruption possibility:
- If write() is interrupted by a signal before it writes any data, it
shall return -1 with errno set to [EINTR].
- If write() is interrupted by a signal after it successfully writes
some data, it shall return the number of bytes written.
But as mbed OS does not have the possibility of signal interruption, if we
strengthen send to write everything, we can make applications' lives
easier - they can just do "send(large amount)" confident that it will
all go in one call (if no errors).
So, rework to make multiple sends to the underlying stack, blocking as
necessary, until all data is written.
This change does not apply to recv(), which is correct in only blocking until
some data is available:
- If O_NONBLOCK is set, read() shall return -1 and set errno to [EAGAIN].
- If O_NONBLOCK is clear, read() shall block the calling thread until some
data becomes available.
- The use of the O_NONBLOCK flag has no effect if there is some data
available.
2017-11-09 12:30:55 +00:00
|
|
|
* By default, send blocks until all data is sent. If socket is set to
|
|
|
|
* non-blocking or times out, a partial amount can be written.
|
|
|
|
* NSAPI_ERROR_WOULD_BLOCK is returned if no data was written.
|
2016-04-19 21:52:06 +00:00
|
|
|
*
|
|
|
|
* @param data Buffer of data to send to the host
|
|
|
|
* @param size Size of the buffer in bytes
|
|
|
|
* @return Number of sent bytes on success, negative error
|
|
|
|
* code on failure
|
2016-04-06 13:50:56 +00:00
|
|
|
*/
|
2016-10-18 19:48:46 +00:00
|
|
|
nsapi_size_or_error_t send(const void *data, nsapi_size_t size);
|
2016-04-06 13:50:56 +00:00
|
|
|
|
2016-04-19 21:52:06 +00:00
|
|
|
/** Receive data over a TCP socket
|
|
|
|
*
|
|
|
|
* The socket must be connected to a remote host. Returns the number of
|
|
|
|
* bytes received into the buffer.
|
|
|
|
*
|
Make TCPSocket send all data when blocking
Previously, send() was somewhat soft - it only ever made one send
call to the underlying stack, so it would typically take as much data
as would fit in the buffer, and only block if it was unable to write
anything.
This is not the intent of a POSIX socket/filehandle write. It should try
to send everything if blocking, and only send less if interrupted by a
signal:
- If the O_NONBLOCK flag is clear, write() shall block the calling
thread until the data can be accepted.
- If the O_NONBLOCK flag is set, write() shall not block the thread.
If some data can be written without blocking the thread, write()
shall write what it can and return the number of bytes written.
Otherwise, it shall return -1 and set errno to [EAGAIN].
This "send all" behaviour is of slightly limited usefulness in POSIX, as
you still usually have to worry about the interruption possibility:
- If write() is interrupted by a signal before it writes any data, it
shall return -1 with errno set to [EINTR].
- If write() is interrupted by a signal after it successfully writes
some data, it shall return the number of bytes written.
But as mbed OS does not have the possibility of signal interruption, if we
strengthen send to write everything, we can make applications' lives
easier - they can just do "send(large amount)" confident that it will
all go in one call (if no errors).
So, rework to make multiple sends to the underlying stack, blocking as
necessary, until all data is written.
This change does not apply to recv(), which is correct in only blocking until
some data is available:
- If O_NONBLOCK is set, read() shall return -1 and set errno to [EAGAIN].
- If O_NONBLOCK is clear, read() shall block the calling thread until some
data becomes available.
- The use of the O_NONBLOCK flag has no effect if there is some data
available.
2017-11-09 12:30:55 +00:00
|
|
|
* By default, recv blocks until some data is received. If socket is set to
|
|
|
|
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK can be returned to
|
|
|
|
* indicate no data.
|
2016-04-19 21:52:06 +00:00
|
|
|
*
|
|
|
|
* @param data Destination buffer for data received from the host
|
|
|
|
* @param size Size of the buffer in bytes
|
|
|
|
* @return Number of received bytes on success, negative error
|
2017-11-30 16:03:20 +00:00
|
|
|
* code on failure. If no data is available to be received
|
|
|
|
* and the peer has performed an orderly shutdown,
|
|
|
|
* recv() returns 0.
|
2016-04-06 13:50:56 +00:00
|
|
|
*/
|
2016-10-18 19:48:46 +00:00
|
|
|
nsapi_size_or_error_t recv(void *data, nsapi_size_t size);
|
2016-04-06 13:50:56 +00:00
|
|
|
|
2016-05-03 20:29:54 +00:00
|
|
|
protected:
|
2016-07-20 02:50:24 +00:00
|
|
|
friend class TCPServer;
|
|
|
|
|
2016-07-20 20:20:03 +00:00
|
|
|
virtual nsapi_protocol_t get_proto();
|
2016-06-06 21:35:12 +00:00
|
|
|
virtual void event();
|
2016-07-20 02:50:24 +00:00
|
|
|
|
2016-06-06 21:35:12 +00:00
|
|
|
volatile unsigned _pending;
|
2017-08-28 15:33:50 +00:00
|
|
|
rtos::EventFlags _event_flag;
|
2016-07-19 16:07:39 +00:00
|
|
|
bool _read_in_progress;
|
|
|
|
bool _write_in_progress;
|
2016-04-05 14:30:31 +00:00
|
|
|
};
|
|
|
|
|
2016-07-19 22:12:22 +00:00
|
|
|
|
2016-04-05 14:30:31 +00:00
|
|
|
#endif
|
2016-10-04 20:02:44 +00:00
|
|
|
|
|
|
|
/** @}*/
|