Commit a33e3a4a authored by Vowstar's avatar Vowstar
Browse files

Merge pull request #687 from DiUS/dev140

Major upgrade to SDK 1.4.0 & open LWIP
parents 093a8959 8fba0f47
unsigned char default_private_key[] = {
0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcd,
0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76, 0xd4, 0x13, 0x30, 0x0e,
0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f, 0x51, 0x09, 0x9d, 0x29,
0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90, 0x80, 0xa1, 0x71, 0xdf,
0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14, 0x90, 0x0a, 0xf9, 0xb7,
0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d, 0x57, 0x41, 0x86, 0x60,
0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46, 0x1b, 0xf6, 0xa2, 0x84,
0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa, 0x91, 0xf8, 0x61, 0x04,
0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a, 0xcc, 0x31, 0x01, 0x14,
0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82, 0xd6, 0xc6, 0xc4, 0xbe,
0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32, 0x7a, 0x86, 0x0e, 0x91,
0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x81, 0x00, 0x95, 0xaa, 0x6e, 0x11, 0xf5, 0x6a, 0x8b, 0xa2,
0xc6, 0x48, 0xc6, 0x7c, 0x37, 0x6b, 0x1f, 0x55, 0x10, 0x76, 0x26, 0x24,
0xc3, 0xf2, 0x5c, 0x5a, 0xdd, 0x2e, 0xf3, 0xa4, 0x1e, 0xbc, 0x7b, 0x1c,
0x80, 0x10, 0x85, 0xbc, 0xd8, 0x45, 0x3c, 0xb8, 0xb2, 0x06, 0x53, 0xb5,
0xd5, 0x7a, 0xe7, 0x0e, 0x92, 0xe6, 0x42, 0xc2, 0xe2, 0x2a, 0xd5, 0xd1,
0x03, 0x9f, 0x6f, 0x53, 0x74, 0x68, 0x72, 0x8e, 0xbf, 0x03, 0xbb, 0xab,
0xbd, 0xa1, 0xf9, 0x81, 0x7d, 0x12, 0xd4, 0x9d, 0xb6, 0xae, 0x4c, 0xad,
0xca, 0xa8, 0xc9, 0x80, 0x8d, 0x0d, 0xd5, 0xd0, 0xa1, 0xbf, 0xec, 0x60,
0x48, 0x49, 0xed, 0x97, 0x0f, 0x5e, 0xed, 0xfc, 0x39, 0x15, 0x96, 0x9e,
0x5d, 0xe2, 0xb4, 0x5d, 0x2e, 0x04, 0xdc, 0x08, 0xa2, 0x65, 0x29, 0x2d,
0x37, 0xfb, 0x62, 0x90, 0x1b, 0x7b, 0xe5, 0x3a, 0x58, 0x05, 0x55, 0xc1,
0x02, 0x41, 0x00, 0xfc, 0x69, 0x28, 0xc9, 0xa8, 0xc4, 0x5c, 0xe3, 0xd0,
0x5e, 0xaa, 0xda, 0xde, 0x87, 0x74, 0xdb, 0xcb, 0x40, 0x78, 0x8e, 0x1d,
0x12, 0x96, 0x16, 0x61, 0x3f, 0xb3, 0x3e, 0xa3, 0x0d, 0xdc, 0x49, 0xa5,
0x25, 0x87, 0xc5, 0x97, 0x85, 0x9d, 0xbb, 0xb4, 0xf0, 0x44, 0xfd, 0x6c,
0xe8, 0xd2, 0x8c, 0xec, 0x33, 0x81, 0x46, 0x1e, 0x10, 0x12, 0x33, 0x16,
0x95, 0x00, 0x4f, 0x75, 0xb4, 0xe5, 0x79, 0x02, 0x41, 0x00, 0xd0, 0xeb,
0x65, 0x07, 0x10, 0x3b, 0xd9, 0x03, 0xeb, 0xdc, 0x6f, 0x4b, 0x8f, 0xc3,
0x87, 0xce, 0x76, 0xd6, 0xc5, 0x14, 0x21, 0x4e, 0xe7, 0x4f, 0x1b, 0xe8,
0x05, 0xf8, 0x84, 0x1a, 0xe0, 0xc5, 0xd6, 0xe3, 0x08, 0xb3, 0x54, 0x57,
0x02, 0x1f, 0xd4, 0xd9, 0xfb, 0xff, 0x40, 0xb1, 0x56, 0x1c, 0x60, 0xf7,
0xac, 0x91, 0xf3, 0xd3, 0xc6, 0x7f, 0x84, 0xfd, 0x84, 0x9d, 0xea, 0x26,
0xee, 0xc9, 0x02, 0x41, 0x00, 0xa6, 0xcf, 0x1c, 0x6c, 0x81, 0x03, 0x1c,
0x5c, 0x56, 0x05, 0x6a, 0x26, 0x70, 0xef, 0xd6, 0x13, 0xb7, 0x74, 0x28,
0xf7, 0xca, 0x50, 0xd1, 0x2d, 0x83, 0x21, 0x64, 0xe4, 0xdd, 0x3f, 0x38,
0xb8, 0xd6, 0xd2, 0x41, 0xb3, 0x1c, 0x9a, 0xea, 0x0d, 0xf5, 0xda, 0xdf,
0xcd, 0x17, 0x9f, 0x9a, 0x1e, 0x15, 0xaf, 0x48, 0x1c, 0xbd, 0x9b, 0x63,
0x5b, 0xad, 0xed, 0xd4, 0xa1, 0xae, 0xa9, 0x59, 0x09, 0x02, 0x40, 0x4e,
0x08, 0xce, 0xa8, 0x8f, 0xc0, 0xba, 0xf3, 0x83, 0x02, 0xc8, 0x33, 0x62,
0x14, 0x77, 0xc2, 0x7f, 0x93, 0x02, 0xf3, 0xdc, 0xe9, 0x1a, 0xee, 0xea,
0x8e, 0x84, 0xc4, 0x69, 0x9b, 0x9c, 0x7f, 0x69, 0x1f, 0x4e, 0x1d, 0xa5,
0x90, 0x06, 0x44, 0x1b, 0x7d, 0xfc, 0x69, 0x40, 0x21, 0xbc, 0xf7, 0x46,
0xa4, 0xdc, 0x39, 0x7b, 0xe8, 0x8b, 0x49, 0x10, 0x44, 0x9d, 0x67, 0x5a,
0x91, 0x86, 0x39, 0x02, 0x40, 0x41, 0x2c, 0x4e, 0xfe, 0xd9, 0x90, 0x89,
0x00, 0x5c, 0x94, 0x0a, 0x4a, 0x7e, 0x1b, 0x1a, 0x80, 0x06, 0x01, 0x37,
0xda, 0x50, 0x61, 0x9d, 0x9c, 0xfe, 0x25, 0x7f, 0xd8, 0xd4, 0xc4, 0x9e,
0x81, 0xf2, 0x0c, 0x1e, 0x38, 0x21, 0x1e, 0x90, 0x3f, 0xd4, 0xba, 0x6c,
0x53, 0xcb, 0xf0, 0x77, 0x79, 0x9b, 0xf1, 0xfa, 0x3f, 0x81, 0xdc, 0xf3,
0x21, 0x02, 0x6d, 0xb7, 0x95, 0xc3, 0x2e, 0xce, 0xd5
};
unsigned int default_private_key_len = 609;
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @mainpage axTLS API
*
* @image html axolotl.jpg
*
* The axTLS library has features such as:
* - The TLSv1 SSL client/server protocol
* - No requirement to use any openssl libraries.
* - A choice between AES block (128/256 bit) and RC4 (128 bit) stream ciphers.
* - RSA encryption/decryption with variable sized keys (up to 4096 bits).
* - Certificate chaining and peer authentication.
* - Session resumption, session renegotiation.
* - ASN.1, X.509, PKCS#8, PKCS#12 keys/certificates with DER/PEM encoding.
* - Highly configurable compile time options.
* - Portable across many platforms (written in ANSI C), and has language
* bindings in C, C#, VB.NET, Java, Perl and Lua.
* - Partial openssl API compatibility (via a wrapper).
* - A very small footprint (around 50-60kB for the library in 'server-only'
* mode).
* - No dependencies on sockets - can use serial connections for example.
* - A very simple API - ~ 20 functions/methods.
*
* A list of these functions/methods are described below.
*
* @ref c_api
*
* @ref bigint_api
*
* @ref csharp_api
*
* @ref java_api
*/
#ifndef HEADER_SSL_H
#define HEADER_SSL_H
#ifdef __cplusplus
extern "C" {
#endif
//#include <time.h>
typedef long time_t;
/* need to predefine before ssl_lib.h gets to it */
#define SSL_SESSION_ID_SIZE 32
#include "ssl/ssl_tls1.h"
/* The optional parameters that can be given to the client/server SSL engine */
#define SSL_CLIENT_AUTHENTICATION 0x00010000
#define SSL_SERVER_VERIFY_LATER 0x00020000
#define SSL_NO_DEFAULT_KEY 0x00040000
#define SSL_DISPLAY_STATES 0x00080000
#define SSL_DISPLAY_BYTES 0x00100000
#define SSL_DISPLAY_CERTS 0x00200000
#define SSL_DISPLAY_RSA 0x00400000
#define SSL_CONNECT_IN_PARTS 0x00800000
/* errors that can be generated */
#define SSL_OK 0
#define SSL_NOT_OK -1
#define SSL_ERROR_DEAD -2
#define SSL_CLOSE_NOTIFY -3
#define SSL_ERROR_CONN_LOST -256
#define SSL_ERROR_SOCK_SETUP_FAILURE -258
#define SSL_ERROR_INVALID_HANDSHAKE -260
#define SSL_ERROR_INVALID_PROT_MSG -261
#define SSL_ERROR_INVALID_HMAC -262
#define SSL_ERROR_INVALID_VERSION -263
#define SSL_ERROR_INVALID_SESSION -265
#define SSL_ERROR_NO_CIPHER -266
#define SSL_ERROR_BAD_CERTIFICATE -268
#define SSL_ERROR_INVALID_KEY -269
#define SSL_ERROR_FINISHED_INVALID -271
#define SSL_ERROR_NO_CERT_DEFINED -272
#define SSL_ERROR_NO_CLIENT_RENOG -273
#define SSL_ERROR_NOT_SUPPORTED -274
#define SSL_X509_OFFSET -512
#define SSL_X509_ERROR(A) (SSL_X509_OFFSET+A)
/* alert types that are recognized */
#define SSL_ALERT_TYPE_WARNING 1
#define SLL_ALERT_TYPE_FATAL 2
/* these are all the alerts that are recognized */
#define SSL_ALERT_CLOSE_NOTIFY 0
#define SSL_ALERT_UNEXPECTED_MESSAGE 10
#define SSL_ALERT_BAD_RECORD_MAC 20
#define SSL_ALERT_HANDSHAKE_FAILURE 40
#define SSL_ALERT_BAD_CERTIFICATE 42
#define SSL_ALERT_ILLEGAL_PARAMETER 47
#define SSL_ALERT_DECODE_ERROR 50
#define SSL_ALERT_DECRYPT_ERROR 51
#define SSL_ALERT_INVALID_VERSION 70
#define SSL_ALERT_NO_RENEGOTIATION 100
/* The ciphers that are supported */
#define SSL_AES128_SHA 0x2f
#define SSL_AES256_SHA 0x35
#define SSL_RC4_128_SHA 0x05
#define SSL_RC4_128_MD5 0x04
/* build mode ids' */
#define SSL_BUILD_SKELETON_MODE 0x01
#define SSL_BUILD_SERVER_ONLY 0x02
#define SSL_BUILD_ENABLE_VERIFICATION 0x03
#define SSL_BUILD_ENABLE_CLIENT 0x04
#define SSL_BUILD_FULL_MODE 0x05
/* offsets to retrieve configuration information */
#define SSL_BUILD_MODE 0
#define SSL_MAX_CERT_CFG_OFFSET 1
#define SSL_MAX_CA_CERT_CFG_OFFSET 2
#define SSL_HAS_PEM 3
/* default session sizes */
#define SSL_DEFAULT_SVR_SESS 1 //modify 5->1 by lhan
#define SSL_DEFAULT_CLNT_SESS 1
/* X.509/X.520 distinguished name types */
#define SSL_X509_CERT_COMMON_NAME 0
#define SSL_X509_CERT_ORGANIZATION 1
#define SSL_X509_CERT_ORGANIZATIONAL_NAME 2
#define SSL_X509_CA_CERT_COMMON_NAME 3
#define SSL_X509_CA_CERT_ORGANIZATION 4
#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME 5
/* SSL object loader types */
#define SSL_OBJ_X509_CERT 1
#define SSL_OBJ_X509_CACERT 2
#define SSL_OBJ_RSA_KEY 3
#define SSL_OBJ_PKCS8 4
#define SSL_OBJ_PKCS12 5
/**
* @defgroup c_api Standard C API
* @brief The standard interface in C.
* @{
*/
/**
* @brief Establish a new client/server context.
*
* This function is called before any client/server SSL connections are made.
*
* Each new connection will use the this context's private key and
* certificate chain. If a different certificate chain is required, then a
* different context needs to be be used.
*
* There are two threading models supported - a single thread with one
* SSL_CTX can support any number of SSL connections - and multiple threads can
* support one SSL_CTX object each (the default). But if a single SSL_CTX
* object uses many SSL objects in individual threads, then the
* CONFIG_SSL_CTX_MUTEXING option needs to be configured.
*
* @param options [in] Any particular options. At present the options
* supported are:
* - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if the server
* authentication fails. The certificate can be authenticated later with a
* call to ssl_verify_cert().
* - SSL_CLIENT_AUTHENTICATION (server only): Enforce client authentication
* i.e. each handshake will include a "certificate request" message from the
* server. Only available if verification has been enabled.
* - SSL_DISPLAY_BYTES (full mode build only): Display the byte sequences
* during the handshake.
* - SSL_DISPLAY_STATES (full mode build only): Display the state changes
* during the handshake.
* - SSL_DISPLAY_CERTS (full mode build only): Display the certificates that
* are passed during a handshake.
* - SSL_DISPLAY_RSA (full mode build only): Display the RSA key details that
* are passed during a handshake.
* - SSL_CONNECT_IN_PARTS (client only): To use a non-blocking version of
* ssl_client_new().
* @param num_sessions [in] The number of sessions to be used for session
* caching. If this value is 0, then there is no session caching. This option
* is not used in skeleton mode.
* @return A client/server context.
*/
EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions);
/**
* @brief Remove a client/server context.
*
* Frees any used resources used by this context. Each connection will be
* sent a "Close Notify" alert (if possible).
* @param ssl_ctx [in] The client/server context.
*/
EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
/**
* @brief (server only) Establish a new SSL connection to an SSL client.
*
* It is up to the application to establish the logical connection (whether it
* is a socket, serial connection etc).
* @param ssl_ctx [in] The server context.
* @param client_fd [in] The client's file descriptor.
* @return An SSL object reference.
*/
//EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
EXP_FUNC SSL *STDCALL sslserver_new(SSL_CTX *ssl_ctx, struct tcp_pcb* client_pcb);
/**
* @brief (client only) Establish a new SSL connection to an SSL server.
*
* It is up to the application to establish the initial logical connection
* (whether it is a socket, serial connection etc).
*
* This is a normally a blocking call - it will finish when the handshake is
* complete (or has failed). To use in non-blocking mode, set
* SSL_CONNECT_IN_PARTS in ssl_ctx_new().
* @param ssl_ctx [in] The client context.
* @param client_fd [in] The client's file descriptor.
* @param session_id [in] A 32 byte session id for session resumption. This
* can be null if no session resumption is being used or required. This option
* is not used in skeleton mode.
* @param sess_id_size The size of the session id (max 32)
* @return An SSL object reference. Use ssl_handshake_status() to check
* if a handshake succeeded.
*/
//EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size);
EXP_FUNC SSL *STDCALL SSLClient_new(SSL_CTX *ssl_ctx, struct tcp_pcb *SslClient_pcb, const
uint8_t *session_id, uint8_t sess_id_size);
/**
* @brief Free any used resources on this connection.
* A "Close Notify" message is sent on this connection (if possible). It is up
* to the application to close the socket or file descriptor.
* @param ssl [in] The ssl object reference.
*/
EXP_FUNC void STDCALL ssl_free(SSL *ssl);
/**
* @brief Read the SSL data stream.
* If the socket is non-blocking and data is blocked then SSO_OK will be
* returned.
* @param ssl [in] An SSL object reference.
* @param in_data [out] If the read was successful, a pointer to the read
* buffer will be here. Do NOT ever free this memory as this buffer is used in
* sucessive calls. If the call was unsuccessful, this value will be null.
* @return The number of decrypted bytes:
* - if > 0, then the handshaking is complete and we are returning the number
* of decrypted bytes.
* - SSL_OK if the handshaking stage is successful (but not yet complete).
* - < 0 if an error.
* @see ssl.h for the error code list.
* @note Use in_data before doing any successive ssl calls.
*/
EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
/**
* @brief Write to the SSL data stream.
* if the socket is non-blocking and data is blocked then a check is made
* to ensure that all data is sent (i.e. blocked mode is forced).
* @param ssl [in] An SSL obect reference.
* @param out_data [in] The data to be written
* @param out_len [in] The number of bytes to be written.
* @return The number of bytes sent, or if < 0 if an error.
* @see ssl.h for the error code list.
*/
EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len);
/**
* @brief Find an ssl object based on a file descriptor.
*
* Goes through the list of SSL objects maintained in a client/server context
* to look for a file descriptor match.
* @param ssl_ctx [in] The client/server context.
* @param client_fd [in] The file descriptor.
* @return A reference to the SSL object. Returns null if the object could not
* be found.
*/
EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, int client_fd);
/**
* @brief Get the session id for a handshake.
*
* This will be a 32 byte sequence and is available after the first
* handshaking messages are sent.
* @param ssl [in] An SSL object reference.
* @return The session id as a 32 byte sequence.
* @note A SSLv23 handshake may have only 16 valid bytes.
*/
EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl);
/**
* @brief Get the session id size for a handshake.
*
* This will normally be 32 but could be 0 (no session id) or something else.
* @param ssl [in] An SSL object reference.
* @return The size of the session id.
*/
EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl);
/**
* @brief Return the cipher id (in the SSL form).
* @param ssl [in] An SSL object reference.
* @return The cipher id. This will be one of the following:
* - SSL_AES128_SHA (0x2f)
* - SSL_AES256_SHA (0x35)
* - SSL_RC4_128_SHA (0x05)
* - SSL_RC4_128_MD5 (0x04)
*/
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
/**
* @brief Return the status of the handshake.
* @param ssl [in] An SSL object reference.
* @return SSL_OK if the handshake is complete and ok.
* @see ssl.h for the error code list.
*/
EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl);
/**
* @brief Retrieve various parameters about the axTLS engine.
* @param offset [in] The configuration offset. It will be one of the following:
* - SSL_BUILD_MODE The build mode. This will be one of the following:
* - SSL_BUILD_SERVER_ONLY (basic server mode)
* - SSL_BUILD_ENABLE_VERIFICATION (server can do client authentication)
* - SSL_BUILD_ENABLE_CLIENT (client/server capabilties)
* - SSL_BUILD_FULL_MODE (client/server with diagnostics)
* - SSL_BUILD_SKELETON_MODE (skeleton mode)
* - SSL_MAX_CERT_CFG_OFFSET The maximum number of certificates allowed.
* - SSL_MAX_CA_CERT_CFG_OFFSET The maximum number of CA certificates allowed.
* - SSL_HAS_PEM 1 if supported
* @return The value of the requested parameter.
*/
EXP_FUNC int STDCALL ssl_get_config(int offset);
/**
* @brief Display why the handshake failed.
*
* This call is only useful in a 'full mode' build. The output is to stdout.
* @param error_code [in] An error code.
* @see ssl.h for the error code list.
*/
//EXP_FUNC void STDCALL ssl_display_error(int error_code);
/**
* @brief Authenticate a received certificate.
*
* This call is usually made by a client after a handshake is complete and the
* context is in SSL_SERVER_VERIFY_LATER mode.
* @param ssl [in] An SSL object reference.
* @return SSL_OK if the certificate is verified.
*/
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
/**
* @brief Retrieve an X.509 distinguished name component.
*
* When a handshake is complete and a certificate has been exchanged, then the
* details of the remote certificate can be retrieved.
*
* This will usually be used by a client to check that the server's common
* name matches the URL.
*
* @param ssl [in] An SSL object reference.
* @param component [in] one of:
* - SSL_X509_CERT_COMMON_NAME
* - SSL_X509_CERT_ORGANIZATION
* - SSL_X509_CERT_ORGANIZATIONAL_NAME
* - SSL_X509_CA_CERT_COMMON_NAME
* - SSL_X509_CA_CERT_ORGANIZATION
* - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
* @return The appropriate string (or null if not defined)
* @note Verification build mode must be enabled.
*/
EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component);
/**
* @brief Retrieve a Subject Alternative DNSName
*
* When a handshake is complete and a certificate has been exchanged, then the
* details of the remote certificate can be retrieved.
*
* This will usually be used by a client to check that the server's DNS
* name matches the URL.
*
* @param ssl [in] An SSL object reference.
* @param dnsindex [in] The index of the DNS name to retrieve.
* @return The appropriate string (or null if not defined)
* @note Verification build mode must be enabled.
*/
EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int dnsindex);
/**
* @brief Force the client to perform its handshake again.
*
* For a client this involves sending another "client hello" message.
* For the server is means sending a "hello request" message.
*
* This is a blocking call on the client (until the handshake completes).
*
* @param ssl [in] An SSL object reference.
* @return SSL_OK if renegotiation instantiation was ok
*/
EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl);
/**
* @brief Process a file that is in binary DER or ASCII PEM format.
*
* These are temporary objects that are used to load private keys,
* certificates etc into memory.
* @param ssl_ctx [in] The client/server context.
* @param obj_type [in] The format of the file. Can be one of:
* - SSL_OBJ_X509_CERT (no password required)
* - SSL_OBJ_X509_CACERT (no password required)
* - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
* - SSL_OBJ_PKCS8 (RC4-128 encrypted data supported)
* - SSL_OBJ_PKCS12 (RC4-128 encrypted data supported)
*
* PEM files are automatically detected (if supported). The object type is
* also detected, and so is not relevant for these types of files.
* @param filename [in] The location of a file in DER/PEM format.
* @param password [in] The password used. Can be null if not required.
* @return SSL_OK if all ok
* @note Not available in skeleton build mode.
*/
EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, const char *filename, const char *password);
/**
* @brief Process binary data.
*
* These are temporary objects that are used to load private keys,
* certificates etc into memory.
* @param ssl_ctx [in] The client/server context.
* @param obj_type [in] The format of the memory data.
* @param data [in] The binary data to be loaded.
* @param len [in] The amount of data to be loaded.
* @param password [in] The password used. Can be null if not required.
* @return SSL_OK if all ok
* @see ssl_obj_load for more details on obj_type.
*/
EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int obj_type, const uint8_t *data, int len, const char *password);
#ifdef CONFIG_SSL_GENERATE_X509_CERT
/**
* @brief Create an X.509 certificate.
*
* This certificate is a self-signed v1 cert with a fixed start/stop validity
* times. It is signed with an internal private key in ssl_ctx.
*
* @param ssl_ctx [in] The client/server context.
* @param options [in] Not used yet.
* @param dn [in] An array of distinguished name strings. The array is defined
* by:
* - SSL_X509_CERT_COMMON_NAME (0)
* - If SSL_X509_CERT_COMMON_NAME is empty or not defined, then the
* hostname will be used.
* - SSL_X509_CERT_ORGANIZATION (1)
* - If SSL_X509_CERT_ORGANIZATION is empty or not defined, then $USERNAME
* will be used.
* - SSL_X509_CERT_ORGANIZATIONAL_NAME (2)
* - SSL_X509_CERT_ORGANIZATIONAL_NAME is optional.
* @param cert_data [out] The certificate as a sequence of bytes.
* @return < 0 if an error, or the size of the certificate in bytes.
* @note cert_data must be freed when there is no more need for it.
*/
EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data);
#endif
/**
* @brief Return the axTLS library version as a string.
*/
EXP_FUNC const char * STDCALL ssl_version(void);
/** @} */
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file tls1.h
*
* @brief The definitions for the TLS library.
*/
#ifndef HEADER_SSL_LIB_H
#define HEADER_SSL_LIB_H
#ifdef __cplusplus
extern "C" {
#endif
#include "c_types.h"
#include "ssl/ssl_version.h"
#include "ssl/ssl_config.h"
//#include "../crypto/os_int.h"
#include "ssl/ssl_crypto.h"
#include "ssl/ssl_crypto_misc.h"
#include "lwip/tcp.h"
#define SSL_PROTOCOL_MIN_VERSION 0x31 /* TLS v1.0 */
#define SSL_PROTOCOL_MINOR_VERSION 0x02 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_MAX 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION1_1 0x32 /* TLS v1.1 */
#define SSL_RANDOM_SIZE 32
#define SSL_SECRET_SIZE 48
#define SSL_FINISHED_HASH_SIZE 12
#define SSL_RECORD_SIZE 5
#define SSL_SERVER_READ 0
#define SSL_SERVER_WRITE 1
#define SSL_CLIENT_READ 2
#define SSL_CLIENT_WRITE 3
#define SSL_HS_HDR_SIZE 4
/* the flags we use while establishing a connection */
#define SSL_NEED_RECORD 0x0001
#define SSL_TX_ENCRYPTED 0x0002
#define SSL_RX_ENCRYPTED 0x0004
#define SSL_SESSION_RESUME 0x0008
#define SSL_IS_CLIENT 0x0010
#define SSL_HAS_CERT_REQ 0x0020
#define SSL_SENT_CLOSE_NOTIFY 0x0040
/* some macros to muck around with flag bits */
#define SET_SSL_FLAG(A) (ssl->flag |= A)
#define CLR_SSL_FLAG(A) (ssl->flag &= ~A)
#define IS_SET_SSL_FLAG(A) (ssl->flag & A)
#define MAX_KEY_BYTE_SIZE 512 /* for a 4096 bit key */
#define RT_MAX_PLAIN_LENGTH 4096
#define RT_EXTRA 1024
#define BM_RECORD_OFFSET 5
#ifdef CONFIG_SSL_SKELETON_MODE
#define NUM_PROTOCOLS 1
#else
#define NUM_PROTOCOLS 4
#endif
#define PARANOIA_CHECK(A, B) if (A < B) { \
ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
/* protocol types */
enum
{
PT_CHANGE_CIPHER_SPEC = 20,
PT_ALERT_PROTOCOL,
PT_HANDSHAKE_PROTOCOL,
PT_APP_PROTOCOL_DATA
};
/* handshaking types */
enum
{
HS_HELLO_REQUEST,
HS_CLIENT_HELLO,
HS_SERVER_HELLO,
HS_CERTIFICATE = 11,
HS_SERVER_KEY_XCHG,
HS_CERT_REQ,
HS_SERVER_HELLO_DONE,
HS_CERT_VERIFY,
HS_CLIENT_KEY_XCHG,
HS_FINISHED = 20
};
typedef struct
{
uint8_t cipher;
uint8_t key_size;
uint8_t iv_size;
uint8_t key_block_size;
uint8_t padding_size;
uint8_t digest_size;
hmac_func hmac;
crypt_func encrypt;
crypt_func decrypt;
} cipher_info_t;
struct _SSLObjLoader
{
uint8_t *buf;
int len;
};
typedef struct _SSLObjLoader SSLObjLoader;
typedef struct
{
time_t conn_time;
uint8_t session_id[SSL_SESSION_ID_SIZE];
uint8_t master_secret[SSL_SECRET_SIZE];
} SSL_SESSION;
typedef struct
{
uint8_t *buf;
int size;
} SSL_CERT;
typedef struct
{
MD5_CTX md5_ctx;
SHA1_CTX sha1_ctx;
uint8_t final_finish_mac[SSL_FINISHED_HASH_SIZE];
uint8_t *key_block;
uint8_t master_secret[SSL_SECRET_SIZE];
uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
uint16_t bm_proc_index;
} DISPOSABLE_CTX;
struct _SSL
{
uint32_t flag;
uint16_t need_bytes;
uint16_t got_bytes;
uint8_t record_type;
uint8_t cipher;
uint8_t sess_id_size;
uint8_t version;
uint8_t client_version;
sint16_t next_state;
sint16_t hs_status;
DISPOSABLE_CTX *dc; /* temporary data which we'll get rid of soon */
//int client_fd;
struct tcp_pcb *SslClient_pcb;//add by ives 12.12.2013
struct pbuf *ssl_pbuf;//add by ives 12.12.2013
const cipher_info_t *cipher_info;
void *encrypt_ctx;
void *decrypt_ctx;
uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA];
uint8_t *bm_data;
uint16_t bm_index;
uint16_t bm_read_index;
struct _SSL *next; /* doubly linked list */
struct _SSL *prev;
struct _SSL_CTX *ssl_ctx; /* back reference to a clnt/svr ctx */
#ifndef CONFIG_SSL_SKELETON_MODE
uint16_t session_index;
SSL_SESSION *session;
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
X509_CTX *x509_ctx;
#endif
uint8_t session_id[SSL_SESSION_ID_SIZE];
uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t read_sequence[8]; /* 64 bit sequence number */
uint8_t write_sequence[8]; /* 64 bit sequence number */
uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */
};
typedef struct _SSL SSL;
struct _SSL_CTX
{
uint32_t options;
uint8_t chain_length;
RSA_CTX *rsa_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION
CA_CERT_CTX *ca_cert_ctx;
#endif
SSL *head;
SSL *tail;
SSL_CERT certs[CONFIG_SSL_MAX_CERTS];
#ifndef CONFIG_SSL_SKELETON_MODE
uint16_t num_sessions;
SSL_SESSION **ssl_sessions;
#endif
#ifdef CONFIG_SSL_CTX_MUTEXING
SSL_CTX_MUTEX_TYPE mutex;
#endif
#ifdef CONFIG_OPENSSL_COMPATIBLE
void *bonus_attr;
#endif
};
typedef struct _SSL_CTX SSL_CTX;
/* backwards compatibility */
typedef struct _SSL_CTX SSLCTX;
extern const uint8_t ssl_prot_prefs[NUM_PROTOCOLS];
SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd);
SSL *ssl_new_context(SSL_CTX *ssl_ctx, struct tcp_pcb *SslClient_pcb);
void disposable_new(SSL *ssl);
void disposable_free(SSL *ssl);
int send_packet(SSL *ssl, uint8_t protocol,
const uint8_t *in, int length);
int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
int process_finished(SSL *ssl, uint8_t *buf, int hs_len);
int process_sslv23_client_hello(SSL *ssl);
int send_alert(SSL *ssl, int error_code);
int send_finished(SSL *ssl);
int send_certificate(SSL *ssl);
int basic_read(SSL *ssl, uint8_t **in_data);
int send_change_cipher_spec(SSL *ssl);
void finished_digest(SSL *ssl, const char *label, uint8_t *digest);
void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
void add_packet(SSL *ssl, const uint8_t *pkt, int len);
int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj);
void ssl_obj_free(SSLObjLoader *ssl_obj);
int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
int load_key_certs(SSL_CTX *ssl_ctx);
#ifdef CONFIG_SSL_CERT_VERIFICATION
int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx);
#endif
#ifdef CONFIG_SSL_ENABLE_CLIENT
int do_client_connect(SSL *ssl);
#endif
#ifdef CONFIG_SSL_FULL_MODE
//void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok);
//void DISPLAY_BYTES(SSL *ssl, const char *format,
// const uint8_t *data, int size, ...);
//void DISPLAY_CERT(SSL *ssl, const X509_CTX *x509_ctx);
//void DISPLAY_RSA(SSL *ssl, const RSA_CTX *rsa_ctx);
//void DISPLAY_ALERT(SSL *ssl, int alert);
#else
#define DISPLAY_STATE(A,B,C,D)
#define DISPLAY_CERT(A,B)
#define DISPLAY_RSA(A,B)
#define DISPLAY_ALERT(A, B)
#ifdef WIN32
void DISPLAY_BYTES(SSL *ssl, const char *format,/* win32 has no variadic macros */
const uint8_t *data, int size, ...);
#else
#define DISPLAY_BYTES(A,B,C,D,...)
#endif
#endif
#ifdef CONFIG_SSL_CERT_VERIFICATION
int process_certificate(SSL *ssl, X509_CTX **x509_ctx);
#endif
SSL_SESSION *ssl_session_update(int max_sessions,
SSL_SESSION *ssl_sessions[], SSL *ssl,
const uint8_t *session_id);
void kill_ssl_session(SSL_SESSION **ssl_sessions, SSL *ssl);
#ifdef __cplusplus
}
#endif
#endif
#define AXTLS_VERSION "1.4.9"
......@@ -58,9 +58,12 @@
#define LUA_OPTIMIZE_MEMORY 0
#endif /* LUA_OPTRAM */
#define READLINE_INTERVAL 80
#define LUA_TASK_PRIO USER_TASK_PRIO_0
#define LUA_PROCESS_LINE_SIG 2
#ifdef DEVKIT_VERSION_0_9
#define KEYLED_INTERVAL 80
#define KEY_SHORT_MS 200
#define KEY_LONG_MS 3000
#define KEY_SHORT_COUNT (KEY_SHORT_MS / READLINE_INTERVAL)
......
#ifndef __USER_VERSION_H__
#define __USER_VERSION_H__
#define NODE_VERSION_MAJOR 0U
#define NODE_VERSION_MINOR 9U
#define NODE_VERSION_REVISION 6U
#define NODE_VERSION_MAJOR 1U
#define NODE_VERSION_MINOR 4U
#define NODE_VERSION_REVISION 0U
#define NODE_VERSION_INTERNAL 0U
#define NODE_VERSION "NodeMCU 0.9.6"
#define BUILD_DATE "build 20150627"
#define NODE_VERSION "NodeMCU 1.4.0"
#ifndef BUILD_DATE
#define BUILD_DATE "20151006"
#endif
extern char SDK_VERSION[];
#endif /* __USER_VERSION_H__ */
......@@ -22,22 +22,12 @@
#include "os_type.h"
os_timer_t lua_timer;
LOCAL os_timer_t readline_timer;
lua_State *globalL = NULL;
lua_Load gLoad;
static const char *progname = LUA_PROGNAME;
#ifdef DEVKIT_VERSION_0_9
static int key_press_count = 0;
int led_high_count = LED_HIGH_COUNT_DEFAULT;
int led_low_count = LED_LOW_COUNT_DEFAULT;
static int led_count = 0;
#endif
#if 0
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
......@@ -135,9 +125,13 @@ static int docall (lua_State *L, int narg, int clear) {
}
static void print_version (void) {
// l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
l_message(NULL, "\n" NODE_VERSION " " BUILD_DATE " powered by " LUA_RELEASE);
static void print_version (lua_State *L) {
lua_pushliteral (L, "\n" NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE " on SDK ");
lua_pushstring (L, SDK_VERSION);
lua_concat (L, 2);
const char *msg = lua_tostring (L, -1);
l_message (NULL, msg);
lua_pop (L, 1);
}
......@@ -399,7 +393,7 @@ static int pmain (lua_State *L) {
lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
luaL_openlibs(L); /* open libraries */
lua_gc(L, LUA_GCRESTART, 0);
print_version();
print_version(L);
s->status = handle_luainit(L);
#if 0
if (s->status != 0) return 0;
......@@ -432,8 +426,8 @@ static int pmain (lua_State *L) {
return 0;
}
void dojob(lua_Load *load);
void readline(lua_Load *load);
static void dojob(lua_Load *load);
static bool readline(lua_Load *load);
char line_buffer[LUA_MAXINPUT];
#ifdef LUA_RPC
......@@ -461,10 +455,7 @@ int lua_main (int argc, char **argv) {
gLoad.line_position = 0;
gLoad.prmt = get_prompt(L, 1);
// dojob(&gLoad);
os_timer_disarm(&lua_timer);
os_timer_setfn(&lua_timer, (os_timer_func_t *)dojob, &gLoad);
os_timer_arm(&lua_timer, READLINE_INTERVAL, 0); // no repeat
dojob(&gLoad);
NODE_DBG("Heap size::%d.\n",system_get_free_heap_size());
legc_set_mode( L, EGC_ALWAYS, 4096 );
......@@ -473,16 +464,17 @@ int lua_main (int argc, char **argv) {
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
void lua_handle_input (bool force)
{
if (force || readline (&gLoad))
dojob (&gLoad);
}
void donejob(lua_Load *load){
lua_close(load->L);
}
#if 0
int log_fd = -1;
int noparse = 0;
#endif
void dojob(lua_Load *load){
static void dojob(lua_Load *load){
size_t l, rs;
int status;
char *b = load->line;
......@@ -538,53 +530,8 @@ void dojob(lua_Load *load){
load->done = 0;
load->line_position = 0;
c_memset(load->line, 0, load->len);
os_timer_disarm(&readline_timer);
os_timer_setfn(&readline_timer, (os_timer_func_t *)readline, load);
os_timer_arm(&readline_timer, READLINE_INTERVAL, 0); // no repeat
c_puts(load->prmt);
// NODE_DBG("dojob() is called with firstline.\n");
}
#ifdef DEVKIT_VERSION_0_9
extern void key_long_press(void *arg);
extern void key_short_press(void *arg);
static bool key_short_pressed = false;
static bool key_long_pressed = false;
void update_key_led(){
uint8_t temp = 1, level = 1;
led_count++;
if(led_count>led_low_count+led_high_count){
led_count = 0; // reset led_count, the level still high
} else if(led_count>led_low_count && led_count <=led_high_count+led_low_count){
level = 1; // output high level
} else if(led_count<=led_low_count){
level = 0; // output low level
}
temp = platform_key_led(level);
if(temp == 0){ // key is pressed
key_press_count++;
if(key_press_count>=KEY_LONG_COUNT){
// key_long_press(NULL);
key_long_pressed = true;
key_short_pressed = false;
// key_press_count = 0;
} else if(key_press_count>=KEY_SHORT_COUNT){ // < KEY_LONG_COUNT
// key_short_press(NULL);
key_short_pressed = true;
}
}else{ // key is released
key_press_count = 0;
if(key_long_pressed){
key_long_press(NULL);
key_long_pressed = false;
}
if(key_short_pressed){
key_short_press(NULL);
key_short_pressed = false;
}
}
}
#endif
#ifndef uart_putc
#define uart_putc uart0_putc
......@@ -594,11 +541,9 @@ extern bool uart0_echo;
extern bool run_input;
extern uint16_t need_len;
extern int16_t end_char;
void readline(lua_Load *load){
static bool readline(lua_Load *load){
// NODE_DBG("readline() is called.\n");
#ifdef DEVKIT_VERSION_0_9
update_key_led();
#endif
bool need_dojob = false;
char ch;
while (uart_getc(&ch))
{
......@@ -644,14 +589,9 @@ void readline(lua_Load *load){
{
/* Get a empty line, then go to get a new line */
c_puts(load->prmt);
os_timer_disarm(&readline_timer);
os_timer_setfn(&readline_timer, (os_timer_func_t *)readline, load);
os_timer_arm(&readline_timer, READLINE_INTERVAL, 0); // no repeat
} else {
load->done = 1;
os_timer_disarm(&lua_timer);
os_timer_setfn(&lua_timer, (os_timer_func_t *)dojob, load);
os_timer_arm(&lua_timer, READLINE_INTERVAL, 0); // no repeat
need_dojob = true;
}
continue;
}
......@@ -693,8 +633,6 @@ void readline(lua_Load *load){
uart_on_data_cb(load->line, load->line_position);
load->line_position = 0;
}
// if there is no input from user, repeat readline()
os_timer_disarm(&readline_timer);
os_timer_setfn(&readline_timer, (os_timer_func_t *)readline, load);
os_timer_arm(&readline_timer, READLINE_INTERVAL, 0); // no repeat
return need_dojob;
}
......@@ -382,6 +382,8 @@ typedef struct __lua_load{
int lua_main( int argc, char **argv );
void lua_handle_input (bool force);
/******************************************************************************
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
*
......
......@@ -10,23 +10,30 @@
#ifndef LWIP_OPEN_SRC
#include "net80211/ieee80211_var.h"
#endif
#include "user_interface.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////////////////
static uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
static u8_t old_xid[4] = {0};
static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
//static u8_t old_xid[4] = {0};
static const uint32 magic_cookie ICACHE_RODATA_ATTR = 0x63538263;
static struct udp_pcb *pcb_dhcps = NULL;
static struct ip_addr broadcast_dhcps;
static struct ip_addr server_address;
static struct ip_addr client_address;//added
static struct ip_addr client_address_plus;
static struct dhcps_msg msg_dhcps;
struct dhcps_state s;
static struct dhcps_lease dhcps_lease;
static bool dhcps_lease_flag = true;
//static bool dhcps_lease_flag = true;
static list_node *plist = NULL;
static uint8 offer = 0xFF;
static bool renew = false;
#define DHCPS_LEASE_TIME_DEF (120)
uint32 dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
/******************************************************************************
* FunctionName : node_insert_to_list
* Description : insert the node to the list
......@@ -36,17 +43,35 @@ static list_node *plist = NULL;
void ICACHE_FLASH_ATTR node_insert_to_list(list_node **phead, list_node* pinsert)
{
list_node *plist = NULL;
struct dhcps_pool *pdhcps_pool = NULL;
struct dhcps_pool *pdhcps_node = NULL;
if (*phead == NULL)
*phead = pinsert;
else {
plist = *phead;
pdhcps_node = pinsert->pnode;
pdhcps_pool = plist->pnode;
if(pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
pinsert->pnext = plist;
*phead = pinsert;
} else {
while (plist->pnext != NULL) {
pdhcps_pool = plist->pnext->pnode;
if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
pinsert->pnext = plist->pnext;
plist->pnext = pinsert;
break;
}
plist = plist->pnext;
}
if(plist->pnext == NULL) {
plist->pnext = pinsert;
}
pinsert->pnext = NULL;
}
}
// pinsert->pnext = NULL;
}
/******************************************************************************
......@@ -126,10 +151,10 @@ static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
*optptr++ = DHCP_OPTION_LEASE_TIME;
*optptr++ = 4;
*optptr++ = 0x00;
*optptr++ = 0x01;
*optptr++ = 0x51;
*optptr++ = 0x80;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 24) & 0xFF;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 16) & 0xFF;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 8) & 0xFF;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 0) & 0xFF;
*optptr++ = DHCP_OPTION_SERVER_ID;
*optptr++ = 4;
......@@ -138,14 +163,20 @@ static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
if (dhcps_router_enabled(offer)){
struct ip_info if_ip;
os_bzero(&if_ip, sizeof(struct ip_info));
wifi_get_ip_info(SOFTAP_IF, &if_ip);
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
*optptr++ = ip4_addr1( &if_ip.gw);
*optptr++ = ip4_addr2( &if_ip.gw);
*optptr++ = ip4_addr3( &if_ip.gw);
*optptr++ = ip4_addr4( &if_ip.gw);
}
#if USE_DNS
#ifdef USE_DNS
*optptr++ = DHCP_OPTION_DNS_SERVER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
......@@ -154,7 +185,7 @@ static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
*optptr++ = ip4_addr4( &ipadd);
#endif
#ifdef USE_CLASS_B_NET
#ifdef CLASS_B_NET
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
......@@ -172,7 +203,7 @@ static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
*optptr++ = DHCP_OPTION_INTERFACE_MTU;
*optptr++ = 2;
#ifdef USE_CLASS_B_NET
#ifdef CLASS_B_NET
*optptr++ = 0x05;
*optptr++ = 0xdc;
#else
......@@ -212,11 +243,6 @@ static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��DHCP msg�ṹ��
*
* @param -- m ָ�򴴽���DHCP msg�ṹ�����?
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
{
......@@ -228,7 +254,7 @@ static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
m->htype = DHCP_HTYPE_ETHERNET;
m->hlen = 6;
m->hops = 0;
os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
// os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
m->secs = 0;
m->flags = htons(BOOTP_BROADCAST);
......@@ -241,7 +267,7 @@ static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
os_memset((char *) m->file, 0, sizeof(m->file));
os_memset((char *) m->options, 0, sizeof(m->options));
os_memcpy((char *) m->options, (char *) magic_cookie, sizeof(magic_cookie));
os_memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie));
}
///////////////////////////////////////////////////////////////////////////////////
/*
......@@ -457,6 +483,7 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
{
struct ip_addr client;
bool is_dhcp_parse_end = false;
struct dhcps_state s;
client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP
......@@ -513,7 +540,11 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
case DHCPREQUEST://3
if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
if(renew == true) {
s.state = DHCPS_STATE_ACK;
} else {
s.state = DHCPS_STATE_NAK;
}
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_NAK\n");
#endif
......@@ -528,7 +559,7 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
break;
case DHCPRELEASE://7
s.state = DHCPS_STATE_IDLE;
s.state = DHCPS_STATE_RELEASE;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_IDLE\n");
#endif
......@@ -544,7 +575,7 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
{
if(os_memcmp((char *)m->options,
(char *)magic_cookie,
&magic_cookie,
sizeof(magic_cookie)) == 0){
#if DHCPS_DEBUG
os_printf("dhcps: len = %d\n", len);
......@@ -574,15 +605,19 @@ static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
* ��¼���ε�xid�ţ�ͬʱ�����IP����
*/
struct ip_addr addr_tmp;
os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
// os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
{
// {
struct dhcps_pool *pdhcps_pool = NULL;
list_node *pnode = NULL;
list_node *pback_node = NULL;
struct ip_addr first_address;
bool flag = false;
POOL_START:
// POOL_START:
first_address.addr = dhcps_lease.start_ip.addr;
client_address.addr = client_address_plus.addr;
renew = false;
// addr_tmp.addr = htonl(client_address_plus.addr);
// addr_tmp.addr++;
// client_address_plus.addr = htonl(addr_tmp.addr);
......@@ -590,8 +625,12 @@ static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
pdhcps_pool = pback_node->pnode;
if (os_memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0){
// os_printf("the same device request ip\n");
if (os_memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
renew = true;
}
client_address.addr = pdhcps_pool->ip.addr;
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pnode = pback_node;
goto POOL_CHECK;
} else if (pdhcps_pool->ip.addr == client_address_plus.addr){
// client_address.addr = client_address_plus.addr;
......@@ -601,25 +640,79 @@ static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
client_address_plus.addr = htonl(addr_tmp.addr);
client_address.addr = client_address_plus.addr;
}
if(flag == false) { // search the fisrt unused ip
if(first_address.addr < pdhcps_pool->ip.addr) {
flag = true;
} else {
addr_tmp.addr = htonl(first_address.addr);
addr_tmp.addr++;
first_address.addr = htonl(addr_tmp.addr);
}
}
}
if (client_address_plus.addr > dhcps_lease.end_ip.addr) {
client_address.addr = first_address.addr;
}
if (client_address.addr > dhcps_lease.end_ip.addr) {
client_address_plus.addr = dhcps_lease.start_ip.addr;
pdhcps_pool = NULL;
pnode = NULL;
} else {
pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
pdhcps_pool->ip.addr = client_address.addr;
os_memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
pnode = (list_node *)os_zalloc(sizeof(list_node ));
pnode->pnode = pdhcps_pool;
pnode->pnext = NULL;
node_insert_to_list(&plist,pnode);
if (client_address.addr == dhcps_lease.end_ip.addr) {
client_address_plus.addr = dhcps_lease.start_ip.addr;
} else {
addr_tmp.addr = htonl(client_address.addr);
addr_tmp.addr++;
client_address_plus.addr = htonl(addr_tmp.addr);
}
}
POOL_CHECK:
if ((client_address_plus.addr > dhcps_lease.end_ip) || (ip_addr_isany(&client_address))){
client_address_plus.addr = dhcps_lease.start_ip;
goto POOL_START;
if ((client_address.addr > dhcps_lease.end_ip.addr) || (ip_addr_isany(&client_address))){
os_printf("client_address_plus.addr %x %d\n", client_address_plus.addr, system_get_free_heap_size());
if(pnode != NULL) {
node_remove_from_list(&plist,pnode);
os_free(pnode);
pnode = NULL;
}
if (pdhcps_pool != NULL) {
os_free(pdhcps_pool);
pdhcps_pool = NULL;
}
// client_address_plus.addr = dhcps_lease.start_ip.addr;
return 4;
}
sint16_t ret = parse_options(&m->options[4], len);;
if(ret == DHCPS_STATE_RELEASE) {
if(pnode != NULL) {
node_remove_from_list(&plist,pnode);
os_free(pnode);
pnode = NULL;
}
if (pdhcps_pool != NULL) {
os_free(pdhcps_pool);
pdhcps_pool = NULL;
}
os_memset(&client_address,0x0,sizeof(client_address));
}
if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) {
return 0;
}
}
// }
#if DHCPS_DEBUG
os_printf("dhcps: xid changed\n");
......@@ -629,8 +722,7 @@ static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
// }
// }
return parse_options(&m->options[4], len);
return ret;
}
return 0;
}
......@@ -652,18 +744,24 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
struct ip_addr *addr,
uint16_t port)
{
sint16_t tlen;
u16_t i;
u16_t dhcps_msg_cnt=0;
u8_t *p_dhcps_msg = (u8_t *)&msg_dhcps;
u8_t *data;
struct dhcps_msg *pmsg_dhcps = NULL;
sint16_t tlen = 0;
u16_t i = 0;
u16_t dhcps_msg_cnt = 0;
u8_t *p_dhcps_msg = NULL;
u8_t *data = NULL;
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> receive a packet\n");
#endif
if (p==NULL) return;
pmsg_dhcps = (struct dhcps_msg *)os_zalloc(sizeof(struct dhcps_msg));
if (NULL == pmsg_dhcps){
pbuf_free(p);
return;
}
p_dhcps_msg = (u8_t *)pmsg_dhcps;
tlen = p->tot_len;
data = p->payload;
......@@ -672,7 +770,6 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
#endif
os_memset(&msg_dhcps, 0, sizeof(dhcps_msg));
for(i=0; i<p->len; i++){
p_dhcps_msg[dhcps_msg_cnt++] = data[i];
#if DHCPS_DEBUG
......@@ -709,25 +806,25 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
#endif
switch(parse_msg(&msg_dhcps, tlen - 240)) {
switch(parse_msg(pmsg_dhcps, tlen - 240)) {
case DHCPS_STATE_OFFER://1
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
#endif
send_offer(&msg_dhcps);
send_offer(pmsg_dhcps);
break;
case DHCPS_STATE_ACK://3
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
#endif
send_ack(&msg_dhcps);
send_ack(pmsg_dhcps);
break;
case DHCPS_STATE_NAK://4
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
#endif
send_nak(&msg_dhcps);
send_nak(pmsg_dhcps);
break;
default :
break;
......@@ -736,13 +833,34 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
#endif
pbuf_free(p);
os_free(pmsg_dhcps);
pmsg_dhcps = NULL;
}
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
{
uint32 softap_ip = 0,local_ip = 0;
uint32 start_ip = 0;
uint32 end_ip = 0;
// if (dhcps_lease_flag) {
if (dhcps_lease.enable == TRUE) {
softap_ip = htonl(ip);
start_ip = htonl(dhcps_lease.start_ip.addr);
end_ip = htonl(dhcps_lease.end_ip.addr);
/*config ip information can't contain local ip*/
if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
dhcps_lease.enable = FALSE;
} else {
/*config ip information must be in the same segment as the local ip*/
softap_ip >>= 8;
if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
|| (end_ip - start_ip > DHCPS_MAX_LEASE)) {
dhcps_lease.enable = FALSE;
}
}
}
if (dhcps_lease_flag) {
if (dhcps_lease.enable == FALSE) {
local_ip = softap_ip = htonl(ip);
softap_ip &= 0xFFFFFF00;
local_ip &= 0xFF;
......@@ -752,27 +870,36 @@ static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
local_ip ++;
os_bzero(&dhcps_lease, sizeof(dhcps_lease));
dhcps_lease.start_ip = softap_ip | local_ip;
dhcps_lease.end_ip = softap_ip | (local_ip + DHCPS_MAX_LEASE);
dhcps_lease.start_ip.addr = softap_ip | local_ip;
dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
}
dhcps_lease.start_ip = htonl(dhcps_lease.start_ip);
dhcps_lease.end_ip= htonl(dhcps_lease.end_ip);
// dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
// dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
// os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
}
///////////////////////////////////////////////////////////////////////////////////
void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
{
os_memset(&msg_dhcps, 0, sizeof(dhcps_msg));
struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
if(apnetif->dhcps_pcb != NULL) {
udp_remove(apnetif->dhcps_pcb);
}
pcb_dhcps = udp_new();
if (pcb_dhcps == NULL || info ==NULL) {
os_printf("dhcps_start(): could not obtain pcb\n");
}
apnetif->dhcps_pcb = pcb_dhcps;
IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
server_address = info->ip;
wifi_softap_init_dhcps_lease(server_address.addr);
client_address_plus.addr = dhcps_lease.start_ip;
client_address_plus.addr = dhcps_lease.start_ip.addr;
udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
udp_recv(pcb_dhcps, handle_dhcp, NULL);
......@@ -784,8 +911,16 @@ void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
void ICACHE_FLASH_ATTR dhcps_stop(void)
{
struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
udp_disconnect(pcb_dhcps);
udp_remove(pcb_dhcps);
// dhcps_lease_flag = true;
if(apnetif->dhcps_pcb != NULL) {
udp_remove(apnetif->dhcps_pcb);
apnetif->dhcps_pcb = NULL;
}
//udp_remove(pcb_dhcps);
list_node *pnode = NULL;
list_node *pback_node = NULL;
pnode = plist;
......@@ -800,42 +935,130 @@ void ICACHE_FLASH_ATTR dhcps_stop(void)
}
}
/******************************************************************************
* FunctionName : wifi_softap_set_dhcps_lease
* Description : set the lease information of DHCP server
* Parameters : please -- Additional argument to set the lease information,
* Little-Endian.
* Returns : true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
{
struct ip_info info;
uint32 softap_ip = 0;
if (please == NULL)
uint32 start_ip = 0;
uint32 end_ip = 0;
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED)
return false;
if(please->enable) {
os_bzero(&info, sizeof(struct ip_info));
wifi_get_ip_info(SOFTAP_IF, &info);
softap_ip = htonl(info.ip.addr);
please->start_ip = htonl(please->start_ip);
please->end_ip = htonl(please->end_ip);
start_ip = htonl(please->start_ip.addr);
end_ip = htonl(please->end_ip.addr);
/*config ip information can't contain local ip*/
if ((please->start_ip <= softap_ip) && (softap_ip <= please->end_ip))
if ((start_ip <= softap_ip) && (softap_ip <= end_ip))
return false;
/*config ip information must be in the same segment as the local ip*/
softap_ip >>= 8;
if ((please->start_ip >> 8 != softap_ip)
|| (please->end_ip >> 8 != softap_ip)) {
if ((start_ip >> 8 != softap_ip)
|| (end_ip >> 8 != softap_ip)) {
return false;
}
if (please->end_ip - please->start_ip > DHCPS_MAX_LEASE)
if (end_ip - start_ip > DHCPS_MAX_LEASE)
return false;
os_bzero(&dhcps_lease, sizeof(dhcps_lease));
dhcps_lease.start_ip = please->start_ip;
dhcps_lease.end_ip = please->end_ip;
dhcps_lease_flag = false;
// dhcps_lease.start_ip.addr = start_ip;
// dhcps_lease.end_ip.addr = end_ip;
dhcps_lease.start_ip.addr = please->start_ip.addr;
dhcps_lease.end_ip.addr = please->end_ip.addr;
}
dhcps_lease.enable = please->enable;
// dhcps_lease_flag = false;
return true;
}
/******************************************************************************
* FunctionName : wifi_softap_get_dhcps_lease
* Description : get the lease information of DHCP server
* Parameters : please -- Additional argument to get the lease information,
* Little-Endian.
* Returns : true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease(struct dhcps_lease *please)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (NULL == please)
return false;
// if (dhcps_lease_flag){
if (dhcps_lease.enable == FALSE){
if (wifi_softap_dhcps_status() == DHCP_STOPPED)
return false;
} else {
// os_bzero(please, sizeof(dhcps_lease));
// if (wifi_softap_dhcps_status() == DHCP_STOPPED){
// please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
// please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
// }
}
// if (wifi_softap_dhcps_status() == DHCP_STARTED){
// os_bzero(please, sizeof(dhcps_lease));
// please->start_ip.addr = dhcps_lease.start_ip.addr;
// please->end_ip.addr = dhcps_lease.end_ip.addr;
// }
please->start_ip.addr = dhcps_lease.start_ip.addr;
please->end_ip.addr = dhcps_lease.end_ip.addr;
return true;
}
static void ICACHE_FLASH_ATTR kill_oldest_dhcps_pool(void)
{
list_node *pre = NULL, *p = NULL;
list_node *minpre = NULL, *minp = NULL;
struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
pre = plist;
p = pre->pnext;
minpre = pre;
minp = p;
while (p != NULL){
pdhcps_pool = p->pnode;
pmin_pool = minp->pnode;
if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){
minp = p;
minpre = pre;
}
pre = p;
p = p->pnext;
}
minpre->pnext = minp->pnext;
os_free(minp->pnode);
minp->pnode = NULL;
os_free(minp);
minp = NULL;
}
void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
{
uint8 num_dhcps_pool = 0;
list_node *pback_node = NULL;
list_node *pnode = NULL;
struct dhcps_pool *pdhcps_pool = NULL;
......@@ -853,6 +1076,71 @@ void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
pback_node = NULL;
} else {
pnode = pnode ->pnext;
num_dhcps_pool ++;
}
}
if (num_dhcps_pool >= MAX_STATION_NUM)
kill_oldest_dhcps_pool();
}
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
{
bool offer_flag = true;
uint8 option = 0;
if (optarg == NULL && wifi_softap_dhcps_status() == false)
return false;
if (level <= OFFER_START || level >= OFFER_END)
return false;
switch (level){
case OFFER_ROUTER:
offer = (*(uint8 *)optarg) & 0x01;
offer_flag = true;
break;
default :
offer_flag = false;
break;
}
return offer_flag;
}
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease_time(uint32 minute)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
return false;
}
if(minute == 0) {
return false;
}
dhcps_lease_time = minute;
return true;
}
bool ICACHE_FLASH_ATTR wifi_softap_reset_dhcps_lease_time(void)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
return false;
}
dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
return true;
}
uint32 ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease_time(void) // minute
{
return dhcps_lease_time;
}
/******************************************************************************
* FunctionName : espconn_init
* Description : dummy the espconn_init
* Parameters : none
* Returns : none
*******************************************************************************/
void espconn_init()
{
// dummy function, do nothing.
}
......@@ -23,14 +23,19 @@
#include "lwip/app/espconn_tcp.h"
#include "lwip/app/espconn_udp.h"
#include "lwip/app/espconn.h"
#include "user_interface.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
espconn_msg *plink_active = NULL;
espconn_msg *pserver_list = NULL;
remot_info premot[5];
uint32 link_timer = 0;
remot_info premot[linkMax];
struct espconn_packet pktinfo[2];
static uint8 espconn_tcp_get_buf_count(espconn_buf *pesp_buf);
/******************************************************************************
* FunctionName : espconn_copy_partial
* Description : reconnect with host
......@@ -122,40 +127,129 @@ void ICACHE_FLASH_ATTR espconn_list_delete(espconn_msg **phead, espconn_msg* pde
}*/
}
/******************************************************************************
* FunctionName : espconn_pbuf_create
* Description : insert the node to the active connection list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_pbuf_create(espconn_buf **phead, espconn_buf* pinsert)
{
espconn_buf *plist = NULL;
if (*phead == NULL)
*phead = pinsert;
else {
plist = *phead;
while (plist->pnext != NULL) {
plist = plist->pnext;
}
plist->pnext = pinsert;
}
pinsert->pnext = NULL;
}
/******************************************************************************
* FunctionName : espconn_pbuf_delete
* Description : remove the node from the active connection list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_pbuf_delete(espconn_buf **phead, espconn_buf* pdelete)
{
espconn_buf *plist = NULL;
plist = *phead;
if (plist == NULL){
*phead = NULL;
} else {
if (plist == pdelete){
*phead = plist->pnext;
} else {
while (plist != NULL) {
if (plist->pnext == pdelete){
plist->pnext = pdelete->pnext;
}
plist = plist->pnext;
}
}
}
}
/******************************************************************************
* FunctionName : espconn_find_connection
* Description : Initialize the server: set up a listening PCB and bind it to
* the defined port
* Parameters : espconn -- the espconn used to build server
* Returns : none
* Returns : true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode)
{
espconn_msg *plist = NULL;
struct ip_addr ip_remot;
struct ip_addr ip_list;
plist = plink_active;
while(plist != NULL){
if (pespconn == plist->pespconn){
if (pespconn == NULL)
return false;
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (pespconn == plist->pespconn) {
*pnode = plist;
return true;
} else {
IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0], pespconn->proto.tcp->remote_ip[1],
pespconn->proto.tcp->remote_ip[2], pespconn->proto.tcp->remote_ip[3]);
}
}
IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0], plist->pcommon.remote_ip[1],
plist->pcommon.remote_ip[2], plist->pcommon.remote_ip[3]);
if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)){
/*find the active server node*/
for (plist = pserver_list; plist != NULL; plist = plist->pnext){
if (pespconn == plist->pespconn) {
if (pespconn->proto.tcp == NULL)
return false;
IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0],
pespconn->proto.tcp->remote_ip[1],
pespconn->proto.tcp->remote_ip[2],
pespconn->proto.tcp->remote_ip[3]);
if ((ip_remot.addr == IPADDR_ANY) || (pespconn->proto.tcp->remote_port == 0))
return false;
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0],
plist->pcommon.remote_ip[1], plist->pcommon.remote_ip[2],
plist->pcommon.remote_ip[3]);
if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)) {
*pnode = plist;
return true;
}
}
plist = plist ->pnext;
return false;
}
}
return false;
}
/******************************************************************************
* FunctionName : espconn_get_acticve_num
* Description : get the count of simulatenously active connections
* Parameters : type -- the type
* Returns : the count of simulatenously active connections
*******************************************************************************/
static uint8 ICACHE_FLASH_ATTR
espconn_get_acticve_num(uint8 type)
{
espconn_msg *plist = NULL;
uint8 num_tcp_active = 0;
for (plist = plink_active; plist != NULL; plist = plist->pnext) {
if (plist->pespconn != NULL && plist->pespconn->type == type) {
num_tcp_active++;
}
}
return num_tcp_active;
}
/******************************************************************************
* FunctionName : espconn_connect
* Description : The function given as the connect
......@@ -170,12 +264,18 @@ espconn_connect(struct espconn *espconn)
uint8 connect_status = 0;
sint8 value = ESPCONN_OK;
espconn_msg *plist = NULL;
remot_info *pinfo = NULL;
if (espconn == NULL) {
return ESPCONN_ARG;
} else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Check the active node count whether is the limit or not*/
if (espconn_get_acticve_num(ESPCONN_TCP) >= espconn_tcp_get_max_con())
return ESPCONN_ISCONN;
/*Check the IP address whether is zero or not in different mode*/
if (wifi_get_opmode() == ESPCONN_STA){
wifi_get_ip_info(STA_NETIF,&ipinfo);
if (ipinfo.ip.addr == 0){
......@@ -202,14 +302,17 @@ espconn_connect(struct espconn *espconn)
wifi_get_ip_info(STA_NETIF,&ipinfo);
if (ipinfo.ip.addr == 0)
return ESPCONN_RTE;
} else if (connect_status == STATION_IDLE){
return ESPCONN_RTE;
} else {
return connect_status;
}
}
}
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_TCP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){
if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){
return ESPCONN_ISCONN;
}
......@@ -239,8 +342,9 @@ espconn_create(struct espconn *espconn)
return ESPCONN_ARG;
}
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_UDP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){
if (espconn->proto.udp->local_port == plist->pespconn->proto.udp->local_port){
return ESPCONN_ISCONN;
}
......@@ -265,34 +369,156 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
{
espconn_msg *pnode = NULL;
bool value = false;
if (espconn == NULL) {
err_t error = ESPCONN_OK;
if (espconn == NULL || psent == NULL || length == 0) {
return ESPCONN_ARG;
}
espconn ->state = ESPCONN_WRITE;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value){
espconn ->state = ESPCONN_WRITE;
switch (espconn ->type) {
case ESPCONN_TCP:
// if (value && (pnode->pcommon.write_len == pnode->pcommon.write_total)){
if (value && (pnode->pcommon.cntr == 0)){
espconn_tcp_sent(pnode, psent, length);
}else
/* calling sent function frequently,make sure last packet has been backup or sent fully*/
if (pnode->pcommon.write_flag){
espconn_buf *pbuf = NULL;
/*If total number of espconn_buf on the unsent lists exceeds the set maximum, return an error */
if (espconn_copy_enabled(pnode)){
if (espconn_tcp_get_buf_count(pnode->pcommon.pbuf) >= pnode ->pcommon.pbuf_num)
return ESPCONN_MAXNUM;
} else {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (pcb->snd_queuelen >= TCP_SND_QUEUELEN)
return ESPCONN_MAXNUM;
}
pbuf = (espconn_buf*) os_zalloc(sizeof(espconn_buf));
if (pbuf == NULL)
return ESPCONN_MEM;
else {
/*Backup the application packet information for send more data*/
pbuf->payload = psent;
pbuf->punsent = pbuf->payload;
pbuf->unsent = length;
pbuf->len = length;
/*insert the espconn_pbuf to the list*/
espconn_pbuf_create(&pnode->pcommon.pbuf, pbuf);
if (pnode->pcommon.ptail == NULL)
pnode->pcommon.ptail = pbuf;
}
/*when set the data copy option. change the flag for next packet*/
if (espconn_copy_disabled(pnode))
pnode->pcommon.write_flag = false;
error = espconn_tcp_write(pnode);
// if (error != ESPCONN_OK){
// /*send the application packet fail,
// * ensure that each allocated is deleted*/
// espconn_pbuf_delete(&pnode->pcommon.pbuf, pbuf);
// os_free(pbuf);
// pbuf = NULL;
// }
return error;
} else
return ESPCONN_ARG;
break;
case ESPCONN_UDP: {
if (value)
espconn_udp_sent(pnode, psent, length);
else
return ESPCONN_ARG;
case ESPCONN_UDP:
return espconn_udp_sent(pnode, psent, length);
break;
}
default :
break;
}
}
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_sendto
* Description : send data for UDP
* Parameters : espconn -- espconn to set for UDP
* psent -- data to send
* length -- length of data to send
* Returns : error
*******************************************************************************/
sint16 ICACHE_FLASH_ATTR
espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length)
{
espconn_msg *pnode = NULL;
bool value = false;
err_t error = ESPCONN_OK;
if (espconn == NULL || psent == NULL || length == 0) {
return ESPCONN_ARG;
}
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn->type == ESPCONN_UDP)
return espconn_udp_sendto(pnode, psent, length);
else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_send
* Description : sent data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length) __attribute__((alias("espconn_sent")));
/******************************************************************************
* FunctionName : espconn_tcp_get_wnd
* Description : get the window size of simulatenously active TCP connections
* Parameters : none
* Returns : the number of TCP_MSS active TCP connections
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_wnd(void)
{
uint8 tcp_num = 0;
tcp_num = (TCP_WND / TCP_MSS);
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_con
* Description : set the window size simulatenously active TCP connections
* Parameters : num -- the number of TCP_MSS
* Returns : ESPCONN_ARG -- Illegal argument
* ESPCONN_OK -- No error
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_wnd(uint8 num)
{
if (num == 0 || num > linkMax)
return ESPCONN_ARG;
TCP_WND = (num * TCP_MSS);
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_mss
* Description : get the mss size of simulatenously active TCP connections
* Parameters : none
* Returns : the size of TCP_MSS active TCP connections
*******************************************************************************/
uint16 ICACHE_FLASH_ATTR espconn_tcp_get_mss(void)
{
uint16 tcp_num = 0;
tcp_num = TCP_MSS;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_con
* Description : get the number of simulatenously active TCP connections
......@@ -316,13 +542,73 @@ uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con(void)
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con(uint8 num)
{
if (num == 0)
if (num == 0 || num > linkMax)
return ESPCONN_ARG;
MEMP_NUM_TCP_PCB = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_retran
* Description : get the Maximum number of retransmissions of data active TCP connections
* Parameters : none
* Returns : the Maximum number of retransmissions
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_retran(void)
{
uint8 tcp_num = 0;
tcp_num = TCP_MAXRTX;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_retran
* Description : set the Maximum number of retransmissions of data active TCP connections
* Parameters : num -- the Maximum number of retransmissions
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_retran(uint8 num)
{
if (num == 0 || num > 12)
return ESPCONN_ARG;
TCP_MAXRTX = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_syn
* Description : get the Maximum number of retransmissions of SYN segments
* Parameters : none
* Returns : the Maximum number of retransmissions
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_syn(void)
{
uint8 tcp_num = 0;
tcp_num = TCP_SYNMAXRTX;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_syn
* Description : set the Maximum number of retransmissions of SYN segments
* Parameters : num -- the Maximum number of retransmissions
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_syn(uint8 num)
{
if (num == 0 || num > 12)
return ESPCONN_ARG;
TCP_SYNMAXRTX = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_con_allow
* Description : get the count of simulatenously active connections on the server
......@@ -368,6 +654,51 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con_allow(struct espconn *espconn, u
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_buf_count
* Description : set the total number of espconn_buf on the unsent lists for one
* activate connection
* Parameters : espconn -- espconn to set the count
* num -- the total number of espconn_buf
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_buf_count(struct espconn *espconn, uint8 num)
{
espconn_msg *plist = NULL;
if (espconn == NULL || (num > TCP_SND_QUEUELEN))
return ESPCONN_ARG;
/*find the node from the active connection list*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn && plist->pespconn == espconn && espconn->type == ESPCONN_TCP){
plist->pcommon.pbuf_num = num;
return ESPCONN_OK;
}
}
if (plist == NULL)
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_buf_count
* Description : get the count of the current node which has espconn_buf
* Parameters : pesp_buf -- the list head of espconn_buf type
* Returns : the count of the current node which has espconn_buf
*******************************************************************************/
static uint8 ICACHE_FLASH_ATTR espconn_tcp_get_buf_count(espconn_buf *pesp_buf)
{
espconn_buf *pbuf_list = pesp_buf;
uint8 pbuf_num = 0;
/*polling the list get the count of the current node*/
while (pbuf_list != NULL){
pbuf_list = pbuf_list->pnext;
pbuf_num ++;
}
return pbuf_num;
}
/******************************************************************************
* FunctionName : espconn_regist_sentcb
* Description : Used to specify the function that should be called when data
......@@ -388,6 +719,26 @@ espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb)
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_regist_sentcb
* Description : Used to specify the function that should be called when data
* has been successfully delivered to the remote host.
* Parameters : espconn -- espconn to set the sent callback
* sent_cb -- sent callback function to call for this espconn
* when data is successfully sent
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_regist_write_finish(struct espconn *espconn, espconn_connect_callback write_finish_fn)
{
if (espconn == NULL || espconn ->proto.tcp == NULL || espconn->type == ESPCONN_UDP) {
return ESPCONN_ARG;
}
espconn ->proto.tcp->write_finish_fn = write_finish_fn;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_regist_connectcb
* Description : used to specify the function that should be called when
......@@ -484,35 +835,19 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui
switch (pespconn->type){
case ESPCONN_TCP:
while(plist != NULL){
if ((plist->pespconn->type == ESPCONN_TCP) && (plist->preverse == pespconn)){
switch (typeflags){
case ESPCONN_SSL:
if (plist->pssl != NULL){
if (plist->preverse == pespconn){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
break;
case ESPCONN_NORM:
if (plist->pssl == NULL){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
break;
default:
break;
}
}
plist = plist->pnext;
}
break;
case ESPCONN_UDP:
while(plist != NULL){
if (plist->pespconn->type == ESPCONN_UDP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
......@@ -545,8 +880,9 @@ espconn_accept(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_TCP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){
if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){
return ESPCONN_ISCONN;
}
......@@ -567,11 +903,13 @@ espconn_accept(struct espconn *espconn)
sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 type_flag)
{
espconn_msg *pnode = NULL;
espconn_msg *ptime_msg = NULL;
bool value = false;
if ((espconn == NULL) || (type_flag > 0x01))
return ESPCONN_ARG;
if (type_flag == 0x01){
/*set the timeout time for one active connection of the server*/
value = espconn_find_connection(espconn, &pnode);
if (value){
pnode->pcommon.timeout = interval;
......@@ -579,10 +917,17 @@ sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 inte
} else
return ESPCONN_ARG;
} else {
link_timer = interval;
os_printf("espconn_regist_time %d\n", link_timer);
/*set the timeout time for all active connection of the server*/
ptime_msg = pserver_list;
while (ptime_msg != NULL){
if (ptime_msg->pespconn == espconn){
ptime_msg->pcommon.timeout = interval;
return ESPCONN_OK;
}
ptime_msg = ptime_msg->pnext;
}
}
return ESPCONN_ARG;
}
/******************************************************************************
......@@ -602,41 +947,233 @@ espconn_disconnect(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value){
/*protect for redisconnection*/
if (espconn->state == ESPCONN_CLOSE)
return ESPCONN_INPROGRESS;
espconn_tcp_disconnect(pnode);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_get_packet_info
* Description : get the packet info with host
* Parameters : espconn -- the espconn used to disconnect the connection
* infoarg -- the packet info
* Returns : the errur code
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg)
{
espconn_msg *pnode = NULL;
err_t err;
bool value = false;
if (espconn == NULL || infoarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (pcb == NULL)
return ESPCONN_ARG;
pnode->pcommon.packet_info.packseq_nxt = pcb->rcv_nxt;
pnode->pcommon.packet_info.packseqno = pcb->snd_nxt;
pnode->pcommon.packet_info.snd_buf_size = pcb->snd_buf;
pnode->pcommon.packet_info.total_queuelen = TCP_SND_QUEUELEN;
pnode->pcommon.packet_info.snd_queuelen = pnode->pcommon.packet_info.total_queuelen - pcb->snd_queuelen;
os_memcpy(infoarg,(void*)&pnode->pcommon.packet_info, sizeof(struct espconn_packet));
return ESPCONN_OK;
} else {
switch (espconn->state){
case ESPCONN_CLOSE:
os_memcpy(infoarg,(void*)&pktinfo[0], sizeof(struct espconn_packet));
err = ESPCONN_OK;
break;
case ESPCONN_NONE:
os_memcpy(infoarg,(void*)&pktinfo[1], sizeof(struct espconn_packet));
err = ESPCONN_OK;
break;
default:
err = ESPCONN_ARG;
break;
}
return err;
}
}
/******************************************************************************
* FunctionName : espconn_set_opt
* Description : access port value for client so that we don't end up bouncing
* Description : set the option for connections so that we don't end up bouncing
* all connections at the same time .
* Parameters : none
* Returns : access port value
* Parameters : espconn -- the espconn used to set the connection
* opt -- the option for set
* Returns : the result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_set_opt(struct espconn *espconn, uint8 opt)
{
espconn_msg *pnode = NULL;
struct tcp_pcb *tpcb;
bool value = false;
if (espconn == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
pnode->pcommon.espconn_opt |= opt;
tpcb = pnode->pcommon.pcb;
if (espconn_delay_disabled(pnode))
tcp_nagle_disable(tpcb);
if (espconn_keepalive_disabled(pnode))
espconn_keepalive_enable(tpcb);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_clear_opt
* Description : clear the option for connections so that we don't end up bouncing
* all connections at the same time .
* Parameters : espconn -- the espconn used to set the connection
* opt -- the option for clear
* Returns : the result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_clear_opt(struct espconn *espconn, uint8 opt)
{
espconn_msg *pnode = NULL;
struct tcp_pcb *tpcb;
bool value = false;
if (espconn == NULL || opt > ESPCONN_END) {
if (espconn == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
pnode->pcommon.espconn_opt = opt;
pnode->pcommon.espconn_opt &= ~opt;
tpcb = pnode->pcommon.pcb;
if (espconn_keepalive_enabled(pnode))
espconn_keepalive_disable(tpcb);
if (espconn_delay_enabled(pnode))
tcp_nagle_enable(tpcb);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_set_keepalive
* Description : access level value for connection so that we set the value for
* keep alive
* Parameters : espconn -- the espconn used to set the connection
* level -- the connection's level
* value -- the value of time(s)
* Returns : access port value
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg)
{
espconn_msg *pnode = NULL;
bool value = false;
sint8 ret = ESPCONN_OK;
if (espconn == NULL || optarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
switch (level){
case ESPCONN_KEEPIDLE:
pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPINTVL:
pcb->keep_intvl = 1000 * (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPCNT:
pcb->keep_cnt = (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
default:
ret = ESPCONN_ARG;
break;
}
return ret;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_get_keepalive
* Description : access level value for connection so that we get the value for
* keep alive
* Parameters : espconn -- the espconn used to get the connection
* level -- the connection's level
* Returns : access keep alive value
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg)
{
espconn_msg *pnode = NULL;
bool value = false;
sint8 ret = ESPCONN_OK;
if (espconn == NULL || optarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
switch (level) {
case ESPCONN_KEEPIDLE:
*(int*)optarg = (int)(pcb->keep_idle/1000);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPINTVL:
*(int*)optarg = (int)(pcb->keep_intvl/1000);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPCNT:
*(int*)optarg = (int)(pcb->keep_cnt);
ret = ESPCONN_OK;
break;
default:
ret = ESPCONN_ARG;
break;
}
return ret;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_delete
* Description : disconnect with host
......@@ -654,6 +1191,7 @@ espconn_delete(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_UDP)
return espconn_tcp_delete(espconn);
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value){
......@@ -670,7 +1208,8 @@ espconn_delete(struct espconn *espconn)
* Parameters : none
* Returns : access port value
*******************************************************************************/
uint32 espconn_port(void)
uint32 ICACHE_FLASH_ATTR
espconn_port(void)
{
uint32 port = 0;
static uint32 randnum = 0;
......@@ -718,32 +1257,17 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t
return dns_gethostbyname(hostname, addr, found, pespconn);
}
sint8 espconn_recv_hold(struct espconn *pespconn) {
espconn_msg *pnode = NULL;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
pespconn->state = ESPCONN_WRITE;
if (!espconn_find_connection(pespconn, &pnode)) {
return ESPCONN_ARG;
}
espconn_tcp_hold(pnode);
return ESPCONN_OK;
/******************************************************************************
* FunctionName : espconn_dns_setserver
* Description : Initialize one of the DNS servers.
* Parameters : numdns -- the index of the DNS server to set must
* be < DNS_MAX_SERVERS = 2
* dnsserver -- IP address of the DNS server to set
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
{
dns_setserver(numdns,dnsserver);
}
sint8 espconn_recv_unhold(struct espconn *pespconn) {
espconn_msg *pnode = NULL;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
pespconn->state = ESPCONN_WRITE;
if (!espconn_find_connection(pespconn, &pnode)) {
return ESPCONN_ARG;
}
espconn_tcp_unhold(pnode);
return ESPCONN_OK;
}
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: espconn_mdns.c
*
* Description: udp proto interface
*
* Modification history:
* 2014/3/31, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "os_type.h"
#include "lwip/mdns.h"
/******************************************************************************
* FunctionName : espconn_mdns_enable
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_enable(void)
{
mdns_enable();
}
/******************************************************************************
* FunctionName : espconn_mdns_disable
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_disable(void)
{
mdns_disable();
}
/******************************************************************************
* FunctionName : espconn_mdns_set_hostname
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_set_hostname(char *name)
{
mdns_set_hostname(name);
}
/******************************************************************************
* FunctionName : espconn_mdns_init
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
char* ICACHE_FLASH_ATTR
espconn_mdns_get_hostname(void)
{
return (char *)mdns_get_hostname();
}
/******************************************************************************
* FunctionName : espconn_mdns_get_servername
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_set_servername(const char *name)
{
mdns_set_servername(name);
}
/******************************************************************************
* FunctionName : espconn_mdns_get_servername
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
char* ICACHE_FLASH_ATTR
espconn_mdns_get_servername(void)
{
return (char *)mdns_get_servername();
}
/******************************************************************************
* FunctionName : mdns_server_register
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_server_register(void)
{
mdns_server_register();
}
/******************************************************************************
* FunctionName : mdns_server_register
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_server_unregister(void)
{
mdns_server_unregister();
}
/******************************************************************************
* FunctionName : espconn_mdns_init
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_close(void)
{
mdns_close();
}
/******************************************************************************
* FunctionName : espconn_mdns_init
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_init(struct mdns_info *info)
{
mdns_init(info);
}
......@@ -24,9 +24,16 @@
#include "lwip/mem.h"
#include "lwip/app/espconn_tcp.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
extern espconn_msg *plink_active;
extern uint32 link_timer;
extern espconn_msg *pserver_list;
extern struct espconn_packet pktinfo[2];
extern struct tcp_pcb ** const tcp_pcb_lists[];
os_event_t espconn_TaskQueue[espconn_TaskQueueLen];
static err_t
espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
......@@ -39,6 +46,178 @@ static void
espconn_server_close(void *arg, struct tcp_pcb *pcb);
///////////////////////////////common function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_kill_oldest
* Description : kill the oldest TCP block
* Parameters : none
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_kill_oldest(void)
{
struct tcp_pcb *pcb, *inactive;
u32_t inactivity;
inactivity = 0;
inactive = NULL;
/* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
if (inactive != NULL) {
tcp_abort(inactive);
}
/* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */
inactivity = 0;
inactive = NULL;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->state == FIN_WAIT_1 || pcb->state == FIN_WAIT_2){
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
}
/*Purges the PCB, removes it from a PCB list and frees the memory*/
if (inactive != NULL) {
tcp_pcb_remove(&tcp_active_pcbs, inactive);
memp_free(MEMP_TCP_PCB, inactive);
}
/* Go through the list of LAST_ACK pcbs and get the oldest pcb. */
inactivity = 0;
inactive = NULL;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->state == LAST_ACK) {
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
}
/*Purges the PCB, removes it from a PCB list and frees the memory*/
if (inactive != NULL) {
tcp_pcb_remove(&tcp_active_pcbs, inactive);
memp_free(MEMP_TCP_PCB, inactive);
}
}
/******************************************************************************
* FunctionName : espconn_kill_oldest_pcb
* Description : find the oldest TCP block by state
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_kill_oldest_pcb(void)
{
struct tcp_pcb *cpcb = NULL;
uint8 i = 0;
uint8 num_tcp_fin = 0;
for(i = 2; i < 4; i ++){
for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
if (cpcb->state == TIME_WAIT){
num_tcp_fin ++;
if (num_tcp_fin == MEMP_NUM_TCP_PCB)
break;
}
if (cpcb->state == FIN_WAIT_1 || cpcb->state == FIN_WAIT_2 || cpcb->state == LAST_ACK){
num_tcp_fin++;
if (num_tcp_fin == MEMP_NUM_TCP_PCB)
break;
}
}
if (num_tcp_fin == MEMP_NUM_TCP_PCB){
num_tcp_fin = 0;
espconn_kill_oldest();
} else if (cpcb == NULL){
num_tcp_fin = 0;
}
}
}
/******************************************************************************
* FunctionName : espconn_kill_pcb
* Description : kill all the TCP block by port
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_kill_pcb(u16_t port)
{
struct tcp_pcb *cpcb = NULL;
uint8 i = 0;
struct tcp_pcb *inactive = NULL;
struct tcp_pcb *prev = NULL;
u8_t pcb_remove;
/* Check if the address already is in use (on all lists) */
for (i = 1; i < 4; i++) {
cpcb = *tcp_pcb_lists[i];
while(cpcb != NULL){
pcb_remove = 0;
if (cpcb->local_port == port) {
++pcb_remove;
}
/* If the PCB should be removed, do it. */
if (pcb_remove) {
/* Remove PCB from tcp_pcb_lists list. */
inactive = cpcb;
cpcb = inactive->next;
tcp_pcb_remove(tcp_pcb_lists[i], inactive);
memp_free(MEMP_TCP_PCB, inactive);
} else {
cpcb = cpcb->next;
}
}
}
}
/******************************************************************************
* FunctionName : espconn_find_current_pcb
* Description : find the TCP block which option
* Parameters : pcurrent_msg -- the node in the list which active
* Returns : TCP block point
*******************************************************************************/
struct tcp_pcb *ICACHE_FLASH_ATTR espconn_find_current_pcb(espconn_msg *pcurrent_msg)
{
uint16 local_port = pcurrent_msg->pcommon.local_port;
uint32 local_ip = pcurrent_msg->pcommon.local_ip;
uint16 remote_port = pcurrent_msg->pcommon.remote_port;
uint32 remote_ip = *((uint32*)&pcurrent_msg->pcommon.remote_ip);
struct tcp_pcb *find_pcb = NULL;
if (pcurrent_msg ->preverse == NULL){/*Find the server's TCP block*/
if (local_ip == 0|| local_port == 0) return pcurrent_msg->pcommon.pcb;
for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) &&
(find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip))
return find_pcb;
}
for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) &&
(find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip))
return find_pcb;
}
} else {/*Find the client's TCP block*/
if (remote_ip == 0|| remote_port == 0) return pcurrent_msg->pcommon.pcb;
for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip))
return find_pcb;
}
for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip))
return find_pcb;
}
}
return NULL;
}
/******************************************************************************
* FunctionName : espconn_tcp_reconnect
......@@ -51,11 +230,14 @@ espconn_tcp_reconnect(void *arg)
{
espconn_msg *precon_cb = arg;
sint8 re_err = 0;
espconn_buf *perr_buf = NULL;
espconn_buf *perr_back = NULL;
espconn_kill_oldest_pcb();
if (precon_cb != NULL) {
struct espconn *espconn = precon_cb->preverse;
re_err = precon_cb->pcommon.err;
if (precon_cb->pespconn != NULL){
if (espconn != NULL){
if (espconn != NULL){/*Process the server's message block*/
if (precon_cb->pespconn->proto.tcp != NULL){
espconn_copy_partial(espconn, precon_cb->pespconn);
espconn_printf("server: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->remote_ip[0],
......@@ -66,17 +248,28 @@ espconn_tcp_reconnect(void *arg)
}
os_free(precon_cb->pespconn);
precon_cb->pespconn = NULL;
} else {
} else {/*Process the client's message block*/
espconn = precon_cb->pespconn;
espconn_printf("client: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->local_ip[0],
espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
}
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
perr_buf = precon_cb->pcommon.pbuf;
while (perr_buf != NULL){
perr_back = perr_buf;
perr_buf = perr_back->pnext;
espconn_pbuf_delete(&precon_cb->pcommon.pbuf,perr_back);
os_free(perr_back);
perr_back = NULL;
}
os_bzero(&pktinfo[1], sizeof(struct espconn_packet));
os_memcpy(&pktinfo[1], (void*)&precon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
os_free(precon_cb);
precon_cb = NULL;
if (espconn->proto.tcp->reconnect_callback != NULL) {
if (espconn && espconn->proto.tcp && espconn->proto.tcp->reconnect_callback != NULL) {
espconn->proto.tcp->reconnect_callback(espconn, re_err);
}
} else {
......@@ -95,14 +288,17 @@ espconn_tcp_disconnect_successful(void *arg)
{
espconn_msg *pdiscon_cb = arg;
sint8 dis_err = 0;
espconn_buf *pdis_buf = NULL;
espconn_buf *pdis_back = NULL;
espconn_kill_oldest_pcb();
if (pdiscon_cb != NULL) {
struct espconn *espconn = pdiscon_cb->preverse;
dis_err = pdiscon_cb->pcommon.err;
if (pdiscon_cb->pespconn != NULL){
struct tcp_pcb *pcb = NULL;
if (espconn != NULL){
if (pdiscon_cb->pespconn->proto.tcp != NULL){
if (espconn != NULL){/*Process the server's message block*/
if (pdiscon_cb->pespconn->proto.tcp != NULL && espconn->proto.tcp){
espconn_copy_partial(espconn, pdiscon_cb->pespconn);
espconn_printf("server: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2],
......@@ -112,27 +308,69 @@ espconn_tcp_disconnect_successful(void *arg)
}
os_free(pdiscon_cb->pespconn);
pdiscon_cb->pespconn = NULL;
} else {
} else {/*Process the client's message block*/
espconn = pdiscon_cb->pespconn;
espconn_printf("client: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->local_ip[0],
espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
}
pcb = pdiscon_cb->pcommon.pcb;
/*process the current TCP block*/
pcb = espconn_find_current_pcb(pdiscon_cb);
if (pcb != NULL){
if (espconn_reuse_disabled(pdiscon_cb)) {
struct tcp_pcb *cpcb = NULL;
struct tcp_pcb *prev = NULL;
u8_t pcb_remove;
espconn_printf("espconn_tcp_disconnect_successful %d, %d\n", pcb->state, pcb->local_port);
cpcb = tcp_tw_pcbs;
while (cpcb != NULL) {
pcb_remove = 0;
if (cpcb->local_port == pcb->local_port) {
++pcb_remove;
}
/* If the PCB should be removed, do it. */
if (pcb_remove) {
struct tcp_pcb *backup_pcb = NULL;
tcp_pcb_purge(cpcb);
/* Remove PCB from tcp_tw_pcbs list. */
if (prev != NULL) {
LWIP_ASSERT("espconn_tcp_delete: middle cpcb != tcp_tw_pcbs",cpcb != tcp_tw_pcbs);
prev->next = cpcb->next;
} else {
/* This PCB was the first. */
LWIP_ASSERT("espconn_tcp_delete: first cpcb == tcp_tw_pcbs",tcp_tw_pcbs == cpcb);
tcp_tw_pcbs = cpcb->next;
}
backup_pcb = cpcb;
cpcb = cpcb->next;
memp_free(MEMP_TCP_PCB, backup_pcb);
} else {
prev = cpcb;
cpcb = cpcb->next;
}
}
} else {
tcp_arg(pcb, NULL);
tcp_err(pcb, NULL);
/*delete TIME_WAIT State pcb after 2MSL time,for not all data received by application.*/
if (pdiscon_cb->pcommon.espconn_opt == ESPCONN_REUSEADDR){
if (pcb->state == TIME_WAIT){
tcp_pcb_remove(&tcp_tw_pcbs,pcb);
memp_free(MEMP_TCP_PCB,pcb);
}
}
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
pdis_buf = pdiscon_cb->pcommon.pbuf;
while (pdis_buf != NULL) {
pdis_back = pdis_buf;
pdis_buf = pdis_back->pnext;
espconn_pbuf_delete(&pdiscon_cb->pcommon.pbuf, pdis_back);
os_free(pdis_back);
pdis_back = NULL;
}
os_bzero(&pktinfo[0], sizeof(struct espconn_packet));
os_memcpy(&pktinfo[0], (void*)&pdiscon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
os_free(pdiscon_cb);
pdiscon_cb = NULL;
if (espconn->proto.tcp->disconnect_callback != NULL) {
if (espconn->proto.tcp && espconn->proto.tcp->disconnect_callback != NULL) {
espconn->proto.tcp->disconnect_callback(espconn);
}
} else {
......@@ -140,15 +378,59 @@ espconn_tcp_disconnect_successful(void *arg)
}
}
/******************************************************************************
* FunctionName : espconn_Task
* Description : espconn processing task
* Parameters : events -- contain the espconn processing data
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_Task(os_event_t *events)
{
espconn_msg *task_msg = NULL;
struct espconn *pespconn = NULL;
task_msg = (espconn_msg *) events->par;
switch (events->sig) {
case SIG_ESPCONN_WRITE: {
pespconn = task_msg->pespconn;
if (pespconn == NULL) {
return;
}
if (pespconn->proto.tcp->write_finish_fn != NULL) {
pespconn->proto.tcp->write_finish_fn(pespconn);
}
}
break;
case SIG_ESPCONN_ERRER:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_reconnect(task_msg);
break;
case SIG_ESPCONN_CLOSE:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_disconnect_successful(task_msg);
break;
default:
break;
}
}
/******************************************************************************
* FunctionName : espconn_tcp_sent
* Description : sent data for client or server
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
* Returns : return espconn error code.
* - ESPCONN_OK. Successful. No error occured.
* - ESPCONN_MEM. Out of memory.
* - ESPCONN_RTE. Could not find route to destination address.
* - More errors could be returned by lower protocol layers.
*******************************************************************************/
void ICACHE_FLASH_ATTR
err_t ICACHE_FLASH_ATTR
espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
{
espconn_msg *ptcp_sent = arg;
......@@ -159,10 +441,12 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
espconn_printf("espconn_tcp_sent ptcp_sent %p psent %p length %d\n", ptcp_sent, psent, length);
/*Check the parameters*/
if (ptcp_sent == NULL || psent == NULL || length == 0) {
return;
return ESPCONN_ARG;
}
/*Set the packet length depend on the sender buffer space*/
pcb = ptcp_sent->pcommon.pcb;
if (tcp_sndbuf(pcb) < length) {
len = tcp_sndbuf(pcb);
......@@ -175,8 +459,12 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
len = 2*pcb->mss;
}
/*Write data for sending, but does not send it immediately*/
do {
espconn_printf("espconn_tcp_sent writing %d bytes %p\n", len, pcb);
if (espconn_copy_disabled(ptcp_sent))
err = tcp_write(pcb, psent, len, 1);
else
err = tcp_write(pcb, psent, len, 0);
if (err == ERR_MEM) {
......@@ -184,19 +472,21 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
}
} while (err == ERR_MEM && len > 1);
/*Find out what we can send and send it, offset the buffer point for next send*/
if (err == ERR_OK) {
data_to_send = true;
ptcp_sent->pcommon.ptrbuf = psent + len;
ptcp_sent->pcommon.cntr = length - len;
ptcp_sent->pcommon.write_len += len;
espconn_printf("espconn_tcp_sent sending %d bytes, remain %d\n", len, ptcp_sent->pcommon.cntr);
}
if (data_to_send == true) {
ptcp_sent->pcommon.ptail->punsent = psent + len;
ptcp_sent->pcommon.ptail->unsent = length - len;
err = tcp_output(pcb);
} else {
ptcp_sent->pespconn ->state = ESPCONN_CLOSE;
/*If enable the copy option, change the flag for next write*/
if (espconn_copy_disabled(ptcp_sent)){
if (ptcp_sent->pcommon.ptail->unsent == 0) {
ptcp_sent->pcommon.write_flag = true;
ets_post(espconn_TaskPrio, SIG_ESPCONN_WRITE, (uint32_t)ptcp_sent);
}
}
espconn_printf("espconn_tcp_sent %d\n", err);
}
return err;
}
/******************************************************************************
......@@ -208,45 +498,17 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
void ICACHE_FLASH_ATTR espconn_tcp_disconnect(espconn_msg *pdiscon)
{
if (pdiscon != NULL){
/*disconnect with the host by send the FIN frame*/
if (pdiscon->preverse != NULL)
espconn_server_close(pdiscon, pdiscon->pcommon.pcb);
else
espconn_client_close(pdiscon, pdiscon->pcommon.pcb);
} else{
espconn_printf("espconn_server_disconnect err.\n");
espconn_printf("espconn_tcp_disconnect err.\n");
}
}
///////////////////////////////client function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_close
* Description : The connection has been successfully closed.
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_cclose_cb(void *arg)
{
espconn_msg *pclose_cb = arg;
if (pclose_cb == NULL) {
return;
}
struct tcp_pcb *pcb = pclose_cb->pcommon.pcb;
espconn_printf("espconn_close %d %d\n", pcb->state, pcb->nrtx);
if (pcb->state == TIME_WAIT || pcb->state == CLOSED) {
pclose_cb ->pespconn ->state = ESPCONN_CLOSE;
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pclose_cb);
espconn_tcp_disconnect_successful((void*)pclose_cb);
} else {
os_timer_arm(&pclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
}
}
/******************************************************************************
* FunctionName : espconn_client_close
* Description : The connection shall be actively closed.
......@@ -260,12 +522,10 @@ espconn_client_close(void *arg, struct tcp_pcb *pcb)
err_t err;
espconn_msg *pclose = arg;
os_timer_disarm(&pclose->pcommon.ptimer);
pclose->pcommon.pcb = pcb;
/*avoid recalling the disconnect function*/
tcp_recv(pcb, NULL);
err = tcp_close(pcb);
os_timer_setfn(&pclose->pcommon.ptimer, espconn_cclose_cb, pclose);
os_timer_arm(&pclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
if (err != ERR_OK) {
/* closing failed, try again later */
......@@ -273,9 +533,69 @@ espconn_client_close(void *arg, struct tcp_pcb *pcb)
} else {
/* closing succeeded */
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
/*switch the state of espconn for application process*/
pclose->pespconn->state = ESPCONN_CLOSE;
ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)pclose);
}
}
//***********Code for WIFI_BLOCK from upper**************
sint8 ICACHE_FLASH_ATTR
espconn_recv_hold(struct espconn *pespconn)
{
//1st, according to espconn code, have to find out the escpconn_msg by pespconn;
espconn_msg *pnode = NULL;
bool value = false;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
value = espconn_find_connection(pespconn, &pnode);
if(value != true)
{
os_printf("RecvHold, By pespconn,find conn_msg fail\n");
return ESPCONN_ARG;
}
//2nd, the actual operation
if(pnode->recv_hold_flag == 0)
{
pnode->recv_hold_flag = 1;
pnode->recv_holded_buf_Len = 0;
}
return ESPCONN_OK;
}
sint8 ICACHE_FLASH_ATTR
espconn_recv_unhold(struct espconn *pespconn)
{
//1st, according to espconn code, have to find out the escpconn_msg by pespconn;
espconn_msg *pnode = NULL;
bool value = false;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
value = espconn_find_connection(pespconn, &pnode);
if(value != true)
{
os_printf("RecvHold, By pespconn,find conn_msg fail\n");
return ESPCONN_ARG;
}
//2nd, the actual operation
if(pnode->recv_hold_flag == 1)
{
if(pespconn->type == ESPCONN_TCP) {
tcp_recved(pnode->pcommon.pcb, pnode->recv_holded_buf_Len);
}
pnode->recv_holded_buf_Len = 0;
pnode->recv_hold_flag = 0;
}
return ESPCONN_OK;
}
//***********Code for WIFI_BLOCK from upper**************
/******************************************************************************
* FunctionName : espconn_client_recv
* Description : Data has been received on this pcb.
......@@ -293,25 +613,35 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
tcp_arg(pcb, arg);
if (p != NULL) {
tcp_recved(pcb, p ->tot_len);
/*To update and advertise a larger window*/
if(precv_cb->recv_hold_flag == 0)
tcp_recved(pcb, p->tot_len);
else
precv_cb->recv_holded_buf_Len += p->tot_len;
}
if (err == ERR_OK && p != NULL) {
char *pdata = NULL;
u16_t length = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
pdata = (char *)os_zalloc(p ->tot_len + 1);
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
pbuf_free(p);
if (length != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb;
if (precv_cb->pespconn->recv_callback != NULL) {
precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length);
}
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pdata);
pdata = NULL;
}
......@@ -324,68 +654,93 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
}
/******************************************************************************
* FunctionName : espconn_client_sent
* Description : Data has been sent and acknowledged by the remote host.
* This means that more data can be sent.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
* FunctionName : espconn_tcp_write
* Description : write the packet which in the active connection's list.
* Parameters : arg -- the node pointer which reverse the packet
* Returns : ESPCONN_MEM: memory error
* ESPCONN_OK:have enough space for write packet
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
err_t ICACHE_FLASH_ATTR espconn_tcp_write(void *arg)
{
espconn_msg *psent_cb = arg;
psent_cb->pcommon.pcb = pcb;
psent_cb->pcommon.write_total += len;
espconn_printf("espconn_client_sent sent %d %d\n", len, psent_cb->pcommon.write_total);
if (psent_cb->pcommon.write_total == psent_cb->pcommon.write_len){
psent_cb->pcommon.write_total = 0;
psent_cb->pcommon.write_len = 0;
if (psent_cb->pcommon.cntr == 0) {
psent_cb->pespconn->state = ESPCONN_CONNECT;
espconn_msg *pwrite = arg;
err_t err = ERR_OK;
struct tcp_pcb *pcb = pwrite->pcommon.pcb;
/*for one active connection,limit the sender buffer space*/
if (tcp_nagle_disabled(pcb) && (pcb->snd_queuelen >= TCP_SND_QUEUELEN))
return ESPCONN_MEM;
if (psent_cb->pespconn->sent_callback != NULL) {
psent_cb->pespconn->sent_callback(psent_cb->pespconn);
while (tcp_sndbuf(pcb) != 0){
if (pwrite->pcommon.ptail != NULL) {
/*Find the node whether in the list's tail or not*/
if (pwrite->pcommon.ptail->unsent == 0) {
pwrite->pcommon.ptail = pwrite->pcommon.ptail->pnext;
continue;
}
/*Send the packet for the active connection*/
err = espconn_tcp_sent(pwrite, pwrite->pcommon.ptail->punsent,pwrite->pcommon.ptail->unsent);
if (err != ERR_OK)
break;
} else
espconn_tcp_sent(psent_cb, psent_cb->pcommon.ptrbuf, psent_cb->pcommon.cntr);
} else {
break;
}
return err;
}
/******************************************************************************
* FunctionName : espconn_tcp_reconnect
* Description : reconnect with host
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR espconn_tcp_finish(void *arg)
{
espconn_msg *pfinish = arg;
espconn_buf *premove = NULL;
uint16 len = 0;
espconn_tcp_write(pfinish);
while (pfinish->pcommon.pbuf != NULL){
premove = pfinish->pcommon.pbuf;
pfinish->pcommon.pbuf->tot_len += len;
/*application packet has been sent and acknowledged by the remote host,
* to prevent memory leaks, ensure that each allocated is deleted*/
if (premove->tot_len >= premove->len){
espconn_pbuf_delete(&pfinish->pcommon.pbuf,premove);
len = premove->tot_len - premove->len;
pfinish->pcommon.packet_info.sent_length = premove->len;
os_free(premove);
premove = NULL;
pfinish->pespconn->state = ESPCONN_CONNECT;
if (pfinish->pespconn->sent_callback != NULL) {
pfinish->pespconn->sent_callback(pfinish->pespconn);
}
pfinish->pcommon.packet_info.sent_length = len;
} else
break;
}
return ERR_OK;
}
/******************************************************************************
* FunctionName : espconn_client_poll
* Description : The poll function is called every 2nd second.
* If there has been no data sent (which resets the retries) in 8 seconds, close.
* If the last portion of a file has not been sent in 2 seconds, close.
*
* This could be increased, but we don't want to waste resources for bad connections.
* FunctionName : espconn_client_sent
* Description : Data has been sent and acknowledged by the remote host.
* This means that more data can be sent.
* Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_client_poll(void *arg, struct tcp_pcb *pcb)
espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
espconn_msg *ppoll_cb = arg;
espconn_printf("espconn_client_poll pcb %p %p %d\n", pcb, arg, pcb->state);
if (arg == NULL) {
tcp_abandon(pcb, 0);
tcp_poll(pcb, NULL, 0);
return ERR_ABRT;
}
ppoll_cb->pcommon.pcb = pcb;
if (pcb->state == ESTABLISHED) {
} else {
tcp_poll(pcb, espconn_client_poll, 0);
espconn_client_close(ppoll_cb->pespconn, pcb);
}
espconn_msg *psent_cb = arg;
psent_cb->pcommon.pcb = pcb;
psent_cb->pcommon.pbuf->tot_len += len;
psent_cb->pcommon.packet_info.sent_length = len;
/*Send more data for one active connection*/
espconn_tcp_finish(psent_cb);
return ERR_OK;
}
......@@ -406,14 +761,14 @@ espconn_client_err(void *arg, err_t err)
LWIP_UNUSED_ARG(err);
if (perr_cb != NULL) {
os_timer_disarm(&perr_cb->pcommon.ptimer);
pcb = perr_cb->pcommon.pcb;
perr_cb->pespconn->state = ESPCONN_CLOSE;
espconn_printf("espconn_client_err %d %d %d\n", pcb->state, pcb->nrtx, err);
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, perr_cb);
// /*remove the node from the client's active connection list*/
// espconn_list_delete(&plink_active, perr_cb);
/*Set the error code depend on the error type and control block state*/
if (err == ERR_ABRT) {
switch (pcb->state) {
case SYN_SENT:
......@@ -450,9 +805,8 @@ espconn_client_err(void *arg, err_t err)
} else {
perr_cb->pcommon.err = err;
}
os_timer_setfn(&perr_cb->pcommon.ptimer,
(os_timer_func_t *) espconn_tcp_reconnect, perr_cb);
os_timer_arm(&perr_cb->pcommon.ptimer, 10, 0);
/*post the singer to the task for processing the connection*/
ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)perr_cb);
}
}
......@@ -468,19 +822,41 @@ static err_t ICACHE_FLASH_ATTR
espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err)
{
espconn_msg *pcon = arg;
espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb);
if (err == ERR_OK){
/*Reserve the remote information for current active connection*/
pcon->pespconn->state = ESPCONN_CONNECT;
pcon->pcommon.err = err;
pcon->pcommon.pcb = tpcb;
tcp_arg(tpcb, (void *)pcon);
pcon->pcommon.local_port = tpcb->local_port;
pcon->pcommon.local_ip = tpcb->local_ip.addr;
pcon->pcommon.remote_port = tpcb->remote_port;
pcon->pcommon.remote_ip[0] = ip4_addr1_16(&tpcb->remote_ip);
pcon->pcommon.remote_ip[1] = ip4_addr2_16(&tpcb->remote_ip);
pcon->pcommon.remote_ip[2] = ip4_addr3_16(&tpcb->remote_ip);
pcon->pcommon.remote_ip[3] = ip4_addr4_16(&tpcb->remote_ip);
pcon->pcommon.write_flag = true;
tcp_arg(tpcb, (void *) pcon);
/*Set the specify function that should be called
* when TCP data has been successfully delivered,
* when active connection receives data*/
tcp_sent(tpcb, espconn_client_sent);
tcp_recv(tpcb, espconn_client_recv);
/*Disable Nagle algorithm default*/
tcp_nagle_disable(tpcb);
/*Default set the total number of espconn_buf on the unsent lists for one*/
espconn_tcp_set_buf_count(pcon->pespconn, 1);
//tcp_poll(tpcb, espconn_client_poll, 1);
if (pcon->pespconn->proto.tcp->connect_callback != NULL) {
pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn);
}
/*Enable keep alive option*/
if (espconn_keepalive_disabled(pcon))
espconn_keepalive_enable(tpcb);
} else{
os_printf("err in host connected (%s)\n",lwip_strerr(err));
}
......@@ -501,24 +877,28 @@ espconn_tcp_client(struct espconn *espconn)
struct ip_addr ipaddr;
espconn_msg *pclient = NULL;
/*Creates a new client control message*/
pclient = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
if (pclient == NULL){
return ESPCONN_MEM;
}
/*Set an IP address given for Little-endian.*/
IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],
espconn->proto.tcp->remote_ip[2],
espconn->proto.tcp->remote_ip[3]);
/*Creates a new TCP protocol control block*/
pcb = tcp_new();
if (pcb == NULL) {
// pclient ->pespconn ->state = ESPCONN_NONE;
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pclient);
pclient = NULL;
return ESPCONN_MEM;
} else {
/*insert the node to the active connection list*/
espconn_list_creat(&plink_active, pclient);
tcp_arg(pcb, (void *)pclient);
......@@ -528,39 +908,33 @@ espconn_tcp_client(struct espconn *espconn)
pclient->pespconn->state = ESPCONN_WAIT;
pclient->pcommon.pcb = pcb;
tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
#if 0
pclient->pcommon.err = tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
if (pclient->pcommon.err != ERR_OK){
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pclient);
memp_free(MEMP_TCP_PCB, pcb);
os_free(pclient);
pclient = NULL;
return ERR_USE;
}
#endif
/*Establish the connection*/
pclient->pcommon.err = tcp_connect(pcb, &ipaddr,
pclient->pespconn->proto.tcp->remote_port, espconn_client_connect);
if (pclient->pcommon.err == ERR_RTE){
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pclient);
espconn_kill_pcb(pcb->local_port);
os_free(pclient);
pclient = NULL;
return ESPCONN_RTE;
}
return pclient->pcommon.err;
}
}
///////////////////////////////server function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_closed
* Description : The connection has been successfully closed.
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_sclose_cb(void *arg)
{
espconn_msg *psclose_cb = arg;
if (psclose_cb == NULL) {
return;
}
struct tcp_pcb *pcb = psclose_cb ->pcommon.pcb;
espconn_printf("espconn_sclose_cb %d %d\n", pcb->state, pcb->nrtx);
if (pcb->state == CLOSED || pcb->state == TIME_WAIT) {
psclose_cb ->pespconn ->state = ESPCONN_CLOSE;
/*remove the node from the server's active connection list*/
espconn_list_delete(&plink_active, psclose_cb);
espconn_tcp_disconnect_successful(psclose_cb);
} else {
os_timer_arm(&psclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
}
}
/******************************************************************************
* FunctionName : espconn_server_close
* Description : The connection shall be actively closed.
......@@ -574,12 +948,10 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb)
err_t err;
espconn_msg *psclose = arg;
os_timer_disarm(&psclose->pcommon.ptimer);
psclose->pcommon.pcb = pcb;
/*avoid recalling the disconnect function*/
tcp_recv(pcb, NULL);
err = tcp_close(pcb);
os_timer_setfn(&psclose->pcommon.ptimer, espconn_sclose_cb, psclose);
os_timer_arm(&psclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
if (err != ERR_OK) {
/* closing failed, try again later */
......@@ -588,6 +960,10 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb)
/* closing succeeded */
tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
/*switch the state of espconn for application process*/
psclose->pespconn->state = ESPCONN_CLOSE;
ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)psclose);
}
}
......@@ -608,26 +984,38 @@ espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
tcp_arg(pcb, arg);
espconn_printf("server has application data received: %d\n", system_get_free_heap_size());
if (p != NULL) {
/*To update and advertise a larger window*/
if(precv_cb->recv_hold_flag == 0)
tcp_recved(pcb, p->tot_len);
else
precv_cb->recv_holded_buf_Len += p->tot_len;
}
if (err == ERR_OK && p != NULL) {
u8_t *data_ptr = NULL;
u32_t data_cntr = 0;
/*clear the count for connection timeout*/
precv_cb->pcommon.recv_check = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
data_ptr = (u8_t *)os_zalloc(p ->tot_len + 1);
data_cntr = pbuf_copy_partial(p, data_ptr, p ->tot_len, 0);
pbuf_free(p);
if (data_cntr != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb;
if (precv_cb->pespconn->recv_callback != NULL) {
precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr);
}
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
}
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(data_ptr);
data_ptr = NULL;
espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size());
......@@ -659,22 +1047,11 @@ espconn_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
psent_cb->pcommon.pcb = pcb;
psent_cb->pcommon.recv_check = 0;
psent_cb->pcommon.write_total += len;
espconn_printf("espconn_server_sent sent %d %d\n", len, psent_cb->pcommon.write_total);
if (psent_cb->pcommon.write_total == psent_cb->pcommon.write_len){
psent_cb->pcommon.write_total = 0;
psent_cb->pcommon.write_len = 0;
if (psent_cb ->pcommon.cntr == 0) {
psent_cb ->pespconn ->state = ESPCONN_CONNECT;
psent_cb->pcommon.pbuf->tot_len += len;
psent_cb->pcommon.packet_info.sent_length = len;
if (psent_cb ->pespconn ->sent_callback != NULL) {
psent_cb ->pespconn ->sent_callback(psent_cb ->pespconn);
}
} else
espconn_tcp_sent(psent_cb, psent_cb ->pcommon.ptrbuf, psent_cb ->pcommon.cntr);
} else {
}
/*Send more data for one active connection*/
espconn_tcp_finish(psent_cb);
return ERR_OK;
}
......@@ -695,30 +1072,37 @@ espconn_server_poll(void *arg, struct tcp_pcb *pcb)
{
espconn_msg *pspoll_cb = arg;
/*exception calling abandon the connection for send a RST frame*/
if (arg == NULL) {
tcp_abandon(pcb, 0);
tcp_poll(pcb, NULL, 0);
return ERR_ABRT;
return ERR_OK;
}
espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state);
pspoll_cb->pcommon.pcb = pcb;
if (pcb->state == ESTABLISHED) {
pspoll_cb->pcommon.recv_check++;
if (pspoll_cb->pcommon.timeout != 0){
if (pspoll_cb->pcommon.recv_check == pspoll_cb->pcommon.timeout) {
if (pspoll_cb->pcommon.timeout != 0){/*no data sent in one active connection's set timeout, close.*/
if (pspoll_cb->pcommon.recv_check >= pspoll_cb->pcommon.timeout) {
pspoll_cb->pcommon.recv_check = 0;
espconn_server_close(pspoll_cb, pcb);
}
} else if (link_timer != 0){
if (pspoll_cb->pcommon.recv_check == link_timer) {
} else {
espconn_msg *ptime_msg = pserver_list;
while (ptime_msg != NULL) {
if (ptime_msg->pespconn == pspoll_cb->preverse){
if (ptime_msg->pcommon.timeout != 0){/*no data sent in server's set timeout, close.*/
if (pspoll_cb->pcommon.recv_check >= ptime_msg->pcommon.timeout){
pspoll_cb->pcommon.recv_check = 0;
espconn_server_close(pspoll_cb, pcb);
}
} else {
if (pspoll_cb->pcommon.recv_check == 0x0a) {
} else {/*don't close for ever*/
pspoll_cb->pcommon.recv_check = 0;
espconn_server_close(pspoll_cb, pcb);
}
break;
}
ptime_msg = ptime_msg->pnext;
}
}
} else {
......@@ -742,13 +1126,14 @@ esponn_server_err(void *arg, err_t err)
espconn_msg *pserr_cb = arg;
struct tcp_pcb *pcb = NULL;
if (pserr_cb != NULL) {
os_timer_disarm(&pserr_cb->pcommon.ptimer);
pcb = pserr_cb->pcommon.pcb;
pserr_cb->pespconn->state = ESPCONN_CLOSE;
/*remove the node from the server's active connection list*/
espconn_list_delete(&plink_active, pserr_cb);
// /*remove the node from the server's active connection list*/
// espconn_list_delete(&plink_active, pserr_cb);
/*Set the error code depend on the error type and control block state*/
if (err == ERR_ABRT) {
switch (pcb->state) {
case SYN_RCVD:
......@@ -789,10 +1174,8 @@ esponn_server_err(void *arg, err_t err)
} else {
pserr_cb->pcommon.err = err;
}
os_timer_setfn(&pserr_cb->pcommon.ptimer,
(os_timer_func_t *) espconn_tcp_reconnect, pserr_cb);
os_timer_arm(&pserr_cb->pcommon.ptimer, 10, 0);
/*post the singer to the task for processing the connection*/
ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)pserr_cb);
}
}
......@@ -812,12 +1195,25 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
remot_info *pinfo = NULL;
LWIP_UNUSED_ARG(err);
paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
if (!espconn || !espconn->proto.tcp) {
return ERR_ARG;
}
tcp_arg(pcb, paccept);
tcp_err(pcb, esponn_server_err);
/*Ensure the active connection is less than the count of active connections on the server*/
espconn_get_connection_info(espconn, &pinfo , 0);
espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt);
if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn))
return ERR_ISCONN;
/*Creates a new active connect control message*/
paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
tcp_arg(pcb, paccept);
if (paccept == NULL)
return ERR_MEM;
/*insert the node to the active connection list*/
/*Insert the node to the active connection list*/
espconn_list_creat(&plink_active, paccept);
paccept->preverse = espconn;
......@@ -828,9 +1224,7 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
if (paccept->pespconn->proto.tcp == NULL)
return ERR_MEM;
//paccept->pcommon.timeout = 0x0a;
//link_timer = 0x0a;
/*Reserve the remote information for current active connection*/
paccept->pcommon.pcb = pcb;
paccept->pcommon.remote_port = pcb->remote_port;
......@@ -838,24 +1232,33 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip);
paccept->pcommon.write_flag = true;
os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4);
espconn->proto.tcp->remote_port = pcb->remote_port;
espconn->state = ESPCONN_CONNECT;
espconn_copy_partial(paccept->pespconn, espconn);
espconn_get_connection_info(espconn, &pinfo , 0);
espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt);
if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn) + 1)
return ERR_ISCONN;
/*Set the specify function that should be called
* when TCP data has been successfully delivered,
* when active connection receives data,
* or periodically from active connection*/
tcp_sent(pcb, espconn_server_sent);
tcp_recv(pcb, espconn_server_recv);
tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */
/*Disable Nagle algorithm default*/
tcp_nagle_disable(pcb);
/*Default set the total number of espconn_buf on the unsent lists for one*/
espconn_tcp_set_buf_count(paccept->pespconn, 1);
if (paccept->pespconn->proto.tcp->connect_callback != NULL) {
paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn);
}
/*Enable keep alive option*/
if (espconn_keepalive_disabled(paccept))
espconn_keepalive_enable(pcb);
return ERR_OK;
}
......@@ -872,19 +1275,25 @@ espconn_tcp_server(struct espconn *espconn)
struct tcp_pcb *pcb = NULL;
espconn_msg *pserver = NULL;
/*Creates a new server control message*/
pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
if (pserver == NULL){
return ESPCONN_MEM;
}
/*Creates a new TCP protocol control block*/
pcb = tcp_new();
if (pcb == NULL) {
// espconn ->state = ESPCONN_NONE;
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pserver);
pserver = NULL;
return ESPCONN_MEM;
} else {
struct tcp_pcb *lpcb = NULL;
/*Binds the connection to a local port number and any IP address*/
tcp_bind(pcb, IP_ADDR_ANY, espconn->proto.tcp->local_port);
lpcb = pcb;
/*malloc and set the state of the connection to be LISTEN*/
pcb = tcp_listen(pcb);
if (pcb != NULL) {
/*insert the node to the active connection list*/
......@@ -892,14 +1301,16 @@ espconn_tcp_server(struct espconn *espconn)
pserver->preverse = pcb;
pserver->pespconn = espconn;
pserver->count_opt = MEMP_NUM_TCP_PCB;
pserver->pcommon.timeout = 0x0a;
espconn ->state = ESPCONN_LISTEN;
/*set the specify argument that should be passed callback function*/
tcp_arg(pcb, (void *)espconn);
// tcp_err(pcb, esponn_server_err);
/*accept callback function to call for this control block*/
tcp_accept(pcb, espconn_tcp_accept);
return ESPCONN_OK;
} else {
// espconn ->state = ESPCONN_NONE;
/*to prevent memory leaks, ensure that each allocated is deleted*/
memp_free(MEMP_TCP_PCB,lpcb);
os_free(pserver);
pserver = NULL;
return ESPCONN_MEM;
......@@ -924,17 +1335,19 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
return ESPCONN_ARG;
espconn_get_connection_info(pdeletecon, &pinfo , 0);
/*make sure all the active connection have been disconnect*/
if (pdeletecon->link_cnt != 0)
return ESPCONN_INPROGRESS;
else {
os_printf("espconn_tcp_delete %p\n",pdeletecon);
espconn_printf("espconn_tcp_delete %p\n",pdeletecon);
pdelete_msg = pserver_list;
while (pdelete_msg != NULL){
if (pdelete_msg->pespconn == pdeletecon){
/*remove the node from the client's active connection list*/
espconn_list_delete(&pserver_list, pdelete_msg);
pcb = pdelete_msg->preverse;
os_printf("espconn_tcp_delete %d\n",pcb->state);
os_printf("espconn_tcp_delete %d, %d\n",pcb->state, pcb->local_port);
espconn_kill_pcb(pcb->local_port);
err = tcp_close(pcb);
os_free(pdelete_msg);
pdelete_msg = NULL;
......@@ -949,18 +1362,13 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
}
}
void espconn_tcp_hold(void *arg) {
espconn_msg *ptcp_sent = arg;
struct tcp_pcb *pcb = NULL;
pcb = ptcp_sent->pcommon.pcb;
pcb->hold = 1;
}
void espconn_tcp_unhold(void *arg) {
espconn_msg *ptcp_sent = arg;
struct tcp_pcb *pcb = NULL;
pcb = ptcp_sent->pcommon.pcb;
pcb->hold = 0;
/******************************************************************************
* FunctionName : espconn_init
* Description : used to init the function that should be used when
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_init(void)
{
ets_task(espconn_Task, espconn_TaskPrio, espconn_TaskQueue, espconn_TaskQueueLen);
}
......@@ -22,8 +22,17 @@
#include "lwip/app/espconn_udp.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
extern espconn_msg *plink_active;
extern uint8 default_interface;
enum send_opt{
ESPCONN_SENDTO,
ESPCONN_SEND
};
static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
{
if (pespconn == NULL) {
......@@ -35,7 +44,7 @@ static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
}
}
static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg, enum send_opt opt)
{
espconn_msg *psent = arg;
......@@ -45,9 +54,14 @@ static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
if (psent->pcommon.cntr == 0) {
psent->pespconn->state = ESPCONN_CONNECT;
sys_timeout(TCP_FAST_INTERVAL, espconn_data_sentcb, psent->pespconn);
// sys_timeout(10, espconn_data_sentcb, psent->pespconn);
espconn_data_sentcb(psent->pespconn);
} else {
if (opt == ESPCONN_SEND){
espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
} else {
espconn_udp_sendto(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
}
}
}
......@@ -57,14 +71,18 @@ static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
* Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : none
* Returns : return espconn error code.
* - ESPCONN_OK. Successful. No error occured.
* - ESPCONN_MEM. Out of memory.
* - ESPCONN_RTE. Could not find route to destination address.
* - More errors could be returned by lower protocol layers.
*******************************************************************************/
void ICACHE_FLASH_ATTR
err_t ICACHE_FLASH_ATTR
espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
{
espconn_msg *pudp_sent = arg;
struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
struct pbuf *p, *q;
struct pbuf *p, *q ,*p_temp;
u8_t *data = NULL;
u16_t cnt = 0;
u16_t datalen = 0;
......@@ -73,11 +91,11 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
return;
return ESPCONN_ARG;
}
if (1024 < length) {
datalen = 1024;
if (1470 < length) {
datalen = 1470;
} else {
datalen = length;
}
......@@ -99,7 +117,7 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
q = q->next;
}
} else {
return;
return ESPCONN_MEM;
}
upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port;
......@@ -109,7 +127,29 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
pudp_sent->pespconn->proto.udp->remote_ip[3]);
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
{
if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
if (pbuf_copy (p_temp,p) != ERR_OK) {
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent: copying to new pbuf failed\n"));
return ESPCONN_ARG;
}
netif_set_default(sta_netif);
err = udp_send(upcb, p_temp);
pbuf_free(p_temp);
netif_set_default(ap_netif);
}
}
err = udp_send(upcb, p);
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err));
if (p->ref != 0) {
......@@ -117,7 +157,115 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
pbuf_free(p);
pudp_sent->pcommon.ptrbuf = psent + datalen;
pudp_sent->pcommon.cntr = length - datalen;
espconn_data_sent(pudp_sent);
espconn_data_sent(pudp_sent, ESPCONN_SEND);
if (err > 0)
return ESPCONN_IF;
return err;
} else {
pbuf_free(p);
return ESPCONN_RTE;
}
}
/******************************************************************************
* FunctionName : espconn_udp_sendto
* Description : sent data for UDP
* Parameters : void *arg -- UDP to send
* uint8* psent -- Data to send
* uint16 length -- Length of data to send
* Returns : return espconn error code.
* - ESPCONN_OK. Successful. No error occured.
* - ESPCONN_MEM. Out of memory.
* - ESPCONN_RTE. Could not find route to destination address.
* - More errors could be returned by lower protocol layers.
*******************************************************************************/
err_t ICACHE_FLASH_ATTR
espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
{
espconn_msg *pudp_sent = arg;
struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
struct espconn *pespconn = pudp_sent->pespconn;
struct pbuf *p, *q ,*p_temp;
struct ip_addr dst_ip;
u16_t dst_port;
u8_t *data = NULL;
u16_t cnt = 0;
u16_t datalen = 0;
u16_t i = 0;
err_t err;
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
return ESPCONN_ARG;
}
if (1470 < length) {
datalen = 1470;
} else {
datalen = length;
}
p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
if (p != NULL) {
q = p;
while (q != NULL) {
data = (u8_t *)q->payload;
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
for (i = 0; i < q->len; i++) {
data[i] = ((u8_t *) psent)[cnt++];
}
q = q->next;
}
} else {
return ESPCONN_MEM;
}
dst_port = pespconn->proto.udp->remote_port;
IP4_ADDR(&dst_ip, pespconn->proto.udp->remote_ip[0],
pespconn->proto.udp->remote_ip[1], pespconn->proto.udp->remote_ip[2],
pespconn->proto.udp->remote_ip[3]);
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
{
if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
if (pbuf_copy (p_temp,p) != ERR_OK) {
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sendto: copying to new pbuf failed\n"));
return ESPCONN_ARG;
}
netif_set_default(sta_netif);
err = udp_sendto(upcb, p_temp, &dst_ip, dst_port);
pbuf_free(p_temp);
netif_set_default(ap_netif);
}
}
err = udp_sendto(upcb, p, &dst_ip, dst_port);
if (p->ref != 0) {
pbuf_free(p);
pudp_sent->pcommon.ptrbuf = psent + datalen;
pudp_sent->pcommon.cntr = length - datalen;
if (err == ERR_OK)
espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
if (err > 0)
return ESPCONN_IF;
return err;
} else {
pbuf_free(p);
return ESPCONN_RTE;
}
}
......@@ -143,15 +291,10 @@ espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb));
upcb->remote_port = port;
upcb->remote_ip = *addr;
precv->pcommon.remote_ip[0] = ip4_addr1_16(&upcb->remote_ip);
precv->pcommon.remote_ip[1] = ip4_addr2_16(&upcb->remote_ip);
precv->pcommon.remote_ip[2] = ip4_addr3_16(&upcb->remote_ip);
precv->pcommon.remote_ip[3] = ip4_addr4_16(&upcb->remote_ip);
os_memcpy(precv->pespconn->proto.udp->remote_ip, precv->pcommon.remote_ip, 4);
precv->pespconn->proto.udp->remote_port = port;
precv->pcommon.remote_ip[0] = ip4_addr1_16(addr);
precv->pcommon.remote_ip[1] = ip4_addr2_16(addr);
precv->pcommon.remote_ip[2] = ip4_addr3_16(addr);
precv->pcommon.remote_ip[3] = ip4_addr4_16(addr);
precv->pcommon.remote_port = port;
precv->pcommon.pcb = upcb;
......@@ -164,31 +307,13 @@ espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
} else {
wifi_get_ip_info(0, &ipconfig);
}
upcb->local_ip = ipconfig.ip;
precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&upcb->local_ip);
precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&upcb->local_ip);
precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&upcb->local_ip);
precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&upcb->local_ip);
precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&ipconfig.ip);
if (p != NULL) {
// q = p;
// while (q != NULL) {
// pdata = (u8_t *)os_zalloc(q ->len + 1);
// length = pbuf_copy_partial(q, pdata, q ->len, 0);
//
// LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %x\n", __LINE__, length));
// precv->pcommon.pcb = upcb;
//
// if (length != 0) {
// if (precv->pespconn->recv_callback != NULL) {
// precv->pespconn->recv_callback(precv->pespconn, pdata, length);
// }
// }
//
// q = q->next;
// os_free(pdata);
// }
pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
precv->pcommon.pcb = upcb;
......
......@@ -35,6 +35,10 @@
#if LWIP_TCP
#include "lwip/tcp.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/*
* This implements a netio server.
* The client sends a command word (4 bytes) then a data length word (4 bytes).
......@@ -321,7 +325,7 @@ netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
LWIP_UNUSED_ARG(err);
ns = mem_malloc(sizeof(struct netio_state));
ns = (struct netio_state *)mem_malloc(sizeof(struct netio_state));
if(ns == NULL){
return ERR_MEM;
......@@ -335,7 +339,7 @@ netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
#if NETIO_USE_STATIC_BUF == 1
ns->buf_ptr = netio_buf;
#else
ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE);
ns->buf_ptr = (u8_t *)mem_malloc(NETIO_BUF_SIZE);
if(ns->buf_ptr == NULL){
mem_free(ns);
......
......@@ -63,6 +63,10 @@
#include "lwip/inet.h"
#endif /* PING_USE_SOCKETS */
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/* ping variables */
static u16_t ping_seq_num = 0;
static u32_t ping_time;
......@@ -93,6 +97,9 @@ ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
iecho->chksum = 0;
iecho->id = PING_ID;
++ ping_seq_num;
if (ping_seq_num == 0x7fff)
ping_seq_num = 0;
iecho->seqno = htons(ping_seq_num);
/* fill the additional data buffer with some data */
......@@ -233,7 +240,7 @@ ping_coarse_tmr(void *arg)
} else {
uint32 delay = system_relative_time(pingmsg->ping_start);
delay /= PING_COARSE;
ping_seq_num = 0;
// ping_seq_num = 0;
if (ping_opt->sent_function == NULL){
os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n",
pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment