Free (GPLv2) TCP/IP stack developed by TASS Belgium
Fork of PicoTCP by
Revision 19:c7debad9a20a, committed 2013-06-08
- Comitter:
- daniele
- Date:
- Sat Jun 08 13:47:53 2013 +0000
- Parent:
- 18:c6f67fcfc62a
- Child:
- 20:3fa3db9fd4a4
- Commit message:
- Refactoring of the socket interface
Changed in this revision
--- a/Socket/Endpoint.cpp Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include "Socket/Socket.h" -#include "Socket/Endpoint.h" -#include "wrapper.h" -#include "proxy_endpoint.h" - -extern "C" -{ -#include "pico_ipv4.h" -} -#include <cstring> -#include <cstdio> - -Endpoint::Endpoint() { - reset_address(); -} -Endpoint::~Endpoint() {} - -void Endpoint::reset_address(void) { - memset(&_remoteHost,0,sizeof(_remoteHost)); -} - -#include "stdio.h" - -int Endpoint::set_address(const char* host, const int port) { - _remoteHost.sin_port = short_be(port); - pico_string_to_ipv4(host,&_remoteHost.sin_addr.s_addr); - memcpy(_ipAddress,host, strlen(host)+1); - return 0; -} - -char* Endpoint::get_address() { - return _ipAddress; -} - -int Endpoint::get_port() { - return short_be(_remoteHost.sin_port); -}
--- a/Socket/Endpoint.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef ENDPOINT_H -#define ENDPOINT_H - -class UDPSocket; - -/** -IP Endpoint (address, port) -*/ -class Endpoint { - friend class UDPSocket; - -public: - /** IP Endpoint (address, port) - */ - Endpoint(void); - - ~Endpoint(void); - - /** Reset the address of this endpoint - */ - void reset_address(void); - - /** Set the address of this endpoint - \param host The endpoint address (it can either be an IP Address or a hostname that will be resolved with DNS). - \param port The endpoint port - \return 0 on success, -1 on failure (when an hostname cannot be resolved by DNS). - */ - int set_address(const char* host, const int port); - - /** Get the IP address of this endpoint - \return The IP address of this endpoint. - */ - char* get_address(void); - - /** Get the port of this endpoint - \return The port of this endpoint - */ - int get_port(void); - -protected: - char _ipAddress[17]; - struct sockaddr_in _remoteHost; - -}; - -#endif
--- a/Socket/Socket.cpp Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include "Socket/Socket.h" -#include "wrapper.h" -#include "proxy_endpoint.h" -#include <cstring> - -using std::memset; - -Socket::Socket() : _sock_fd(-1),_blocking(true) -{ - //set_blocking(true,1500); // ? -} - -void Socket::set_blocking(bool blocking, unsigned int timeout) { - _blocking = blocking; - _timeout = timeout; -} - -int Socket::init_socket(int type) { - if (_sock_fd != -1) - { - printf("Sock open already...\n"); - return -1; - } - - int fd = picotcp_socket(AF_INET, type, 0); - if (fd < 0) - { - printf("Error opening socket...\n"); - return -1; - } - - _sock_fd = fd; - return 0; -} - -int Socket::set_option(int level, int optname, const void *optval, socklen_t optlen) { - return picotcp_setsockopt(_sock_fd, optname, (void *)optval); -} - -int Socket::get_option(int level, int optname, void *optval, socklen_t *optlen) { - return picotcp_getsockopt(_sock_fd, optname, optval); -} - -int Socket::select(struct timeval *timeout, bool read, bool write) { - return picotcp_select(_sock_fd, timeout, read, write); -} - -int Socket::wait_readable(TimeInterval& timeout) { - return (select(&timeout._time, true, false) == 0 ? -1 : 0); -} - -int Socket::wait_writable(TimeInterval& timeout) { - return (select(&timeout._time, false, true) == 0 ? -1 : 0); -} - -int Socket::close() { - if (_sock_fd < 0) - return -1; - - picotcp_close(_sock_fd); - _sock_fd = -1; - - return 0; -} - -Socket::~Socket() { - close(); //Don't want to leak -} - -TimeInterval::TimeInterval(unsigned int ms) { - _time.tv_sec = ms / 1000; - _time.tv_usec = (ms - (_time.tv_sec * 1000)) * 1000; -}
--- a/Socket/Socket.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef SOCKET_H_ -#define SOCKET_H_ - -#ifdef __cplusplus -extern "C" { -#endif - #include "pico_dns_client.h" -#ifdef __cplusplus -} -#endif - -#include "wrapper.h" -#include "proxy_endpoint.h" - -class TimeInterval; - -/** Socket file descriptor and select wrapper - */ -class Socket { -public: - /** Socket - */ - Socket(); - - /** Set blocking or non-blocking mode of the socket and a timeout on - blocking socket operations - \param blocking true for blocking mode, false for non-blocking mode. - \param timeout timeout in ms [Default: (1500)ms]. - */ - void set_blocking(bool blocking, unsigned int timeout=1500); - - /** Set socket options - \param level stack level (see: lwip/sockets.h) - \param optname option ID - \param optval option value - \param socklen_t length of the option value - \return 0 on success, -1 on failure - */ - int set_option(int level, int optname, const void *optval, socklen_t optlen); - - /** Get socket options - \param level stack level (see: lwip/sockets.h) - \param optname option ID - \param optval buffer pointer where to write the option value - \param socklen_t length of the option value - \return 0 on success, -1 on failure - */ - int get_option(int level, int optname, void *optval, socklen_t *optlen); - - /** Close the socket file descriptor - */ - int close(); - - ~Socket(); - -protected: - int _sock_fd; - int init_socket(int type); - - int wait_readable(TimeInterval& timeout); - int wait_writable(TimeInterval& timeout); - - bool _blocking; - unsigned int _timeout; - -private: - int select(struct timeval *timeout, bool read, bool write); -}; - -/** Time interval class used to specify timeouts - */ -class TimeInterval { - friend class Socket; - -public: - /** Time Interval - \param ms time interval expressed in milliseconds - */ - TimeInterval(unsigned int ms); - -private: - struct timeval _time; - struct stack_endpoint * ep; -}; - - -inline struct hostent *gethostbyname(const char *name) { - return picotcp_gethostbyname(name); - -} -/* DNS -inline int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { - return picotcp_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); -}*/ -#endif /* SOCKET_H_ */
--- a/Socket/TCPSocketConnection.cpp Fri Jun 07 13:44:59 2013 +0000 +++ b/Socket/TCPSocketConnection.cpp Sat Jun 08 13:47:53 2013 +0000 @@ -50,7 +50,7 @@ return -1; } - if (picotcp_connect(_sock_fd, (struct sockaddr *) &_remoteHost, sizeof(_remoteHost)) < 0) { + if (picotcp_connect(_ep, (struct sockaddr *) &_remoteHost, sizeof(_remoteHost)) < 0) { close(); return -1; } @@ -64,7 +64,7 @@ } int TCPSocketConnection::send(char* data, int length) { - if ((_sock_fd < 0) || !_is_connected) + if ((_ep < 0) || !_is_connected) return -1; if (!_blocking) { @@ -75,43 +75,26 @@ return -1; } } - - int n = picotcp_write(_sock_fd, data, length); - _is_connected = (picotcp_state(_sock_fd) == SOCK_CONNECTED); - - return n; + return picotcp_write(_ep, data, length); } // -1 if unsuccessful, else number of bytes written int TCPSocketConnection::send_all(char* data, int length) { - if ((_sock_fd < 0) || !_is_connected) + if ((_ep < 0) || !_is_connected) return -1; - - size_t writtenLen = 0; - TimeInterval timeout(_timeout); - while (writtenLen < length) { - if (!_blocking) { - // Wait for socket to be writeable - if (wait_writable(timeout) != 0) - return writtenLen; - } - int ret = picotcp_write(_sock_fd, data + writtenLen, length - writtenLen); - if (ret > 0) { - writtenLen += ret; - continue; - } else if (ret == 0) { - _is_connected = (picotcp_state(_sock_fd) == SOCK_CONNECTED); - return writtenLen; - } else { - return -1; //Connnection error + if (!_blocking) { + TimeInterval timeout(_timeout); + // Wait for socket to be writeable + if (wait_writable(timeout) != 0) { + return 0; } } - return writtenLen; + return picotcp_write(_ep, data, length); } int TCPSocketConnection::receive(char* data, int length) { - if ((_sock_fd < 0) || !_is_connected) + if ((_ep < 0) || !_is_connected) return -1; if (!_blocking) { @@ -122,36 +105,10 @@ return -1; } } - - int n = picotcp_read(_sock_fd, data, length); - _is_connected = (picotcp_state(_sock_fd) == SOCK_CONNECTED); - - return n; + return picotcp_read(_ep, data, length); } // -1 if unsuccessful, else number of bytes received int TCPSocketConnection::receive_all(char* data, int length) { - if ((_sock_fd < 0) || !_is_connected) - return -1; - - size_t readLen = 0; - TimeInterval timeout(_timeout); - while (readLen < length) { - if (!_blocking) { - //Wait for socket to be readable - if (wait_readable(timeout) != 0) - return readLen; - } - - int ret = picotcp_read(_sock_fd, data + readLen, length - readLen); - if (ret > 0) { - readLen += ret; - } else if (ret == 0) { - _is_connected = (picotcp_state(_sock_fd) == SOCK_CONNECTED); - return readLen; - } else { - return -1; //Connnection error - } - } - return readLen; + return receive(data, length); }
--- a/Socket/TCPSocketConnection.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef TCPSOCKET_H -#define TCPSOCKET_H - -#include "Socket/Socket.h" -#include "Socket/Endpoint.h" - -/** -TCP socket connection -*/ -class TCPSocketConnection : public Socket, public Endpoint { - friend class TCPSocketServer; - -public: - /** TCP socket connection - */ - TCPSocketConnection(); - - /** Connects this TCP socket to the server - \param host The host to connect to. It can either be an IP Address or a hostname that will be resolved with DNS. - \param port The host's port to connect to. - \return 0 on success, -1 on failure. - */ - int connect(const char* host, const int port); - - /** Check if the socket is connected - \return true if connected, false otherwise. - */ - bool is_connected(void); - - /** Send data to the remote host. - \param data The buffer to send to the host. - \param length The length of the buffer to send. - \return the number of written bytes on success (>=0) or -1 on failure - */ - int send(char* data, int length); - - /** Send all the data to the remote host. - \param data The buffer to send to the host. - \param length The length of the buffer to send. - \return the number of written bytes on success (>=0) or -1 on failure - */ - int send_all(char* data, int length); - - /** Receive data from the remote host. - \param data The buffer in which to store the data received from the host. - \param length The maximum length of the buffer. - \return the number of received bytes on success (>=0) or -1 on failure - */ - int receive(char* data, int length); - - /** Receive all the data from the remote host. - \param data The buffer in which to store the data received from the host. - \param length The maximum length of the buffer. - \return the number of received bytes on success (>=0) or -1 on failure - */ - int receive_all(char* data, int length); - -private: - bool _is_connected; - -}; - -#endif
--- a/Socket/TCPSocketServer.cpp Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include "TCPSocketServer.h" -#include "wrapper.h" - -#include <cstring> - -using std::memset; -using std::memcpy; - -TCPSocketServer::TCPSocketServer() { - -} - -int TCPSocketServer::bind(int port) { - if (init_socket(SOCK_STREAM) < 0) - return -1; - - struct sockaddr_in localHost; - memset(&localHost, 0, sizeof(localHost)); - - localHost.sin_family = AF_INET; - localHost.sin_port = short_be(port); - localHost.sin_addr.s_addr = INADDR_ANY; - - if (picotcp_bind(_sock_fd, (struct sockaddr *) &localHost, sizeof(localHost)) < 0) { - close(); - return -1; - } - - return 0; -} - -int TCPSocketServer::listen(int max) { - if (_sock_fd < 0) - return -1; - - if (picotcp_listen(_sock_fd, max) < 0) { - close(); - return -1; - } - - return 0; -} - -int TCPSocketServer::accept(TCPSocketConnection& connection) { - if (_sock_fd < 0) - return -1; - - if (!_blocking) { - printf("Not blocking...\n"); - TimeInterval timeout(_timeout); - if (wait_readable(timeout) != 0) - return -1; - } - connection.reset_address(); - - socklen_t newSockRemoteHostLen = sizeof(connection._remoteHost); - int fd = picotcp_accept(_sock_fd, (struct sockaddr*) &connection._remoteHost, &newSockRemoteHostLen); - if (fd < 0) - return -1; //Accept failed - - connection._sock_fd = fd; - connection.set_blocking(true,1500); - connection._is_connected = true; - - return 0; -}
--- a/Socket/TCPSocketServer.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef TCPSOCKETSERVER_H -#define TCPSOCKETSERVER_H - -#include "Socket/Socket.h" -#include "wrapper.h" -#include "TCPSocketConnection.h" - -/** TCP Server. - */ -class TCPSocketServer : public Socket { - public: - /** Instantiate a TCP Server. - */ - TCPSocketServer(); - - /** Bind a socket to a specific port. - \param port The port to listen for incoming connections on. - \return 0 on success, -1 on failure. - */ - int bind(int port); - - /** Start listening for incoming connections. - \param backlog number of pending connections that can be queued up at any - one time [Default: 1]. - \return 0 on success, -1 on failure. - */ - int listen(int backlog=1); - - /** Accept a new connection. - \param connection A TCPSocketConnection instance that will handle the incoming connection. - \return 0 on success, -1 on failure. - */ - int accept(TCPSocketConnection& connection); -}; - -#endif
--- a/Socket/UDPSocket.cpp Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "Socket/UDPSocket.h" -#include "wrapper.h" -#include "proxy_endpoint.h" - -#include <cstring> - -using std::memset; - -UDPSocket::UDPSocket() { -} - -int UDPSocket::init(void) { - return init_socket(SOCK_DGRAM); -} - -// Server initialization -int UDPSocket::bind(int port) { - if (init_socket(SOCK_DGRAM) < 0) - return -1; - - struct sockaddr_in localHost; - std::memset(&localHost, 0, sizeof(localHost)); - - localHost.sin_family = AF_INET; - localHost.sin_port = short_be(port); - localHost.sin_addr.s_addr = INADDR_ANY; - - if (picotcp_bind(_sock_fd, (struct sockaddr *) &localHost, (socklen_t)sizeof(localHost)) < 0) { - close(); - return -1; - } - - return 0; -} - -int UDPSocket::join_multicast_group(EthernetInterface& eth, const char* address) { - - return picotcp_join_multicast(_sock_fd,address,eth.getIPAddress()); -} - -int UDPSocket::set_broadcasting(void) { - int option = 1; - return set_option(SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)); -} - -// -1 if unsuccessful, else number of bytes written -int UDPSocket::sendTo(Endpoint &remote, char *packet, int length) { - if (_sock_fd < 0) - { - printf("Error on socket descriptor \n"); - return -1; - } - - /* This is not needed for our udp sock ? - if (_blocking) { - TimeInterval timeout(_timeout); - if (wait_writable(timeout) != 0) - return 0; - }*/ - - return picotcp_sendto(_sock_fd, packet, length, (struct sockaddr *) &remote._remoteHost, sizeof(remote._remoteHost)); -} - -// -1 if unsuccessful, else number of bytes received -int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length) { - if (_sock_fd < 0) - return -1; - - if (!_blocking) { - TimeInterval timeout(_timeout); - if (wait_readable(timeout) != 0) - return 0; - } - //remote.reset_address(); why is this needed ? - socklen_t remoteHostLen = sizeof(remote._remoteHost); - return picotcp_recvfrom(_sock_fd, buffer, length, (struct sockaddr*) &remote._remoteHost, &remoteHostLen); -}
--- a/Socket/UDPSocket.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * - * PicoTCP Socket interface for mbed. - * Copyright (C) 2013 TASS Belgium NV - * - * Released under GPL v2 - * - * Other licensing models might apply at the sole discretion of the copyright holders. - * - * - * This software is based on the mbed.org EthernetInterface implementation: - * Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef UDPSOCKET_H -#define UDPSOCKET_H - -#include "Socket/Socket.h" -#include "Socket/Endpoint.h" -#include "EthernetInterface.h" -#include <cstdint> - -/** -UDP Socket -*/ -class UDPSocket : public Socket { - -public: - /** Instantiate an UDP Socket. - */ - UDPSocket(); - - /** Init the UDP Client Socket without binding it to any specific port - \return 0 on success, -1 on failure. - */ - int init(void); - - /** Bind a UDP Server Socket to a specific port - \param port The port to listen for incoming connections on - \return 0 on success, -1 on failure. - */ - int bind(int port); - - /** Join the multicast group at the given address - \param address The address of the multicast group - \return 0 on success, -1 on failure. - */ - int join_multicast_group(EthernetInterface& eth, const char* address); - - /** Set the socket in broadcasting mode - \return 0 on success, -1 on failure. - */ - int set_broadcasting(void); - - /** Send a packet to a remote endpoint - \param remote The remote endpoint - \param packet The packet to be sent - \param length The length of the packet to be sent - \return the number of written bytes on success (>=0) or -1 on failure - */ - int sendTo(Endpoint &remote, char *packet, int length); - - /** Receive a packet from a remote endpoint - \param remote The remote endpoint - \param buffer The buffer for storing the incoming packet data. If a packet - is too long to fit in the supplied buffer, excess bytes are discarded - \param length The length of the buffer - \return the number of received bytes on success (>=0) or -1 on failure - */ - int receiveFrom(Endpoint &remote, char *buffer, int length); -}; - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/bsd/proxy_endpoint.cpp Sat Jun 08 13:47:53 2013 +0000 @@ -0,0 +1,272 @@ +/********************************************************************* +PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. +See LICENSE and COPYING for usage. + +Author: Daniele Lacamera <daniele.lacamera@tass.be> +*********************************************************************/ + +#include "wrapper.h" +#include "proxy_endpoint.h" +#include "mbed.h" +#include "rtos.h" +#include "Queue.h" +#include "Socket.h" + +#define pt_proxy_dbg(...) + +typedef struct stack_endpoint *eplen_t; + +void picotcp_init(void) +{ + picotcp_start(); +} + +struct stack_endpoint *picotcp_socket(uint16_t net, uint16_t proto, uint16_t timeout) +{ + osEvent evt; + struct stack_endpoint *ep; + struct picotcp_socketcall *skc = + (struct picotcp_socketcall *)pico_zalloc(sizeof(struct picotcp_socketcall)); + + skc->family = net; + skc->proto = proto; + skc->timeout = timeout; + + picotcp_socketcall_queue.put(skc); + evt = picotcp_socketcall_response_queue.get(); + if(evt.status == osEventMessage) { + ep = (struct stack_endpoint *)evt.value.p; + if (ep->retval == 0) + ep->state = SOCK_OPEN; + return ep; + } + return NULL; +} + +static void picotcp_prepare_call(struct stack_endpoint *ep) +{ + ep->pending = 0; + ep->t_call = 0; + ep->t_expire = 0; +} + +static int picotcp_call(struct stack_endpoint *ep) +{ + osStatus st; + osEvent evt; + pt_proxy_dbg("Call in progress... (%x)\n", ep->pending); + st = ep->CallActivateQueue->put(ep); + pt_proxy_dbg("Waiting... (put returned %x)\n", st); + + while(1) { + evt = ep->CallResponseQueue->get(); + if(evt.status == osEventMessage) { + ep = (struct stack_endpoint *)evt.value.p; + pt_proxy_dbg("Unlocked.\n"); + ep->pending = 0; + return ep->retval; + } + } +} + + +int picotcp_state(struct stack_endpoint *ep) +{ +/* TODO: return one of: + SOCK_OPEN, + SOCK_BOUND, + SOCK_LISTEN, + SOCK_CONNECTED, + SOCK_CLOSED +*/ + return ep->state; +} + +int picotcp_bind(struct stack_endpoint *ep, struct sockaddr *local_addr, socklen_t len) +{ + int ret; + picotcp_prepare_call(ep); + ep->pending = TOK_BIND; + memcpy(&ep->addr, &((struct sockaddr_in *)local_addr)->sin_addr.s_addr, 4); + ep->port = ((struct sockaddr_in *)local_addr)->sin_port; + ret = picotcp_call(ep); + if (ret == 0) { + ep->state = SOCK_BOUND; + pt_proxy_dbg("Socket is bound \n"); + } else { + pt_proxy_dbg("Bind error: %d\n", ep->code); + } + return ret; +} + +int picotcp_listen(struct stack_endpoint *ep, int queue) +{ + int ret; + picotcp_prepare_call(ep); + ep->pending = TOK_LISTEN; + ep->size = queue; + ret = picotcp_call(ep); + if (ret == 0) + ep->state = SOCK_LISTEN; +} + +int picotcp_connect(struct stack_endpoint *ep, struct sockaddr *_srv_addr, socklen_t len) +{ + picotcp_prepare_call(ep); + ep->pending = TOK_LISTEN; + if (len == sizeof(struct sockaddr_in)) { + struct sockaddr_in *srv_addr = (struct sockaddr_in *)_srv_addr; + srv_addr->sin_family = AF_INET; + memcpy(&ep->peer, &srv_addr->sin_addr.s_addr, 4); + ep->peer_port = srv_addr->sin_port; + } else { + return -1; + } + return picotcp_call(ep); +} + +struct stack_endpoint *picotcp_accept(struct stack_endpoint *ep, struct sockaddr *_orig, socklen_t *len) +{ + osEvent evt; + struct stack_endpoint *aep; + picotcp_prepare_call(ep); + ep->pending = TOK_ACCEPT; + ep->CallActivateQueue->put(ep); + evt = ep->CallResponseQueue->get(); + if(evt.status == osEventMessage) { + aep = (struct stack_endpoint *)evt.value.p; + if (aep->retval == 0) { + aep->state = SOCK_CONNECTED; + if (len && (*len > 0)) { + struct sockaddr_in *orig = (struct sockaddr_in *)_orig; + orig->sin_family = AF_INET; + memcpy(&orig->sin_addr.s_addr, &aep->peer, 4); + orig->sin_port = aep->peer_port; + } + } + return aep; + } + else + return NULL; +} + +int picotcp_select(struct stack_endpoint *ep, struct timeval *timeout, int read, int write) +{ + int ret; + picotcp_prepare_call(ep); + ep->pending = TOK_POLL; + ep->timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + ep->events = PICO_SOCK_EV_ERR; + ep->events = PICO_SOCK_EV_FIN; + ep->events = PICO_SOCK_EV_CLOSE; + ep->events |= PICO_SOCK_EV_CONN; + if (read) { + ep->events |= PICO_SOCK_EV_RD; + } + if (write) + ep->events |= PICO_SOCK_EV_WR; + ret = picotcp_call(ep); + //printf("select returning %d\n", ret); + return ret; +} + +int picotcp_send(struct stack_endpoint *ep,void * buff, int len, int flags) +{ + if (!buff || (len <= 0)) + return 0; + picotcp_prepare_call(ep); + ep->pending = TOK_SEND; + ep->buffer = (uint8_t *)buff; + ep->size = len; + return picotcp_call(ep); +} + +int picotcp_recv(struct stack_endpoint *ep,void * buff, int len, int flags) +{ + if (!buff || (len <= 0)) + return 0; + picotcp_prepare_call(ep); + ep->pending = TOK_RECV; + ep->buffer = (uint8_t *)buff; + ep->size = len; + return picotcp_call(ep); +} + +int picotcp_sendto(struct stack_endpoint *ep,void * buff, int len, struct sockaddr *a, socklen_t l) +{ + if (!buff || (len <= 0)) + return 0; + picotcp_prepare_call(ep); + ep->pending = TOK_SENDTO; + ep->buffer = (uint8_t *)buff; + ep->size = len; + memcpy(&ep->peer, &(((struct sockaddr_in *)a)->sin_addr.s_addr), 4); /** XXX IPv4 only! **/ + return picotcp_call(ep); +} + +int picotcp_recvfrom(struct stack_endpoint *ep,void * buff, int len, struct sockaddr *a, socklen_t *l) +{ + int ret; + + if (!buff || (len <= 0)) + return 0; + picotcp_prepare_call(ep); + ep->pending = TOK_SENDTO; + ep->buffer = (uint8_t *)buff; + ep->size = len; + ret = picotcp_call(ep); + if (ret > 0) + memcpy( &(((struct sockaddr_in *)a)->sin_addr.s_addr), &ep->peer, 4); /* IPv4 ONLY */ + return ret; + +} + +int picotcp_read(struct stack_endpoint *ep,void *buf, int len) +{ + if (!buf || (len <= 0)) + return 0; + + picotcp_prepare_call(ep); + ep->pending = TOK_READ; + ep->buffer = (uint8_t *)buf; + ep->size = len; + return picotcp_call(ep); +} + +int picotcp_write(struct stack_endpoint *ep,void *buf, int len) +{ + if (!buf || (len <= 0)) + return 0; + picotcp_prepare_call(ep); + ep->pending = TOK_WRITE; + ep->buffer = (uint8_t *)buf; + ep->size = len; + return picotcp_call(ep); +} + +int picotcp_setsockopt(struct stack_endpoint *ep, int option, void *value) +{ + /* TODO */ + return -1; +} + +int picotcp_getsockopt(struct stack_endpoint *ep, int option, void *value) +{ + /* TODO */ + return -1; +} + +int picotcp_close(struct stack_endpoint *ep) +{ + picotcp_prepare_call(ep); + ep->pending = TOK_CLOSE; + ep->state = SOCK_CLOSED; + return picotcp_call(ep); +} + +int picotcp_join_multicast(struct stack_endpoint *ep,const char* address,const char* local) +{ + /* TODO */ + return -1; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/bsd/proxy_endpoint.h Sat Jun 08 13:47:53 2013 +0000 @@ -0,0 +1,111 @@ +/********************************************************************* +PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. +See LICENSE and COPYING for usage. + +Author: Daniele Lacamera <daniele.lacamera@tass.be> +*********************************************************************/ + +#ifndef __PICOTCP_BSD_LAYER +#define __PICOTCP_BSD_LAYER + +extern "C" { +#include "pico_stack.h" +#include "pico_tree.h" +#include "pico_dns_client.h" +#include "pico_socket.h" +#include "pico_addressing.h" +#include "pico_protocol.h" +#include "pico_config.h" +#include "pico_ipv4.h" +#include "pico_device.h" +}; +#include "mbed.h" +#include "rtos.h" +#include "Queue.h" +#include "PicoCondition.h" + +struct sockaddr; + +struct ip_addr_s { + uint32_t s_addr; +}; + +typedef struct ip_addr_s ip_addr_t; + +struct sockaddr_in +{ + ip_addr_t sin_addr; + uint16_t sin_family; + uint16_t sin_port; +}; + +struct timeval { + uint32_t tv_sec; + uint32_t tv_usec; +}; + +/* Description of data base entry for a single host. */ +struct hostent +{ + char *h_name; /* Official name of host. */ + char **h_aliases; /* Alias list. */ + int h_addrtype; /* Host address type. */ + int h_length; /* Length of address. */ + char **h_addr_list; /* List of addresses from name server. */ +# define h_addr h_addr_list[0] /* Address, for backward compatibility.*/ +}; + +#ifndef PF_INET +#define PF_INET 2 +#define PF_INET6 10 +#define AF_INET PF_INET +#define AF_INET6 PF_INET6 + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 + +#define SOL_SOCKET 1 +#define SO_BROADCAST 6 + +#define INADDR_ANY 0u + +#endif + +enum socket_state_e { + SOCK_OPEN, + SOCK_BOUND, + SOCK_LISTEN, + SOCK_CONNECTED, + SOCK_CLOSED +}; + +typedef int socklen_t; + +void picotcp_init(void); + +struct stack_endpoint * picotcp_socket(uint16_t net, uint16_t proto, uint16_t flags); +int picotcp_state(struct stack_endpoint *); +int picotcp_bind(struct stack_endpoint *, struct sockaddr *local_addr, socklen_t len); + +int picotcp_listen(struct stack_endpoint *, int queue); +int picotcp_connect(struct stack_endpoint *, struct sockaddr *srv_addr, socklen_t len); +struct stack_endpoint * picotcp_accept(struct stack_endpoint *, struct sockaddr *orig, socklen_t *); +int picotcp_select(struct stack_endpoint *, struct timeval *timeout, int read, int write); + +int picotcp_send(struct stack_endpoint *,void * buff, int len, int flags); +int picotcp_recv(struct stack_endpoint *,void * buff, int len, int flags); +int picotcp_sendto(struct stack_endpoint *,void * buff, int len, struct sockaddr*,socklen_t); +int picotcp_recvfrom(struct stack_endpoint *,void * buff, int len, struct sockaddr *, socklen_t *); +int picotcp_read(struct stack_endpoint *,void *buf, int len); +int picotcp_write(struct stack_endpoint *,void *buf, int len); +int picotcp_setsockopt(struct stack_endpoint *, int option, void *value); +int picotcp_getsockopt(struct stack_endpoint *, int option, void *value); +struct hostent * picotcp_gethostbyname(const char *url); +char * picotcp_gethostbyaddr(const char *ip); +int picotcp_close(struct stack_endpoint *); +// set blocking +int picotcp_setblocking(struct stack_endpoint *,int blocking); +int picotcp_join_multicast(struct stack_endpoint *,const char* address,const char* local); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/bsd/stack_endpoint.cpp Sat Jun 08 13:47:53 2013 +0000 @@ -0,0 +1,454 @@ +/********************************************************************* +PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. +See LICENSE and COPYING for usage. + +Authors: Daniele Lacamera +*********************************************************************/ + +#include "wrapper.h" +#include "rtos.h" +#include "cmsis_os.h" +#include "mbed.h" +#include "Socket.h" + +//#define ptsock_dbg printf +#define ptsock_dbg(...) + +int in_the_stack = 0; + + +static Thread * serverThread = NULL; +// global queue for open requests +Queue<struct picotcp_socketcall,10> picotcp_socketcall_queue; +Queue<struct stack_endpoint,10> picotcp_socketcall_response_queue; + +static inline void sendOpenResponse(struct stack_endpoint * arg) +{ + picotcp_socketcall_response_queue.put(arg); +} + +static inline uint16_t readSocketCommand(struct stack_endpoint * endp) +{ + osEvent event = endp->CallActivateQueue->get(0); // Tx for Client, Rx for Me, non blocking + if(event.status == osEventMessage) + return *((uint16_t *)event.value.p); + return NO_COMMAND; +} + +static inline void sendSocketResponse(struct stack_endpoint *endp) +{ + endp->CallResponseQueue->put(endp); +} + +static int stack_compare(void *ka, void *kb) +{ + struct stack_endpoint *a = (struct stack_endpoint *)ka, *b = (struct stack_endpoint *)kb; + if (a->s < b->s) + return -1; + if (a->s > b->s) + return 1; + return 0; +} + +PICO_TREE_DECLARE(stack_ep_tree, stack_compare); + +static struct stack_endpoint *GET_SOCK_BY_PICOSOCK(struct pico_socket *s) +{ + struct stack_endpoint test; + test.s = s; + return (struct stack_endpoint *)pico_tree_findKey(&stack_ep_tree, &test); +} + +static void stack_Add(struct stack_endpoint *ep) +{ + pico_tree_insert(&stack_ep_tree, ep); +} + +static void stack_Del(struct stack_endpoint *ep) +{ + pico_tree_delete(&stack_ep_tree, ep); +} + +static void status_pending_off(struct stack_endpoint *ep) +{ + //ep->pending = NO_COMMAND; //no event +} + + +static int close_ep(struct stack_endpoint *ep){ + stack_Del(ep); + pico_free(ep); + return 0; +} + +static int send_wakeup(struct stack_endpoint *ep) +{ + int ret = 0; + if (ep->pending == NO_COMMAND) + return -1; + ep->retval = 1; + // send response + sendSocketResponse(ep); + return ret; +} + + + +static int send_retval(struct stack_endpoint *ep, int retval) +{ + int ret = 0; + if (ep->pending == NO_COMMAND) + return -1; + ep->retval = retval; + // send queue + sendSocketResponse(ep); + status_pending_off(ep); + return ret; +} + +static int send_error(struct stack_endpoint *ep) +{ + ep->code = pico_err; + return send_retval(ep, -1); +} +static void set_timer(struct stack_endpoint *ep) +{ + if (ep->timeout == osWaitForever) + return; + + if (ep->t_call == 0) { + ep->t_call = PICO_TIME_MS(); + ep->t_expire = ep->t_call + ep->timeout; + } +} + +static void check_timer_expired(struct stack_endpoint *ep) +{ + if (ep->timeout == osWaitForever) + return; /* never */ + + if (ep->t_expire < PICO_TIME_MS()) { + ep->retval = 0; + sendSocketResponse(ep); + } +} + + +static void retry_connect(struct stack_endpoint *ep) +{ + if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) { + ep->revents &= (~PICO_SOCK_EV_CONN); + ep->revents |= PICO_SOCK_EV_WR; + ptsock_dbg("Established. sock state: %x\n", ep->s->state); + send_retval(ep, 0); + }else { + pico_socket_connect(ep->s, &ep->addr, ep->port); + ep->events |= PICO_SOCK_EV_CONN; + } +} + +static void retry_accept(struct stack_endpoint *ep) +{ + struct pico_ip4 peer ={}; + uint16_t port = 0; + + struct stack_endpoint *aep; + struct pico_socket *sa; + set_timer(ep); + if (ep->revents & PICO_SOCK_EV_CONN) { + ptsock_dbg("Incoming connection...\n"); + sa = pico_socket_accept(ep->s, &peer.addr, &port); + if (sa) { + ptsock_dbg("Accepted!\n"); + aep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint)); + if (!aep) { + send_error(ep); + return; + } + + aep->sock_fd = (uint16_t)pico_rand(); + aep->s = sa; + aep->connected = 1; + aep->peer = peer; + aep->peer_port = port; + aep->addr = ep->addr;//copy parent's address + aep->port = ep->port; + aep->pending = NO_COMMAND; + aep->revents |= PICO_SOCK_EV_WR; + ep->revents &= (~PICO_SOCK_EV_CONN); + aep->CallResponseQueue = new Queue<struct stack_endpoint,2>(); + aep->CallActivateQueue = new Queue<struct stack_endpoint,2>(); + aep->state = SOCK_CONNECTED; + stack_Add(aep); + ep->retval = 0; + ep->CallResponseQueue->put(aep); + } else { + send_error(ep); + } + return; + } + ep->events |= PICO_SOCK_EV_CONN; + check_timer_expired(ep); +} + +static void retry_close(struct stack_endpoint *ep) +{ + + if ((!ep->connected) || (ep->revents & PICO_SOCK_EV_CLOSE) || (ep->revents & PICO_SOCK_EV_FIN)) { + pico_socket_close(ep->s); + close_ep(ep); + } +} + +static void retry_write(struct stack_endpoint *ep) +{ + + if (ep->pending == NO_COMMAND) + return; + + if (!ep->buffer) { + send_error(ep); + return; + } + + if (ep->pending == TOK_SENDTO) { + ep->size = pico_socket_sendto(ep->s, ep->buffer, ep->size, &ep->addr, ep->port); + } else { + ep->size = pico_socket_write(ep->s, ep->buffer, ep->size); + } + ep->revents &= (~PICO_SOCK_EV_WR); + if (ep->size < 0) + send_error(ep); + else if (ep->size > 0) + send_retval(ep, ep->size); + else { + ep->events |= PICO_SOCK_EV_WR; + return; + } +} + +static void retry_read(struct stack_endpoint *ep) +{ + int len; + if (ep->pending == NO_COMMAND) + return; + + ptsock_dbg("in retry-read, len: %d \n", len); + + + + if (!ep->buffer) { + send_error(ep); + return; + } else { + if (ep->pending == TOK_RECVFROM) + len = pico_socket_recvfrom(ep->s, ep->buffer, ep->size, &ep->addr, &ep->port); + else { + len = pico_socket_read(ep->s, ep->buffer, ep->size); + } + } + + if (ep->size > len) + ep->revents &= (~PICO_SOCK_EV_RD); + + if (len == 0) { + ptsock_dbg("Read returned 0."); + ep->events |= PICO_SOCK_EV_RD; + return; + } + send_retval(ep, len); +} + +void retry_poll(struct stack_endpoint *ep) +{ + if (ep->pending == NO_COMMAND) + return; + + set_timer(ep); + + if ((ep->events & ep->revents) != 0) { + send_retval(ep, 1); + return; + } + + check_timer_expired(ep); +} + +static void retry_token(struct stack_endpoint *ep) +{ + if (ep->pending == NO_COMMAND) + return; + ptsock_dbg("in retry-token, cmd: %04x\n", ep->pending); + switch(ep->pending) { + case TOK_POLL: + retry_poll(ep); + break; + case TOK_CONNECT: + retry_connect(ep); + break; + case TOK_ACCEPT: + retry_accept(ep); + break; + + case TOK_READ: + case TOK_RECV: + case TOK_RECVFROM: + retry_read(ep); + break; + + case TOK_WRITE: + case TOK_SEND: + case TOK_SENDTO: + retry_write(ep); + break; + + case TOK_CLOSE: + retry_close(ep); + break; + default: + break; + } +} + +static void wakeup(uint16_t ev, struct pico_socket *s) +{ + int t; + struct stack_endpoint *ep = GET_SOCK_BY_PICOSOCK(s); + + if (!ep) { + ptsock_dbg("WAKEUP: no socket :(\n"); + return; + } + t = ep->pending; + ptsock_dbg("Wake up event: %04x\n", ev); + ep->revents |= ev; + + if (ev & PICO_SOCK_EV_ERR) { + ep->revents = PICO_SOCK_EV_ERR; + send_error(ep); + return; + } + + if ((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) { + ep->connected = 0; + } + if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) { + if ((ev & PICO_SOCK_EV_CONN) && (ep->pending == TOK_CONNECT)) { + ptsock_dbg("** Connected\n"); + ep->connected = 1; + } + } + if (ev & PICO_SOCK_EV_WR) + ep->revents |= PICO_SOCK_EV_WR; + if ( (ep->pending != 0) && ((ep->events & ep->revents)!=0) ) + retry_token(ep); +} + +static int stack_parse_requests(void) +{ + struct stack_endpoint *ep = NULL; + struct picotcp_socketcall *skc; + osEvent event; // used to see the status of queue get + struct pico_tree_node * index = NULL; + uint16_t proto,net; + int ret = 0; + int yes = 1; + // first check if the global queue has something in it + // and open a new socket if so + do + { + stack_endpoint *stack_ep = NULL; + + event = picotcp_socketcall_queue.get(0); // non blocking get + if(event.status == osEventMessage) { + ret = 1; + // Get the arguments + skc = (struct picotcp_socketcall *)event.value.p; + + // open new socket and send the response + stack_ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint)); + if(!stack_ep) + { + ptsock_dbg("Out of memory\n"); + return -1; + } + stack_ep->CallActivateQueue = new Queue<struct stack_endpoint,2>(); + stack_ep->CallResponseQueue = new Queue<struct stack_endpoint,2>(); + + net = ((skc->family == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4); + proto = ((skc->proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP); + stack_ep->s = pico_socket_open( net, proto, &wakeup ); + + if (!stack_ep->s) + stack_ep->retval = -1; + //pico_socket_setoption(stack_ep->s, PICO_SOCKET_OPT_TCPNODELAY, &yes); + + //stack_ep->pending = NO_COMMAND; + stack_Add(stack_ep); + // send the response back to the client + sendOpenResponse(stack_ep); + ptsock_dbg("New socket added: %p\n", stack_ep->s); + } + }while(event.status == osEventMessage); + + // go through all the sockets and check if there is a request from someone + // call to the get function has timeout 0, must be non blocking + // if a request has come from someone parse it + pico_tree_foreach(index,&stack_ep_tree) + { + ep = (struct stack_endpoint *)index->keyValue; + // check if data has arrived + event = ep->CallActivateQueue->get(0); // again non blocking + if(event.status == osEventMessage) + { + ret = 1; + //printf("Socket contacted. CMD: %X\n", ep->pending); + // check command sent + switch(ep->pending) + { + case TOK_BIND: + if(pico_socket_bind(ep->s, &ep->addr, &ep->port) == 0) { + ptsock_dbg("stack: bind success (addr: %08x, port %d)!\n", ep->addr.addr, ep->port); + send_retval(ep, 0); + } else { + ptsock_dbg("stack: bind error (pico_s: %p, addr: %08x, port %d err: %d)!\n", ep->s, ep->addr.addr, ep->port, pico_err); + send_error(ep); + } + break; + case TOK_LISTEN: + if(pico_socket_listen(ep->s, ep->size) == 0) + send_retval(ep, 0); + else + send_error(ep); + break; + default: + retry_token(ep); + } + break; + } + } + return ret; +} + +void pico_wrapper_loop(const void * arg) +{ + (void)arg; + int ret = 0; + while(1) { + pico_stack_tick(); + // parse all requests + ret = stack_parse_requests(); + if (ret == 0) { + Thread::wait(2); + } + } +} + +void picotcp_start(void) +{ + if (serverThread == NULL) { + printf (" *** PicoTCP initialized *** \n"); + serverThread = new Thread(pico_wrapper_loop); + serverThread->set_priority(osPriorityIdle); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/bsd/wrapper.h Sat Jun 08 13:47:53 2013 +0000 @@ -0,0 +1,91 @@ +#ifndef ____WRAPPER_H +#define ____WRAPPER_H + +#ifdef __cplusplus +extern "C"{ +#endif + +#include "pico_ipv4.h" +#include "pico_ipv6.h" +#include "pico_stack.h" +#include "pico_socket.h" + +#ifdef __cplusplus +} +#endif + +#include "mbed.h" +#include "rtos.h" + +#define PT_MAX_SOCKETS 255 + +extern Queue<struct picotcp_socketcall,10> picotcp_socketcall_queue; +extern Queue<struct stack_endpoint,10> picotcp_socketcall_response_queue; + +#define NO_COMMAND 0x0u +#define TOK_OPEN 0x0080U +#define TOK_WRITE 0x0001U +#define TOK_READ 0x0002U +#define TOK_SEND 0x0005U +#define TOK_RECV 0x0006U +#define TOK_SENDTO 0x0009U +#define TOK_RECVFROM 0x000aU +#define TOK_LISTEN 0x0010U +#define TOK_CONNECT 0x0011U +#define TOK_ACCEPT 0x0012U +#define TOK_BIND 0x0020U +#define TOK_SETSOCKOPT 0x0031U +#define TOK_GETSOCKOPT 0x0032U +#define TOK_CLOSE 0x0040U +#define TOK_SHUTDOWN 0x0041U +#define TOK_POLL 0x0051U +#define TOK_POLL_END 0x0052U +#define TOK_DNS 0x0061U +#define TOK_DHCP_ENBL 0x0071U + +// this is used to share memory between here and +// the Socket code, after opening the socket +// sockfd = globalQueue.get(); +// this->ep = pico_get_socket(sockfd); +struct stack_endpoint { + int retval; + uint16_t sock_fd; + struct pico_socket *s; + int connected; + int events; + int revents; + Queue<struct stack_endpoint,2> *CallResponseQueue;//receive queue of 1 element of type + Queue<struct stack_endpoint,2> *CallActivateQueue;//transmit queue of 1 element of type + uint16_t pending; // pending command + // parameters + struct pico_ip4 addr; // local address + struct pico_ip4 peer; // peer address + uint16_t peer_port; // peer port + uint16_t port; // local port + uint16_t code; // error code + uint16_t sockfd; // socket identifier + uint8_t * buffer; //buffer, used read/write functions + int size; // this is for read/write/listen commands + uint32_t timeout; // this is used for timeout sockets + uint32_t t_call; // time for the start of the blocking call + uint32_t t_expire; // call expire time + int state; // for pico_state +}; + +struct picotcp_socketcall { + uint32_t sock_fd; + uint32_t timeout; + uint16_t family; + uint16_t proto; +}; + +#define MAXTOKEN 2000 +#define TOK_CMD(t) ((t->cmd & 0x00FF)) +#define TOK_R_CMD(t) ((t->cmd & 0xFF00)) +#define TOKEN_DATA_OFFSET (sizeof(struct token)) +#define MAXTOKEN_DATA (MAXTOKEN - TOKEN_DATA_OFFSET) +#define TOKEN_DATA_BUF(t) ((uint8_t *)(t + TOKEN_DATA_OFFSET)) + +void picotcp_start(void); +struct stack_endpoint *pico_get_socket(uint16_t sockfd); +#endif
--- a/Socket/posix/proxy_endpoint.cpp Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/********************************************************************* -PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. -See LICENSE and COPYING for usage. - -Author: Daniele Lacamera <daniele.lacamera@tass.be> -*********************************************************************/ - -#include "wrapper.h" -#include "proxy_endpoint.h" -#include "mbed.h" -#include "rtos.h" -#include "Queue.h" -#include "PicoCondition.h" - -typedef int socklen_t; - -void picotcp_init(void) -{ -} - -int picotcp_socket(uint16_t net, uint16_t proto, uint16_t flags) -{ -} - -int picotcp_state(int sock) -{ - -} - -// maybe instead of passing the sockfd would be faster -// to pass directly the socket structure from inside the -// Socket class. -int picotcp_bind(int sock, struct sockaddr *local_addr, socklen_t len) -{ -} - -int picotcp_listen(int sock, int queue) -{ -} - -int picotcp_connect(int sock, struct sockaddr *srv_addr, socklen_t len) -{ -} - -int picotcp_accept(int sock, struct sockaddr *orig, socklen_t *) -{ -} - -int picotcp_select(int sock, struct timeval *timeout, int read, int write) -{ -} - -int picotcp_send(int sock,void * buff, int len, int flags) -{ -} - -int picotcp_recv(int sock,void * buff, int len, int flags) -{ -} - -int picotcp_sendto(int sock,void * buff, int len, struct sockaddr*,socklen_t) -{ -} - -int picotcp_recvfrom(int sock,void * buff, int len, struct sockaddr *, socklen_t *) -{ -} - -int picotcp_read(int sock,void *buf, int len) -{ -} - -int picotcp_write(int sock,void *buf, int len) -{ -} - -int picotcp_setsockopt(int sock, int option, void *value) -{ -} - -int picotcp_getsockopt(int sock, int option, void *value) -{ -} - -int picotcp_close(int sock) -{ -} - -int picotcp_join_multicast(int sock,const char* address,const char* local) -{ -} -
--- a/Socket/posix/proxy_endpoint.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/********************************************************************* -PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved. -See LICENSE and COPYING for usage. - -Author: Daniele Lacamera <daniele.lacamera@tass.be> -*********************************************************************/ - -#ifndef __PICOTCP_BSD_LAYER -#define __PICOTCP_BSD_LAYER - -extern "C" { -#include "pico_stack.h" -#include "pico_tree.h" -#include "pico_dns_client.h" -#include "pico_socket.h" -#include "pico_addressing.h" -#include "pico_protocol.h" -#include "pico_config.h" -#include "pico_ipv4.h" -#include "pico_device.h" -}; -#include "mbed.h" -#include "rtos.h" -#include "Queue.h" -#include "PicoCondition.h" - -struct sockaddr; - -struct ip_addr_s { - uint32_t s_addr; -}; - -typedef struct ip_addr_s ip_addr_t; - -struct sockaddr_in -{ - ip_addr_t sin_addr; - uint16_t sin_family; - uint16_t sin_port; -}; - -struct timeval { - uint32_t tv_sec; - uint32_t tv_usec; -}; - -/* Description of data base entry for a single host. */ -struct hostent -{ - char *h_name; /* Official name of host. */ - char **h_aliases; /* Alias list. */ - int h_addrtype; /* Host address type. */ - int h_length; /* Length of address. */ - char **h_addr_list; /* List of addresses from name server. */ -# define h_addr h_addr_list[0] /* Address, for backward compatibility.*/ -}; - -#ifndef PF_INET -#define PF_INET 2 -#define PF_INET6 10 -#define AF_INET PF_INET -#define AF_INET6 PF_INET6 - -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 - -#define SOL_SOCKET 1 -#define SO_BROADCAST 6 - -#define INADDR_ANY 0u - -#endif - -enum socket_state_e { - SOCK_OPEN, - SOCK_BOUND, - SOCK_LISTEN, - SOCK_CONNECTED, - SOCK_CLOSED -}; - -typedef int socklen_t; - -void picotcp_init(void); - -int picotcp_socket(uint16_t net, uint16_t proto, uint16_t flags); -int picotcp_state(int sock); -int picotcp_bind(int sock, struct sockaddr *local_addr, socklen_t len); - -int picotcp_listen(int sock, int queue); -int picotcp_connect(int sock, struct sockaddr *srv_addr, socklen_t len); -int picotcp_accept(int sock, struct sockaddr *orig, socklen_t *); -int picotcp_select(int sock, struct timeval *timeout, int read, int write); - -int picotcp_send(int sock,void * buff, int len, int flags); -int picotcp_recv(int sock,void * buff, int len, int flags); -int picotcp_sendto(int sock,void * buff, int len, struct sockaddr*,socklen_t); -int picotcp_recvfrom(int sock,void * buff, int len, struct sockaddr *, socklen_t *); -int picotcp_read(int sock,void *buf, int len); -int picotcp_write(int sock,void *buf, int len); -int picotcp_setsockopt(int sock, int option, void *value); -int picotcp_getsockopt(int sock, int option, void *value); -struct hostent * picotcp_gethostbyname(const char *url); -char * picotcp_gethostbyaddr(const char *ip); -int picotcp_close(int sock); -// set blocking -int picotcp_setblocking(int sock,int blocking); -int picotcp_join_multicast(int sock,const char* address,const char* local); - - -#endif
--- a/Socket/posix/stack_endpoint.cpp Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,456 +0,0 @@ -/********************************************************************* -PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. -See LICENSE and COPYING for usage. - -Authors: Daniele Lacamera -*********************************************************************/ - -#include "wrapper.h" -#include "rtos.h" -#include "cmsis_os.h" -#include "mbed.h" - -//#define ptsock_dbg printf -#define ptsock_dbg(...) - -int in_the_stack = 0; - -#define NO_COMMAND 0xFFFFu - -Thread * serverThread = NULL; -// global queue for open requests -Queue<struct stack_endpoint,10> openReqQueue; - -static inline void sendOpenResponse(struct stack_endpoint * arg) -{ - openReqQueue.put(arg); -} - -static inline uint16_t readSocketCommand(struct stack_endpoint * endp) -{ - osEvent event = endp->TxQueue.get(0); // Tx for Client, Rx for Me, non blocking - if(event.status == osEventMessage) - return *((uint16_t *)event.value.p); - - return NO_COMMAND; -} - -static inline void sendSocketResponse(struct stack_endpoint *endp) -{ - endp->RxQueue.put(&endp->reply); -} - -static int stack_compare(void *ka, void *kb) -{ - struct stack_endpoint *a = (struct stack_endpoint *)ka, *b = (struct stack_endpoint *)kb; - if (a->sock_fd < b->sock_fd) - return -1; - if (a->sock_fd > b->sock_fd) - return 1; - return 0; -} - -PICO_TREE_DECLARE(stack_ep_tree, stack_compare); - -struct stack_endpoint *pico_get_socket(uint16_t sockfd) -{ - struct stack_endpoint test; - test.sock_fd = sockfd; - return (struct stack_endpoint *)pico_tree_findKey(&stack_ep_tree, &test); -} - -static struct stack_endpoint *GET_SOCK_BY_PICOSOCK(struct pico_socket *s) -{ - struct pico_tree_node *index; - pico_tree_foreach(index,&stack_ep_tree) - { - if(s == index->keyValue) - return (struct stack_endpoint *)index->keyValue; - } - return NULL; -} - -static void stack_Add(struct stack_endpoint *ep) -{ - pico_tree_insert(&stack_ep_tree, ep); -} - -static void stack_Del(struct stack_endpoint *ep) -{ - pico_tree_delete(&stack_ep_tree, ep); -} - -static void status_pending_off(struct stack_endpoint *ep) -{ - ep->pending = NO_COMMAND; //no event -} - - -static int close_ep(struct stack_endpoint *ep){ - stack_Del(ep); - pico_free(ep); - return 0; -} - -static int send_wakeup(struct stack_endpoint *ep) -{ - int ret = 0; - if (ep->pending == NO_COMMAND) - return -1; - ep->reply = TOK_R_WAKEUP; - // send response - sendSocketResponse(ep); - return ret; -} - -static int send_wait(struct stack_endpoint *ep) -{ - int ret = 0; - if (!ep->pending) - return -1; - ep->reply = TOK_R_WAIT; - // send response - sendSocketResponse(ep); - return ret; -} - -static int send_error(struct stack_endpoint *ep) -{ - int ret = 0; - if (ep->pending == NO_COMMAND) - return -1; - - ep->reply = TOK_R_ERR; - ep->code = pico_err; - // send queue instead - sendSocketResponse(ep); - - status_pending_off(ep); - return ret; -} - -static int send_ok(struct stack_endpoint *ep) -{ - int ret = 0; - if (ep->pending == NO_COMMAND) - return -1; - - ep->reply = TOK_R_OK; - // send queue - sendSocketResponse(ep); - status_pending_off(ep); - return ret; -} - -static int send_data_end(struct stack_endpoint *ep) -{ - int ret = 0; - if (ep->pending == NO_COMMAND) - return -1; - ep->reply = TOK_R_DATA_END; - // send queue - sendSocketResponse(ep); - status_pending_off(ep); - return ret; -} - -//static int send_data(struct stack_endpoint *ep) -//{ -// int ret; -// if (!ep->pending) -// return -1; -// // send queue -// ep->reply = TOK_R_DATA; -// sendSocketResponse(ep); -// ret = vde_send(ep->vde, ep->pending, sizeof(struct token), 0); -// return ret; -//} - -static void retry_connect(struct stack_endpoint *ep) -{ - - if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) { - ep->revents &= (~PICO_SOCK_EV_CONN); - ep->revents |= PICO_SOCK_EV_WR; - ptsock_dbg("Established. sock state: %x\n", ep->s->state); - send_ok(ep); - }else { - pico_socket_connect(ep->s, &ep->addr, ep->port); - } -} - -static void retry_accept(struct stack_endpoint *ep) -{ - struct pico_ip4 peer ={}; - uint16_t port = 0; - - struct stack_endpoint *aep; - struct pico_socket *sa; - if (ep->revents & PICO_SOCK_EV_CONN) { - sa = pico_socket_accept(ep->s, &peer.addr, &port); - if (sa) { - aep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint)); - if (!aep) { - send_error(ep); - return; - } - - aep->sock_fd = (uint16_t)pico_rand(); - aep->s = sa; - aep->connected = 1; - aep->peer = peer; - aep->peer_port = port; - aep->addr = ep->addr;//copy parent's address - aep->pending = NO_COMMAND; - aep->revents |= PICO_SOCK_EV_WR; - stack_Add(aep); - ep->revents &= (~PICO_SOCK_EV_CONN); - // I don't think it's ok to set wr event for the listening socket - send_ok(ep); - } else { - send_error(ep); - } - } -} - -static void retry_close(struct stack_endpoint *ep) -{ - - if ((!ep->connected) || (ep->revents & PICO_SOCK_EV_CLOSE) || (ep->revents & PICO_SOCK_EV_FIN)) { - pico_socket_close(ep->s); - close_ep(ep); - } -} - -static void retry_write(struct stack_endpoint *ep) -{ - - if (ep->pending == NO_COMMAND) - return; - - if (!ep->buffer) { - send_error(ep); - return; - } - - if (ep->pending == TOK_SENDTO) { - ep->size = pico_socket_sendto(ep->s, ep->buffer, ep->size, &ep->addr, ep->port); - } else { - ep->size = pico_socket_write(ep->s, ep->buffer, ep->size); - } - ep->revents &= (~PICO_SOCK_EV_WR); - if (ep->size < 0) - send_error(ep); - else - send_data_end(ep); -} - -static void retry_read(struct stack_endpoint *ep) -{ - if (ep->pending == NO_COMMAND) - return; - - ptsock_dbg("in retry-read\n"); - - if (!ep->buffer) { - send_error(ep); - return; - } else { - if (ep->pending == TOK_RECVFROM) - ep->size = pico_socket_recvfrom(ep->s, ep->buffer, ep->size, &ep->addr, &ep->port); - else { - ep->size = pico_socket_read(ep->s, ep->buffer, ep->size); - } - } - if(ep->size <= 0) - ep->revents &= (~PICO_SOCK_EV_RD); - else - send_data_end(ep); - ptsock_dbg("STACK> sending 'DATA' (size = %d)\n", ep->size); - -} - -void retry_poll(struct stack_endpoint *ep) -{ - // todo: polling -} - -static void retry_token(struct stack_endpoint *ep) -{ - if (ep->pending == NO_COMMAND) - return; - ptsock_dbg("in retry-token, cmd: %04x\n", ep->pending); - switch(ep->pending) { - case TOK_POLL: - retry_poll(ep); - break; - case TOK_CONNECT: - retry_connect(ep); - break; - case TOK_ACCEPT: - retry_accept(ep); - break; - - case TOK_READ: - case TOK_RECV: - case TOK_RECVFROM: - retry_read(ep); - break; - - case TOK_WRITE: - case TOK_SEND: - case TOK_SENDTO: - retry_write(ep); - break; - - case TOK_CLOSE: - retry_close(ep); - break; - default: - break; - } -} - -static void wakeup(uint16_t ev, struct pico_socket *s) -{ - int t; - struct stack_endpoint *ep = GET_SOCK_BY_PICOSOCK(s); - - if (!ep) { - ptsock_dbg("WAKEUP: no socket :(\n"); - return; - } - t = ep->pending; - ptsock_dbg("Wake up event: %04x\n", ev); - ep->revents |= ev; - - if (ev & PICO_SOCK_EV_ERR) { - ep->revents = PICO_SOCK_EV_ERR; - send_error(ep); - return; - } - - if ((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) { - ep->connected = 0; - } - if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) { - if ((ev & PICO_SOCK_EV_CONN) && (ep->pending == TOK_CONNECT)) { - ptsock_dbg("** Connected\n"); - ep->connected = 1; - } - } - if (ev & PICO_SOCK_EV_WR) - ep->revents |= PICO_SOCK_EV_WR; - if (t) - retry_token(ep); -} - -static void timer_cb(unsigned long now, void * arg) -{ - struct stack_endpoint * endpoint = (struct stack_endpoint *)arg; - // check if the event was acknowledged so you don't send twice! - if(endpoint->pending != NO_COMMAND) //still waiting - { - endpoint->reply = TOK_R_TIO; - endpoint->pending = NO_COMMAND; - endpoint->RxQueue.put(&endpoint->reply); //release - } -} - -static int stack_parse_requests(void) -{ - uint16_t t;// command - struct stack_endpoint *ep = NULL; - osEvent event; // used to see the status of queue get - struct pico_tree_node * index = NULL; - uint16_t proto,net; - // first check if the global queue has something in it - // and open a new socket if so - do - { - stack_endpoint *stack_ep = NULL; - - event = openReqQueue.get(0); // non blocking get - if(event.status != osEventMessage) - break; - // open new socket and send the response - stack_ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint)); - t = *((uint16_t *)event.value.p); - if(!stack_ep) - { - ptsock_dbg("Out of memory\n"); - return -1; - } - - proto = ep->code & 0xFF; - net = ((((ep->code>>8) & 0xdd) == 0xdd)?PICO_PROTO_IPV6:PICO_PROTO_IPV4); - stack_ep->s = pico_socket_open( net,proto,&wakeup ); - if(!stack_ep->s) - { - pico_free(stack_ep); - ptsock_dbg("Out of memory\n"); - return -1; - } - - stack_ep->pending = NO_COMMAND; - stack_Add(stack_ep); - - // send the response back to the client - sendOpenResponse(stack_ep); - }while(event.status == osEventMessage); - - // go through all the sockets and check if there is a request from someone - // call to the qet function has timeout 0, must be non blocking - // if a request has come from someone parse it - pico_tree_foreach(index,&stack_ep_tree) - { - ep = (struct stack_endpoint *)index->keyValue; - // check if data has arrived - event = ep->TxQueue.get(0); // again non blocking - if(event.status == osEventMessage) - { - // check command sent - t = *((uint16_t *)event.value.p); - switch(t) - { - case TOK_BIND: - if(pico_socket_bind(ep->s, &ep->addr, &ep->port) == 0) - send_ok(ep); - else - send_error(ep); - break; - case TOK_LISTEN: - if(pico_socket_listen(ep->s, ep->size) == 0) - send_ok(ep); - else - send_error(ep); - break; - default: - ep->pending = t; - if(ep->timeout > 0) //make sure to set timeout to 0 when using blocking sockets - { - // start timer - pico_timer_add(ep->timeout,&timer_cb,(void *)ep); - } - retry_token(ep); - } - } - } - - return 0; -} - -void pico_wrapper_loop(const void * arg) -{ - (void)arg; - while(1) { - pico_stack_tick(); - // parse all requests - stack_parse_requests(); - } -} - -void pico_start_looping(void) -{ - serverThread = new Thread(pico_wrapper_loop); -} \ No newline at end of file
--- a/Socket/posix/wrapper.h Fri Jun 07 13:44:59 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -#ifndef ____WRAPPER_H -#define ____WRAPPER_H - -#ifdef __cplusplus -extern "C"{ -#endif - -#include "pico_ipv4.h" -#include "pico_ipv6.h" -#include "pico_stack.h" -#include "pico_socket.h" - -#ifdef __cplusplus -} -#endif - -#include "mbed.h" -#include "rtos.h" - -#define PT_MAX_SOCKETS 255 - -extern Queue<struct stack_endpoint,10> openReqQueue; - -#define TOK_OPEN 0x0000U -#define TOK_WRITE 0x0001U -#define TOK_READ 0x0002U -#define TOK_SEND 0x0005U -#define TOK_RECV 0x0006U -#define TOK_SENDTO 0x0009U -#define TOK_RECVFROM 0x000aU -#define TOK_LISTEN 0x0010U -#define TOK_CONNECT 0x0011U -#define TOK_ACCEPT 0x0012U -#define TOK_BIND 0x0020U -#define TOK_SETSOCKOPT 0x0031U -#define TOK_GETSOCKOPT 0x0032U -#define TOK_CLOSE 0x0040U -#define TOK_SHUTDOWN 0x0041U -#define TOK_POLL 0x0051U -#define TOK_POLL_END 0x0052U -#define TOK_DNS 0x0061U -#define TOK_DHCP_ENBL 0x0071U - -#define TOK_R_OK 0x0100U -#define TOK_R_WAKEUP 0x0200U -#define TOK_R_WAIT 0x0400U -#define TOK_R_DATA 0x8000U -#define TOK_R_DATA_END 0x8200U -#define TOK_R_TIO 0x8400U -#define TOK_R_ERR 0xFF00U - -// this is used to share memory between here and -// the Socket code, after opening the socket -// sockfd = globalQueue.get(); -// this->ep = pico_get_socket(sockfd); -struct stack_endpoint { - uint16_t sock_fd; - struct pico_socket *s; - int connected; - int revents; - Queue<uint16_t,1> RxQueue;//receive queue of 1 element of type uint16_t - Queue<uint16_t,1> TxQueue;//transmit queue of 1 element of type uint16_t - uint16_t pending; // pending command - // parameters - uint16_t reply; // response - struct pico_ip4 addr; // local address - struct pico_ip4 peer; // peer address - uint16_t peer_port; // peer port - uint16_t port; // local port - uint16_t code; // error code - uint16_t sockfd; // socket identifier - uint8_t * buffer; //buffer, used read/write functions - int size; // this is for read/write/listen commands - uint16_t timeout; // this is used for timeout sockets -}; - -#define MAXTOKEN 2000 -#define TOK_CMD(t) ((t->cmd & 0x00FF)) -#define TOK_R_CMD(t) ((t->cmd & 0xFF00)) -#define TOKEN_DATA_OFFSET (sizeof(struct token)) -#define MAXTOKEN_DATA (MAXTOKEN - TOKEN_DATA_OFFSET) -#define TOKEN_DATA_BUF(t) ((uint8_t *)(t + TOKEN_DATA_OFFSET)) - -void pico_wrapper_loop(void); -void pico_start_looping(void); -struct stack_endpoint *pico_get_socket(uint16_t sockfd); -#endif