source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifiHD/src/ard_tcp.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

File size: 22.1 KB
Line 
1/*
2 * ard_tcp.c
3 *
4 *  Created on: May 27, 2010
5 *      Author: mlf by Metodo2 srl
6 */
7
8//#define _APP_DEBUG_
9#include "lwip/opt.h"
10
11#include "lwip/mem.h"
12#include "lwip/raw.h"
13#include "lwip/icmp.h"
14#include "lwip/netif.h"
15#include "lwip/sys.h"
16#include "lwip/sockets.h"
17#include "lwip/inet.h"
18#include "lwip/inet_chksum.h"
19#include "lwip/tcp.h"
20#include "lwip/udp.h"
21
22#include "ard_tcp.h"
23#include "ard_spi.h"
24#include "timer.h"
25#include "util.h"
26
27#include "getopt.h"
28#include "ard_utils.h"
29#include "debug.h"
30#include "trace.h"
31
32unsigned int startTime = 0;
33extern bool ifStatus;
34
35static err_t tcp_data_sent(void *arg, struct tcp_pcb *pcb, u16_t len);
36
37static void atcp_init_pend_flags(struct ttcp* _ttcp)
38{
39        int i = 0;
40        for (; i<MAX_CLIENT_ACCEPTED; ++i)
41        {
42                if (_ttcp) _ttcp->pending_close[i] = false;
43        }               
44}
45
46/**
47 * Clean up and free the ttcp structure
48 */
49static void ard_tcp_destroy(struct ttcp* ttcp) {
50        err_t err = ERR_OK;
51        DUMP_TCP_STATE(ttcp);
52
53        uint8_t sock = getSock(ttcp);
54        if (sock == -1)
55                WARN("ttcp already deallocated!\n");
56
57        freeAllTcpData(sock);
58        int i = 0;
59        for (; i<MAX_CLIENT_ACCEPTED; ++i)
60        {
61                if (ttcp->tpcb[i]) {
62                        tcp_arg(ttcp->tpcb[i], NULL);
63                        tcp_sent(ttcp->tpcb[i], NULL);
64                        tcp_recv(ttcp->tpcb[i], NULL);
65                        tcp_err(ttcp->tpcb[i], NULL);
66                        //TEMPORAQARY
67                        //err = tcp_close(ttcp->tpcb);
68                        INFO_TCP("Closing tpcb: state:0x%x err:%d\n", ttcp->tpcb[i]->state, err);
69                }               
70        }
71
72        if (ttcp->lpcb) {
73                tcp_arg(ttcp->lpcb, NULL);
74                tcp_accept(ttcp->lpcb, NULL);
75                err = tcp_close(ttcp->lpcb);
76                INFO_TCP("Closing lpcb: state:0x%x err:%d\n", ttcp->lpcb->state, err);
77        }
78
79        if (ttcp->upcb) {
80                udp_disconnect(ttcp->upcb);
81                udp_remove(ttcp->upcb);
82        }
83
84        FREE_PAYLOAD(ttcp);
85        free(ttcp);
86}
87
88/**
89 * Invoked when transfer is done or aborted (non-zero result).
90 */
91static void ard_tcp_done(struct ttcp* ttcp, int result) {
92//      if (result == 0)
93//              ard_tcp_print_stats(ttcp);
94
95        if (ttcp->done_cb)
96                ttcp->done_cb(ttcp->opaque, result);
97
98        ard_tcp_destroy(ttcp);
99        clearMapSockTcp(getSock(ttcp), GET_TCP_MODE(ttcp));
100}
101
102/**
103 * Only used in TCP mode.
104 * Will transmit a maximum of pbuf->tot_len bytes.
105 * Called upon connect and when there's space available in the TCP send window
106 *
107 */
108static err_t tcp_send_data_pcb(struct ttcp *ttcp, struct tcp_pcb *pcb) {
109        err_t err = ERR_OK;
110        uint32_t len;
111
112        GET_CLIENT_ID(ttcp, pcb);
113       
114        len = ttcp->left[id];
115        ttcp->buff_sent[id] = 0;
116
117        if (len == 0) return ERR_MEM;
118
119        INFO_TCP_VER("left=%d len:%d\n", ttcp->left[id], len);
120
121        /* don't send more than we have in the payload */
122        if (len > ttcp->buflen)
123                len = ttcp->buflen;
124
125        /* We cannot send more data than space available in the send
126         buffer. */
127        if (len > tcp_sndbuf(pcb))
128                len = tcp_sndbuf(pcb);
129
130        IF_TCP(startTime = timer_get_ms());
131        err = tcp_write(pcb, ttcp->payload[id], len, TCP_WRITE_FLAG_COPY);
132        if (err != ERR_OK)
133        {
134                INFO_TCP("tcp_write failed %p state:%d len:%d err:%d\n", 
135                                pcb, pcb->state, len, err);
136                ttcp->buff_sent[id] = 0;
137        }else{
138                ttcp->buff_sent[id] = 1;
139                ttcp->left[id] -= len;
140        }
141
142        return err;
143}
144
145
146/**
147 * Only used in TCP mode.
148 */
149static err_t tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err) {
150        struct ttcp* _ttcp = arg;
151
152        if (_ttcp == NULL) return ERR_ARG;
153
154        GET_CLIENT_ID(_ttcp, tpcb);
155        INFO_TCP("TTCP [%p-%p]: connect %d %d\n", _ttcp, tpcb, err, tpcb->state);
156
157        _connected =  ( tpcb->state == ESTABLISHED) ? 1 : 0;
158        _ttcp->tcp_poll_retries[id] = 0;
159
160        _ttcp->start_time = timer_get_ms();
161
162        return ERR_OK;
163}
164
165static void cleanSockState_cb(void *ctx) {
166        struct ttcp* _ttcp = ctx;
167
168        if (_ttcp == NULL) return;
169
170        int sock = getSock(_ttcp);
171        if (sock != -1)
172                clearMapSockTcp(sock, GET_TCP_MODE(_ttcp));
173        INFO_TCP("TTCP [%p]: cleanSockState_cb %d\n", _ttcp, sock);
174        _connected = false;
175}
176
177/**
178 * Only used in TCP mode.
179 */
180
181static err_t close_conn_pcb(struct tcp_pcb* tpcb) {
182
183        err_t err = tcp_close(tpcb);
184        if (err== ERR_OK)
185        {
186                tcp_arg(tpcb, NULL);
187                tcp_sent(tpcb, NULL);
188                tcp_recv(tpcb, NULL);
189        }
190
191        INFO_TCP("Closing tpcb[%p]: state:0x%x err:%d\n", tpcb, tpcb->state, err);
192        return err;
193}
194
195static void atcp_conn_err_cb(void *arg, err_t err) {
196        struct ttcp* _ttcp = arg;
197
198        WARN("TTCP [%p]: connection error: %d currId:%d\n",
199                        _ttcp, err, getCurrClientConnId());
200
201        if (ifStatus == false)
202                printk("Abort connection\n");
203
204        if (err == ERR_ABRT)
205        {
206                removeNewClientConn(_ttcp, GET_CURR_PCB(_ttcp));
207                FREE_PAYLOAD_ID(_ttcp, getCurrClientConnId());
208        }
209}
210
211static void atcp_conn_cli_err_cb(void *arg, err_t err) {
212        struct ttcp* _ttcp = arg;
213
214        if (_ttcp == NULL) return;
215
216        WARN("TTCP [%p]: connection error: %d arg:%p\n",
217                        _ttcp, err, arg);
218
219        if (ifStatus == false)
220                printk("Abort connection\n");
221
222        if ((_ttcp)&&(err == ERR_ABRT))
223        {
224                WARN("TTCP [%p]: free memory\n", _ttcp);
225                cleanSockState_cb(_ttcp);
226                // TODO
227                FREE_PAYLOAD(_ttcp);
228        }
229
230        //atcp_init_pend_flags(_ttcp);
231}
232
233static err_t close_conn(struct ttcp *_ttcp, struct tcp_pcb* tpcb) {
234
235        if (_ttcp == NULL) return ERR_MEM;
236       
237        GET_CLIENT_ID(_ttcp, tpcb);
238
239        err_t err = close_conn_pcb(_ttcp->tpcb[id]);
240
241        if (err == ERR_MEM)
242        {
243                WARN("Cannot close id:%d-%p put pending\n", id, _ttcp->tpcb[id]);
244                _ttcp->pending_close[id] = true;
245        }               
246        else{
247                _ttcp->pending_close[id] = false;
248                removeNewClientConn(_ttcp, _ttcp->tpcb[id]);
249                FREE_PAYLOAD_ID(_ttcp, id);
250                INFO_TCP("----------------------\n");
251        }
252        return err;
253}
254
255void closeConnections()
256{
257        int ii=0;
258        for (; ii<MAX_MODE_NUM; ii++)
259        {
260                int i = 0;
261                for (; i<MAX_SOCK_NUM; i++)
262                {
263                        void* p = getTTCP(i, ii);
264                        if (p)
265                        {
266                                ttcp_t* _ttcp = (ttcp_t* )p;
267                                if (_ttcp->udp == TCP_MODE)
268                                {
269                                        ard_tcp_destroy(_ttcp);
270                                        clearMapSockTcp(getSock(_ttcp), GET_TCP_MODE(_ttcp));
271                                }
272                        }
273                }
274        }
275}
276
277/**
278 * Only used in TCP mode.
279 */
280static err_t atcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
281                err_t err) {
282        struct ttcp* ttcp = arg;
283
284        if (err == ERR_OK && p != NULL) {
285                DATA_LED_ON();
286                /* for print_stats() */
287                ttcp->recved += p->tot_len;
288
289                if ((ttcp->verbose)||(verboseDebug & INFO_TCP_FLAG)) {
290                        INFO_TCP("len:%d\n",p->tot_len);
291                        DUMP_TCP(p->payload, p->tot_len);
292                        ttcp->print_cnt++;
293                }
294
295                uint8_t* pBufferStore = insert_pBuf(p, ttcp->sock, (void*) pcb);
296                INFO_TCP("sock:%d pcb:%p pbuf:%p err:%d bufStore:%p len:%d\n",
297                                ttcp->sock, pcb, p, err, pBufferStore, p->tot_len);
298                pbuf_free(p);
299                DATA_LED_OFF();
300        }
301
302        /* p will be NULL when remote end is done */
303        if (err == ERR_OK && p == NULL) {
304                INFO_TCP("atcp_recv_cb p=NULL on sock:%d pcb:%p\n",     ttcp->sock, pcb);
305                close_conn(ttcp, pcb);
306        }
307
308        if (err!=ERR_OK)
309                WARN("err=%d p=%p\n", err, p);
310        return ERR_OK;
311}
312
313void ack_recved(void* pcb, int len) {
314        // Comment the call because it is activated on atcp_recv_cb
315        INFO_TCP("Received %p len:%d\n", pcb, len);
316        tcp_recved(pcb, len);
317}
318
319static err_t atcp_poll(void *arg, struct tcp_pcb *pcb) {
320        struct ttcp* _ttcp = arg;
321
322        if (_ttcp == NULL) return ERR_ARG;
323       
324        GET_CLIENT_ID(_ttcp, pcb);
325
326        if (_ttcp->left[id]>0)
327                ++_ttcp->tcp_poll_retries[id];
328
329        if (_ttcp->tcp_poll_retries[id] > 4) {
330                WARN("ARD TCP [%p] arg=%p retries=%d abort\n",
331                                pcb, arg, _ttcp->tcp_poll_retries[id]);
332                _ttcp->tcp_poll_retries[id] = 0;
333                tcp_abort(pcb);
334                _ttcp->pending_close[id] = false;
335            return ERR_ABRT;
336        }
337       
338        if (pcb)
339                INFO_TCP_POLL("keepAliveCnt:%d keep_idle:%d persist_cnt:%d\n", 
340                                                pcb->keep_cnt_sent, pcb->keep_idle, pcb->persist_cnt);
341       
342        if (_ttcp->left[id] > 0)
343                INFO_TCP("ARD TCP [%p-%p] arg=%p retries=%d pend.close:%d len:%d\n",
344                        (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, pcb, arg,
345                        _ttcp->tcp_poll_retries[id], _ttcp->pending_close[id], (_ttcp)?_ttcp->left[id]:0);
346        tcp_send_data_pcb(_ttcp, pcb);
347
348        if (_ttcp->pending_close[id])
349        {               
350                err_t err = ERR_OK;
351                if (id >=0){
352                        err = tcp_close(pcb);
353                        if (err == ERR_MEM)
354                        {
355                                _ttcp->pending_close[id] = true;
356                        }
357                        else
358                        {
359                                _ttcp->pending_close[id] = false;
360                                removeNewClientConn(_ttcp, _ttcp->tpcb[id]);
361                                FREE_PAYLOAD_ID(_ttcp, id);
362                                INFO_TCP("----------------------\n");
363                        }
364                }       
365                INFO_TCP("ARD TCP [%p-%p] try to close pending:%d err:%d id:%d\n", pcb, 
366                        (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, _ttcp->pending_close[id], err, id);
367        }
368        return ERR_OK;
369}
370
371static err_t atcp_poll_conn(void *arg, struct tcp_pcb *pcb) {
372        struct ttcp* _ttcp = arg;
373
374        if (_ttcp == NULL) return ERR_ARG;
375
376        GET_CLIENT_ID(_ttcp, pcb)
377       
378        INFO_TCP_POLL("ARD TCP [%p-%p] arg=%p retries=%d pend.close:%d conn:%d\n",
379                (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, pcb, arg,
380                _ttcp->tcp_poll_retries[id], _ttcp->pending_close[id], _connected);
381
382        if (id != NO_VALID_ID)
383        {
384                if (_ttcp->pending_close[id])
385                        ++(_ttcp->tcp_poll_retries[id]);
386        }
387
388        if (_ttcp->tcp_poll_retries[id] > 8) {
389                WARN("ARD TCP [%p-%p] arg=%p retries=%d\n",
390                                pcb, GET_FIRST_CLIENT_TCP(_ttcp), arg, _ttcp->tcp_poll_retries[id]);
391                _ttcp->tcp_poll_retries[id] = 0;
392                tcp_abort(pcb);
393                return ERR_ABRT;
394        }
395
396        if ((_ttcp)&&(_connected)) tcp_send_data_pcb(_ttcp, pcb);
397
398        if ((id != NO_VALID_ID) && (_ttcp->pending_close[id]))
399        {
400                err_t err = tcp_close(pcb);
401                if (err == ERR_MEM)
402                {
403                        _ttcp->pending_close[id] = true;
404                }
405                else
406                {
407                        cleanSockState_cb(_ttcp);
408                        FREE_PAYLOAD_ID(_ttcp, id);
409                        _ttcp->pending_close[id] = false;
410                }
411
412                INFO_TCP("ARD TCP [%p-%p] try to close pending:%d\n", pcb, (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, _ttcp->pending_close[id]);
413        }
414        return ERR_OK;
415}
416
417int8_t currConnId = 0;
418
419int8_t getCurrClientConnId() { return currConnId;}
420
421int8_t getNewClientConnId(struct ttcp* _ttcp, struct tcp_pcb *newpcb)
422{
423        if (_ttcp != NULL){
424                int i = 0;
425                for (; i<MAX_CLIENT_ACCEPTED; ++i)
426                {
427                        int idx = GET_IDX_CONN(i);
428
429                        if (_ttcp->tpcb[idx] == newpcb)
430                        {
431                                INFO_TCP_VER("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, newpcb);
432                                return idx;
433                        }                               
434                }
435        }
436        WARN("No Valid Id for ttcp:%p pcb:%p\n",  _ttcp, newpcb);
437        return NO_VALID_ID;
438}
439
440struct tcp_pcb * getFirstClient(struct ttcp* _ttcp, bool verbose)
441{
442        if (_ttcp != NULL){
443                int i = 0;
444                for (; i<MAX_CLIENT_ACCEPTED; ++i)
445                {
446                        int idx = GET_IDX_CONN(i);
447                        if (_ttcp->tpcb[idx] != NULL)
448                        {
449                                if (verbose) INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, _ttcp->tpcb[idx]);
450                                currConnId = idx;
451                                return _ttcp->tpcb[idx];
452                        }                               
453                }
454        }
455        if (verbose) WARN("No Valid client for ttcp:%p\n",  _ttcp);
456        return NULL;
457}
458
459
460int8_t setNewClientConn(struct ttcp* _ttcp, struct tcp_pcb *newpcb, uint8_t id)
461{
462        if ((_ttcp != NULL)&&(id>=0)&&(id<MAX_CLIENT_ACCEPTED)){
463                INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, id, newpcb);
464                _ttcp->tpcb[id] = newpcb;
465                return id;
466        }
467        return NO_VALID_ID;
468}
469
470int8_t insertNewClientConn(struct ttcp* _ttcp, struct tcp_pcb *newpcb)
471{
472        if (_ttcp != NULL){
473                int i = 0;
474                for (; i<MAX_CLIENT_ACCEPTED; ++i)
475                {
476                        int idx = GET_IDX_CONN(i);
477                        if ((_ttcp->tpcb[idx] == NULL)||(_ttcp->tpcb[idx] == newpcb))
478                        {
479                                INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, newpcb);
480                                _ttcp->tpcb[idx] = newpcb;
481                                return idx;
482                        }
483                }
484        }
485        return NO_VALID_ID;
486}
487
488int8_t removeNewClientConn(struct ttcp* _ttcp, struct tcp_pcb *newpcb)
489{
490        if (_ttcp != NULL){
491                int i = 0;
492                for (; i<MAX_CLIENT_ACCEPTED; ++i)
493                {
494                        int idx = GET_IDX_CONN(i);
495                        if (_ttcp->tpcb[idx] == newpcb)
496                        {
497                                INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, newpcb);
498                                _ttcp->tpcb[idx] = NULL;
499                                return idx;
500                        }
501                }
502        }
503        return NO_VALID_ID;
504}
505
506bool cleanNewClientConn(struct ttcp* _ttcp)
507{
508        if (_ttcp != NULL){
509                int i = 0;
510                for (; i<MAX_CLIENT_ACCEPTED; ++i)
511                        _ttcp->tpcb[i] = NULL;
512                return true;
513        }
514        return false;
515}
516
517
518/**
519 * Only used in TCP mode.
520 */
521static err_t atcp_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
522        struct ttcp* _ttcp = arg;
523
524        if (_ttcp == NULL) return ERR_ARG;
525
526        INFO_TCP("ARD TCP [%p]: accept new [%p]\n", _ttcp, newpcb);
527        INFO_TCP("local:%d remote:%d state:%d\n", newpcb->local_port, newpcb->remote_port, newpcb->state);
528
529        int8_t id = insertNewClientConn(_ttcp, newpcb);
530
531        ASSERT((_ttcp->payload[id]==NULL), "payload not freed!");
532        _ttcp->payload[id] = malloc(_ttcp->buflen);
533        INFO_TCP("Alloc payload %d-%p\n", id, _ttcp->payload[id]);
534        if (_ttcp->payload[id] == NULL) {
535                WARN("TTCP [%p]: could not allocate payload\n", _ttcp);
536                return -1;
537        }
538        tcp_arg(_ttcp->tpcb[id], _ttcp);
539        tcp_recv(_ttcp->tpcb[id], atcp_recv_cb);
540        tcp_err(_ttcp->tpcb[id], atcp_conn_err_cb);
541        tcp_poll(_ttcp->tpcb[id], atcp_poll, 4);
542        // Copy the pointer to ttcp also to TRANSMIT mode for the clients connected to the server
543        int _sock = getSock(_ttcp);
544        if ((_sock != -1)&&(IS_VALID_SOCK(_sock)))
545                setMapSockMode(_sock, _ttcp, TTCP_MODE_TRANSMIT);
546        _ttcp->start_time = timer_get_ms();
547        return ERR_OK;
548}
549
550/**
551 * Start TCP transfer.
552 */
553static int atcp_start(struct ttcp* ttcp) {
554        err_t err = ERR_OK;
555
556        struct tcp_pcb * p = tcp_new();
557       
558        if (p == NULL) {
559                WARN("TTCP [%p]: could not allocate pcb\n", ttcp);
560                return -1;
561        }
562
563        currConnId = 0;
564        tcp_arg(p, ttcp);
565        atcp_init_pend_flags(ttcp);
566
567        if (ttcp->mode == TTCP_MODE_TRANSMIT) {
568                int8_t id = insertNewClientConn(ttcp, p);
569                ttcp->payload[id] = malloc(ttcp->buflen);
570                INFO_TCP("Alloc payload %d-%p\n", id, ttcp->payload[id]);
571                if (ttcp->payload[id] == NULL) {
572                        WARN("TTCP [%p]: could not allocate payload\n", ttcp);
573                        return -1;
574                }
575               
576                struct tcp_pcb * pcb = p;
577                tcp_err(pcb, atcp_conn_cli_err_cb);
578                tcp_recv(pcb, atcp_recv_cb);
579                tcp_sent(pcb, tcp_data_sent);
580                tcp_poll(pcb, atcp_poll_conn, 4);
581                _connected = false;
582                INFO_TCP("[tpcb]-%p payload:%p\n", pcb, ttcp->payload[id]);
583                DUMP_TCP_STATE(ttcp);
584                if (tcp_connect(pcb, &ttcp->addr, ttcp->port, tcp_connect_cb)
585                                != ERR_OK) {
586                        WARN("TTCP [%p]: tcp connect failed\n", ttcp);
587                        return -1;
588                }
589
590        } else {
591                INFO_TCP("BEFORE BIND ttcp:%p lpcb:%p pcb:%p\n", ttcp, ttcp->lpcb, GET_FIRST_CLIENT_TCP(ttcp));
592
593                err = tcp_bind(p, IP_ADDR_ANY, ttcp->port);
594                if (err != ERR_OK){
595                        WARN("TTCP [%p]: bind failed err=%d Port already used\n", ttcp, err);
596                        return -1;
597                }
598
599                ttcp->lpcb = tcp_listen(p);
600                if (ttcp->lpcb == NULL) {
601                        WARN("TTCP [%p]: listen failed\n", ttcp);
602                        return -1;
603                }
604
605                DUMP_TCP_STATE(ttcp);
606                tcp_accept(ttcp->lpcb, atcp_accept_cb);
607        }
608
609        return 0;
610}
611
612/**
613 * Only used in UDP mode. Will finalize the ttcp process when an end marker
614 * is seen.
615 */
616static void audp_recv_cb(void *arg, struct udp_pcb *upcb, struct pbuf *p,
617                struct ip_addr *addr, u16_t port) {
618        struct ttcp* ttcp = arg;
619
620        /* for print_stats() */
621        ttcp->recved += p->tot_len;
622        DUMP(p->payload,p->tot_len);
623        if (ttcp->verbose) {
624                printk(".");
625                if (ttcp->print_cnt % 80 == 0)
626                        printk("\n");
627                ttcp->print_cnt++;
628        }
629        INFO_TCP("UDP Insert %p sock:%d addr:%s port:%d\n", p, ttcp->sock,
630                        ip2str(*addr), port);
631        insert_pBuf(p, ttcp->sock, (void*) upcb);
632        setRemoteClient(ttcp->sock, addr->addr, port);
633
634        pbuf_free(p);
635}
636
637/**
638 * Start UDP transfer.
639 */
640static int udp_start(struct ttcp* ttcp) {
641        err_t err = ERR_OK;
642        ttcp->udp_end_marker_left = 5;
643        ttcp->upcb = udp_new();
644        if (ttcp->upcb == NULL) {
645                WARN("TTCP [%p]: could not allocate pcb\n", ttcp);
646                return -1;
647        }
648
649        INFO_TCP("%s, upcb:%p %s:%d\n", __FUNCTION__, ttcp->upcb, ip2str(ttcp->addr), ttcp->port);
650        if (ttcp->mode == TTCP_MODE_TRANSMIT) {
651                if (udp_connect(ttcp->upcb, &(ttcp->addr), ttcp->port) != ERR_OK) {
652                        WARN("TTCP [%p]: udp connect failed\n", ttcp);
653                        return -1;
654                }
655                udp_recv(ttcp->upcb, audp_recv_cb, ttcp);
656        } else {
657                /* bind to any IP address on port specified */
658                err = udp_bind(ttcp->upcb, IP_ADDR_ANY, ttcp->port);
659                if  (err!= ERR_OK) {
660                        WARN("TTCP [%p]: bind failed err=%d Port already used\n", ttcp, err);
661                    return -1;
662                }
663                // clear remote client data
664                setRemoteClient(ttcp->sock, 0, 0);
665                udp_recv(ttcp->upcb, audp_recv_cb, ttcp);
666        }
667        INFO_TCP("%s, loc:0x%x-%d rem:0x%x-%d\n", __FUNCTION__, 
668                 ttcp->upcb->local_ip.addr, ttcp->upcb->local_port, 
669                 ttcp->upcb->remote_ip.addr, ttcp->upcb->remote_port);
670        return 0;
671}
672
673/**
674 * Start a new ttcp transfer. It should be possible to call this function
675 * multiple times in order to get multiple ttcp streams. done_cb() will be
676 * invoked upon completion.
677 *
678 */
679int ard_tcp_start(struct ip_addr addr, uint16_t port, void *opaque,
680                ard_tcp_done_cb_t *done_cb, int mode, uint16_t nbuf, uint16_t buflen,
681                int udp, int verbose, uint8_t sock, void** _ttcp) {
682        struct ttcp* ttcp;
683        int status;
684
685        if (mode != TTCP_MODE_TRANSMIT && mode != TTCP_MODE_RECEIVE) {
686                WARN("TTCP [-]: invalid mode\n");
687                return -1;
688        }
689
690        if (nbuf == 0) {
691                WARN("TTCP [-]: invalid nbuf\n");
692                return -1;
693        }
694
695        if (buflen == 0) {
696                WARN("TTCP [-]: invalid buflen\n");
697                return -1;
698        }
699
700        ttcp = calloc(1, sizeof(struct ttcp));
701        if (ttcp == NULL) {
702                WARN("TTCP [-]: could not allocate memory for ttcp\n");
703                return -1;
704        }
705
706        ttcp->addr = addr;
707        ttcp->port = port;
708        ttcp->nbuf = nbuf;
709        ttcp->mode = mode;
710        ttcp->done_cb = done_cb;
711        ttcp->opaque = opaque;
712        ttcp->udp = udp;
713        ttcp->verbose = verbose;
714        ttcp->buflen = buflen;
715        cleanNewClientConn(ttcp);
716
717        if (ttcp->udp)
718                status = udp_start(ttcp);
719        else
720                status = atcp_start(ttcp);
721
722        if (status) {
723                WARN("Start server FAILED!\n");
724                goto fail;
725        }
726        INFO_TCP("TTCP [%p-%p]: nbuf=%d, buflen=%d, port=%d (%s/%s)\n", ttcp,
727                        ((ttcp->udp==1)?(void*)ttcp->upcb:GET_FIRST_CLIENT_TCP(ttcp)), ttcp->nbuf, ttcp->buflen, 
728                        ttcp->port, ProtMode2Str(ttcp->udp), Mode2Str(ttcp->mode));
729
730        *_ttcp = (void*) ttcp;
731        ttcp->sock = sock;
732
733        return 0;
734
735        fail: ard_tcp_destroy(ttcp);
736        return -1;
737}
738
739void ard_tcp_stop(void* ttcp) {
740        struct ttcp* _ttcp = (struct ttcp*) ttcp;
741        if (_ttcp == NULL)
742        {
743                WARN("ttcp = NULL!\n");
744                return;
745        }
746        if (_ttcp->mode == TTCP_MODE_TRANSMIT) {
747                int i = getCurrClientConnId();
748                ard_tcp_destroy(_ttcp);
749        clearMapSockTcp(getSock(_ttcp), GET_TCP_MODE(_ttcp));
750        _ttcp->tcp_poll_retries[i] = 0;
751        }else{
752                DUMP_TCP_STATE(_ttcp);
753
754                int i = getCurrClientConnId();
755                if ((_ttcp)&&(_ttcp->tpcb[i])&&(_ttcp->tpcb[i]->state!=LAST_ACK)&&(_ttcp->tpcb[i]->state!=CLOSED))
756                {
757                        // Flush all the data
758                        err_t err=tcp_output(_ttcp->tpcb[i]);
759                        INFO_TCP("flush data: tpcb:%p err:%d\n", _ttcp->tpcb[i], err);
760                        // if any socket  cannot be close stop the close connection
761                        close_conn(_ttcp, _ttcp->tpcb[i]);
762                }
763        }
764}
765
766uint8_t getStateTcp(void* p, bool client) {
767        struct ttcp* _ttcp = (struct ttcp*) p;
768
769        if (ifStatus == false)
770                return CLOSED;
771        struct tcp_pcb * pcb = GET_FIRST_CLIENT_TCP_NV(_ttcp);
772        if ((_ttcp != NULL) && ((pcb != NULL) || (client==0))) {
773                IF_SPI_POLL(DUMP_TCP_STATE(_ttcp));
774                if (client)
775                {
776                        if ((pcb->state != ESTABLISHED)&&(pcb->state != CLOSED))
777                                DUMP_TCP_STATE(_ttcp);
778                        return pcb->state;
779                }                       
780                else
781                {
782                        return _ttcp->lpcb->state;
783                }                       
784        } else {
785                WARN_POLL("TCP not initialized ttcp:%p tpcb:%p lpcb:%p\n",
786                                _ttcp, ((_ttcp)?pcb:0), ((_ttcp)?_ttcp->lpcb:0));
787        }
788        return CLOSED;
789}
790
791uint8_t getModeTcp(void* p) {
792        struct ttcp* _ttcp = (struct ttcp*) p;
793
794        if (_ttcp != NULL)
795                return _ttcp->mode;
796        return 0;
797}
798
799uint8_t isDataSent(void* p) {
800        struct ttcp *_ttcp = (struct ttcp *)p;
801
802        int8_t id = getCurrClientConnId();
803        if ((_ttcp)&&(!_ttcp->buff_sent[id]))
804        {
805                return 0;
806        }
807
808        return 1;
809}
810
811static err_t tcp_data_sent(void *arg, struct tcp_pcb *pcb, u16_t len) {
812        struct ttcp *_ttcp;
813
814        LWIP_UNUSED_ARG(len);
815
816        _ttcp = arg;
817
818        if (_ttcp == NULL) return ERR_ARG;
819
820        GET_CLIENT_ID(_ttcp, pcb);
821        _ttcp->tcp_poll_retries[id] = 0;
822        _ttcp->buff_sent[id] = 1;
823
824        INFO_TCP("Packet sent pcb:%p len:%d dur:%d left:%d\n", pcb, len, timer_get_ms() - startTime,
825                        (_ttcp)?(_ttcp->left[id]):0);
826
827        if ((_ttcp)&&(_ttcp->left[id] > 0)) {
828                tcp_send_data_pcb(_ttcp, pcb);
829        }
830
831        return ERR_OK;
832}
833
834int sendTcpData(void* p, uint8_t* buf, uint16_t len) 
835{
836        struct ttcp* _ttcp = (struct ttcp*) p;
837
838        if (_ttcp==NULL)
839        {
840                WARN("ttcp == NULL!\n");
841                return WL_FAILURE;
842        }
843       
844        struct tcp_pcb * pcb = GET_FIRST_CLIENT_TCP_NV(_ttcp);
845        GET_CLIENT_ID(_ttcp, pcb);
846       
847        INFO_TCP_VER("ttcp:%p pcb:%p buf:%p len:%d\n", _ttcp, pcb, buf, len);
848        DUMP_TCP(buf,len);
849        IF_TCP_VER(DUMP_TCP_STATE(_ttcp));
850
851        if ((_ttcp != NULL) && (pcb != NULL) &&
852                        (buf != NULL) && (len != 0) && (_ttcp->payload[id] != NULL)) {
853                if (pcb->state == ESTABLISHED || pcb->state == CLOSE_WAIT ||
854                        pcb->state == SYN_SENT || pcb->state == SYN_RCVD) {
855
856                memcpy(_ttcp->payload[id], buf, len);
857                _ttcp->payload[id][len]='\0';
858                INFO_TCP_VER("'%s'\n", _ttcp->payload[id]);
859                _ttcp->left[id] = len;
860                tcp_sent(pcb, tcp_data_sent);
861                tcp_send_data_pcb(_ttcp, pcb);
862
863                return WL_SUCCESS;
864                }
865        }
866        //printk("Write failure _ttcp=%p _ttcp->tpcb=%p buf=%p len=%d\n", _ttcp, _ttcp->tpcb, buf, len);
867        return WL_FAILURE;
868}
869
870int sendUdpData(void* ttcp, uint8_t* buf, uint16_t len) {
871        struct ttcp* _ttcp = (struct ttcp*) ttcp;
872        if ((_ttcp != NULL) && (buf != NULL) && (len != 0))
873        {
874                INFO_TCP("buf:%p len:%d\n", buf, len);
875                DUMP_TCP(buf,len);
876        }else{
877                return WL_FAILURE;
878        }
879
880        struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
881        if (p == NULL) {
882                WARN("TTCP [%p]: could not allocate pbuf\n", ttcp);
883                return WL_FAILURE;
884        }
885        memcpy(p->payload, buf, len);
886        if (udp_send(_ttcp->upcb, p) != ERR_OK) {
887                WARN("TTCP [%p]: udp_send() failed\n", _ttcp);
888                pbuf_free(p);
889                return WL_FAILURE;
890        }
891
892        pbuf_free(p);
893        return WL_SUCCESS;
894}
895
896
897
898char
899                usage[] =
900                                "Usage: ttcp -t/-r [-options] host\n\
901        -l      length of bufs written to network (default 1024)\n\
902        -n      number of bufs written to network (default 1024)\n\
903        -p      port number to send to (default 2000)\n\
904        -u      udp\n\
905        -v      verbose\n";
906
907/**
908 *
909 */
910cmd_state_t cmd_ttcp(int argc, char* argv[], void* ctx) {
911
912        int c;
913        int mode = TTCP_MODE_TRANSMIT;
914        int verbose = 0;
915        uint16_t buflen = 1024;
916        uint16_t nbuf = 1024;
917        uint16_t port = 2000;
918        int udp = 0;
919        struct ip_addr addr = { 0 };
920
921        optind = 1;
922        while ((c = getopt(argc, argv, "utrl:n:p:v")) != -1) {
923                switch (c) {
924                case 't':
925                        mode = TTCP_MODE_TRANSMIT;
926                        break;
927                case 'r':
928                        mode = TTCP_MODE_RECEIVE;
929                        break;
930                case 'l':
931                        buflen = atoi(optarg);
932                        break;
933                case 'v':
934                        verbose = 1;
935                        break;
936                case 'n':
937                        nbuf = atoi(optarg);
938                        break;
939                case 'u':
940                        udp = 1;
941                        break;
942                case 'p':
943                        port = atoi(optarg);
944                        break;
945                }
946        }
947
948        if (mode == TTCP_MODE_TRANSMIT) {
949                if (optind >= argc) {
950                        printk("%s", usage);
951                        return CMD_DONE;
952                }
953
954                addr = str2ip(argv[optind]);
955                if (!addr.addr) {
956                        printk("%s", usage);
957                        return CMD_DONE;
958                }
959        }
960        void* _ttcp = NULL;
961        if (ard_tcp_start(addr, port, NULL, NULL, mode, nbuf, buflen, udp, verbose,
962                        0, &_ttcp))
963                return CMD_DONE;
964
965        return CMD_DONE;
966}
967
968
969#if 0
970#include "lwip/sockets.h"
971
972void testlwip()
973{
974        int Sock;
975        fd_set fdsetR;
976        FD_ZERO(&fdsetR);
977        FD_SET(Sock, &fdsetR);
978        fd_set fdsetE = fdsetR;
979
980        int rc;
981        const int cMillies = 10000;
982        struct timeval timeout;
983        timeout.tv_sec = cMillies / 1000;
984        timeout.tv_usec = (cMillies % 1000) * 1000;
985        //rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
986}
987#endif
Note: See TracBrowser for help on using the repository browser.