/* * ard_tcp.c * * Created on: May 27, 2010 * Author: mlf by Metodo2 srl */ //#define _APP_DEBUG_ #include "lwip/opt.h" #include "lwip/mem.h" #include "lwip/raw.h" #include "lwip/icmp.h" #include "lwip/netif.h" #include "lwip/sys.h" #include "lwip/sockets.h" #include "lwip/inet.h" #include "lwip/inet_chksum.h" #include "lwip/tcp.h" #include "lwip/udp.h" #include "ard_tcp.h" #include "ard_spi.h" #include "timer.h" #include "util.h" #include "getopt.h" #include "ard_utils.h" #include "debug.h" #include "trace.h" unsigned int startTime = 0; extern bool ifStatus; static err_t tcp_data_sent(void *arg, struct tcp_pcb *pcb, u16_t len); static void atcp_init_pend_flags(struct ttcp* _ttcp) { int i = 0; for (; ipending_close[i] = false; } } /** * Clean up and free the ttcp structure */ static void ard_tcp_destroy(struct ttcp* ttcp) { err_t err = ERR_OK; DUMP_TCP_STATE(ttcp); uint8_t sock = getSock(ttcp); if (sock == -1) WARN("ttcp already deallocated!\n"); freeAllTcpData(sock); int i = 0; for (; itpcb[i]) { tcp_arg(ttcp->tpcb[i], NULL); tcp_sent(ttcp->tpcb[i], NULL); tcp_recv(ttcp->tpcb[i], NULL); tcp_err(ttcp->tpcb[i], NULL); //TEMPORAQARY //err = tcp_close(ttcp->tpcb); INFO_TCP("Closing tpcb: state:0x%x err:%d\n", ttcp->tpcb[i]->state, err); } } if (ttcp->lpcb) { tcp_arg(ttcp->lpcb, NULL); tcp_accept(ttcp->lpcb, NULL); err = tcp_close(ttcp->lpcb); INFO_TCP("Closing lpcb: state:0x%x err:%d\n", ttcp->lpcb->state, err); } if (ttcp->upcb) { udp_disconnect(ttcp->upcb); udp_remove(ttcp->upcb); } FREE_PAYLOAD(ttcp); free(ttcp); } /** * Invoked when transfer is done or aborted (non-zero result). */ static void ard_tcp_done(struct ttcp* ttcp, int result) { // if (result == 0) // ard_tcp_print_stats(ttcp); if (ttcp->done_cb) ttcp->done_cb(ttcp->opaque, result); ard_tcp_destroy(ttcp); clearMapSockTcp(getSock(ttcp), GET_TCP_MODE(ttcp)); } /** * Only used in TCP mode. * Will transmit a maximum of pbuf->tot_len bytes. * Called upon connect and when there's space available in the TCP send window * */ static err_t tcp_send_data_pcb(struct ttcp *ttcp, struct tcp_pcb *pcb) { err_t err = ERR_OK; uint32_t len; GET_CLIENT_ID(ttcp, pcb); len = ttcp->left[id]; ttcp->buff_sent[id] = 0; if (len == 0) return ERR_MEM; INFO_TCP_VER("left=%d len:%d\n", ttcp->left[id], len); /* don't send more than we have in the payload */ if (len > ttcp->buflen) len = ttcp->buflen; /* We cannot send more data than space available in the send buffer. */ if (len > tcp_sndbuf(pcb)) len = tcp_sndbuf(pcb); IF_TCP(startTime = timer_get_ms()); err = tcp_write(pcb, ttcp->payload[id], len, TCP_WRITE_FLAG_COPY); if (err != ERR_OK) { INFO_TCP("tcp_write failed %p state:%d len:%d err:%d\n", pcb, pcb->state, len, err); ttcp->buff_sent[id] = 0; }else{ ttcp->buff_sent[id] = 1; ttcp->left[id] -= len; } return err; } /** * Only used in TCP mode. */ static err_t tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err) { struct ttcp* _ttcp = arg; if (_ttcp == NULL) return ERR_ARG; GET_CLIENT_ID(_ttcp, tpcb); INFO_TCP("TTCP [%p-%p]: connect %d %d\n", _ttcp, tpcb, err, tpcb->state); _connected = ( tpcb->state == ESTABLISHED) ? 1 : 0; _ttcp->tcp_poll_retries[id] = 0; _ttcp->start_time = timer_get_ms(); return ERR_OK; } static void cleanSockState_cb(void *ctx) { struct ttcp* _ttcp = ctx; if (_ttcp == NULL) return; int sock = getSock(_ttcp); if (sock != -1) clearMapSockTcp(sock, GET_TCP_MODE(_ttcp)); INFO_TCP("TTCP [%p]: cleanSockState_cb %d\n", _ttcp, sock); _connected = false; } /** * Only used in TCP mode. */ static err_t close_conn_pcb(struct tcp_pcb* tpcb) { err_t err = tcp_close(tpcb); if (err== ERR_OK) { tcp_arg(tpcb, NULL); tcp_sent(tpcb, NULL); tcp_recv(tpcb, NULL); } INFO_TCP("Closing tpcb[%p]: state:0x%x err:%d\n", tpcb, tpcb->state, err); return err; } static void atcp_conn_err_cb(void *arg, err_t err) { struct ttcp* _ttcp = arg; WARN("TTCP [%p]: connection error: %d currId:%d\n", _ttcp, err, getCurrClientConnId()); if (ifStatus == false) printk("Abort connection\n"); if (err == ERR_ABRT) { removeNewClientConn(_ttcp, GET_CURR_PCB(_ttcp)); FREE_PAYLOAD_ID(_ttcp, getCurrClientConnId()); } } static void atcp_conn_cli_err_cb(void *arg, err_t err) { struct ttcp* _ttcp = arg; if (_ttcp == NULL) return; WARN("TTCP [%p]: connection error: %d arg:%p\n", _ttcp, err, arg); if (ifStatus == false) printk("Abort connection\n"); if ((_ttcp)&&(err == ERR_ABRT)) { WARN("TTCP [%p]: free memory\n", _ttcp); cleanSockState_cb(_ttcp); // TODO FREE_PAYLOAD(_ttcp); } //atcp_init_pend_flags(_ttcp); } static err_t close_conn(struct ttcp *_ttcp, struct tcp_pcb* tpcb) { if (_ttcp == NULL) return ERR_MEM; GET_CLIENT_ID(_ttcp, tpcb); err_t err = close_conn_pcb(_ttcp->tpcb[id]); if (err == ERR_MEM) { WARN("Cannot close id:%d-%p put pending\n", id, _ttcp->tpcb[id]); _ttcp->pending_close[id] = true; } else{ _ttcp->pending_close[id] = false; removeNewClientConn(_ttcp, _ttcp->tpcb[id]); FREE_PAYLOAD_ID(_ttcp, id); INFO_TCP("----------------------\n"); } return err; } void closeConnections() { int ii=0; for (; iiudp == TCP_MODE) { ard_tcp_destroy(_ttcp); clearMapSockTcp(getSock(_ttcp), GET_TCP_MODE(_ttcp)); } } } } } /** * Only used in TCP mode. */ static err_t atcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { struct ttcp* ttcp = arg; if (err == ERR_OK && p != NULL) { DATA_LED_ON(); /* for print_stats() */ ttcp->recved += p->tot_len; if ((ttcp->verbose)||(verboseDebug & INFO_TCP_FLAG)) { INFO_TCP("len:%d\n",p->tot_len); DUMP_TCP(p->payload, p->tot_len); ttcp->print_cnt++; } uint8_t* pBufferStore = insert_pBuf(p, ttcp->sock, (void*) pcb); INFO_TCP("sock:%d pcb:%p pbuf:%p err:%d bufStore:%p len:%d\n", ttcp->sock, pcb, p, err, pBufferStore, p->tot_len); pbuf_free(p); DATA_LED_OFF(); } /* p will be NULL when remote end is done */ if (err == ERR_OK && p == NULL) { INFO_TCP("atcp_recv_cb p=NULL on sock:%d pcb:%p\n", ttcp->sock, pcb); close_conn(ttcp, pcb); } if (err!=ERR_OK) WARN("err=%d p=%p\n", err, p); return ERR_OK; } void ack_recved(void* pcb, int len) { // Comment the call because it is activated on atcp_recv_cb INFO_TCP("Received %p len:%d\n", pcb, len); tcp_recved(pcb, len); } static err_t atcp_poll(void *arg, struct tcp_pcb *pcb) { struct ttcp* _ttcp = arg; if (_ttcp == NULL) return ERR_ARG; GET_CLIENT_ID(_ttcp, pcb); if (_ttcp->left[id]>0) ++_ttcp->tcp_poll_retries[id]; if (_ttcp->tcp_poll_retries[id] > 4) { WARN("ARD TCP [%p] arg=%p retries=%d abort\n", pcb, arg, _ttcp->tcp_poll_retries[id]); _ttcp->tcp_poll_retries[id] = 0; tcp_abort(pcb); _ttcp->pending_close[id] = false; return ERR_ABRT; } if (pcb) INFO_TCP_POLL("keepAliveCnt:%d keep_idle:%d persist_cnt:%d\n", pcb->keep_cnt_sent, pcb->keep_idle, pcb->persist_cnt); if (_ttcp->left[id] > 0) INFO_TCP("ARD TCP [%p-%p] arg=%p retries=%d pend.close:%d len:%d\n", (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, pcb, arg, _ttcp->tcp_poll_retries[id], _ttcp->pending_close[id], (_ttcp)?_ttcp->left[id]:0); tcp_send_data_pcb(_ttcp, pcb); if (_ttcp->pending_close[id]) { err_t err = ERR_OK; if (id >=0){ err = tcp_close(pcb); if (err == ERR_MEM) { _ttcp->pending_close[id] = true; } else { _ttcp->pending_close[id] = false; removeNewClientConn(_ttcp, _ttcp->tpcb[id]); FREE_PAYLOAD_ID(_ttcp, id); INFO_TCP("----------------------\n"); } } INFO_TCP("ARD TCP [%p-%p] try to close pending:%d err:%d id:%d\n", pcb, (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, _ttcp->pending_close[id], err, id); } return ERR_OK; } static err_t atcp_poll_conn(void *arg, struct tcp_pcb *pcb) { struct ttcp* _ttcp = arg; if (_ttcp == NULL) return ERR_ARG; GET_CLIENT_ID(_ttcp, pcb) INFO_TCP_POLL("ARD TCP [%p-%p] arg=%p retries=%d pend.close:%d conn:%d\n", (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, pcb, arg, _ttcp->tcp_poll_retries[id], _ttcp->pending_close[id], _connected); if (id != NO_VALID_ID) { if (_ttcp->pending_close[id]) ++(_ttcp->tcp_poll_retries[id]); } if (_ttcp->tcp_poll_retries[id] > 8) { WARN("ARD TCP [%p-%p] arg=%p retries=%d\n", pcb, GET_FIRST_CLIENT_TCP(_ttcp), arg, _ttcp->tcp_poll_retries[id]); _ttcp->tcp_poll_retries[id] = 0; tcp_abort(pcb); return ERR_ABRT; } if ((_ttcp)&&(_connected)) tcp_send_data_pcb(_ttcp, pcb); if ((id != NO_VALID_ID) && (_ttcp->pending_close[id])) { err_t err = tcp_close(pcb); if (err == ERR_MEM) { _ttcp->pending_close[id] = true; } else { cleanSockState_cb(_ttcp); FREE_PAYLOAD_ID(_ttcp, id); _ttcp->pending_close[id] = false; } INFO_TCP("ARD TCP [%p-%p] try to close pending:%d\n", pcb, (_ttcp)?GET_FIRST_CLIENT_TCP(_ttcp):0, _ttcp->pending_close[id]); } return ERR_OK; } int8_t currConnId = 0; int8_t getCurrClientConnId() { return currConnId;} int8_t getNewClientConnId(struct ttcp* _ttcp, struct tcp_pcb *newpcb) { if (_ttcp != NULL){ int i = 0; for (; itpcb[idx] == newpcb) { INFO_TCP_VER("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, newpcb); return idx; } } } WARN("No Valid Id for ttcp:%p pcb:%p\n", _ttcp, newpcb); return NO_VALID_ID; } struct tcp_pcb * getFirstClient(struct ttcp* _ttcp, bool verbose) { if (_ttcp != NULL){ int i = 0; for (; itpcb[idx] != NULL) { if (verbose) INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, _ttcp->tpcb[idx]); currConnId = idx; return _ttcp->tpcb[idx]; } } } if (verbose) WARN("No Valid client for ttcp:%p\n", _ttcp); return NULL; } int8_t setNewClientConn(struct ttcp* _ttcp, struct tcp_pcb *newpcb, uint8_t id) { if ((_ttcp != NULL)&&(id>=0)&&(idtpcb[id] = newpcb; return id; } return NO_VALID_ID; } int8_t insertNewClientConn(struct ttcp* _ttcp, struct tcp_pcb *newpcb) { if (_ttcp != NULL){ int i = 0; for (; itpcb[idx] == NULL)||(_ttcp->tpcb[idx] == newpcb)) { INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, newpcb); _ttcp->tpcb[idx] = newpcb; return idx; } } } return NO_VALID_ID; } int8_t removeNewClientConn(struct ttcp* _ttcp, struct tcp_pcb *newpcb) { if (_ttcp != NULL){ int i = 0; for (; itpcb[idx] == newpcb) { INFO_TCP("ttcp:%p id=%d, tpcb=%p\n", _ttcp, idx, newpcb); _ttcp->tpcb[idx] = NULL; return idx; } } } return NO_VALID_ID; } bool cleanNewClientConn(struct ttcp* _ttcp) { if (_ttcp != NULL){ int i = 0; for (; itpcb[i] = NULL; return true; } return false; } /** * Only used in TCP mode. */ static err_t atcp_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) { struct ttcp* _ttcp = arg; if (_ttcp == NULL) return ERR_ARG; INFO_TCP("ARD TCP [%p]: accept new [%p]\n", _ttcp, newpcb); INFO_TCP("local:%d remote:%d state:%d\n", newpcb->local_port, newpcb->remote_port, newpcb->state); int8_t id = insertNewClientConn(_ttcp, newpcb); ASSERT((_ttcp->payload[id]==NULL), "payload not freed!"); _ttcp->payload[id] = malloc(_ttcp->buflen); INFO_TCP("Alloc payload %d-%p\n", id, _ttcp->payload[id]); if (_ttcp->payload[id] == NULL) { WARN("TTCP [%p]: could not allocate payload\n", _ttcp); return -1; } tcp_arg(_ttcp->tpcb[id], _ttcp); tcp_recv(_ttcp->tpcb[id], atcp_recv_cb); tcp_err(_ttcp->tpcb[id], atcp_conn_err_cb); tcp_poll(_ttcp->tpcb[id], atcp_poll, 4); // Copy the pointer to ttcp also to TRANSMIT mode for the clients connected to the server int _sock = getSock(_ttcp); if ((_sock != -1)&&(IS_VALID_SOCK(_sock))) setMapSockMode(_sock, _ttcp, TTCP_MODE_TRANSMIT); _ttcp->start_time = timer_get_ms(); return ERR_OK; } /** * Start TCP transfer. */ static int atcp_start(struct ttcp* ttcp) { err_t err = ERR_OK; struct tcp_pcb * p = tcp_new(); if (p == NULL) { WARN("TTCP [%p]: could not allocate pcb\n", ttcp); return -1; } currConnId = 0; tcp_arg(p, ttcp); atcp_init_pend_flags(ttcp); if (ttcp->mode == TTCP_MODE_TRANSMIT) { setNewClientConn(ttcp, p, 0); struct tcp_pcb * pcb = GET_FIRST_CLIENT_TCP(ttcp); tcp_err(pcb, atcp_conn_cli_err_cb); tcp_recv(pcb, atcp_recv_cb); tcp_sent(pcb, tcp_data_sent); tcp_poll(pcb, atcp_poll_conn, 4); _connected = false; INFO_TCP("[tpcb]-%p payload:%p\n", pcb, ttcp->payload[currConnId]); DUMP_TCP_STATE(ttcp); if (tcp_connect(pcb, &ttcp->addr, ttcp->port, tcp_connect_cb) != ERR_OK) { WARN("TTCP [%p]: tcp connect failed\n", ttcp); return -1; } } else { INFO_TCP("BEFORE BIND ttcp:%p lpcb:%p pcb:%p\n", ttcp, ttcp->lpcb, GET_FIRST_CLIENT_TCP(ttcp)); err = tcp_bind(p, IP_ADDR_ANY, ttcp->port); if (err != ERR_OK){ WARN("TTCP [%p]: bind failed err=%d Port already used\n", ttcp, err); return -1; } ttcp->lpcb = tcp_listen(p); if (ttcp->lpcb == NULL) { WARN("TTCP [%p]: listen failed\n", ttcp); return -1; } DUMP_TCP_STATE(ttcp); tcp_accept(ttcp->lpcb, atcp_accept_cb); } return 0; } /** * Only used in UDP mode. Will finalize the ttcp process when an end marker * is seen. */ static void audp_recv_cb(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { struct ttcp* ttcp = arg; /* for print_stats() */ ttcp->recved += p->tot_len; DUMP(p->payload,p->tot_len); if (ttcp->verbose) { printk("."); if (ttcp->print_cnt % 80 == 0) printk("\n"); ttcp->print_cnt++; } INFO_TCP("UDP Insert %p sock:%d addr:%s port:%d\n", p, ttcp->sock, ip2str(*addr), port); insert_pBuf(p, ttcp->sock, (void*) upcb); setRemoteClient(ttcp->sock, addr->addr, port); pbuf_free(p); } /** * Start UDP transfer. */ static int udp_start(struct ttcp* ttcp) { err_t err = ERR_OK; ttcp->udp_end_marker_left = 5; ttcp->upcb = udp_new(); if (ttcp->upcb == NULL) { WARN("TTCP [%p]: could not allocate pcb\n", ttcp); return -1; } INFO_TCP("%s, upcb:%p %s:%d\n", __FUNCTION__, ttcp->upcb, ip2str(ttcp->addr), ttcp->port); if (ttcp->mode == TTCP_MODE_TRANSMIT) { if (udp_connect(ttcp->upcb, &(ttcp->addr), ttcp->port) != ERR_OK) { WARN("TTCP [%p]: udp connect failed\n", ttcp); return -1; } udp_recv(ttcp->upcb, audp_recv_cb, ttcp); } else { /* bind to any IP address on port specified */ err = udp_bind(ttcp->upcb, IP_ADDR_ANY, ttcp->port); if (err!= ERR_OK) { WARN("TTCP [%p]: bind failed err=%d Port already used\n", ttcp, err); return -1; } // clear remote client data setRemoteClient(ttcp->sock, 0, 0); udp_recv(ttcp->upcb, audp_recv_cb, ttcp); } INFO_TCP("%s, loc:0x%x-%d rem:0x%x-%d\n", __FUNCTION__, ttcp->upcb->local_ip.addr, ttcp->upcb->local_port, ttcp->upcb->remote_ip.addr, ttcp->upcb->remote_port); return 0; } /** * Start a new ttcp transfer. It should be possible to call this function * multiple times in order to get multiple ttcp streams. done_cb() will be * invoked upon completion. * */ int ard_tcp_start(struct ip_addr addr, uint16_t port, void *opaque, ard_tcp_done_cb_t *done_cb, int mode, uint16_t nbuf, uint16_t buflen, int udp, int verbose, uint8_t sock, void** _ttcp) { struct ttcp* ttcp; int status; if (mode != TTCP_MODE_TRANSMIT && mode != TTCP_MODE_RECEIVE) { WARN("TTCP [-]: invalid mode\n"); return -1; } if (nbuf == 0) { WARN("TTCP [-]: invalid nbuf\n"); return -1; } if (buflen == 0) { WARN("TTCP [-]: invalid buflen\n"); return -1; } ttcp = calloc(1, sizeof(struct ttcp)); if (ttcp == NULL) { WARN("TTCP [-]: could not allocate memory for ttcp\n"); return -1; } ttcp->addr = addr; ttcp->port = port; ttcp->nbuf = nbuf; ttcp->mode = mode; ttcp->done_cb = done_cb; ttcp->opaque = opaque; ttcp->udp = udp; ttcp->verbose = verbose; ttcp->buflen = buflen; cleanNewClientConn(ttcp); if (ttcp->udp) status = udp_start(ttcp); else status = atcp_start(ttcp); if (status) { WARN("Start server FAILED!\n"); goto fail; } INFO_TCP("TTCP [%p-%p]: nbuf=%d, buflen=%d, port=%d (%s/%s)\n", ttcp, ((ttcp->udp==1)?(void*)ttcp->upcb:GET_FIRST_CLIENT_TCP(ttcp)), ttcp->nbuf, ttcp->buflen, ttcp->port, ProtMode2Str(ttcp->udp), Mode2Str(ttcp->mode)); *_ttcp = (void*) ttcp; ttcp->sock = sock; return 0; fail: ard_tcp_destroy(ttcp); return -1; } void ard_tcp_stop(void* ttcp) { struct ttcp* _ttcp = (struct ttcp*) ttcp; if (_ttcp == NULL) { WARN("ttcp = NULL!\n"); return; } if (_ttcp->mode == TTCP_MODE_TRANSMIT) { int i = getCurrClientConnId(); ard_tcp_destroy(_ttcp); clearMapSockTcp(getSock(_ttcp), GET_TCP_MODE(_ttcp)); _ttcp->tcp_poll_retries[i] = 0; }else{ DUMP_TCP_STATE(_ttcp); int i = getCurrClientConnId(); if ((_ttcp)&&(_ttcp->tpcb[i])&&(_ttcp->tpcb[i]->state!=LAST_ACK)&&(_ttcp->tpcb[i]->state!=CLOSED)) { // Flush all the data err_t err=tcp_output(_ttcp->tpcb[i]); INFO_TCP("flush data: tpcb:%p err:%d\n", _ttcp->tpcb[i], err); // if any socket cannot be close stop the close connection close_conn(_ttcp, _ttcp->tpcb[i]); } } } uint8_t getStateTcp(void* p, bool client) { struct ttcp* _ttcp = (struct ttcp*) p; if (ifStatus == false) return CLOSED; struct tcp_pcb * pcb = GET_FIRST_CLIENT_TCP_NV(_ttcp); if ((_ttcp != NULL) && ((pcb != NULL) || (client==0))) { IF_SPI_POLL(DUMP_TCP_STATE(_ttcp)); if (client) { if ((pcb->state != ESTABLISHED)&&(pcb->state != CLOSED)) DUMP_TCP_STATE(_ttcp); return pcb->state; } else { return _ttcp->lpcb->state; } } else { WARN_POLL("TCP not initialized ttcp:%p tpcb:%p lpcb:%p\n", _ttcp, ((_ttcp)?pcb:0), ((_ttcp)?_ttcp->lpcb:0)); } return CLOSED; } uint8_t getModeTcp(void* p) { struct ttcp* _ttcp = (struct ttcp*) p; if (_ttcp != NULL) return _ttcp->mode; return 0; } uint8_t isDataSent(void* p) { struct ttcp *_ttcp = (struct ttcp *)p; int8_t id = getCurrClientConnId(); if ((_ttcp)&&(!_ttcp->buff_sent[id])) { return 0; } return 1; } static err_t tcp_data_sent(void *arg, struct tcp_pcb *pcb, u16_t len) { struct ttcp *_ttcp; LWIP_UNUSED_ARG(len); _ttcp = arg; if (_ttcp == NULL) return ERR_ARG; GET_CLIENT_ID(_ttcp, pcb); _ttcp->tcp_poll_retries[id] = 0; _ttcp->buff_sent[id] = 1; INFO_TCP("Packet sent pcb:%p len:%d dur:%d left:%d\n", pcb, len, timer_get_ms() - startTime, (_ttcp)?(_ttcp->left[id]):0); if ((_ttcp)&&(_ttcp->left[id] > 0)) { tcp_send_data_pcb(_ttcp, pcb); } return ERR_OK; } int sendTcpData(void* p, uint8_t* buf, uint16_t len) { struct ttcp* _ttcp = (struct ttcp*) p; if (_ttcp==NULL) { WARN("ttcp == NULL!\n"); return WL_FAILURE; } struct tcp_pcb * pcb = GET_FIRST_CLIENT_TCP_NV(_ttcp); GET_CLIENT_ID(_ttcp, pcb); INFO_TCP_VER("ttcp:%p pcb:%p buf:%p len:%d\n", _ttcp, pcb, buf, len); DUMP_TCP(buf,len); IF_TCP_VER(DUMP_TCP_STATE(_ttcp)); if ((_ttcp != NULL) && (pcb != NULL) && (buf != NULL) && (len != 0) && (_ttcp->payload[id] != NULL)) { if (pcb->state == ESTABLISHED || pcb->state == CLOSE_WAIT || pcb->state == SYN_SENT || pcb->state == SYN_RCVD) { memcpy(_ttcp->payload[id], buf, len); _ttcp->payload[id][len]='\0'; INFO_TCP_VER("'%s'\n", _ttcp->payload[id]); _ttcp->left[id] = len; tcp_sent(pcb, tcp_data_sent); tcp_send_data_pcb(_ttcp, pcb); return WL_SUCCESS; } } //printk("Write failure _ttcp=%p _ttcp->tpcb=%p buf=%p len=%d\n", _ttcp, _ttcp->tpcb, buf, len); return WL_FAILURE; } int sendUdpData(void* ttcp, uint8_t* buf, uint16_t len) { struct ttcp* _ttcp = (struct ttcp*) ttcp; if ((_ttcp != NULL) && (buf != NULL) && (len != 0)) { INFO_TCP("buf:%p len:%d\n", buf, len); DUMP_TCP(buf,len); }else{ return WL_FAILURE; } struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); if (p == NULL) { WARN("TTCP [%p]: could not allocate pbuf\n", ttcp); return WL_FAILURE; } memcpy(p->payload, buf, len); if (udp_send(_ttcp->upcb, p) != ERR_OK) { WARN("TTCP [%p]: udp_send() failed\n", _ttcp); pbuf_free(p); return WL_FAILURE; } pbuf_free(p); return WL_SUCCESS; } char usage[] = "Usage: ttcp -t/-r [-options] host\n\ -l length of bufs written to network (default 1024)\n\ -n number of bufs written to network (default 1024)\n\ -p port number to send to (default 2000)\n\ -u udp\n\ -v verbose\n"; /** * */ cmd_state_t cmd_ttcp(int argc, char* argv[], void* ctx) { int c; int mode = TTCP_MODE_TRANSMIT; int verbose = 0; uint16_t buflen = 1024; uint16_t nbuf = 1024; uint16_t port = 2000; int udp = 0; struct ip_addr addr = { 0 }; optind = 1; while ((c = getopt(argc, argv, "utrl:n:p:v")) != -1) { switch (c) { case 't': mode = TTCP_MODE_TRANSMIT; break; case 'r': mode = TTCP_MODE_RECEIVE; break; case 'l': buflen = atoi(optarg); break; case 'v': verbose = 1; break; case 'n': nbuf = atoi(optarg); break; case 'u': udp = 1; break; case 'p': port = atoi(optarg); break; } } if (mode == TTCP_MODE_TRANSMIT) { if (optind >= argc) { printk("%s", usage); return CMD_DONE; } addr = str2ip(argv[optind]); if (!addr.addr) { printk("%s", usage); return CMD_DONE; } } void* _ttcp = NULL; if (ard_tcp_start(addr, port, NULL, NULL, mode, nbuf, buflen, udp, verbose, 0, &_ttcp)) return CMD_DONE; return CMD_DONE; } #if 0 #include "lwip/sockets.h" void testlwip() { int Sock; fd_set fdsetR; FD_ZERO(&fdsetR); FD_SET(Sock, &fdsetR); fd_set fdsetE = fdsetR; int rc; const int cMillies = 10000; struct timeval timeout; timeout.tv_sec = cMillies / 1000; timeout.tv_usec = (cMillies % 1000) * 1000; //rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout); } #endif