Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
/*
2
  Asynchronous TCP library for Espressif MCUs
3
 
4
  Copyright (c) 2016 Hristo Gochkov. All rights reserved.
5
  This file is part of the esp8266 core for Arduino environment.
6
 
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public
9
  License as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
 
12
  This library is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
  Lesser General Public License for more details.
16
 
17
  You should have received a copy of the GNU Lesser General Public
18
  License along with this library; if not, write to the Free Software
19
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
*/
21
/*
22
 * Compatibility for AxTLS with LWIP raw tcp mode (http://lwip.wikia.com/wiki/Raw/TCP)
23
 * Original Code and Inspiration: Slavey Karadzhov
24
 */
25
 
26
// To handle all the definitions needed for debug printing, we need to delay
27
// macro definitions till later.
28
#define DEBUG_SKIP__DEBUG_PRINT_MACROS 1
29
#include <async_config.h>
30
#undef DEBUG_SKIP__DEBUG_PRINT_MACROS
31
 
32
#if ASYNC_TCP_SSL_ENABLED
33
 
34
#include "lwip/opt.h"
35
#include "lwip/tcp.h"
36
#include "lwip/inet.h"
37
#include <stdlib.h>
38
#include <stdint.h>
39
#include <stdarg.h>
40
#include <stdbool.h>
41
#include <tcp_axtls.h>
42
 
43
// ets_uart_printf is defined in esp8266_undocumented.h, in newer Arduino ESP8266 Core.
44
extern int ets_uart_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
45
#include <DebugPrintMacros.h>
46
#ifndef TCP_SSL_DEBUG
47
#define TCP_SSL_DEBUG(...) do { (void)0;} while(false)
48
#endif
49
 
50
uint8_t * default_private_key = NULL;
51
uint16_t default_private_key_len = 0;
52
 
53
uint8_t * default_certificate = NULL;
54
uint16_t default_certificate_len = 0;
55
 
56
static uint8_t _tcp_ssl_has_client = 0;
57
 
58
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password){
59
  uint32_t options = SSL_CONNECT_IN_PARTS;
60
  SSL_CTX *ssl_ctx;
61
 
62
  if(private_key_file){
63
    options |= SSL_NO_DEFAULT_KEY;
64
  }
65
 
66
  if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL){
67
    TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: failed to allocate context\n");
68
    return NULL;
69
  }
70
 
71
  if (private_key_file){
72
    int obj_type = SSL_OBJ_RSA_KEY;
73
    if (strstr(private_key_file, ".p8"))
74
      obj_type = SSL_OBJ_PKCS8;
75
    else if (strstr(private_key_file, ".p12"))
76
      obj_type = SSL_OBJ_PKCS12;
77
 
78
    if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password)){
79
      TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load private key '%s' failed\n", private_key_file);
80
      return NULL;
81
    }
82
  }
83
 
84
  if (cert){
85
    if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert, NULL)){
86
      TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load certificate '%s' failed\n", cert);
87
      return NULL;
88
    }
89
  }
90
  return ssl_ctx;
91
}
92
 
93
struct tcp_ssl_pcb {
94
  struct tcp_pcb *tcp;
95
  int fd;
96
  SSL_CTX* ssl_ctx;
97
  SSL *ssl;
98
  uint8_t type;
99
  int handshake;
100
  void * arg;
101
  tcp_ssl_data_cb_t on_data;
102
  tcp_ssl_handshake_cb_t on_handshake;
103
  tcp_ssl_error_cb_t on_error;
104
  int last_wr;
105
  struct pbuf *tcp_pbuf;
106
  int pbuf_offset;
107
  struct tcp_ssl_pcb * next;
108
};
109
 
110
typedef struct tcp_ssl_pcb tcp_ssl_t;
111
 
112
static tcp_ssl_t * tcp_ssl_array = NULL;
113
static int tcp_ssl_next_fd = 0;
114
 
115
uint8_t tcp_ssl_has_client(){
116
  return _tcp_ssl_has_client;
117
}
118
 
119
tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp) {
120
 
121
  if(tcp_ssl_next_fd < 0){
122
    tcp_ssl_next_fd = 0;//overflow
123
  }
124
 
125
  tcp_ssl_t * new_item = (tcp_ssl_t*)malloc(sizeof(tcp_ssl_t));
126
  if(!new_item){
127
    TCP_SSL_DEBUG("tcp_ssl_new: failed to allocate tcp_ssl\n");
128
    return NULL;
129
  }
130
 
131
  new_item->tcp = tcp;
132
  new_item->handshake = SSL_NOT_OK;
133
  new_item->arg = NULL;
134
  new_item->on_data = NULL;
135
  new_item->on_handshake = NULL;
136
  new_item->on_error = NULL;
137
  new_item->tcp_pbuf = NULL;
138
  new_item->pbuf_offset = 0;
139
  new_item->next = NULL;
140
  new_item->ssl_ctx = NULL;
141
  new_item->ssl = NULL;
142
  new_item->type = TCP_SSL_TYPE_CLIENT;
143
  new_item->fd = tcp_ssl_next_fd++;
144
 
145
  if(tcp_ssl_array == NULL){
146
    tcp_ssl_array = new_item;
147
  } else {
148
    tcp_ssl_t * item = tcp_ssl_array;
149
    while(item->next != NULL)
150
      item = item->next;
151
    item->next = new_item;
152
  }
153
 
154
  TCP_SSL_DEBUG("tcp_ssl_new: %d\n", new_item->fd);
155
  return new_item;
156
}
157
 
158
tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp) {
159
  if(tcp == NULL) {
160
    return NULL;
161
  }
162
  tcp_ssl_t * item = tcp_ssl_array;
163
  while(item && item->tcp != tcp){
164
    item = item->next;
165
  }
166
  return item;
167
}
168
 
169
int tcp_ssl_new_client(struct tcp_pcb *tcp){
170
  SSL_CTX* ssl_ctx;
171
  tcp_ssl_t * tcp_ssl;
172
 
173
  if(tcp == NULL) {
174
    return -1;
175
  }
176
 
177
  if(tcp_ssl_get(tcp) != NULL){
178
    TCP_SSL_DEBUG("tcp_ssl_new_client: tcp_ssl already exists\n");
179
    return -1;
180
  }
181
 
182
  ssl_ctx = ssl_ctx_new(SSL_CONNECT_IN_PARTS | SSL_SERVER_VERIFY_LATER, 1);
183
  if(ssl_ctx == NULL){
184
    TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl context\n");
185
    return -1;
186
  }
187
 
188
  tcp_ssl = tcp_ssl_new(tcp);
189
  if(tcp_ssl == NULL){
190
    ssl_ctx_free(ssl_ctx);
191
    return -1;
192
  }
193
 
194
  tcp_ssl->ssl_ctx = ssl_ctx;
195
 
196
  tcp_ssl->ssl = ssl_client_new(ssl_ctx, tcp_ssl->fd, NULL, 0, NULL);
197
  if(tcp_ssl->ssl == NULL){
198
    TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl\n");
199
    tcp_ssl_free(tcp);
200
    return -1;
201
  }
202
 
203
  return tcp_ssl->fd;
204
}
205
 
206
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx){
207
  tcp_ssl_t * tcp_ssl;
208
 
209
  if(tcp == NULL) {
210
    return -1;
211
  }
212
 
213
  if(ssl_ctx == NULL){
214
    return -1;
215
  }
216
 
217
  if(tcp_ssl_get(tcp) != NULL){
218
    TCP_SSL_DEBUG("tcp_ssl_new_server: tcp_ssl already exists\n");
219
    return -1;
220
  }
221
 
222
  tcp_ssl = tcp_ssl_new(tcp);
223
  if(tcp_ssl == NULL){
224
    return -1;
225
  }
226
 
227
  tcp_ssl->type = TCP_SSL_TYPE_SERVER;
228
  tcp_ssl->ssl_ctx = ssl_ctx;
229
 
230
  _tcp_ssl_has_client = 1;
231
  tcp_ssl->ssl = ssl_server_new(ssl_ctx, tcp_ssl->fd);
232
  if(tcp_ssl->ssl == NULL){
233
    TCP_SSL_DEBUG("tcp_ssl_new_server: failed to allocate ssl\n");
234
    tcp_ssl_free(tcp);
235
    return -1;
236
  }
237
 
238
  return tcp_ssl->fd;
239
}
240
 
241
int tcp_ssl_free(struct tcp_pcb *tcp) {
242
 
243
  if(tcp == NULL) {
244
    return -1;
245
  }
246
 
247
  tcp_ssl_t * item = tcp_ssl_array;
248
 
249
  if(item->tcp == tcp){
250
    tcp_ssl_array = tcp_ssl_array->next;
251
    if(item->tcp_pbuf != NULL){
252
      pbuf_free(item->tcp_pbuf);
253
    }
254
    TCP_SSL_DEBUG("tcp_ssl_free: %d\n", item->fd);
255
    if(item->ssl)
256
      ssl_free(item->ssl);
257
    if(item->type == TCP_SSL_TYPE_CLIENT && item->ssl_ctx)
258
      ssl_ctx_free(item->ssl_ctx);
259
    if(item->type == TCP_SSL_TYPE_SERVER)
260
      _tcp_ssl_has_client = 0;
261
    free(item);
262
    return 0;
263
  }
264
 
265
  while(item->next && item->next->tcp != tcp)
266
    item = item->next;
267
 
268
  if(item->next == NULL){
269
    return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;//item not found
270
  }
271
 
272
  tcp_ssl_t * i = item->next;
273
  item->next = i->next;
274
  if(i->tcp_pbuf != NULL){
275
    pbuf_free(i->tcp_pbuf);
276
  }
277
  TCP_SSL_DEBUG("tcp_ssl_free: %d\n", i->fd);
278
  if(i->ssl)
279
    ssl_free(i->ssl);
280
  if(i->type == TCP_SSL_TYPE_CLIENT && i->ssl_ctx)
281
    ssl_ctx_free(i->ssl_ctx);
282
  if(i->type == TCP_SSL_TYPE_SERVER)
283
    _tcp_ssl_has_client = 0;
284
  free(i);
285
  return 0;
286
}
287
 
288
#ifdef AXTLS_2_0_0_SNDBUF
289
int tcp_ssl_sndbuf(struct tcp_pcb *tcp){
290
  int expected;
291
  int available;
292
  int result = -1;
293
 
294
  if(tcp == NULL) {
295
    return result;
296
  }
297
  tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
298
  if(!tcp_ssl){
299
    TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_ssl is NULL\n");
300
    return result;
301
  }
302
  available = tcp_sndbuf(tcp);
303
  if(!available){
304
    TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is zero\n");
305
    return 0;
306
  }
307
  result = available;
308
  while((expected = ssl_calculate_write_length(tcp_ssl->ssl, result)) > available){
309
    result -= (expected - available) + 4;
310
  }
311
 
312
  if(expected > 0){
313
    //TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is %d from %d\n", result, available);
314
    return result;
315
  }
316
 
317
  return 0;
318
}
319
#endif
320
 
321
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len) {
322
  if(tcp == NULL) {
323
    return -1;
324
  }
325
  tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
326
  if(!tcp_ssl){
327
    TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n");
328
    return 0;
329
  }
330
  tcp_ssl->last_wr = 0;
331
 
332
#ifdef AXTLS_2_0_0_SNDBUF
333
  int expected_len = ssl_calculate_write_length(tcp_ssl->ssl, len);
334
  int available_len = tcp_sndbuf(tcp);
335
  if(expected_len < 0 || expected_len > available_len){
336
    TCP_SSL_DEBUG("tcp_ssl_write: data will not fit! %u < %d(%u)\r\n", available_len, expected_len, len);
337
    return -1;
338
  }
339
#endif
340
 
341
  int rc = ssl_write(tcp_ssl->ssl, data, len);
342
 
343
  //TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc);
344
 
345
  if (rc < 0){
346
    if(rc != SSL_CLOSE_NOTIFY) {
347
      TCP_SSL_DEBUG("tcp_ssl_write error: %d\r\n", rc);
348
    }
349
    return rc;
350
  }
351
 
352
  return tcp_ssl->last_wr;
353
}
354
 
355
/**
356
 * Reads data from the SSL over TCP stream. Returns decrypted data.
357
 * @param tcp_pcb *tcp - pointer to the raw tcp object
358
 * @param pbuf *p - pointer to the buffer with the TCP packet data
359
 *
360
 * @return int
361
 *      0 - when everything is fine but there are no symbols to process yet
362
 *      < 0 - when there is an error
363
 *      > 0 - the length of the clear text characters that were read
364
 */
365
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) {
366
  if(tcp == NULL) {
367
    return -1;
368
  }
369
  tcp_ssl_t* fd_data = NULL;
370
 
371
  int read_bytes = 0;
372
  int total_bytes = 0;
373
  uint8_t *read_buf;
374
 
375
  fd_data = tcp_ssl_get(tcp);
376
  if(fd_data == NULL) {
377
    TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n");
378
    return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
379
  }
380
 
381
  if(p == NULL) {
382
    TCP_SSL_DEBUG("tcp_ssl_read:p == NULL\n");
383
    return ERR_TCP_SSL_INVALID_DATA;
384
  }
385
 
386
  //TCP_SSL_DEBUG("READY TO READ SOME DATA\n");
387
 
388
  fd_data->tcp_pbuf = p;
389
  fd_data->pbuf_offset = 0;
390
 
391
  do {
392
    read_bytes = ssl_read(fd_data->ssl, &read_buf);
393
    TCP_SSL_DEBUG("tcp_ssl_ssl_read: %d\n", read_bytes);
394
 
395
    if(read_bytes < SSL_OK) {
396
      if(read_bytes != SSL_CLOSE_NOTIFY) {
397
        TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes);
398
      }
399
      total_bytes = read_bytes;
400
      break;
401
    } else if(read_bytes > 0){
402
      if(fd_data->on_data){
403
        fd_data->on_data(fd_data->arg, tcp, read_buf, read_bytes);
404
        // fd_data may have been freed in callback
405
        fd_data = tcp_ssl_get(tcp);
406
        if(NULL == fd_data)
407
          return SSL_CLOSE_NOTIFY;
408
      }
409
      total_bytes+= read_bytes;
410
    } else {
411
      if(fd_data->handshake != SSL_OK) {
412
        // fd_data may be freed in callbacks.
413
        int handshake = fd_data->handshake = ssl_handshake_status(fd_data->ssl);
414
        if(handshake == SSL_OK){
415
          TCP_SSL_DEBUG("tcp_ssl_read: handshake OK\n");
416
          if(fd_data->on_handshake)
417
            fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data->ssl);
418
          fd_data = tcp_ssl_get(tcp);
419
          if(NULL == fd_data)
420
            return SSL_CLOSE_NOTIFY;
421
        } else if(handshake != SSL_NOT_OK){
422
          TCP_SSL_DEBUG("tcp_ssl_read: handshake error: %d\n", handshake);
423
          if(fd_data->on_error)
424
            fd_data->on_error(fd_data->arg, fd_data->tcp, handshake);
425
          return handshake;
426
          // With current code APP gets called twice at onError handler.
427
          // Once here and again after return when handshake != SSL_CLOSE_NOTIFY.
428
          // As always APP must never free resources at onError only at onDisconnect.
429
        }
430
      }
431
    }
432
  } while (p->tot_len - fd_data->pbuf_offset > 0);
433
 
434
  tcp_recved(tcp, p->tot_len);
435
  fd_data->tcp_pbuf = NULL;
436
  pbuf_free(p);
437
 
438
  return total_bytes;
439
}
440
 
441
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp){
442
  tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
443
  if(tcp_ssl){
444
    return tcp_ssl->ssl;
445
  }
446
  return NULL;
447
}
448
 
449
bool tcp_ssl_has(struct tcp_pcb *tcp){
450
  return tcp_ssl_get(tcp) != NULL;
451
}
452
 
453
int tcp_ssl_is_server(struct tcp_pcb *tcp){
454
  tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
455
  if(tcp_ssl){
456
    return tcp_ssl->type;
457
  }
458
  return -1;
459
}
460
 
461
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg){
462
  tcp_ssl_t * item = tcp_ssl_get(tcp);
463
  if(item) {
464
    item->arg = arg;
465
  }
466
}
467
 
468
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg){
469
  tcp_ssl_t * item = tcp_ssl_get(tcp);
470
  if(item) {
471
    item->on_data = arg;
472
  }
473
}
474
 
475
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg){
476
  tcp_ssl_t * item = tcp_ssl_get(tcp);
477
  if(item) {
478
    item->on_handshake = arg;
479
  }
480
}
481
 
482
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg){
483
  tcp_ssl_t * item = tcp_ssl_get(tcp);
484
  if(item) {
485
    item->on_error = arg;
486
  }
487
}
488
 
489
static tcp_ssl_file_cb_t _tcp_ssl_file_cb = NULL;
490
static void * _tcp_ssl_file_arg = NULL;
491
 
492
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg){
493
  _tcp_ssl_file_cb = cb;
494
  _tcp_ssl_file_arg = arg;
495
}
496
 
497
int ax_get_file(const char *filename, uint8_t **buf) {
498
    //TCP_SSL_DEBUG("ax_get_file: %s\n", filename);
499
    if(_tcp_ssl_file_cb){
500
      return _tcp_ssl_file_cb(_tcp_ssl_file_arg, filename, buf);
501
    }
502
    *buf = 0;
503
    return 0;
504
}
505
 
506
tcp_ssl_t* tcp_ssl_get_by_fd(int fd) {
507
  tcp_ssl_t * item = tcp_ssl_array;
508
  while(item && item->fd != fd){
509
    item = item->next;
510
  }
511
  return item;
512
}
513
/*
514
 * The LWIP tcp raw version of the SOCKET_WRITE(A, B, C)
515
 */
516
int ax_port_write(int fd, uint8_t *data, uint16_t len) {
517
  tcp_ssl_t *fd_data = NULL;
518
  int tcp_len = 0;
519
  err_t err = ERR_OK;
520
 
521
  //TCP_SSL_DEBUG("ax_port_write: %d, %d\n", fd, len);
522
 
523
  fd_data = tcp_ssl_get_by_fd(fd);
524
  if(fd_data == NULL) {
525
    //TCP_SSL_DEBUG("ax_port_write: tcp_ssl[%d] is NULL\n", fd);
526
    return ERR_MEM;
527
  }
528
 
529
  if (data == NULL || len == 0) {
530
    return 0;
531
  }
532
 
533
  if (tcp_sndbuf(fd_data->tcp) < len) {
534
    tcp_len = tcp_sndbuf(fd_data->tcp);
535
    if(tcp_len == 0) {
536
      TCP_SSL_DEBUG("ax_port_write: tcp_sndbuf is zero: %d\n", len);
537
      return ERR_MEM;
538
    }
539
  } else {
540
    tcp_len = len;
541
  }
542
 
543
  if (tcp_len > 2 * fd_data->tcp->mss) {
544
    tcp_len = 2 * fd_data->tcp->mss;
545
  }
546
 
547
  err = tcp_write(fd_data->tcp, data, tcp_len, TCP_WRITE_FLAG_COPY);
548
  if(err < ERR_OK) {
549
    if (err == ERR_MEM) {
550
      TCP_SSL_DEBUG("ax_port_write: No memory %d (%d)\n", tcp_len, len);
551
      return err;
552
    }
553
    TCP_SSL_DEBUG("ax_port_write: tcp_write error: %ld\n", err);
554
    return err;
555
  } else if (err == ERR_OK) {
556
    //TCP_SSL_DEBUG("ax_port_write: tcp_output: %d / %d\n", tcp_len, len);
557
    err = tcp_output(fd_data->tcp);
558
    if(err != ERR_OK) {
559
      TCP_SSL_DEBUG("ax_port_write: tcp_output err: %ld\n", err);
560
      return err;
561
    }
562
  }
563
 
564
  fd_data->last_wr += tcp_len;
565
 
566
  return tcp_len;
567
}
568
 
569
/*
570
 * The LWIP tcp raw version of the SOCKET_READ(A, B, C)
571
 */
572
int ax_port_read(int fd, uint8_t *data, int len) {
573
  tcp_ssl_t *fd_data = NULL;
574
  uint8_t *read_buf = NULL;
575
  uint8_t *pread_buf = NULL;
576
  u16_t recv_len = 0;
577
 
578
  //TCP_SSL_DEBUG("ax_port_read: %d, %d\n", fd, len);
579
 
580
  fd_data = tcp_ssl_get_by_fd(fd);
581
  if (fd_data == NULL) {
582
    TCP_SSL_DEBUG("ax_port_read: tcp_ssl[%d] is NULL\n", fd);
583
    return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
584
  }
585
 
586
  if(fd_data->tcp_pbuf == NULL || fd_data->tcp_pbuf->tot_len == 0) {
587
    return 0;
588
  }
589
 
590
  read_buf =(uint8_t*)calloc(fd_data->tcp_pbuf->len + 1, sizeof(uint8_t));
591
  pread_buf = read_buf;
592
  if (pread_buf != NULL){
593
    recv_len = pbuf_copy_partial(fd_data->tcp_pbuf, read_buf, len, fd_data->pbuf_offset);
594
    fd_data->pbuf_offset += recv_len;
595
  }
596
 
597
  if (recv_len != 0) {
598
    memcpy(data, read_buf, recv_len);
599
  }
600
 
601
  if(len < recv_len) {
602
    TCP_SSL_DEBUG("ax_port_read: got %d bytes more than expected\n", recv_len - len);
603
  }
604
 
605
  free(pread_buf);
606
  pread_buf = NULL;
607
 
608
  return recv_len;
609
}
610
 
611
void ax_wdt_feed() {}
612
 
613
#endif