// Receive a HTTP request void httpd_recv(chanend tcp_svr, xtcp_connection_t *conn) { struct httpd_state_t *hs = (struct httpd_state_t *) conn->appstate; char data[XTCP_CLIENT_BUF_SIZE]; int len; // Receive the data from the TCP stack len = xtcp_recv(tcp_svr, data); // If we already have data to send, return if ( hs == NULL || hs->dptr != NULL) { return; } // Otherwise we have data, so parse it parse_http_request(hs, &data[0], len); // If we are required to send data if (hs->dptr != NULL) { // Initate a send request with the TCP stack. // It will then reply with event XTCP_REQUEST_DATA // when it's ready to send xtcp_init_send(tcp_svr, conn); } //// }
void httpd_recv(chanend tcp_svr, xtcp_connection_t *conn, chanend page_svr, chanend led_svr) { struct httpd_state_t *hs = (struct httpd_state_t *) conn->appstate; char data[XTCP_CLIENT_BUF_SIZE]; int len; len = xtcp_recv(tcp_svr, data); // this assumes that a request fits in one read!! if (hs == NULL || hs->pss.cmdptr != 0) return; parse_http_request(hs, &data[0], len, page_svr, led_svr); if (hs->pss.cmdptr != 0) xtcp_init_send(tcp_svr, conn); else xtcp_close(tcp_svr, conn); }
void telnet_config_event_handler(chanend c_xtcp, chanend c_uart_config, chanend c_flash_data, xtcp_connection_t *conn) { switch (conn->event) { case XTCP_IFUP: case XTCP_IFDOWN: case XTCP_ALREADY_HANDLED: return; default: break; } if (conn->local_port == S2E_TELNET_CONFIG_PORT) { connection_state_t *st = get_state_from_connection(conn); int close_request; int len; switch (conn->event) { case XTCP_NEW_CONNECTION: st = get_new_state(); if (!st) { xtcp_abort(c_xtcp, conn); break; } st->sending_welcome = 1; st->sending_ack = 0; st->err = NULL; st->conn_id = conn->id; init_telnet_parse_state(&st->telnet_parsing_state); reset_parsing_state(st); xtcp_init_send(c_xtcp, conn); break; case XTCP_RECV_DATA: len = xtcp_recv(c_xtcp, buf); if (!st || !st->active) break; len = parse_telnet_buffer(buf, len, &st->telnet_parsing_state, &close_request); parse_config(c_xtcp, c_uart_config, c_flash_data, conn, buf, len, st); if (close_request) xtcp_close(c_xtcp, conn); break; case XTCP_REQUEST_DATA: case XTCP_RESEND_DATA: if (!st || !st->active) { xtcp_complete_send(c_xtcp); break; } // When sending either st->sending_welcome is true, // st->sending_ack is true or st->err is non null. Depending on // whether the connection is sending a welcome message, ack or // error message if (st->sending_welcome) { xtcp_send(c_xtcp, welcome_msg, sizeof(welcome_msg)); } else if (st->sending_ack) { int len = construct_ack(st, buf); xtcp_send(c_xtcp, buf, len); } else if (st->err) { int len = strlen(st->err); strcpy(buf, st->err); buf[len] = '\n'; xtcp_send(c_xtcp, buf, len+1); } else { xtcp_complete_send(c_xtcp); } break; case XTCP_SENT_DATA: xtcp_complete_send(c_xtcp); if (st) { st->sending_ack = 0; st->sending_welcome = 0; st->err = NULL; } break; case XTCP_CLOSED: case XTCP_ABORTED: case XTCP_TIMED_OUT: if (st) { st->active = 0; } break; default: break; } conn->event = XTCP_ALREADY_HANDLED; } }
/** * This function parses received UART configuration requests from telnet * client, validates the requests and executes respective commands. * Various configuration commands supported are: * (a) UART configuration fetch (GET) - for a specified UART * (b) UART configuration apply (SET) - for a specified UART * (c) UART configuration save (SAVE) - apply working UART configurations * for all UARTs repectively * (d) UART configuration retrieve (FETCH) - fetch UART configuration stored * in flash, for all UARTs * @param c_xtcp Channel-end between XTCP and TCP handler thread * @param c_uart_configChannel-end to communicate UART configuration data * TCP handler and UART handler thread * @param c_flash_data Channel-end to communicate UART configuration data * stored in flash to TCP handler thread * @param conn Reference to structure holding IP configuration info * @param buf Buffer containing received UART command * @param len length of buffer * @param st Reference to structure holding Telnet configuration * state information * @return None */ static void parse_config(chanend c_xtcp, chanend c_uart_config, chanend c_flash_data, xtcp_connection_t *conn, char *buf, int len, connection_state_t *st) { char *end = buf + len; while (buf < end) { if (st->config_parsing_state0 == PARSING_SEP) { if (*buf=='~') { buf++; continue; } else { st->config_parsing_state0 = PARSING_VALUE; st->buf_len = 0; continue; } } switch (*buf) { case '~': if (st->config_parsing_state1 == PARSING_TERM) { st->err = invalid_cmd_msg; xtcp_init_send(c_xtcp, conn); reset_parsing_state(st); } else { store_value(st); st->config_parsing_state0 = PARSING_SEP; buf++; } break; case '@': if (st->config_parsing_state1 == PARSING_TERM) { execute_command(c_xtcp, c_uart_config, c_flash_data, conn, st); reset_parsing_state(st); } else { st->err = invalid_cmd_msg; xtcp_init_send(c_xtcp, conn); reset_parsing_state(st); } buf++; break; case 10: case 13: // Newline resets everything reset_parsing_state(st); buf++; break; default: if (st->buf_len < MAX_VALUE_LEN) { st->buf[st->buf_len] = *buf; st->buf_len++; } buf++; break; } } }
static void execute_command(chanend c_xtcp, chanend c_uart_config, chanend c_flash_data, xtcp_connection_t *conn, connection_state_t *st) { int out_channel_id; int flash_result; uart_config_data_t data1; int telnet_port1; switch (st->cmd) { case TELNET_CONFIG_CMD_SET: st->err = s2e_validate_uart_config(&st->config_in); if (st->err) { xtcp_init_send(c_xtcp, conn); return; } st->err = s2e_validate_telnet_port(st->config_in.channel_id, st->telnet_port_in); if (st->err) { xtcp_init_send(c_xtcp, conn); return; } uart_config_data_t *config = uart_get_config(st->config_in.channel_id); *config = st->config_in; uart_set_config(c_uart_config, &st->config_in); telnet_to_uart_set_port(c_xtcp, st->config_in.channel_id, st->telnet_port_in); out_channel_id = st->config_in.channel_id; break; case TELNET_CONFIG_CMD_GET: st->err = s2e_validate_channel_id(st->config_in.channel_id); if (st->err) { xtcp_init_send(c_xtcp, conn); return; } out_channel_id = st->config_in.channel_id; break; case TELNET_CONFIG_CMD_SAVE: // Received Save request from web page send_cmd_to_flash_thread(c_flash_data, UART_CONFIG, FLASH_CMD_SAVE); for(int i = 0; i < NUM_UART_CHANNELS; i++) { uart_config_data_t *data1 = uart_get_config(i); send_data_to_flash_thread(c_flash_data, data1); } flash_result = get_flash_access_result(c_flash_data); if (flash_result != S2E_FLASH_OK) { st->err = flash_err_msg; xtcp_init_send(c_xtcp, conn); return; } out_channel_id = 7; break; case TELNET_CONFIG_CMD_RESTORE: // Received Restore request from web page send_cmd_to_flash_thread(c_flash_data, UART_CONFIG, FLASH_CMD_RESTORE); flash_result = get_flash_access_result(c_flash_data); if (flash_result == S2E_FLASH_OK) { for (int i = 0; i < NUM_UART_CHANNELS; i++) { get_data_from_flash_thread(c_flash_data, &data1, &telnet_port1); uart_config_data_t *config = uart_get_config(data1.channel_id); *config = data1; uart_set_config(c_uart_config, &data1); telnet_to_uart_set_port(c_xtcp, data1.channel_id, telnet_port1); } } else { st->err = flash_err_msg; xtcp_init_send(c_xtcp, conn); return; } out_channel_id = 7; break; default: st->err = invalid_cmd_msg; xtcp_init_send(c_xtcp, conn); return; break; } st->config_out = *uart_get_config(out_channel_id); st->telnet_port_out = telnet_to_uart_get_port(out_channel_id); st->cmd_out = st->cmd; st->sending_ack = 1; xtcp_init_send(c_xtcp, conn); }
static void process_xscope_data(chanend c_xtcp, xscope_protocol xscope_data) { /* Custom protocol definition * Start with cmd_type, send end_token as 0 as last * Listen: 0-dc-inport-proto-dc * Connect: 1-dc-out_port-proto-host_ipconfig * Send: 2-1-local_port-dc-remote_addr * Close: 2-2-local_port-dc-remote_addr */ #define CONTROLLER_IP {169, 254, 196, 179} #if !defined(CONTROLLER_IP) #warning No define of form CONTROLLER_IP #error Rebuild the application with this define assigned to the host controller ip #endif xtcp_ipaddr_t ipaddr = CONTROLLER_IP; /*ipaddr[0] = atoi(xscope_data.ip_addr_1); ipaddr[1] = atoi(xscope_data.ip_addr_2); ipaddr[2] = atoi(xscope_data.ip_addr_3); ipaddr[3] = atoi(xscope_data.ip_addr_4);*/ switch (xscope_data.cmd_type) { case XSCOPE_CMD_LISTEN: //listen; for server type conn xtcp_listen(c_xtcp, xscope_data.port_no, xscope_data.protocol); printstr("Listening on port: "); printintln(xscope_data.port_no); break; case XSCOPE_CMD_CONNECT: //connect; for client type conn xtcp_connect(c_xtcp, xscope_data.port_no, ipaddr, xscope_data.protocol); printstr("Connected to host on port: "); printintln(xscope_data.port_no); break; case XSCOPE_CMD_SEND: { //Send data int conn_id; xtcp_connection_t conn; if (PROTO_TCP == xscope_data.protocol) conn_id = get_tcp_conn_id(ipaddr, xscope_data.port_no); else if (PROTO_UDP == xscope_data.protocol) conn_id = get_udp_conn_id(ipaddr, xscope_data.port_no); if (conn_id) { conn.id = conn_id; xtcp_init_send(c_xtcp, &conn); printstr("Sending data on the connection: "); printintln(conn_id); } } break; case XSCOPE_CMD_CLOSE: { //Close command int conn_id; xtcp_connection_t conn; if (PROTO_TCP == xscope_data.protocol) conn_id = get_tcp_conn_id(ipaddr, xscope_data.port_no); else if (PROTO_UDP == xscope_data.protocol) conn_id = get_udp_conn_id(ipaddr, xscope_data.port_no); if (conn_id) { conn.id = conn_id; xtcp_close(c_xtcp, &conn); printstr("Closing the connection: "); printintln(conn_id); } } break; case XSCOPE_CMD_CTRLR_SEND: //this is a controller send command; do nothing break; default: printstrln("unknown command received"); break; } }