/*---------------------------------------------------------------------------*/ void tcpip_uipcall(struct net_buf *buf) { uip_udp_appstate_t *ts; #if UIP_UDP if(uip_conn(buf) != NULL) { ts = &uip_conn(buf)->appstate; } else { ts = &uip_udp_conn(buf)->appstate; } #else /* UIP_UDP */ ts = &uip_conn(buf)->appstate; #endif /* UIP_UDP */ #if UIP_TCP { static unsigned char i; struct listenport *l; /* If this is a connection request for a listening port, we must mark the connection with the right process ID. */ if(uip_connected()) { l = &s.listenports[0]; for(i = 0; i < UIP_LISTENPORTS; ++i) { if(l->port == uip_conn->lport && l->p != PROCESS_NONE) { ts->p = l->p; ts->state = NULL; break; } ++l; } /* Start the periodic polling, if it isn't already active. */ start_periodic_tcp_timer(); } } #endif /* UIP_TCP */ if(ts->p != NULL) { process_post_synch(ts->p, tcpip_event, ts->state, buf); } }
/* This is called by contiki/ip/tcpip.c:tcpip_uipcall() when packet * is processed. */ PROCESS_THREAD(tcp, ev, data, buf, user_data) { PROCESS_BEGIN(); while(1) { PROCESS_YIELD_UNTIL(ev == tcpip_event); if (POINTER_TO_INT(data) == TCP_WRITE_EVENT) { /* We want to send data to peer. */ struct net_context *context = user_data; if (!context) { continue; } do { context = user_data; if (!context || !buf) { break; } if (!context->ps.net_buf || context->ps.net_buf != buf) { NET_DBG("psock init %p buf %p\n", &context->ps, buf); PSOCK_INIT(&context->ps, buf); } handle_tcp_connection(&context->ps, POINTER_TO_INT(data), buf); PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); if (POINTER_TO_INT(data) != TCP_WRITE_EVENT) { goto read_data; } } while(!(uip_closed(buf) || uip_aborted(buf) || uip_timedout(buf))); context = user_data; if (context && context->tcp_type == NET_TCP_TYPE_CLIENT) { NET_DBG("\nConnection closed.\n"); ip_buf_sent_status(buf) = -ECONNRESET; } continue; } read_data: /* We are receiving data from peer. */ if (buf && uip_newdata(buf)) { struct net_buf *clone; if (!uip_len(buf)) { continue; } /* Note that uIP stack will reuse the buffer when * sending ACK to peer host. The sending will happen * right after this function returns. Because of this * we cannot use the same buffer to pass data to * application. */ clone = net_buf_clone(buf); if (!clone) { NET_ERR("No enough RX buffers, " "packet %p discarded\n", buf); continue; } ip_buf_appdata(clone) = uip_buf(clone) + (ip_buf_appdata(buf) - (void *)uip_buf(buf)); ip_buf_appdatalen(clone) = uip_len(buf); ip_buf_len(clone) = ip_buf_len(buf); ip_buf_context(clone) = user_data; uip_set_conn(clone) = uip_conn(buf); uip_flags(clone) = uip_flags(buf); uip_flags(clone) |= UIP_CONNECTED; NET_DBG("packet received context %p buf %p len %d " "appdata %p appdatalen %d\n", ip_buf_context(clone), clone, ip_buf_len(clone), ip_buf_appdata(clone), ip_buf_appdatalen(clone)); nano_fifo_put(net_context_get_queue(user_data), clone); /* We let the application to read the data now */ fiber_yield(); } } PROCESS_END(); }