// Send some data back for a HTTP request void httpd_send(chanend tcp_svr, xtcp_connection_t *conn) { struct httpd_state_t *hs = (struct httpd_state_t *) conn->appstate; // Check if we need to resend previous data if (conn->event == XTCP_RESEND_DATA) { xtcp_send(tcp_svr, hs->prev_dptr, (hs->dptr - hs->prev_dptr)); return; } // Check if we have no data to send if (hs->dlen == 0 || hs->dptr == NULL) { // Terminates the send process xtcp_complete_send(tcp_svr); // Close the connection xtcp_close(tcp_svr, conn); } // We need to send some new data else { int len = hs->dlen; if (len > conn->mss) len = conn->mss; xtcp_send(tcp_svr, hs->dptr, len); hs->prev_dptr = hs->dptr; hs->dptr += len; hs->dlen -= len; } //// }
void httpd_init_state(chanend tcp_svr, xtcp_connection_t *conn) { int i; for (i=0;i<NUM_HTTPD_CONNECTIONS;i++) { if (!connection_states[i].active) break; } if (i==NUM_HTTPD_CONNECTIONS) { printstr("Too many httpd connections!"); xtcp_close(tcp_svr, conn); } else { // printstr("open "); //printintln(i); connection_states[i].active = 1; connection_states[i].conn_id = conn->id; connection_states[i].pss.cmdptr = 0; connection_states[i].pss.dptr = 0; connection_states[i].pss.saved_dptr = 0; connection_states[i].pss.bfcount = 0; connection_states[i].saved_pss = connection_states[i].pss; xtcp_set_connection_appstate(tcp_svr, conn, (xtcp_appstate_t) &connection_states[i]); } return; }
void demo_protocol_periodic(chanend tcp_svr, int t) { // timeout any inactive connections for (int i = 0; i < NUM_DEMO_PROTOCOL_CONNECTIONS; i++) { struct demo_protocol_state_t *st = &connection_states[i]; xtcp_connection_t conn; if (st->active) { if ((t - st->last_used) > DEMO_PROTOCOL_CONN_TIMEOUT_TIMER_TICKS) { conn.id = st->conn_id; xtcp_close(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); }
// Parses a HTTP request for a GET static void parse_telnet_stream(chanend tcp_svr, xtcp_connection_t *conn, telnetd_state_t *hs, char *data, int len) { int i = 0; while (i<len) { switch (hs->parse_state) { case PARSING_CMD: switch (data[i]) { case SB: hs->parse_state = PARSING_OPTIONS; break; case SE: hs->parse_state = PARSING_DATA; break; case WILL: case WONT: hs->parse_state = PARSING_REQUEST; break; case DO: case DONT: hs->parse_state = PARSING_NOTIFICATION; break; case IP: xtcp_close(tcp_svr, conn); return; default: // unsupported command - ignore hs->parse_state = PARSING_DATA; break; }; i++; break; case PARSING_NOTIFICATION: // just ignore everything the other side tells us for now hs->parse_state = PARSING_DATA; i++; break; case PARSING_REQUEST: #if 0 switch (data[i]) { case SUPPRESS_GA: hs->pending_cmd = DO; hs->pending_cmd_data = data[i]; break; default: hs->pending_cmd = DONT; hs->pending_cmd_data = data[i]; break; }; telnetd_init_send(tcp_svr, hs, conn); #endif hs->parse_state = PARSING_DATA; i++; break; case PARSING_OPTIONS: if (data[i] == IAC) hs->parse_state = PARSING_CMD; i++; break; case PARSING_DATA: switch (data[i]) { case IAC: hs->parse_state = PARSING_CMD; break; case CR: hs->line_buf_in[hs->inptr] = NUL; hs->parse_state = PARSING_EOL; break; default: if (hs->inptr < TELNET_LINE_BUFFER_LEN && data[i] != NUL && !(data[i] & 0x80)) { hs->line_buf_in[hs->inptr] = data[i]; hs->inptr++; } break; } i++; break; case PARSING_EOL: if (data[i] == LF) { telnetd_recv_line(tcp_svr, hs->index, hs->line_buf_in, hs->inptr); hs->inptr = 0; hs->parse_state = PARSING_DATA; } i++; break; } } if (hs->first_recv) { hs->first_recv = 0; telnetd_new_connection(tcp_svr,hs->index); } }
void httpd_handle_send_request(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]; char *dptr = &data[0]; int len; int maxlen; if (hs->pss.cmdptr == 0) { xtcp_send(tcp_svr, data, 0); xtcp_close(tcp_svr, conn); return; } switch (conn->event) { case XTCP_REQUEST_DATA: break; case XTCP_SENT_DATA: break; case XTCP_RESEND_DATA: hs->pss = hs->saved_pss; break; default: break; } hs->saved_pss = hs->pss; maxlen = conn->mss; len = 0; // fill up the data buffer to maxlen while (len != maxlen && hs->pss.cmdptr != 0) { if (len + hs->pss.left <= maxlen) { page_server_get_data(page_svr, (char *) dptr, &(hs->pss), hs->pss.left); len += hs->pss.left; dptr += hs->pss.left; hs->pss.dptr += hs->pss.left; if (!page_server_eof(page_svr, &(hs->pss))) page_server_next_cmd(page_svr, &(hs->pss)); else hs->pss.cmdptr = 0; } else { int partial_len = maxlen - len; page_server_get_data(page_svr, (char *) dptr, &(hs->pss), partial_len); len += partial_len; hs->pss.left -= partial_len; hs->pss.dptr += partial_len; } } xtcp_send(tcp_svr, data, len); return; }
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; } }
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; } }