/* 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(); }
/* Run Server * Function tat will create a new socket, accept and handle connections from clients */ void run_server ( settings_t **settings, char* ( *callback ) ( char* ) ) { fd_set master; fd_set readSet; int listener; int new_fd; int max_fd; int i; /* Create our socket for handling connections */ listener = create_tcp_socket ( LISTEN_PORT ); /* Zero out the master fd_set */ FD_ZERO ( &master ); /* Add the server socket to the set of sockets */ FD_SET ( listener, &master ); /* The highest file descriptor (fd) */ max_fd = listener; /* Infinite loop */ for ( ;; ) { /* Copy the master set into a temporary fd */ readSet = master; /* Handle multiple connections via Select */ if ( select ( max_fd + 1, &readSet, NULL, NULL, NULL ) == -1 ) { DIE ( "select() failed" ); } /* Spin through all of the items in readSet and check for connections or requests */ for ( i = 0; i <= max_fd; i++ ) { /* We've got a new one! */ if (FD_ISSET ( i, &readSet ) ) { if ( i == listener ) { /* Accept a new client */ new_fd = accept_tcp_connection ( listener ); /* Add it to the list of sockets */ FD_SET ( new_fd, &master ); /* Specify the new max, if need be */ if ( new_fd > max_fd ) { max_fd = new_fd; } } else { /* Process information coming from a given socket, and close if necessary */ if ( handle_tcp_connection ( i, callback ) == 0 ) { close ( i ); FD_CLR ( i, &master ); } } } } } /* shut down */ close ( listener ); }